1 /* Find CU for given offset.
2 Copyright (C) 2003-2010, 2014, 2016, 2017, 2018 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2003.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
9 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
19 or both in parallel, as here.
21 elfutils is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
39 findcu_cb (const void *arg1, const void *arg2)
41 struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1;
42 struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2;
44 /* Find out which of the two arguments is the search value. It has
48 if (cu1->start < cu2->start)
50 if (cu1->start >= cu2->end)
55 if (cu2->start < cu1->start)
57 if (cu2->start >= cu1->end)
65 __libdw_finddbg_cb (const void *arg1, const void *arg2)
67 Dwarf *dbg1 = (Dwarf *) arg1;
68 Dwarf *dbg2 = (Dwarf *) arg2;
70 Elf_Data *dbg1_data = dbg1->sectiondata[IDX_debug_info];
71 unsigned char *dbg1_start = dbg1_data->d_buf;
72 size_t dbg1_size = dbg1_data->d_size;
74 Elf_Data *dbg2_data = dbg2->sectiondata[IDX_debug_info];
75 unsigned char *dbg2_start = dbg2_data->d_buf;
76 size_t dbg2_size = dbg2_data->d_size;
78 /* Find out which of the two arguments is the search value. It has
82 if (dbg1_start < dbg2_start)
84 if (dbg1_start >= dbg2_start + dbg2_size)
89 if (dbg2_start < dbg1_start)
91 if (dbg2_start >= dbg1_start + dbg1_size)
100 __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
102 Dwarf_Off *const offsetp
103 = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
104 void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree;
106 Dwarf_Off oldoff = *offsetp;
109 uint8_t address_size;
111 Dwarf_Off abbrev_offset;
113 Dwarf_Off subdie_offset;
115 if (__libdw_next_unit (dbg, debug_types, oldoff, offsetp, NULL,
116 &version, &unit_type, &abbrev_offset,
117 &address_size, &offset_size,
118 &unit_id8, &subdie_offset) != 0)
119 /* No more entries. */
122 /* We only know how to handle the DWARF version 2 through 5 formats.
123 For v4 debug types we only handle version 4. */
124 if (unlikely (version < 2) || unlikely (version > 5)
125 || (debug_types && unlikely (version != 4)))
127 __libdw_seterrno (DWARF_E_VERSION);
131 /* We only handle 32 or 64 bit (4 or 8 byte) addresses and offsets.
132 Just assume we are dealing with 64bit in case the size is "unknown".
133 Too much code assumes if it isn't 4 then it is 8 (or the other way
135 if (unlikely (address_size != 4 && address_size != 8))
137 if (unlikely (offset_size != 4 && offset_size != 8))
140 /* Invalid or truncated debug section data? */
141 size_t sec_idx = debug_types ? IDX_debug_types : IDX_debug_info;
142 Elf_Data *data = dbg->sectiondata[sec_idx];
143 if (unlikely (*offsetp > data->d_size))
144 *offsetp = data->d_size;
146 /* Create an entry for this CU. */
147 struct Dwarf_CU *newp = libdw_typed_alloc (dbg, struct Dwarf_CU);
150 newp->sec_idx = sec_idx;
151 newp->start = oldoff;
152 newp->end = *offsetp;
153 newp->address_size = address_size;
154 newp->offset_size = offset_size;
155 newp->version = version;
156 newp->unit_id8 = unit_id8;
157 newp->subdie_offset = subdie_offset;
158 Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41);
159 newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset;
163 newp->split = (Dwarf_CU *) -1;
164 newp->base_address = (Dwarf_Addr) -1;
165 newp->addr_base = (Dwarf_Off) -1;
166 newp->str_off_base = (Dwarf_Off) -1;
167 newp->ranges_base = (Dwarf_Off) -1;
168 newp->locs_base = (Dwarf_Off) -1;
170 newp->startp = data->d_buf + newp->start;
171 newp->endp = data->d_buf + newp->end;
173 /* v4 debug type units have version == 4 and unit_type == DW_UT_type. */
175 newp->unit_type = DW_UT_type;
176 else if (version < 5)
178 /* This is a reasonable guess (and needed to get the CUDIE). */
179 newp->unit_type = DW_UT_compile;
181 /* But set it correctly from the actual CUDIE tag. */
182 Dwarf_Die cudie = CUDIE (newp);
183 int tag = INTUSE(dwarf_tag) (&cudie);
184 if (tag == DW_TAG_compile_unit)
186 Dwarf_Attribute dwo_id;
187 if (INTUSE(dwarf_attr) (&cudie, DW_AT_GNU_dwo_id, &dwo_id) != NULL)
190 if (INTUSE(dwarf_formudata) (&dwo_id, &id8) == 0)
192 if (INTUSE(dwarf_haschildren) (&cudie) == 0
193 && INTUSE(dwarf_hasattr) (&cudie,
194 DW_AT_GNU_dwo_name) == 1)
195 newp->unit_type = DW_UT_skeleton;
197 newp->unit_type = DW_UT_split_compile;
199 newp->unit_id8 = id8;
203 else if (tag == DW_TAG_partial_unit)
204 newp->unit_type = DW_UT_partial;
205 else if (tag == DW_TAG_type_unit)
206 newp->unit_type = DW_UT_type;
209 newp->unit_type = unit_type;
211 /* Store a reference to any type unit ids in the hash for quick lookup. */
212 if (unit_type == DW_UT_type || unit_type == DW_UT_split_type)
213 Dwarf_Sig8_Hash_insert (&dbg->sig8_hash, unit_id8, newp);
215 /* Add the new entry to the search tree. */
216 if (tsearch (newp, tree, findcu_cb) == NULL)
218 /* Something went wrong. Undo the operation. */
220 __libdw_seterrno (DWARF_E_NOMEM);
229 __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool v4_debug_types)
231 void **tree = v4_debug_types ? &dbg->tu_tree : &dbg->cu_tree;
232 Dwarf_Off *next_offset
233 = v4_debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
235 /* Maybe we already know that CU. */
236 struct Dwarf_CU fake = { .start = start, .end = 0 };
237 struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb);
241 if (start < *next_offset)
243 __libdw_seterrno (DWARF_E_INVALID_DWARF);
247 /* No. Then read more CUs. */
250 struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, v4_debug_types);
254 /* Is this the one we are looking for? */
255 if (start < *next_offset || start == newp->start)
263 __libdw_findcu_addr (Dwarf *dbg, void *addr)
267 if (addr >= dbg->sectiondata[IDX_debug_info]->d_buf
268 && addr < (dbg->sectiondata[IDX_debug_info]->d_buf
269 + dbg->sectiondata[IDX_debug_info]->d_size))
271 tree = &dbg->cu_tree;
272 start = addr - dbg->sectiondata[IDX_debug_info]->d_buf;
274 else if (dbg->sectiondata[IDX_debug_types] != NULL
275 && addr >= dbg->sectiondata[IDX_debug_types]->d_buf
276 && addr < (dbg->sectiondata[IDX_debug_types]->d_buf
277 + dbg->sectiondata[IDX_debug_types]->d_size))
279 tree = &dbg->tu_tree;
280 start = addr - dbg->sectiondata[IDX_debug_types]->d_buf;
285 struct Dwarf_CU fake = { .start = start, .end = 0 };
286 struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb);
296 __libdw_find_split_dbg_addr (Dwarf *dbg, void *addr)
298 /* XXX Assumes split DWARF only has CUs in main IDX_debug_info. */
299 Elf_Data fake_data = { .d_buf = addr, .d_size = 0 };
300 Dwarf fake = { .sectiondata[IDX_debug_info] = &fake_data };
301 Dwarf **found = tfind (&fake, &dbg->split_tree, __libdw_finddbg_cb);