1 /*
2
3 Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
4 Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
5 Portions Copyright 2012 SN Systems Ltd. All rights reserved.
6
7
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of version 2.1 of the GNU Lesser General Public License
10 as published by the Free Software Foundation.
11
12 This program is distributed in the hope that it would be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 Further, this software is distributed without any warranty that it is
17 free of the rightful claim of any third person regarding infringement
18 or the like. Any license provided herein, whether implied or
19 otherwise, applies only to this software file. Patent licenses, if
20 any, provided herein do not apply to combinations of this program with
21 other software, or any other product whatsoever.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this program; if not, write the Free Software
25 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
26 USA.
27
28 */
29
30 #include "config.h"
31 #include <stdio.h>
32 #include "dwarf_incl.h"
33 #include "dwarf_alloc.h"
34 #include "dwarf_error.h"
35 #include "dwarf_util.h"
36 #include "dwarf_arange.h"
37 #include "dwarf_global.h" /* for _dwarf_fixup_* */
38 #include "dwarfstring.h"
39
40 static void
free_aranges_chain(Dwarf_Debug dbg,Dwarf_Chain head)41 free_aranges_chain(Dwarf_Debug dbg, Dwarf_Chain head)
42 {
43 Dwarf_Chain cur = head;
44 Dwarf_Chain next = 0;
45
46 if(!head) {
47 return;
48 }
49 next = head->ch_next;
50 for( ;cur; cur = next) {
51 void *item = cur->ch_item;
52 int type = cur->ch_itemtype;
53
54 next = cur->ch_next;
55 if (item && type) {
56 dwarf_dealloc(dbg,item,type);
57 cur->ch_item = 0;
58 dwarf_dealloc(dbg,cur,DW_DLA_CHAIN);
59 }
60 }
61 }
62
63 /* Common code for two user-visible routines to share.
64 Errors here result in memory leaks, but errors here
65 are serious (making aranges unusable) so we assume
66 callers will not repeat the error often or mind the leaks.
67 */
68 static int
dwarf_get_aranges_list(Dwarf_Debug dbg,Dwarf_Chain * chain_out,Dwarf_Signed * chain_count_out,Dwarf_Error * error)69 dwarf_get_aranges_list(Dwarf_Debug dbg,
70 Dwarf_Chain * chain_out,
71 Dwarf_Signed * chain_count_out,
72 Dwarf_Error * error)
73 {
74 /* Sweeps through the arange. */
75 Dwarf_Small *arange_ptr = 0;
76 Dwarf_Small *arange_ptr_start = 0;
77
78 /* Start of arange header. Used for rounding offset of arange_ptr
79 to twice the tuple size. Libdwarf requirement. */
80 Dwarf_Small *header_ptr = 0;
81
82 /* Version of .debug_aranges header. */
83 Dwarf_Unsigned version = 0;
84
85 /* Offset of current set of aranges into .debug_info. */
86 Dwarf_Off info_offset = 0;
87 /* Size in bytes of addresses in target. */
88 Dwarf_Small address_size = 0;
89 /* Size in bytes of segment offsets in target. */
90 Dwarf_Small segment_size = 0;
91 /* Count of total number of aranges. */
92 Dwarf_Signed arange_count = 0;
93 Dwarf_Arange arange = 0;
94 Dwarf_Unsigned section_size = 0;
95 Dwarf_Byte_Ptr arange_end_section = 0;
96 /* Used to chain Dwarf_Aranges structs. */
97 Dwarf_Chain curr_chain = NULL;
98 Dwarf_Chain prev_chain = NULL;
99 Dwarf_Chain head_chain = NULL;
100
101 if (!dbg->de_debug_aranges.dss_size) {
102 return DW_DLV_NO_ENTRY;
103 }
104 arange_ptr = dbg->de_debug_aranges.dss_data;
105 arange_ptr_start = arange_ptr;
106 section_size = dbg->de_debug_aranges.dss_size;
107 arange_end_section = arange_ptr + section_size;
108
109 do {
110 /* Length of current set of aranges.
111 This is local length, which begins just
112 after the length field itself. */
113 Dwarf_Unsigned area_length = 0;
114 Dwarf_Small remainder = 0;
115 Dwarf_Unsigned range_entry_size = 0;
116 int local_length_size;
117 int local_extension_size = 0;
118 Dwarf_Small *end_this_arange = 0;
119 int res = 0;
120
121
122 header_ptr = arange_ptr;
123 if (header_ptr >= arange_end_section) {
124 free_aranges_chain(dbg,head_chain);
125 _dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
126 return DW_DLV_ERROR;
127 }
128 res = _dwarf_read_area_length_ck_wrapper(dbg,&area_length,
129 &arange_ptr,&local_length_size,&local_extension_size,
130 section_size,arange_end_section,error);
131 if (res != DW_DLV_OK) {
132 free_aranges_chain(dbg,head_chain);
133 return res;
134 }
135 /* arange_ptr has been incremented appropriately past
136 the length field by READ_AREA_LENGTH. */
137
138 if (area_length > dbg->de_debug_aranges.dss_size) {
139 free_aranges_chain(dbg,head_chain);
140 _dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
141 return DW_DLV_ERROR;
142 }
143 if ((area_length + local_length_size + local_extension_size) >
144 dbg->de_debug_aranges.dss_size) {
145 free_aranges_chain(dbg,head_chain);
146 _dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
147 return DW_DLV_ERROR;
148 }
149
150 end_this_arange = arange_ptr + area_length;
151 if (end_this_arange > arange_end_section) {
152 free_aranges_chain(dbg,head_chain);
153 _dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
154 return DW_DLV_ERROR;
155 }
156 if (!area_length) {
157 /* We read 4 bytes of zero, so area-length zero.
158 Keep scanning. First seen Nov 27, 2018
159 in GNU-cc in windows dll. */
160 continue;
161 }
162
163 res = _dwarf_read_unaligned_ck_wrapper(dbg,&version,
164 arange_ptr,DWARF_HALF_SIZE,end_this_arange,error);
165 if (res != DW_DLV_OK) {
166 free_aranges_chain(dbg,head_chain);
167 return res;
168 }
169 arange_ptr += DWARF_HALF_SIZE;
170 if (arange_ptr >= end_this_arange) {
171 free_aranges_chain(dbg,head_chain);
172 _dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
173 return DW_DLV_ERROR;
174 }
175 if (version != DW_ARANGES_VERSION2) {
176 free_aranges_chain(dbg,head_chain);
177 _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
178 return (DW_DLV_ERROR);
179 }
180 res = _dwarf_read_unaligned_ck_wrapper(dbg,&info_offset,
181 arange_ptr,local_length_size,end_this_arange,error);
182 if (res != DW_DLV_OK) {
183 free_aranges_chain(dbg,head_chain);
184 return res;
185 }
186
187 arange_ptr += local_length_size;
188 if (arange_ptr >= end_this_arange) {
189 free_aranges_chain(dbg,head_chain);
190 _dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
191 return DW_DLV_ERROR;
192 }
193 /* This applies to debug_info only, not to debug_types. */
194 if (info_offset >= dbg->de_debug_info.dss_size) {
195 FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset,
196 "arange info offset.a");
197 if (info_offset >= dbg->de_debug_info.dss_size) {
198 free_aranges_chain(dbg,head_chain);
199 _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
200 return (DW_DLV_ERROR);
201 }
202 }
203
204 address_size = *(Dwarf_Small *) arange_ptr;
205 if (address_size > sizeof(Dwarf_Addr)) {
206 free_aranges_chain(dbg,head_chain);
207 _dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR);
208 return DW_DLV_ERROR;
209 }
210 if (address_size == 0) {
211 free_aranges_chain(dbg,head_chain);
212 _dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ZERO);
213 return DW_DLV_ERROR;
214 }
215 /* It is not an error if the sizes differ.
216 Unusual, but not an error. */
217 arange_ptr = arange_ptr + sizeof(Dwarf_Small);
218
219 /* The following deref means we better
220 check the pointer for off-end. */
221 if (arange_ptr >= end_this_arange) {
222 free_aranges_chain(dbg,head_chain);
223 _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
224 return DW_DLV_ERROR;
225 }
226
227 /* Even DWARF2 had a segment_size field here, meaning
228 size in bytes of a segment descriptor on the target
229 system. */
230 segment_size = *(Dwarf_Small *) arange_ptr;
231 if (segment_size > sizeof(Dwarf_Addr)) {
232 free_aranges_chain(dbg,head_chain);
233 _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
234 return (DW_DLV_ERROR);
235 }
236 arange_ptr = arange_ptr + sizeof(Dwarf_Small);
237
238 /* Code below will check for == end_this_arange as appropriate. */
239 if (arange_ptr > end_this_arange) {
240 free_aranges_chain(dbg,head_chain);
241 _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
242 return (DW_DLV_ERROR);
243 }
244
245 range_entry_size = 2*address_size + segment_size;
246 /* Round arange_ptr offset to next multiple of address_size. */
247 remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
248 (range_entry_size);
249 if (remainder != 0) {
250 arange_ptr = arange_ptr + (2 * address_size) - remainder;
251 }
252
253 do {
254 Dwarf_Addr range_address = 0;
255 Dwarf_Unsigned segment_selector = 0;
256 Dwarf_Unsigned range_length = 0;
257 /* For segmented address spaces, the first field to
258 read is a segment selector (new in DWARF4).
259 The version number DID NOT CHANGE from 2, which
260 is quite surprising.
261 Also surprising since the segment_size
262 was always there
263 in the table header! */
264 /* We want to test cu_version here but
265 currently with no way to do that.
266 So we just hope no one using
267 segment_selectors, really. FIXME */
268 if (segment_size) {
269 /* Only applies if cu_version >= 4. */
270 res = _dwarf_read_unaligned_ck_wrapper(dbg,
271 &segment_selector,
272 arange_ptr,segment_size,end_this_arange,error);
273 if (res != DW_DLV_OK) {
274 free_aranges_chain(dbg,head_chain);
275 return res;
276 }
277 arange_ptr += address_size;
278 }
279
280 res = _dwarf_read_unaligned_ck_wrapper(dbg,&range_address,
281 arange_ptr,address_size,end_this_arange,error);
282 if (res != DW_DLV_OK) {
283 free_aranges_chain(dbg,head_chain);
284 return res;
285 }
286 arange_ptr += address_size;
287
288 res = _dwarf_read_unaligned_ck_wrapper(dbg,&range_length,
289 arange_ptr,address_size,end_this_arange,error);
290 if (res != DW_DLV_OK) {
291 free_aranges_chain(dbg,head_chain);
292 return res;
293 }
294
295 arange_ptr += address_size;
296
297 {
298 /* We used to suppress all-zero entries, but
299 now we return all aranges entries so we show
300 the entire content. March 31, 2010. */
301
302 arange = (Dwarf_Arange)
303 _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
304 if (arange == NULL) {
305 free_aranges_chain(dbg,head_chain);
306 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
307 return (DW_DLV_ERROR);
308 }
309
310 arange->ar_segment_selector = segment_selector;
311 arange->ar_segment_selector_size = segment_size;
312 arange->ar_address = range_address;
313 arange->ar_length = range_length;
314 arange->ar_info_offset = info_offset;
315 arange->ar_dbg = dbg;
316 arange_count++;
317
318 curr_chain = (Dwarf_Chain)
319 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
320 if (curr_chain == NULL) {
321 free_aranges_chain(dbg,head_chain);
322 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
323 return (DW_DLV_ERROR);
324 }
325
326 curr_chain->ch_item = arange;
327 curr_chain->ch_itemtype = DW_DLA_ARANGE;
328 if (head_chain == NULL)
329 head_chain = prev_chain = curr_chain;
330 else {
331 prev_chain->ch_next = curr_chain;
332 prev_chain = curr_chain;
333 }
334 }
335 /* The current set of ranges is terminated by
336 range_address 0 and range_length 0, but that
337 does not necessarily terminate the ranges for this CU!
338 There can be multiple sets in that DWARF
339 does not explicitly forbid multiple sets.
340 DWARF2,3,4 section 7.20
341 We stop short to avoid overrun of the end of the CU. */
342
343 } while (end_this_arange >= (arange_ptr + range_entry_size));
344
345 /* A compiler could emit some padding bytes here. dwarf2/3
346 (dwarf4 sec 7.20) does not clearly make extra padding
347 bytes illegal. */
348 if (end_this_arange < arange_ptr) {
349 Dwarf_Unsigned pad_count = arange_ptr - end_this_arange;
350 Dwarf_Unsigned offset = arange_ptr - arange_ptr_start;
351 dwarfstring aramsg;
352
353 dwarfstring_constructor(&aramsg);
354 /* Safe. Length strictly limited. */
355 dwarfstring_append_printf_u(&aramsg,
356 "DW_DLE_ARANGE_LENGTH_BAD."
357 " 0x%" DW_PR_XZEROS DW_PR_DUx,
358 pad_count);
359 dwarfstring_append_printf_u(&aramsg,
360 " pad bytes at offset 0x%" DW_PR_XZEROS DW_PR_DUx
361 " in .debug_aranges",
362 offset);
363 dwarf_insert_harmless_error(dbg,
364 dwarfstring_string(&aramsg));
365 dwarfstring_destructor(&aramsg);
366 }
367 /* For most compilers, arange_ptr == end_this_arange at
368 this point. But not if there were padding bytes */
369 arange_ptr = end_this_arange;
370 } while (arange_ptr < arange_end_section);
371
372 if (arange_ptr != arange_end_section) {
373 free_aranges_chain(dbg,head_chain);
374 _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
375 return (DW_DLV_ERROR);
376 }
377 *chain_out = head_chain;
378 *chain_count_out = arange_count;
379 return DW_DLV_OK;
380 }
381
382 /*
383 This function returns the count of the number of
384 aranges in the .debug_aranges section. It sets
385 aranges to point to a block of Dwarf_Arange's
386 describing the arange's. It returns DW_DLV_ERROR
387 on error.
388
389 Must be identical in most aspects to
390 dwarf_get_aranges_addr_offsets!
391
392 */
393 int
dwarf_get_aranges(Dwarf_Debug dbg,Dwarf_Arange ** aranges,Dwarf_Signed * returned_count,Dwarf_Error * error)394 dwarf_get_aranges(Dwarf_Debug dbg,
395 Dwarf_Arange ** aranges,
396 Dwarf_Signed * returned_count, Dwarf_Error * error)
397 {
398 /* Count of total number of aranges. */
399 Dwarf_Signed arange_count = 0;
400
401 Dwarf_Arange *arange_block = 0;
402
403 /* Used to chain Dwarf_Aranges structs. */
404 Dwarf_Chain curr_chain = NULL;
405 Dwarf_Chain prev_chain = NULL;
406 Dwarf_Chain head_chain = NULL;
407 Dwarf_Signed i = 0;
408 int res = DW_DLV_ERROR;
409
410 /* ***** BEGIN CODE ***** */
411
412 if (dbg == NULL) {
413 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
414 return (DW_DLV_ERROR);
415 }
416
417 res = _dwarf_load_section(dbg, &dbg->de_debug_aranges, error);
418 if (res != DW_DLV_OK) {
419 return res;
420 }
421 /* aranges points in to info, so if info needs expanding
422 we have to load it. */
423 res = _dwarf_load_debug_info(dbg, error);
424 if (res != DW_DLV_OK) {
425 return res;
426 }
427
428 res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error);
429 if (res != DW_DLV_OK) {
430 free_aranges_chain(dbg,head_chain);
431 return res;
432 }
433
434 arange_block = (Dwarf_Arange *)
435 _dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count);
436 if (arange_block == NULL) {
437 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
438 free_aranges_chain(dbg,head_chain);
439 return DW_DLV_ERROR;
440 }
441
442 /* See also free_aranges_chain() above */
443 curr_chain = head_chain;
444 for (i = 0; i < arange_count; i++) {
445
446 /* Copies pointers. No dealloc of ch_item, */
447 *(arange_block + i) = curr_chain->ch_item;
448 curr_chain->ch_item = 0;
449 prev_chain = curr_chain;
450 curr_chain = curr_chain->ch_next;
451 dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
452 }
453
454 *aranges = arange_block;
455 *returned_count = (arange_count);
456 return DW_DLV_OK;
457 }
458
459 /*
460 This function returns DW_DLV_OK if it succeeds
461 and DW_DLV_ERR or DW_DLV_OK otherwise.
462 count is set to the number of addresses in the
463 .debug_aranges section.
464 For each address, the corresponding element in
465 an array is set to the address itself(aranges) and
466 the section offset (offsets).
467 Must be identical in most aspects to
468 dwarf_get_aranges!
469 */
470 int
_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,Dwarf_Addr ** addrs,Dwarf_Off ** offsets,Dwarf_Signed * count,Dwarf_Error * error)471 _dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
472 Dwarf_Addr ** addrs,
473 Dwarf_Off ** offsets,
474 Dwarf_Signed * count,
475 Dwarf_Error * error)
476 {
477 Dwarf_Signed i = 0;
478
479 /* Used to chain Dwarf_Aranges structs. */
480 Dwarf_Chain curr_chain = NULL;
481 Dwarf_Chain prev_chain = NULL;
482 Dwarf_Chain head_chain = NULL;
483
484 Dwarf_Signed arange_count = 0;
485 Dwarf_Addr *arange_addrs = 0;
486 Dwarf_Off *arange_offsets = 0;
487
488 int res = DW_DLV_ERROR;
489
490 /* ***** BEGIN CODE ***** */
491
492 if (error != NULL)
493 *error = NULL;
494
495 if (dbg == NULL) {
496 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
497 return (DW_DLV_ERROR);
498 }
499
500 res = _dwarf_load_section(dbg, &dbg->de_debug_aranges,error);
501 if (res != DW_DLV_OK) {
502 return res;
503 }
504 /* aranges points in to info, so if info needs expanding
505 we have to load it. */
506 res = _dwarf_load_debug_info(dbg, error);
507 if (res != DW_DLV_OK) {
508 return res;
509 }
510 res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error);
511 if (res != DW_DLV_OK) {
512 return res;
513 }
514 arange_addrs = (Dwarf_Addr *)
515 _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
516 if (arange_addrs == NULL) {
517 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
518 return (DW_DLV_ERROR);
519 }
520 arange_offsets = (Dwarf_Off *)
521 _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
522 if (arange_offsets == NULL) {
523 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
524 return (DW_DLV_ERROR);
525 }
526
527 curr_chain = head_chain;
528 for (i = 0; i < arange_count; i++) {
529 Dwarf_Arange ar = curr_chain->ch_item;
530 int itemtype = curr_chain->ch_itemtype;
531
532 curr_chain->ch_item = 0;
533 arange_addrs[i] = ar->ar_address;
534 arange_offsets[i] = ar->ar_info_offset;
535 prev_chain = curr_chain;
536 curr_chain = curr_chain->ch_next;
537 if (ar && itemtype) {
538 dwarf_dealloc(dbg, ar, itemtype);
539 }
540 dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
541 }
542 *count = arange_count;
543 *offsets = arange_offsets;
544 *addrs = arange_addrs;
545 return (DW_DLV_OK);
546 }
547
548
549 /*
550 This function takes a pointer to a block
551 of Dwarf_Arange's, and a count of the
552 length of the block. It checks if the
553 given address is within the range of an
554 address range in the block. If yes, it
555 returns the appropriate Dwarf_Arange.
556 Otherwise, it returns DW_DLV_ERROR.
557 */
558 int
dwarf_get_arange(Dwarf_Arange * aranges,Dwarf_Unsigned arange_count,Dwarf_Addr address,Dwarf_Arange * returned_arange,Dwarf_Error * error)559 dwarf_get_arange(Dwarf_Arange * aranges,
560 Dwarf_Unsigned arange_count,
561 Dwarf_Addr address,
562 Dwarf_Arange * returned_arange, Dwarf_Error * error)
563 {
564 Dwarf_Arange curr_arange = 0;
565 Dwarf_Unsigned i = 0;
566
567 if (aranges == NULL) {
568 _dwarf_error(NULL, error, DW_DLE_ARANGES_NULL);
569 return (DW_DLV_ERROR);
570 }
571 for (i = 0; i < arange_count; i++) {
572 curr_arange = *(aranges + i);
573 if (address >= curr_arange->ar_address &&
574 address <
575 curr_arange->ar_address + curr_arange->ar_length) {
576 *returned_arange = curr_arange;
577 return (DW_DLV_OK);
578 }
579 }
580
581 return (DW_DLV_NO_ENTRY);
582 }
583
584
585 /*
586 This function takes an Dwarf_Arange,
587 and returns the offset of the first
588 die in the compilation-unit that the
589 arange belongs to. Returns DW_DLV_ERROR
590 on error.
591
592 For an arange, the cu_die can only be from debug_info,
593 not debug_types, it seems.
594 */
595 int
dwarf_get_cu_die_offset(Dwarf_Arange arange,Dwarf_Off * returned_offset,Dwarf_Error * error)596 dwarf_get_cu_die_offset(Dwarf_Arange arange,
597 Dwarf_Off * returned_offset,
598 Dwarf_Error * error)
599 {
600 Dwarf_Debug dbg = 0;
601 Dwarf_Off offset = 0;
602 Dwarf_Unsigned headerlen = 0;
603 int cres = 0;
604
605 if (arange == NULL) {
606 _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
607 return (DW_DLV_ERROR);
608 }
609 dbg = arange->ar_dbg;
610 offset = arange->ar_info_offset;
611 /* This applies to debug_info only, not to debug_types. */
612 if (!dbg->de_debug_info.dss_data) {
613 int res = _dwarf_load_debug_info(dbg, error);
614
615 if (res != DW_DLV_OK) {
616 return res;
617 }
618 }
619
620 cres = _dwarf_length_of_cu_header(dbg, offset,
621 true, &headerlen,error);
622 if (cres != DW_DLV_OK) {
623 return cres;
624 }
625 *returned_offset = headerlen + offset;
626 return DW_DLV_OK;
627 }
628
629 /* This function takes an Dwarf_Arange,
630 and returns the offset of the CU header
631 in the compilation-unit that the
632 arange belongs to. Returns DW_DLV_ERROR
633 on error.
634 Ensures .debug_info loaded so
635 the cu_offset is meaningful. */
636 int
dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,Dwarf_Off * cu_header_offset_returned,Dwarf_Error * error)637 dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
638 Dwarf_Off * cu_header_offset_returned,
639 Dwarf_Error * error)
640 {
641 Dwarf_Debug dbg = 0;
642 if (arange == NULL) {
643 _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
644 return (DW_DLV_ERROR);
645 }
646 dbg = arange->ar_dbg;
647 /* This applies to debug_info only, not to debug_types. */
648 /* Like dwarf_get_arange_info this ensures debug_info loaded:
649 the cu_header is in debug_info and will be used else
650 we would not call dwarf_get_arange_cu_header_offset. */
651 if (!dbg->de_debug_info.dss_data) {
652 int res = _dwarf_load_debug_info(dbg, error);
653 if (res != DW_DLV_OK) {
654 return res;
655 }
656 }
657 *cu_header_offset_returned = arange->ar_info_offset;
658 return DW_DLV_OK;
659 }
660
661
662
663
664 /*
665 This function takes a Dwarf_Arange, and returns
666 true if it is not NULL. It also stores the start
667 address of the range in *start, the length of the
668 range in *length, and the offset of the first die
669 in the compilation-unit in *cu_die_offset. It
670 returns false on error.
671 If cu_die_offset returned ensures .debug_info loaded so
672 the cu_die_offset is meaningful.
673 */
674 int
dwarf_get_arange_info(Dwarf_Arange arange,Dwarf_Addr * start,Dwarf_Unsigned * length,Dwarf_Off * cu_die_offset,Dwarf_Error * error)675 dwarf_get_arange_info(Dwarf_Arange arange,
676 Dwarf_Addr * start,
677 Dwarf_Unsigned * length,
678 Dwarf_Off * cu_die_offset, Dwarf_Error * error)
679 {
680 if (arange == NULL) {
681 _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
682 return (DW_DLV_ERROR);
683 }
684
685 if (start != NULL)
686 *start = arange->ar_address;
687 if (length != NULL)
688 *length = arange->ar_length;
689 if (cu_die_offset != NULL) {
690 Dwarf_Debug dbg = arange->ar_dbg;
691 Dwarf_Off headerlen = 0;
692 Dwarf_Off offset = arange->ar_info_offset;
693 int cres = 0;
694
695 /* This applies to debug_info only, not to debug_types. */
696 if (!dbg->de_debug_info.dss_data) {
697 int res = _dwarf_load_debug_info(dbg, error);
698 if (res != DW_DLV_OK) {
699 return res;
700 }
701 }
702
703 cres = _dwarf_length_of_cu_header(dbg, offset,
704 true, &headerlen,error);
705 if (cres != DW_DLV_OK) {
706 return cres;
707 }
708 *cu_die_offset = headerlen + offset;
709 }
710 return (DW_DLV_OK);
711 }
712
713
714 /* New for DWARF4, entries may have segment information.
715 *segment is only meaningful if *segment_entry_size is non-zero. */
716 int
dwarf_get_arange_info_b(Dwarf_Arange arange,Dwarf_Unsigned * segment,Dwarf_Unsigned * segment_entry_size,Dwarf_Addr * start,Dwarf_Unsigned * length,Dwarf_Off * cu_die_offset,Dwarf_Error * error)717 dwarf_get_arange_info_b(Dwarf_Arange arange,
718 Dwarf_Unsigned* segment,
719 Dwarf_Unsigned* segment_entry_size,
720 Dwarf_Addr * start,
721 Dwarf_Unsigned* length,
722 Dwarf_Off * cu_die_offset,
723 Dwarf_Error * error)
724 {
725 if (arange == NULL) {
726 _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
727 return DW_DLV_ERROR;
728 }
729
730 if (segment != NULL) {
731 *segment = arange->ar_segment_selector;
732 }
733 if (segment_entry_size != NULL) {
734 *segment_entry_size = arange->ar_segment_selector_size;
735 }
736 if (start != NULL)
737 *start = arange->ar_address;
738 if (length != NULL)
739 *length = arange->ar_length;
740 if (cu_die_offset != NULL) {
741 Dwarf_Debug dbg = arange->ar_dbg;
742 Dwarf_Off offset = arange->ar_info_offset;
743 Dwarf_Unsigned headerlen = 0;
744 int cres = 0;
745
746 /* This applies to debug_info only, not to debug_types. */
747 if (!dbg->de_debug_info.dss_data) {
748 int res = _dwarf_load_debug_info(dbg, error);
749 if (res != DW_DLV_OK) {
750 return res;
751 }
752 }
753 cres = _dwarf_length_of_cu_header(dbg, offset,
754 true, &headerlen,error);
755 if (cres != DW_DLV_OK) {
756 return cres;
757 }
758 *cu_die_offset = offset + headerlen;
759
760 }
761 return (DW_DLV_OK);
762 }
763