xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_arange.c (revision 379728489ed47862c4927c75771e767b9476c9c4)
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
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
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
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
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
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
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
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
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
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