/src/elfutils/libdw/dwarf_cu_dwp_section_info.c
Line | Count | Source |
1 | | /* Read DWARF package file index sections. |
2 | | Copyright (c) 2023 Meta Platforms, Inc. and affiliates. |
3 | | This file is part of elfutils. |
4 | | |
5 | | This file is free software; you can redistribute it and/or modify |
6 | | it under the terms of either |
7 | | |
8 | | * the GNU Lesser General Public License as published by the Free |
9 | | Software Foundation; either version 3 of the License, or (at |
10 | | your option) any later version |
11 | | |
12 | | or |
13 | | |
14 | | * the GNU General Public License as published by the Free |
15 | | Software Foundation; either version 2 of the License, or (at |
16 | | your option) any later version |
17 | | |
18 | | or both in parallel, as here. |
19 | | |
20 | | elfutils is distributed in the hope that it will be useful, but |
21 | | WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
23 | | General Public License for more details. |
24 | | |
25 | | You should have received copies of the GNU General Public License and |
26 | | the GNU Lesser General Public License along with this program. If |
27 | | not, see <http://www.gnu.org/licenses/>. */ |
28 | | |
29 | | #ifdef HAVE_CONFIG_H |
30 | | # include <config.h> |
31 | | #endif |
32 | | |
33 | | #include <assert.h> |
34 | | |
35 | | #include "libdwP.h" |
36 | | |
37 | | static Dwarf_Package_Index * |
38 | | __libdw_read_package_index (Dwarf *dbg, bool tu) |
39 | 0 | { |
40 | 0 | Elf_Data *data; |
41 | 0 | if (tu) |
42 | 0 | data = dbg->sectiondata[IDX_debug_tu_index]; |
43 | 0 | else |
44 | 0 | data = dbg->sectiondata[IDX_debug_cu_index]; |
45 | | |
46 | | /* We need at least 16 bytes for the header. */ |
47 | 0 | if (data == NULL || data->d_size < 16) |
48 | 0 | { |
49 | 0 | invalid: |
50 | 0 | __libdw_seterrno (DWARF_E_INVALID_DWARF); |
51 | 0 | return NULL; |
52 | 0 | } |
53 | | |
54 | 0 | const unsigned char *datap = data->d_buf; |
55 | 0 | const unsigned char *endp = datap + data->d_size; |
56 | 0 | uint16_t version; |
57 | | /* In GNU DebugFission for DWARF 4, the version is 2 as a uword. In the |
58 | | standardized DWARF 5 format, it is a uhalf followed by a padding uhalf. |
59 | | Check for both. */ |
60 | 0 | if (read_4ubyte_unaligned (dbg, datap) == 2) |
61 | 0 | version = 2; |
62 | 0 | else |
63 | 0 | { |
64 | 0 | version = read_2ubyte_unaligned (dbg, datap); |
65 | 0 | if (version != 5) |
66 | 0 | { |
67 | 0 | __libdw_seterrno (DWARF_E_VERSION); |
68 | 0 | return NULL; |
69 | 0 | } |
70 | 0 | } |
71 | 0 | datap += 4; |
72 | 0 | uint32_t section_count = read_4ubyte_unaligned_inc (dbg, datap); |
73 | 0 | uint32_t unit_count = read_4ubyte_unaligned_inc (dbg, datap); |
74 | 0 | uint32_t slot_count = read_4ubyte_unaligned_inc (dbg, datap); |
75 | | |
76 | | /* The specification has a stricter requirement that |
77 | | slot_count > 3 * unit_count / 2, but this is enough for us. */ |
78 | 0 | if (slot_count < unit_count) |
79 | 0 | goto invalid; |
80 | | |
81 | | /* After the header, the section must contain: |
82 | | |
83 | | 8 byte signature per hash table slot |
84 | | + 4 byte index per hash table slot |
85 | | + Section offset table with 1 header row, 1 row per unit, 1 column per |
86 | | section, 4 bytes per field |
87 | | + Section size table with 1 row per unit, 1 column per section, 4 bytes |
88 | | per field |
89 | | |
90 | | We have to be careful about overflow when checking this. */ |
91 | 0 | const unsigned char *hash_table = datap; |
92 | 0 | if ((size_t) (endp - hash_table) < (uint64_t) slot_count * 12) |
93 | 0 | goto invalid; |
94 | 0 | const unsigned char *indices = hash_table + (size_t) slot_count * 8; |
95 | 0 | const unsigned char *sections = indices + (size_t) slot_count * 4; |
96 | 0 | if ((size_t) (endp - sections) < (uint64_t) section_count * 4) |
97 | 0 | goto invalid; |
98 | 0 | const unsigned char *section_offsets = sections + (size_t) section_count * 4; |
99 | 0 | if ((uint64_t) unit_count * section_count > UINT64_MAX / 8 |
100 | 0 | || ((size_t) (endp - section_offsets) |
101 | 0 | < (uint64_t) unit_count * section_count * 8)) |
102 | 0 | goto invalid; |
103 | 0 | const unsigned char *section_sizes |
104 | 0 | = section_offsets + (uint64_t) unit_count * section_count * 4; |
105 | |
|
106 | 0 | Dwarf_Package_Index *index = malloc (sizeof (*index)); |
107 | 0 | if (index == NULL) |
108 | 0 | { |
109 | 0 | __libdw_seterrno (DWARF_E_NOMEM); |
110 | 0 | return NULL; |
111 | 0 | } |
112 | | |
113 | 0 | index->dbg = dbg; |
114 | | /* Set absent sections to UINT32_MAX. */ |
115 | 0 | for (size_t i = 0; |
116 | 0 | i < sizeof (index->sections) / sizeof (index->sections[0]); i++) |
117 | 0 | index->sections[i] = UINT32_MAX; |
118 | 0 | for (size_t i = 0; i < section_count; i++) |
119 | 0 | { |
120 | 0 | uint32_t section = read_4ubyte_unaligned (dbg, sections + i * 4); |
121 | | /* 2 is DW_SECT_TYPES in version 2 and reserved in version 5. We ignore |
122 | | it for version 5. |
123 | | 5 is DW_SECT_LOC in version 2 and DW_SECT_LOCLISTS in version 5. We |
124 | | use the same index for both. |
125 | | 7 is DW_SECT_MACINFO in version 2 and DW_SECT_MACRO in version 5. We |
126 | | use the same index for both. |
127 | | 8 is DW_SECT_MACRO in version 2 and DW_SECT_RNGLISTS in version 5. We |
128 | | use the same index for version 2's DW_SECT_MACRO as version 2's |
129 | | DW_SECT_MACINFO/version 5's DW_SECT_MACRO. |
130 | | We ignore unknown sections. */ |
131 | 0 | if (section == 0) |
132 | 0 | continue; |
133 | 0 | if (version == 2) |
134 | 0 | { |
135 | 0 | if (section > 8) |
136 | 0 | continue; |
137 | 0 | else if (section == 8) |
138 | 0 | section = DW_SECT_MACRO; |
139 | 0 | } |
140 | 0 | else if (section == 2 |
141 | 0 | || (section |
142 | 0 | > sizeof (index->sections) / sizeof (index->sections[0]))) |
143 | 0 | continue; |
144 | 0 | index->sections[section - 1] = i; |
145 | 0 | } |
146 | | |
147 | | /* DW_SECT_INFO (or DW_SECT_TYPES for DWARF 4 type units) and DW_SECT_ABBREV |
148 | | are required. */ |
149 | 0 | if (((!tu || dbg->sectiondata[IDX_debug_types] == NULL) |
150 | 0 | && index->sections[DW_SECT_INFO - 1] == UINT32_MAX) |
151 | 0 | || (tu && dbg->sectiondata[IDX_debug_types] != NULL |
152 | 0 | && index->sections[DW_SECT_TYPES - 1] == UINT32_MAX) |
153 | 0 | || index->sections[DW_SECT_ABBREV - 1] == UINT32_MAX) |
154 | 0 | { |
155 | 0 | free (index); |
156 | 0 | __libdw_seterrno (DWARF_E_INVALID_DWARF); |
157 | 0 | return NULL; |
158 | 0 | } |
159 | | |
160 | 0 | index->section_count = section_count; |
161 | 0 | index->unit_count = unit_count; |
162 | 0 | index->slot_count = slot_count; |
163 | 0 | index->last_unit_found = 0; |
164 | 0 | index->hash_table = hash_table; |
165 | 0 | index->indices = indices; |
166 | 0 | index->section_offsets = section_offsets; |
167 | 0 | index->section_sizes = section_sizes; |
168 | 0 | index->debug_info_offsets = NULL; |
169 | |
|
170 | 0 | return index; |
171 | 0 | } |
172 | | |
173 | | static Dwarf_Package_Index * |
174 | | __libdw_package_index (Dwarf *dbg, bool tu) |
175 | 0 | { |
176 | 0 | if (tu && dbg->tu_index != NULL) |
177 | 0 | return dbg->tu_index; |
178 | 0 | else if (!tu && dbg->cu_index != NULL) |
179 | 0 | return dbg->cu_index; |
180 | | |
181 | 0 | Dwarf_Package_Index *index = __libdw_read_package_index (dbg, tu); |
182 | 0 | if (index == NULL) |
183 | 0 | return NULL; |
184 | | |
185 | | /* Offsets in the section offset table are 32-bit unsigned integers. In |
186 | | practice, the .debug_info.dwo section for very large executables can be |
187 | | larger than 4GB. GNU dwp as of binutils 2.41 and llvm-dwp before LLVM 15 |
188 | | both accidentally truncate offsets larger than 4GB. |
189 | | |
190 | | LLVM 15 detects the overflow and errors out instead; see LLVM commit |
191 | | f8df8114715b ("[DWP][DWARF] Detect and error on debug info offset |
192 | | overflow"). However, lldb in LLVM 16 supports using dwp files with |
193 | | truncated offsets by recovering them directly from the unit headers in the |
194 | | .debug_info.dwo section; see LLVM commit c0db06227721 ("[DWARFLibrary] Add |
195 | | support to re-construct cu-index"). Since LLVM 17, the overflow error can |
196 | | be turned into a warning instead; see LLVM commit 53a483cee801 ("[DWP] add |
197 | | overflow check for llvm-dwp tools if offset overflow"). |
198 | | |
199 | | LLVM's support for > 4GB offsets is effectively an extension to the DWARF |
200 | | package file format, which we implement here. The strategy is to walk the |
201 | | unit headers in .debug_info.dwo in lockstep with the DW_SECT_INFO columns |
202 | | in the section offset tables. As long as they are in the same order |
203 | | (which they are in practice for both GNU dwp and llvm-dwp), we can |
204 | | correlate the truncated offset and produce a corrected array of offsets. |
205 | | |
206 | | Note that this will be fixed properly in DWARF 6: |
207 | | https://dwarfstd.org/issues/220708.2.html. */ |
208 | 0 | if (index->sections[DW_SECT_INFO - 1] != UINT32_MAX |
209 | 0 | && dbg->sectiondata[IDX_debug_info]->d_size > UINT32_MAX) |
210 | 0 | { |
211 | 0 | Dwarf_Package_Index *cu_index, *tu_index = NULL; |
212 | 0 | if (tu) |
213 | 0 | { |
214 | 0 | tu_index = index; |
215 | 0 | assert (dbg->cu_index == NULL); |
216 | 0 | cu_index = __libdw_read_package_index (dbg, false); |
217 | 0 | if (cu_index == NULL) |
218 | 0 | { |
219 | 0 | free(index); |
220 | 0 | return NULL; |
221 | 0 | } |
222 | 0 | } |
223 | 0 | else |
224 | 0 | { |
225 | 0 | cu_index = index; |
226 | 0 | if (dbg->sectiondata[IDX_debug_tu_index] != NULL |
227 | 0 | && dbg->sectiondata[IDX_debug_types] == NULL) |
228 | 0 | { |
229 | 0 | assert (dbg->tu_index == NULL); |
230 | 0 | tu_index = __libdw_read_package_index (dbg, true); |
231 | 0 | if (tu_index == NULL) |
232 | 0 | { |
233 | 0 | free(index); |
234 | 0 | return NULL; |
235 | 0 | } |
236 | 0 | } |
237 | 0 | } |
238 | | |
239 | 0 | cu_index->debug_info_offsets = malloc (cu_index->unit_count |
240 | 0 | * sizeof (Dwarf_Off)); |
241 | 0 | if (cu_index->debug_info_offsets == NULL) |
242 | 0 | { |
243 | 0 | free (tu_index); |
244 | 0 | free (cu_index); |
245 | 0 | __libdw_seterrno (DWARF_E_NOMEM); |
246 | 0 | return NULL; |
247 | 0 | } |
248 | 0 | if (tu_index != NULL) |
249 | 0 | { |
250 | 0 | tu_index->debug_info_offsets = malloc (tu_index->unit_count |
251 | 0 | * sizeof (Dwarf_Off)); |
252 | 0 | if (tu_index->debug_info_offsets == NULL) |
253 | 0 | { |
254 | 0 | free (tu_index); |
255 | 0 | free (cu_index->debug_info_offsets); |
256 | 0 | free (cu_index); |
257 | 0 | __libdw_seterrno (DWARF_E_NOMEM); |
258 | 0 | return NULL; |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | 0 | Dwarf_Off off = 0; |
263 | 0 | uint32_t cui = 0, tui = 0; |
264 | 0 | uint32_t cu_count = cu_index->unit_count; |
265 | 0 | const unsigned char *cu_offset |
266 | 0 | = cu_index->section_offsets + cu_index->sections[DW_SECT_INFO - 1] * 4; |
267 | 0 | uint32_t tu_count = 0; |
268 | 0 | const unsigned char *tu_offset = NULL; |
269 | 0 | if (tu_index != NULL) |
270 | 0 | { |
271 | 0 | tu_count = tu_index->unit_count; |
272 | 0 | tu_offset = tu_index->section_offsets |
273 | 0 | + tu_index->sections[DW_SECT_INFO - 1] * 4; |
274 | 0 | } |
275 | 0 | while (cui < cu_count || tui < tu_count) |
276 | 0 | { |
277 | 0 | Dwarf_Off next_off; |
278 | 0 | uint8_t unit_type; |
279 | 0 | if (__libdw_next_unit (dbg, false, off, &next_off, NULL, NULL, |
280 | 0 | &unit_type, NULL, NULL, NULL, NULL, NULL) |
281 | 0 | != 0) |
282 | 0 | { |
283 | 0 | not_sorted: |
284 | 0 | free (cu_index->debug_info_offsets); |
285 | 0 | cu_index->debug_info_offsets = NULL; |
286 | 0 | if (tu_index != NULL) |
287 | 0 | { |
288 | 0 | free (tu_index->debug_info_offsets); |
289 | 0 | tu_index->debug_info_offsets = NULL; |
290 | 0 | } |
291 | 0 | break; |
292 | 0 | } |
293 | 0 | if (unit_type != DW_UT_split_type && cui < cu_count) |
294 | 0 | { |
295 | 0 | if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, cu_offset)) |
296 | 0 | goto not_sorted; |
297 | 0 | cu_index->debug_info_offsets[cui++] = off; |
298 | 0 | cu_offset += cu_index->section_count * 4; |
299 | 0 | } |
300 | 0 | else if (unit_type == DW_UT_split_type && tu_index != NULL |
301 | 0 | && tui < tu_count) |
302 | 0 | { |
303 | 0 | if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, tu_offset)) |
304 | 0 | goto not_sorted; |
305 | 0 | tu_index->debug_info_offsets[tui++] = off; |
306 | 0 | tu_offset += tu_index->section_count * 4; |
307 | 0 | } |
308 | 0 | off = next_off; |
309 | 0 | } |
310 | | |
311 | 0 | if (tu) |
312 | 0 | dbg->cu_index = cu_index; |
313 | 0 | else if (tu_index != NULL) |
314 | 0 | dbg->tu_index = tu_index; |
315 | 0 | } |
316 | | |
317 | 0 | if (tu) |
318 | 0 | dbg->tu_index = index; |
319 | 0 | else |
320 | 0 | dbg->cu_index = index; |
321 | 0 | return index; |
322 | 0 | } |
323 | | |
324 | | static int |
325 | | __libdw_dwp_unit_row (Dwarf_Package_Index *index, uint64_t unit_id, |
326 | | uint32_t *unit_rowp) |
327 | 0 | { |
328 | 0 | if (index == NULL) |
329 | 0 | return -1; |
330 | | |
331 | 0 | uint32_t hash = unit_id; |
332 | 0 | uint32_t hash2 = (unit_id >> 32) | 1; |
333 | | /* Only check each slot once. */ |
334 | 0 | for (uint32_t n = index->slot_count; n-- > 0; ) |
335 | 0 | { |
336 | 0 | size_t slot = hash & (index->slot_count - 1); |
337 | 0 | uint64_t sig = read_8ubyte_unaligned (index->dbg, |
338 | 0 | index->hash_table + slot * 8); |
339 | 0 | if (sig == unit_id) |
340 | 0 | { |
341 | 0 | uint32_t row = read_4ubyte_unaligned (index->dbg, |
342 | 0 | index->indices + slot * 4); |
343 | 0 | if (row > index->unit_count) |
344 | 0 | { |
345 | 0 | __libdw_seterrno (DWARF_E_INVALID_DWARF); |
346 | 0 | return -1; |
347 | 0 | } |
348 | 0 | *unit_rowp = row; |
349 | 0 | return 0; |
350 | 0 | } |
351 | 0 | else if (sig == 0 |
352 | 0 | && read_4ubyte_unaligned (index->dbg, |
353 | 0 | index->indices + slot * 4) == 0) |
354 | 0 | break; |
355 | 0 | hash += hash2; |
356 | 0 | } |
357 | 0 | *unit_rowp = 0; |
358 | 0 | return 0; |
359 | 0 | } |
360 | | |
361 | | static int |
362 | | __libdw_dwp_section_info (Dwarf_Package_Index *index, uint32_t unit_row, |
363 | | unsigned int section, Dwarf_Off *offsetp, |
364 | | Dwarf_Off *sizep) |
365 | 0 | { |
366 | 0 | if (index == NULL) |
367 | 0 | return -1; |
368 | 0 | if (unit_row == 0) |
369 | 0 | { |
370 | 0 | __libdw_seterrno (DWARF_E_INVALID_DWARF); |
371 | 0 | return -1; |
372 | 0 | } |
373 | 0 | if (index->sections[section - 1] == UINT32_MAX) |
374 | 0 | { |
375 | 0 | if (offsetp != NULL) |
376 | 0 | *offsetp = 0; |
377 | 0 | if (sizep != NULL) |
378 | 0 | *sizep = 0; |
379 | 0 | return 0; |
380 | 0 | } |
381 | 0 | size_t i = (size_t)(unit_row - 1) * index->section_count |
382 | 0 | + index->sections[section - 1]; |
383 | 0 | if (offsetp != NULL) |
384 | 0 | { |
385 | 0 | if (section == DW_SECT_INFO && index->debug_info_offsets != NULL) |
386 | 0 | *offsetp = index->debug_info_offsets[unit_row - 1]; |
387 | 0 | else |
388 | 0 | *offsetp = read_4ubyte_unaligned (index->dbg, |
389 | 0 | index->section_offsets + i * 4); |
390 | 0 | } |
391 | 0 | if (sizep != NULL) |
392 | 0 | *sizep = read_4ubyte_unaligned (index->dbg, |
393 | 0 | index->section_sizes + i * 4); |
394 | 0 | return 0; |
395 | 0 | } |
396 | | |
397 | | int |
398 | | internal_function |
399 | | __libdw_dwp_find_unit (Dwarf *dbg, bool debug_types, Dwarf_Off off, |
400 | | uint16_t version, uint8_t unit_type, uint64_t unit_id8, |
401 | | uint32_t *unit_rowp, Dwarf_Off *abbrev_offsetp) |
402 | 0 | { |
403 | 0 | if (version >= 5 |
404 | 0 | && unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type) |
405 | 0 | { |
406 | 0 | not_dwp: |
407 | 0 | *unit_rowp = 0; |
408 | 0 | *abbrev_offsetp = 0; |
409 | 0 | return 0; |
410 | 0 | } |
411 | 0 | bool tu = unit_type == DW_UT_split_type || debug_types; |
412 | 0 | if (dbg->sectiondata[tu ? IDX_debug_tu_index : IDX_debug_cu_index] == NULL) |
413 | 0 | goto not_dwp; |
414 | 0 | Dwarf_Package_Index *index = __libdw_package_index (dbg, tu); |
415 | 0 | if (index == NULL) |
416 | 0 | return -1; |
417 | | |
418 | | /* This is always called for ascending offsets. The most obvious way for a |
419 | | producer to generate the section offset table is sorted by offset; both |
420 | | GNU dwp and llvm-dwp do this. In this common case, we can avoid the full |
421 | | lookup. */ |
422 | 0 | if (index->last_unit_found < index->unit_count) |
423 | 0 | { |
424 | 0 | Dwarf_Off offset, size; |
425 | 0 | if (__libdw_dwp_section_info (index, index->last_unit_found + 1, |
426 | 0 | debug_types ? DW_SECT_TYPES : DW_SECT_INFO, |
427 | 0 | &offset, &size) != 0) |
428 | 0 | return -1; |
429 | 0 | if (offset <= off && off - offset < size) |
430 | 0 | { |
431 | 0 | *unit_rowp = ++index->last_unit_found; |
432 | 0 | goto done; |
433 | 0 | } |
434 | 0 | else |
435 | | /* The units are not sorted. Don't try again. */ |
436 | 0 | index->last_unit_found = index->unit_count; |
437 | 0 | } |
438 | | |
439 | 0 | if (version >= 5 || debug_types) |
440 | 0 | { |
441 | | /* In DWARF 5 and in type units, the unit signature is available in the |
442 | | unit header. */ |
443 | 0 | if (__libdw_dwp_unit_row (index, unit_id8, unit_rowp) != 0) |
444 | 0 | return -1; |
445 | 0 | } |
446 | 0 | else |
447 | 0 | { |
448 | | /* In DWARF 4 compilation units, the unit signature is an attribute. We |
449 | | can't parse attributes in the split unit until we get the abbreviation |
450 | | table offset from the package index, which is a chicken-and-egg |
451 | | problem. We could get the signature from the skeleton unit, but that |
452 | | may not be available. |
453 | | |
454 | | Instead, we resort to a linear scan through the section offset table. |
455 | | Finding all units is therefore quadratic in the number of units. |
456 | | However, this will likely never be needed in practice because of the |
457 | | sorted fast path above. If this ceases to be the case, we can try to |
458 | | plumb through the skeleton unit's signature when it is available, or |
459 | | build a sorted lookup table for binary search. */ |
460 | 0 | if (index->sections[DW_SECT_INFO - 1] == UINT32_MAX) |
461 | 0 | { |
462 | 0 | __libdw_seterrno (DWARF_E_INVALID_DWARF); |
463 | 0 | return -1; |
464 | 0 | } |
465 | 0 | for (uint32_t i = 0; i < index->unit_count; i++) |
466 | 0 | { |
467 | 0 | Dwarf_Off offset, size; |
468 | 0 | __libdw_dwp_section_info (index, i + 1, DW_SECT_INFO, &offset, |
469 | 0 | &size); |
470 | 0 | if (offset <= off && off - offset < size) |
471 | 0 | { |
472 | 0 | *unit_rowp = i + 1; |
473 | 0 | goto done; |
474 | 0 | } |
475 | 0 | } |
476 | 0 | __libdw_seterrno (DWARF_E_INVALID_DWARF); |
477 | 0 | return -1; |
478 | 0 | } |
479 | | |
480 | 0 | done: |
481 | 0 | return __libdw_dwp_section_info (index, *unit_rowp, DW_SECT_ABBREV, |
482 | 0 | abbrev_offsetp, NULL); |
483 | 0 | } |
484 | | |
485 | | Dwarf_CU * |
486 | | internal_function |
487 | | __libdw_dwp_findcu_id (Dwarf *dbg, uint64_t unit_id8) |
488 | 0 | { |
489 | 0 | Dwarf_Package_Index *index = __libdw_package_index (dbg, false); |
490 | 0 | uint32_t unit_row; |
491 | 0 | Dwarf_Off offset; |
492 | 0 | Dwarf_CU *cu; |
493 | 0 | if (__libdw_dwp_unit_row (index, unit_id8, &unit_row) == 0 |
494 | 0 | && __libdw_dwp_section_info (index, unit_row, DW_SECT_INFO, &offset, |
495 | 0 | NULL) == 0 |
496 | 0 | && (cu = __libdw_findcu (dbg, offset, false)) != NULL |
497 | 0 | && cu->unit_type == DW_UT_split_compile |
498 | 0 | && cu->unit_id8 == unit_id8) |
499 | 0 | return cu; |
500 | 0 | else |
501 | 0 | return NULL; |
502 | 0 | } |
503 | | |
504 | | int |
505 | | dwarf_cu_dwp_section_info (Dwarf_CU *cu, unsigned int section, |
506 | | Dwarf_Off *offsetp, Dwarf_Off *sizep) |
507 | 0 | { |
508 | 0 | if (cu == NULL) |
509 | 0 | return -1; |
510 | 0 | if (section < DW_SECT_INFO || section > DW_SECT_RNGLISTS) |
511 | 0 | { |
512 | 0 | __libdw_seterrno (DWARF_E_UNKNOWN_SECTION); |
513 | 0 | return -1; |
514 | 0 | } |
515 | 0 | if (cu->dwp_row == 0) |
516 | 0 | { |
517 | 0 | if (offsetp != NULL) |
518 | 0 | *offsetp = 0; |
519 | 0 | if (sizep != NULL) |
520 | 0 | *sizep = 0; |
521 | 0 | return 0; |
522 | 0 | } |
523 | 0 | else |
524 | 0 | { |
525 | 0 | Dwarf_Package_Index *index |
526 | 0 | = cu->unit_type == DW_UT_split_compile |
527 | 0 | ? cu->dbg->cu_index : cu->dbg->tu_index; |
528 | 0 | return __libdw_dwp_section_info (index, cu->dwp_row, section, offsetp, |
529 | 0 | sizep); |
530 | 0 | } |
531 | 0 | } |
532 | | INTDEF(dwarf_cu_dwp_section_info) |