1*7304104dSAndroid Build Coastguard Worker /* Return sibling of given DIE.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2003-2010, 2014, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2003.
5*7304104dSAndroid Build Coastguard Worker
6*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker it under the terms of either
8*7304104dSAndroid Build Coastguard Worker
9*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker your option) any later version
12*7304104dSAndroid Build Coastguard Worker
13*7304104dSAndroid Build Coastguard Worker or
14*7304104dSAndroid Build Coastguard Worker
15*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker your option) any later version
18*7304104dSAndroid Build Coastguard Worker
19*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker
21*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24*7304104dSAndroid Build Coastguard Worker General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker
26*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
28*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
29*7304104dSAndroid Build Coastguard Worker
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker
34*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
35*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
36*7304104dSAndroid Build Coastguard Worker #include <string.h>
37*7304104dSAndroid Build Coastguard Worker
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker int
dwarf_siblingof(Dwarf_Die * die,Dwarf_Die * result)40*7304104dSAndroid Build Coastguard Worker dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result)
41*7304104dSAndroid Build Coastguard Worker {
42*7304104dSAndroid Build Coastguard Worker /* Ignore previous errors. */
43*7304104dSAndroid Build Coastguard Worker if (die == NULL)
44*7304104dSAndroid Build Coastguard Worker return -1;
45*7304104dSAndroid Build Coastguard Worker
46*7304104dSAndroid Build Coastguard Worker /* result is declared NN */
47*7304104dSAndroid Build Coastguard Worker
48*7304104dSAndroid Build Coastguard Worker if (result != die)
49*7304104dSAndroid Build Coastguard Worker result->addr = NULL;
50*7304104dSAndroid Build Coastguard Worker
51*7304104dSAndroid Build Coastguard Worker unsigned int level = 0;
52*7304104dSAndroid Build Coastguard Worker
53*7304104dSAndroid Build Coastguard Worker /* Copy of the current DIE. */
54*7304104dSAndroid Build Coastguard Worker Dwarf_Die this_die = *die;
55*7304104dSAndroid Build Coastguard Worker /* Temporary attributes we create. */
56*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute sibattr;
57*7304104dSAndroid Build Coastguard Worker /* Copy of the CU in the request. */
58*7304104dSAndroid Build Coastguard Worker sibattr.cu = this_die.cu;
59*7304104dSAndroid Build Coastguard Worker /* That's the address we start looking. */
60*7304104dSAndroid Build Coastguard Worker unsigned char *addr;
61*7304104dSAndroid Build Coastguard Worker
62*7304104dSAndroid Build Coastguard Worker /* Search for the beginning of the next die on this level. We
63*7304104dSAndroid Build Coastguard Worker must not return the dies for children of the given die. */
64*7304104dSAndroid Build Coastguard Worker do
65*7304104dSAndroid Build Coastguard Worker {
66*7304104dSAndroid Build Coastguard Worker /* Find the end of the DIE or the sibling attribute. */
67*7304104dSAndroid Build Coastguard Worker addr = __libdw_find_attr (&this_die, DW_AT_sibling, &sibattr.code,
68*7304104dSAndroid Build Coastguard Worker &sibattr.form);
69*7304104dSAndroid Build Coastguard Worker if (addr != NULL && sibattr.code == DW_AT_sibling)
70*7304104dSAndroid Build Coastguard Worker {
71*7304104dSAndroid Build Coastguard Worker Dwarf_Off offset;
72*7304104dSAndroid Build Coastguard Worker sibattr.valp = addr;
73*7304104dSAndroid Build Coastguard Worker if (unlikely (__libdw_formref (&sibattr, &offset) != 0))
74*7304104dSAndroid Build Coastguard Worker /* Something went wrong. */
75*7304104dSAndroid Build Coastguard Worker return -1;
76*7304104dSAndroid Build Coastguard Worker
77*7304104dSAndroid Build Coastguard Worker /* The sibling attribute should point after this DIE in the CU.
78*7304104dSAndroid Build Coastguard Worker But not after the end of the CU. */
79*7304104dSAndroid Build Coastguard Worker size_t size = sibattr.cu->endp - sibattr.cu->startp;
80*7304104dSAndroid Build Coastguard Worker size_t die_off = this_die.addr - this_die.cu->startp;
81*7304104dSAndroid Build Coastguard Worker if (unlikely (offset >= size || offset <= die_off))
82*7304104dSAndroid Build Coastguard Worker {
83*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
84*7304104dSAndroid Build Coastguard Worker return -1;
85*7304104dSAndroid Build Coastguard Worker }
86*7304104dSAndroid Build Coastguard Worker
87*7304104dSAndroid Build Coastguard Worker /* Compute the next address. */
88*7304104dSAndroid Build Coastguard Worker addr = sibattr.cu->startp + offset;
89*7304104dSAndroid Build Coastguard Worker }
90*7304104dSAndroid Build Coastguard Worker else if (unlikely (addr == NULL)
91*7304104dSAndroid Build Coastguard Worker || unlikely (this_die.abbrev == DWARF_END_ABBREV))
92*7304104dSAndroid Build Coastguard Worker return -1;
93*7304104dSAndroid Build Coastguard Worker else if (this_die.abbrev->has_children)
94*7304104dSAndroid Build Coastguard Worker /* This abbreviation has children. */
95*7304104dSAndroid Build Coastguard Worker ++level;
96*7304104dSAndroid Build Coastguard Worker
97*7304104dSAndroid Build Coastguard Worker /* End of the buffer. */
98*7304104dSAndroid Build Coastguard Worker unsigned char *endp = sibattr.cu->endp;
99*7304104dSAndroid Build Coastguard Worker
100*7304104dSAndroid Build Coastguard Worker while (1)
101*7304104dSAndroid Build Coastguard Worker {
102*7304104dSAndroid Build Coastguard Worker /* Make sure we are still in range. Some producers might skip
103*7304104dSAndroid Build Coastguard Worker the trailing NUL bytes. */
104*7304104dSAndroid Build Coastguard Worker if (addr >= endp)
105*7304104dSAndroid Build Coastguard Worker return 1;
106*7304104dSAndroid Build Coastguard Worker
107*7304104dSAndroid Build Coastguard Worker if (*addr != '\0')
108*7304104dSAndroid Build Coastguard Worker break;
109*7304104dSAndroid Build Coastguard Worker
110*7304104dSAndroid Build Coastguard Worker if (level-- == 0)
111*7304104dSAndroid Build Coastguard Worker {
112*7304104dSAndroid Build Coastguard Worker if (result != die)
113*7304104dSAndroid Build Coastguard Worker result->addr = addr;
114*7304104dSAndroid Build Coastguard Worker /* No more sibling at all. */
115*7304104dSAndroid Build Coastguard Worker return 1;
116*7304104dSAndroid Build Coastguard Worker }
117*7304104dSAndroid Build Coastguard Worker
118*7304104dSAndroid Build Coastguard Worker ++addr;
119*7304104dSAndroid Build Coastguard Worker }
120*7304104dSAndroid Build Coastguard Worker
121*7304104dSAndroid Build Coastguard Worker /* Initialize the 'current DIE'. */
122*7304104dSAndroid Build Coastguard Worker this_die.addr = addr;
123*7304104dSAndroid Build Coastguard Worker this_die.abbrev = NULL;
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker while (level > 0);
126*7304104dSAndroid Build Coastguard Worker
127*7304104dSAndroid Build Coastguard Worker /* Maybe we reached the end of the CU. */
128*7304104dSAndroid Build Coastguard Worker unsigned char *endp = sibattr.cu->endp;
129*7304104dSAndroid Build Coastguard Worker if (addr >= endp)
130*7304104dSAndroid Build Coastguard Worker return 1;
131*7304104dSAndroid Build Coastguard Worker
132*7304104dSAndroid Build Coastguard Worker /* Clear the entire DIE structure. This signals we have not yet
133*7304104dSAndroid Build Coastguard Worker determined any of the information. */
134*7304104dSAndroid Build Coastguard Worker memset (result, '\0', sizeof (Dwarf_Die));
135*7304104dSAndroid Build Coastguard Worker
136*7304104dSAndroid Build Coastguard Worker /* We have the address. */
137*7304104dSAndroid Build Coastguard Worker result->addr = addr;
138*7304104dSAndroid Build Coastguard Worker
139*7304104dSAndroid Build Coastguard Worker /* Same CU as the parent. */
140*7304104dSAndroid Build Coastguard Worker result->cu = sibattr.cu;
141*7304104dSAndroid Build Coastguard Worker
142*7304104dSAndroid Build Coastguard Worker return 0;
143*7304104dSAndroid Build Coastguard Worker }
144*7304104dSAndroid Build Coastguard Worker INTDEF(dwarf_siblingof)
145