• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Return vhild of current DIE.
2    Copyright (C) 2003, 2004 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
4 
5    This program is Open Source software; you can redistribute it and/or
6    modify it under the terms of the Open Software License version 1.0 as
7    published by the Open Source Initiative.
8 
9    You should have received a copy of the Open Software License along
10    with this program; if not, you may obtain a copy of the Open Software
11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13    3001 King Ranch Road, Ukiah, CA 95482.   */
14 
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 
19 #include "libdwP.h"
20 #include <string.h>
21 
22 /* Some arbitrary value not conflicting with any existing code.  */
23 #define INVALID 0xffffe444
24 
25 
26 unsigned char *
27 internal_function_def
__libdw_find_attr(Dwarf_Die * die,unsigned int search_name,unsigned int * codep,unsigned int * formp)28 __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
29 		   unsigned int *codep, unsigned int *formp)
30 {
31   Dwarf *dbg = die->cu->dbg;
32   unsigned char *readp = (unsigned char *) die->addr;
33 
34   /* First we have to get the abbreviation code so that we can decode
35      the data in the DIE.  */
36   unsigned int abbrev_code;
37   get_uleb128 (abbrev_code, readp);
38 
39   /* Find the abbreviation entry.  */
40   Dwarf_Abbrev *abbrevp = die->abbrev;
41   if (abbrevp == NULL)
42     {
43       abbrevp = __libdw_findabbrev (die->cu, abbrev_code);
44       die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
45     }
46   if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l))
47     {
48       __libdw_seterrno (DWARF_E_INVALID_DWARF);
49       return NULL;
50     }
51 
52   /* Search the name attribute.  */
53   unsigned char *const endp
54     = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
55        + dbg->sectiondata[IDX_debug_abbrev]->d_size);
56 
57   unsigned char *attrp = die->abbrev->attrp;
58   while (1)
59     {
60       /* Are we still in bounds?  This test needs to be refined.  */
61       if (unlikely (attrp + 1 >= endp))
62 	{
63 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
64 	  return NULL;
65 	}
66 
67       /* Get attribute name and form.
68 
69 	 XXX We don't check whether this reads beyond the end of the
70 	 section.  */
71       unsigned int attr_name;
72       get_uleb128 (attr_name, attrp);
73       unsigned int attr_form;
74       get_uleb128 (attr_form, attrp);
75 
76       /* We can stop if we found the attribute with value zero.  */
77       if (attr_name == 0 && attr_form == 0)
78 	break;
79 
80       /* Is this the name attribute?  */
81       if (attr_name == search_name && search_name != INVALID)
82 	{
83 	  if (codep != NULL)
84 	    *codep = attr_name;
85 	  if (formp != NULL)
86 	    *formp = attr_form;
87 
88 	  return readp;
89 	}
90 
91       /* Skip over the rest of this attribute (if there is any).  */
92       if (attr_form != 0)
93 	{
94 	  size_t len = __libdw_form_val_len (dbg, die->cu, attr_form, readp);
95 
96 	  if (unlikely (len == (size_t) -1l))
97 	    {
98 	      readp = NULL;
99 	      break;
100 	    }
101 
102 	  // XXX We need better boundary checks.
103 	  readp += len;
104 	}
105     }
106 
107   // XXX Do we need other values?
108   if (codep != NULL)
109     *codep = INVALID;
110   if (formp != NULL)
111     *formp = INVALID;
112 
113   return readp;
114 }
115 
116 
117 int
dwarf_child(die,result)118 dwarf_child (die, result)
119      Dwarf_Die *die;
120      Dwarf_Die *result;
121 {
122   /* Ignore previous errors.  */
123   if (die == NULL)
124     return -1;
125 
126   /* Skip past the last attribute.  */
127   void *addr = NULL;
128 
129   /* If we already know there are no children do not search.  */
130   if (die->abbrev != (Dwarf_Abbrev *) -1
131       && (die->abbrev == NULL || die->abbrev->has_children))
132     addr = __libdw_find_attr (die, INVALID, NULL, NULL);
133   if (die->abbrev == (Dwarf_Abbrev *) -1l)
134     return -1;
135 
136   /* Make sure the DIE really has children.  */
137   if (! die->abbrev->has_children)
138     /* There cannot be any children.  */
139     return 1;
140 
141   if (addr == NULL)
142     return -1;
143 
144   /* RESULT can be the same as DIE.  So preserve what we need.  */
145   struct Dwarf_CU *cu = die->cu;
146 
147   /* Clear the entire DIE structure.  This signals we have not yet
148      determined any of the information.  */
149   memset (result, '\0', sizeof (Dwarf_Die));
150 
151   /* We have the address.  */
152   result->addr = addr;
153 
154   /* Same CU as the parent.  */
155   result->cu = cu;
156 
157   return 0;
158 }
159