1 /*
2 
3   Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
4   Portions Copyright (C) 2007-2011 David Anderson. All Rights Reserved.
5 
6   This program is free software; you can redistribute it
7   and/or modify it under the terms of version 2.1 of the
8   GNU Lesser General Public License as published by the Free
9   Software Foundation.
10 
11   This program is distributed in the hope that it would be
12   useful, but WITHOUT ANY WARRANTY; without even the implied
13   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14   PURPOSE.
15 
16   Further, this software is distributed without any warranty
17   that it is free of the rightful claim of any third person
18   regarding infringement or the like.  Any license provided
19   herein, whether implied or otherwise, applies only to this
20   software file.  Patent licenses, if any, provided herein
21   do not apply to combinations of this program with other
22   software, or any other product whatsoever.
23 
24   You should have received a copy of the GNU Lesser General
25   Public License along with this program; if not, write the
26   Free Software Foundation, Inc., 51 Franklin Street - Fifth
27   Floor, Boston MA 02110-1301, USA.
28 
29 */
30 
31 #include "config.h"
32 #include <stdio.h>
33 #include "dwarf_incl.h"
34 #include "dwarf_alloc.h"
35 #include "dwarf_error.h"
36 #include "dwarf_util.h"
37 #include "dwarfstring.h"
38 #include "dwarf_global.h"
39 
40 
41 #ifdef __sgi  /* __sgi should only be defined for IRIX/MIPS. */
42 /* The 'fixup' here intended for IRIX targets only.
43    With a  2+GB Elf64 IRIX executable (under 4GB in size),
44    some DIE offsets wrongly
45    got the 32bit upper bit sign extended.  For the cu-header
46    offset in the .debug_pubnames section  and in the
47    .debug_aranges section.
48    the 'varp' here is a pointer to an offset into .debug_info.
49    We fix up the offset here if it seems advisable..
50 
51    As of June 2005 we have identified a series of mistakes
52    in ldx64 that can cause this (64 bit values getting passed
53    thru 32-bit signed knothole).
54 */
55 void
_dwarf_fix_up_offset_irix(Dwarf_Debug dbg,Dwarf_Unsigned * varp,char * caller_site_name)56 _dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
57     Dwarf_Unsigned * varp, char *caller_site_name)
58 {
59 
60     Dwarf_Unsigned var = *varp;
61 
62 #define UPPER33 0xffffffff80000000LL
63 #define LOWER32         0xffffffffLL
64     /*  Restrict the hack to the known case. Upper 32 bits erroneously
65         sign extended from lower 32 upper bit. */
66     if ((var & UPPER33) == UPPER33) {
67         var &= LOWER32;
68         /* Apply the fix. Dreadful hack. */
69         *varp = var;
70     }
71 #undef UPPER33
72 #undef LOWER32
73     return;
74 }
75 #endif  /* __sgi */
76 
77 static void
dealloc_globals_chain(Dwarf_Debug dbg,Dwarf_Chain head_chain)78 dealloc_globals_chain(Dwarf_Debug dbg,
79     Dwarf_Chain head_chain)
80 {
81     Dwarf_Chain curr_chain = 0;
82     Dwarf_Chain prev_chain = 0;
83     int chaintype = DW_DLA_CHAIN;
84 
85     curr_chain = head_chain;
86     for (; curr_chain; ) {
87         void *item = curr_chain->ch_item;
88         int itemtype = curr_chain->ch_itemtype;
89 
90         prev_chain = curr_chain;
91         dwarf_dealloc(dbg, item,itemtype);
92         prev_chain->ch_item = 0;
93         curr_chain = curr_chain->ch_next;
94         dwarf_dealloc(dbg, prev_chain, chaintype);
95     }
96 }
97 
98 int
dwarf_get_globals(Dwarf_Debug dbg,Dwarf_Global ** globals,Dwarf_Signed * return_count,Dwarf_Error * error)99 dwarf_get_globals(Dwarf_Debug dbg,
100     Dwarf_Global ** globals,
101     Dwarf_Signed * return_count, Dwarf_Error * error)
102 {
103     int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error);
104     if (res != DW_DLV_OK) {
105         return res;
106     }
107     if (!dbg->de_debug_pubnames.dss_size) {
108         return DW_DLV_NO_ENTRY;
109     }
110 
111     res = _dwarf_internal_get_pubnames_like_data(dbg,
112         dbg->de_debug_pubnames.dss_data,
113         dbg->de_debug_pubnames.dss_size,
114         globals,
115         return_count,
116         error,
117         DW_DLA_GLOBAL_CONTEXT,
118         DW_DLA_GLOBAL,
119         DW_DLE_PUBNAMES_LENGTH_BAD,
120         DW_DLE_PUBNAMES_VERSION_ERROR);
121     return res;
122 
123 }
124 
125 /* Deallocating fully requires deallocating the list
126    and all entries.  But some internal data is
127    not exposed, so we need a function with internal knowledge.
128 */
129 
130 void
dwarf_globals_dealloc(Dwarf_Debug dbg,Dwarf_Global * dwgl,Dwarf_Signed count)131 dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
132     Dwarf_Signed count)
133 {
134     _dwarf_internal_globals_dealloc(dbg, dwgl,
135         count,
136         DW_DLA_GLOBAL_CONTEXT,
137         DW_DLA_GLOBAL, DW_DLA_LIST);
138     return;
139 }
140 
141 void
_dwarf_internal_globals_dealloc(Dwarf_Debug dbg,Dwarf_Global * dwgl,Dwarf_Signed count,int context_DLA_code,int global_DLA_code,int list_DLA_code)142 _dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
143     Dwarf_Signed count,
144     int context_DLA_code,
145     int global_DLA_code, int list_DLA_code)
146 {
147     Dwarf_Signed i;
148     struct Dwarf_Global_Context_s *glcp = 0;
149     struct Dwarf_Global_Context_s *lastglcp = 0;
150 
151     if(!dwgl) {
152         return;
153     }
154     for (i = 0; i < count; i++) {
155         Dwarf_Global dgb = dwgl[i];
156 
157         if (!dgb) {
158             continue;
159         }
160         /*  Avoids duplicate frees of repeated
161             use of contexts (while assuming that
162             all uses of a particular gl_context
163             will appear next to each other. */
164         glcp = dgb->gl_context;
165         if (lastglcp != glcp) {
166             lastglcp = glcp;
167             dwarf_dealloc(dbg, glcp, context_DLA_code);
168         }
169         dwarf_dealloc(dbg, dgb, global_DLA_code);
170     }
171     dwarf_dealloc(dbg, dwgl, list_DLA_code);
172     return;
173 }
174 
175 /* Sweeps the complete  section.  */
176 int
_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,Dwarf_Small * section_data_ptr,Dwarf_Unsigned section_length,Dwarf_Global ** globals,Dwarf_Signed * return_count,Dwarf_Error * error,int context_DLA_code,int global_DLA_code,int length_err_num,int version_err_num)177 _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
178     Dwarf_Small * section_data_ptr,
179     Dwarf_Unsigned section_length,
180     Dwarf_Global ** globals,
181     Dwarf_Signed * return_count,
182     Dwarf_Error * error,
183     int context_DLA_code,
184     int global_DLA_code,
185     int length_err_num,
186     int version_err_num)
187 {
188     Dwarf_Small *pubnames_like_ptr = 0;
189     Dwarf_Off pubnames_section_offset = 0;
190     Dwarf_Small *section_end_ptr = section_data_ptr +section_length;
191 
192     /*  Points to the context for the current set of global names, and
193         contains information to identify the compilation-unit that the
194         set refers to. */
195     Dwarf_Global_Context pubnames_context = 0;
196 
197     Dwarf_Unsigned version = 0;
198 
199     /*  Offset from the start of compilation-unit for the current
200         global. */
201     Dwarf_Off die_offset_in_cu = 0;
202 
203     Dwarf_Unsigned global_count = 0;
204 
205     /* Points to the current global read. */
206     Dwarf_Global global = 0;
207 
208     /*  Used to chain the Dwarf_Global_s structs for creating contiguous
209         list of pointers to the structs. */
210     Dwarf_Chain curr_chain = 0;
211     Dwarf_Chain prev_chain = 0;
212     Dwarf_Chain head_chain = 0;
213 
214     /* Points to contiguous block of Dwarf_Global's to be returned. */
215     Dwarf_Global *ret_globals = 0;
216     int mres = 0;
217 
218     /* Temporary counter. */
219     Dwarf_Unsigned i = 0;
220 
221     if (dbg == NULL) {
222         _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
223         return (DW_DLV_ERROR);
224     }
225     /* We will eventually need the .debug_info data. Load it now. */
226     if (!dbg->de_debug_info.dss_data) {
227         int res = _dwarf_load_debug_info(dbg, error);
228 
229         if (res != DW_DLV_OK) {
230             return res;
231         }
232     }
233     if (section_data_ptr == NULL) {
234         return (DW_DLV_NO_ENTRY);
235     }
236     pubnames_like_ptr = section_data_ptr;
237     do {
238         Dwarf_Unsigned length = 0;
239         int local_extension_size = 0;
240         int local_length_size = 0;
241 
242         /*  Some compilers emit padding at the end of each cu's area.
243             pubnames_ptr_past_end_cu records the true area end for the
244             pubnames(like) content of a cu.
245             Essentially the length in the header and the 0
246             terminator of the data are redundant information. The
247             dwarf2/3 spec does not mention what to do if the length is
248             past the 0 terminator. So we take any bytes left after the 0
249             as padding and ignore them. */
250         Dwarf_Small *pubnames_ptr_past_end_cu = 0;
251 
252 
253         pubnames_context = (Dwarf_Global_Context)
254             _dwarf_get_alloc(dbg, context_DLA_code, 1);
255         if (pubnames_context == NULL) {
256             dealloc_globals_chain(dbg,head_chain);
257             _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
258             return DW_DLV_ERROR;
259         }
260         /*  READ_AREA_LENGTH updates pubnames_like_ptr for consumed
261             bytes. */
262         mres = _dwarf_read_area_length_ck_wrapper(dbg,
263             &length,&pubnames_like_ptr,&local_length_size,
264             &local_extension_size,section_length,section_end_ptr,
265             error);
266         if (mres != DW_DLV_OK) {
267             dealloc_globals_chain(dbg,head_chain);
268             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
269             return mres;
270         }
271         pubnames_context->pu_length_size = local_length_size;
272         pubnames_context->pu_length = length;
273         pubnames_context->pu_extension_size = local_extension_size;
274         pubnames_context->pu_dbg = dbg;
275         pubnames_context->pu_pub_offset = pubnames_section_offset;
276         pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
277 
278         mres = _dwarf_read_unaligned_ck_wrapper(dbg,
279             &version,pubnames_like_ptr,DWARF_HALF_SIZE,
280             section_end_ptr,error);
281         if (mres != DW_DLV_OK) {
282             dealloc_globals_chain(dbg,head_chain);
283             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
284             return mres;
285         }
286         pubnames_context->pu_version = version;
287         pubnames_like_ptr += DWARF_HALF_SIZE;
288         /* ASSERT: DW_PUBNAMES_VERSION2 == DW_PUBTYPES_VERSION2 */
289         if (version != DW_PUBNAMES_VERSION2) {
290             dealloc_globals_chain(dbg,head_chain);
291             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
292             _dwarf_error(dbg, error, version_err_num);
293             return DW_DLV_ERROR;
294         }
295 
296         /* Offset of CU header in debug section. */
297         mres = _dwarf_read_unaligned_ck_wrapper(dbg,
298             &pubnames_context->pu_offset_of_cu_header,
299             pubnames_like_ptr,
300             pubnames_context->pu_length_size,
301             section_end_ptr,error);
302         if (mres != DW_DLV_OK) {
303             dealloc_globals_chain(dbg,head_chain);
304             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
305             return mres;
306         }
307 
308         pubnames_like_ptr += pubnames_context->pu_length_size;
309 
310         FIX_UP_OFFSET_IRIX_BUG(dbg,
311             pubnames_context->pu_offset_of_cu_header,
312             "pubnames cu header offset");
313         mres = _dwarf_read_unaligned_ck_wrapper(dbg,
314             &pubnames_context->pu_info_length,
315             pubnames_like_ptr,
316             pubnames_context->pu_length_size,
317             section_end_ptr,error);
318         if (mres != DW_DLV_OK) {
319             dealloc_globals_chain(dbg,head_chain);
320             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
321             return mres;
322         }
323         pubnames_like_ptr += pubnames_context->pu_length_size;
324 
325         if (pubnames_like_ptr > (section_data_ptr + section_length)) {
326             dealloc_globals_chain(dbg,head_chain);
327             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
328             _dwarf_error(dbg, error, length_err_num);
329             return (DW_DLV_ERROR);
330         }
331 
332         /*  Read initial offset (of DIE within CU) of a pubname, final
333             entry is not a pair, just a zero offset. */
334         mres = _dwarf_read_unaligned_ck_wrapper(dbg,
335             &die_offset_in_cu,
336             pubnames_like_ptr,
337             pubnames_context->pu_length_size,
338             section_end_ptr,error);
339         if (mres != DW_DLV_OK) {
340             dealloc_globals_chain(dbg,head_chain);
341             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
342             return mres;
343         }
344         pubnames_like_ptr += pubnames_context->pu_length_size;
345         FIX_UP_OFFSET_IRIX_BUG(dbg,
346             die_offset_in_cu, "offset of die in cu");
347         if (pubnames_like_ptr > (section_data_ptr + section_length)) {
348             dealloc_globals_chain(dbg,head_chain);
349             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
350             _dwarf_error(dbg, error, length_err_num);
351             return DW_DLV_ERROR;
352         }
353 
354         /* Loop thru pairs. DIE off with CU followed by string. */
355         if (dbg->de_return_empty_pubnames && die_offset_in_cu == 0) {
356             /*  Here we have a pubnames CU with no actual
357                 entries so we fake up an entry to hold the
358                 header data.  There are no 'pairs' here,
359                 just the end of list zero value.  We do this
360                 only if de_return_empty_pubnames is set
361                 so that we by default return exactly the same
362                 data this always returned, yet dwarfdump can
363                 request the empty-cu records get created
364                 to test that feature.
365                 see dwarf_get_globals_header()  */
366             global =
367                 (Dwarf_Global) _dwarf_get_alloc(dbg, global_DLA_code, 1);
368             if (global == NULL) {
369                 dealloc_globals_chain(dbg,head_chain);
370                 dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
371                 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
372                 return (DW_DLV_ERROR);
373             }
374             global_count++;
375             global->gl_context = pubnames_context;
376             global->gl_named_die_offset_within_cu = 0;
377             global->gl_name = (Dwarf_Small *)"";
378             /* Finish off current entry chain */
379             curr_chain =
380                 (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
381             if (curr_chain == NULL) {
382                 dealloc_globals_chain(dbg,head_chain);
383                 dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
384                 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
385                 return DW_DLV_ERROR;
386             }
387             /* Put current global on singly_linked list. */
388             curr_chain->ch_itemtype = global_DLA_code;
389             curr_chain->ch_item = (Dwarf_Global) global;
390             if (head_chain == NULL)
391                 head_chain = prev_chain = curr_chain;
392             else {
393                 prev_chain->ch_next = curr_chain;
394                 prev_chain = curr_chain;
395             }
396             /* There is no next entry, we are at it already */
397         } else if (!die_offset_in_cu) {
398             /*  The section is empty.
399                 Nowhere to record pubnames_context); */
400             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
401             pubnames_context = 0;
402             continue;
403         }
404         while (die_offset_in_cu) {
405             int res = 0;
406 
407             /*  Already read offset, pubnames_like_ptr
408                 now points to the string. */
409             global =
410                 (Dwarf_Global) _dwarf_get_alloc(dbg, global_DLA_code, 1);
411             if (global == NULL) {
412                 dealloc_globals_chain(dbg,head_chain);
413                 dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
414                 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
415                 return (DW_DLV_ERROR);
416             }
417             global_count++;
418             global->gl_context = pubnames_context;
419             global->gl_named_die_offset_within_cu = die_offset_in_cu;
420             global->gl_name = pubnames_like_ptr;
421             res = _dwarf_check_string_valid(dbg,section_data_ptr,
422                 pubnames_like_ptr,section_end_ptr,
423                 DW_DLE_STRING_OFF_END_PUBNAMES_LIKE,error);
424             if (res != DW_DLV_OK) {
425                 dealloc_globals_chain(dbg,head_chain);
426                 dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
427                 return res;
428             }
429             pubnames_like_ptr = pubnames_like_ptr +
430                 strlen((char *) pubnames_like_ptr) + 1;
431 
432             /* Finish off current entry chain */
433             curr_chain =
434                 (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
435             if (curr_chain == NULL) {
436                 dealloc_globals_chain(dbg,head_chain);
437                 dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
438                 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
439                 return (DW_DLV_ERROR);
440             }
441             /* Put current global on singly_linked list. */
442             curr_chain->ch_item = (Dwarf_Global) global;
443             curr_chain->ch_itemtype = global_DLA_code;
444             if (head_chain == NULL)
445                 head_chain = prev_chain = curr_chain;
446             else {
447                 prev_chain->ch_next = curr_chain;
448                 prev_chain = curr_chain;
449             }
450 
451             /* Read offset for the *next* entry */
452             mres = _dwarf_read_unaligned_ck_wrapper(dbg,
453                 &die_offset_in_cu,
454                 pubnames_like_ptr,
455                 pubnames_context->pu_length_size,
456                 section_end_ptr,error);
457             if (mres != DW_DLV_OK) {
458                 dealloc_globals_chain(dbg,head_chain);
459                 dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
460                 return mres;
461             }
462             pubnames_like_ptr += pubnames_context->pu_length_size;
463             FIX_UP_OFFSET_IRIX_BUG(dbg,
464                 die_offset_in_cu, "offset of next die in cu");
465             if (pubnames_like_ptr > (section_data_ptr + section_length)) {
466                 dealloc_globals_chain(dbg,head_chain);
467                 dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
468                 _dwarf_error(dbg, error, length_err_num);
469                 return DW_DLV_ERROR;
470             }
471         }
472         /* ASSERT: die_offset_in_cu == 0 */
473         if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
474             /* This is some kind of error. This simply cannot happen.
475             The encoding is wrong or the length in the header for
476             this cu's contribution is wrong. */
477             _dwarf_error(dbg, error, length_err_num);
478             dealloc_globals_chain(dbg,head_chain);
479             dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
480             return DW_DLV_ERROR;
481         }
482         /*  If there is some kind of padding at the end of the section,
483             as emitted by some compilers, skip over that padding and
484             simply ignore the bytes thus passed-over.  With most
485             compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at
486             this point */
487         {
488             Dwarf_Unsigned increment =
489                 pubnames_context->pu_length_size +
490                 pubnames_context->pu_length +
491                 pubnames_context->pu_extension_size;
492             pubnames_section_offset += increment;
493         }
494         pubnames_like_ptr = pubnames_ptr_past_end_cu;
495     } while (pubnames_like_ptr < section_end_ptr);
496 
497     /* Points to contiguous block of Dwarf_Global's. */
498     ret_globals = (Dwarf_Global *)
499         _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
500     if (ret_globals == NULL) {
501         dealloc_globals_chain(dbg,head_chain);
502         dwarf_dealloc(dbg,pubnames_context,context_DLA_code);
503         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
504         return DW_DLV_ERROR;
505     }
506 
507     /*  Store pointers to Dwarf_Global_s structs in contiguous block,
508         and deallocate the chain.  This ignores the various
509         headers */
510     curr_chain = head_chain;
511     for (i = 0; i < global_count; i++) {
512         *(ret_globals + i) = curr_chain->ch_item;
513         prev_chain = curr_chain;
514         curr_chain = curr_chain->ch_next;
515         prev_chain->ch_item = 0; /* Not actually necessary. */
516         dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
517     }
518     *globals = ret_globals;
519     *return_count = (Dwarf_Signed) global_count;
520     return DW_DLV_OK;
521 }
522 
523 
524 /*  Given a pubnames entry (or other like section entry)
525     return thru the ret_name pointer
526     a pointer to the string which is the entry name.  */
527 int
dwarf_globname(Dwarf_Global glob,char ** ret_name,Dwarf_Error * error)528 dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
529 {
530     if (glob == NULL) {
531         _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
532         return (DW_DLV_ERROR);
533     }
534 
535     *ret_name = (char *) (glob->gl_name);
536     return DW_DLV_OK;
537 }
538 
539 
540 /*  Given a pubnames entry (or other like section entry)
541     return thru the ret_off pointer the
542     global offset of the DIE for this entry.
543     The global offset is the offset within the .debug_info
544     section as a whole.  */
545 int
dwarf_global_die_offset(Dwarf_Global global,Dwarf_Off * ret_off,Dwarf_Error * error)546 dwarf_global_die_offset(Dwarf_Global global,
547     Dwarf_Off * ret_off, Dwarf_Error * error)
548 {
549     if (global == NULL) {
550         _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
551         return (DW_DLV_ERROR);
552     }
553 
554     if (global->gl_context == NULL) {
555         _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
556         return (DW_DLV_ERROR);
557     }
558 
559     *ret_off = (global->gl_named_die_offset_within_cu +
560         global->gl_context->pu_offset_of_cu_header);
561     return DW_DLV_OK;
562 }
563 
564 /*  Given a pubnames entry (or other like section entry)
565     return thru the ret_off pointer the
566     offset of the compilation unit header of the
567     compilation unit the global is part of.
568 
569     In early versions of this, the value returned was
570     the offset of the compilation unit die, and
571     other cu-local die offsets were faked so adding this to
572     such a cu-local offset got a true section offset.
573     Now things do as they say (adding *cu_header_offset to
574     a cu-local offset gets the section offset).  */
575 int
dwarf_global_cu_offset(Dwarf_Global global,Dwarf_Off * cu_header_offset,Dwarf_Error * error)576 dwarf_global_cu_offset(Dwarf_Global global,
577     Dwarf_Off * cu_header_offset,
578     Dwarf_Error * error)
579 {
580     Dwarf_Global_Context con = 0;
581 
582     if (global == NULL) {
583         _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
584         return (DW_DLV_ERROR);
585     }
586 
587     con = global->gl_context;
588 
589     if (con == NULL) {
590         _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
591         return (DW_DLV_ERROR);
592     }
593 
594     /*  In early libdwarf, this incorrectly returned the offset of the
595         CU DIE. Now correctly returns the header offset. */
596     *cu_header_offset = con->pu_offset_of_cu_header;
597 
598     return DW_DLV_OK;
599 }
600 
601 static void
build_off_end_msg(Dwarf_Unsigned offval,Dwarf_Unsigned withincr,Dwarf_Unsigned secsize,dwarfstring * m)602 build_off_end_msg(Dwarf_Unsigned offval,
603    Dwarf_Unsigned withincr,
604    Dwarf_Unsigned secsize,
605    dwarfstring *m)
606 {
607     const char *msg = "past";
608     if (offval < secsize){
609         msg = "too near";
610     }
611     dwarfstring_append_printf_u(m,"DW_DLE_OFFSET_BAD: "
612         "The CU header offset of %u in a pubnames-like entry ",
613         withincr);
614     dwarfstring_append_printf_s(m,
615         "would put us %s the end of .debug_info. "
616         "No room for a DIE there... "
617         "Corrupt Dwarf.",(char *)msg);
618     return;
619 }
620 
621 
622 /*
623   Give back the pubnames entry (or any other like section)
624   name, symbol DIE offset, and the cu-DIE offset.
625 
626   Various errors are possible.
627 
628   The string pointer returned thru ret_name is not
629   dwarf_get_alloc()ed, so no dwarf_dealloc()
630   DW_DLA_STRING should be applied to it.
631 
632 */
633 int
dwarf_global_name_offsets(Dwarf_Global global,char ** ret_name,Dwarf_Off * die_offset,Dwarf_Off * cu_die_offset,Dwarf_Error * error)634 dwarf_global_name_offsets(Dwarf_Global global,
635     char **ret_name,
636     Dwarf_Off * die_offset,
637     Dwarf_Off * cu_die_offset,
638     Dwarf_Error * error)
639 {
640     Dwarf_Global_Context con = 0;
641     Dwarf_Debug dbg = 0;
642     Dwarf_Off cuhdr_off = 0;
643 
644     if (global == NULL) {
645         _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
646         return (DW_DLV_ERROR);
647     }
648 
649     con = global->gl_context;
650 
651     if (con == NULL) {
652         _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
653         return (DW_DLV_ERROR);
654     }
655 
656     cuhdr_off = con->pu_offset_of_cu_header;
657     /*  The offset had better not be too close to the end. If it is,
658         _dwarf_length_of_cu_header() will step off the end and therefore
659         must not be used. 10 is a meaningless heuristic, but no CU
660         header is that small so it is safe. An erroneous offset is due
661         to a bug in the tool chain. A bug like this has been seen on
662         IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and
663         with 2 million pubnames entries. */
664 #define MIN_CU_HDR_SIZE 10
665     dbg = con->pu_dbg;
666     if (dbg == NULL) {
667         _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
668         return (DW_DLV_ERROR);
669     }
670     /* Cannot refer to debug_types */
671     if (dbg->de_debug_info.dss_size &&
672         ((cuhdr_off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) {
673         dwarfstring m;
674         dwarfstring_constructor(&m);
675         build_off_end_msg(cuhdr_off,cuhdr_off+MIN_CU_HDR_SIZE,
676             dbg->de_debug_info.dss_size,&m);
677         _dwarf_error_string(dbg, error, DW_DLE_OFFSET_BAD,
678             dwarfstring_string(&m));
679         dwarfstring_destructor(&m);
680         return (DW_DLV_ERROR);
681     }
682 #undef MIN_CU_HDR_SIZE
683     /*  If global->gl_named_die_offset_within_cu
684         is zero then this is a fake global for
685         a pubnames CU with no pubnames. The offset is from the
686         start of the CU header, so no die can have a zero
687         offset, all valid offsets are positive numbers */
688     if (die_offset) {
689         if(global->gl_named_die_offset_within_cu) {
690             *die_offset = global->gl_named_die_offset_within_cu + cuhdr_off;
691         } else {
692             *die_offset = 0;
693         }
694     }
695     *ret_name = (char *) global->gl_name;
696     if (cu_die_offset) {
697         /* Globals cannot refer to debug_types */
698         int cres = 0;
699         Dwarf_Unsigned headerlen = 0;
700         int res = _dwarf_load_debug_info(dbg, error);
701 
702         if (res != DW_DLV_OK) {
703             return res;
704         }
705         /*  The offset had better not be too close to the end.
706             If it is,
707             _dwarf_length_of_cu_header() will step off the end and
708             therefore must not be used. 10 is a meaningless heuristic,
709             but no CU header is that small so it is safe. */
710         /* Globals cannot refer to debug_types */
711         if ((cuhdr_off + 10) >= dbg->de_debug_info.dss_size) {
712             dwarfstring m;
713 
714             dwarfstring_constructor(&m);
715             build_off_end_msg(cuhdr_off,cuhdr_off+10,
716                 dbg->de_debug_info.dss_size,&m);
717             _dwarf_error_string(dbg, error, DW_DLE_OFFSET_BAD,
718                 dwarfstring_string(&m));
719             dwarfstring_destructor(&m);
720             return (DW_DLV_ERROR);
721         }
722         cres = _dwarf_length_of_cu_header(dbg, cuhdr_off,true,
723             &headerlen,error);
724         if(cres != DW_DLV_OK) {
725             return cres;
726         }
727         *cu_die_offset = cuhdr_off + headerlen;
728     }
729     return DW_DLV_OK;
730 }
731 
732 
733 /*  New February 2019 from better dwarfdump printing
734     of debug_pubnames and pubtypes.
735     For ao the Dwarf_Global records in one pubnames
736     CU group exactly the same data will be returned.
737 
738 */
739 int
dwarf_get_globals_header(Dwarf_Global global,Dwarf_Off * pub_section_hdr_offset,Dwarf_Unsigned * pub_offset_size,Dwarf_Unsigned * pub_cu_length,Dwarf_Unsigned * version,Dwarf_Off * info_header_offset,Dwarf_Unsigned * info_length,Dwarf_Error * error)740 dwarf_get_globals_header(Dwarf_Global global,
741     Dwarf_Off      *pub_section_hdr_offset,
742     Dwarf_Unsigned *pub_offset_size,
743     Dwarf_Unsigned *pub_cu_length,
744     Dwarf_Unsigned *version,
745     Dwarf_Off      *info_header_offset,
746     Dwarf_Unsigned *info_length,
747     Dwarf_Error*   error)
748 {
749     Dwarf_Global_Context con = 0;
750     Dwarf_Debug dbg = 0;
751 
752     if (global == NULL) {
753         _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
754         return DW_DLV_ERROR;
755     }
756     con = global->gl_context;
757     if (con == NULL) {
758         _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
759         return DW_DLV_ERROR;
760     }
761     dbg = con->pu_dbg;
762     if (dbg == NULL) {
763         _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
764         return DW_DLV_ERROR;
765     }
766     if(pub_section_hdr_offset) {
767         *pub_section_hdr_offset = con->pu_pub_offset;
768     }
769     if (pub_offset_size) {
770         *pub_offset_size = con->pu_length_size;
771     }
772     if (pub_cu_length) {
773         *pub_cu_length = con->pu_length;
774     }
775     if (version) {
776         *version = con->pu_version;
777     }
778     if(info_header_offset) {
779         *info_header_offset = con->pu_offset_of_cu_header;
780     }
781     if (info_length) {
782         *info_length = con->pu_info_length;
783     }
784     return DW_DLV_OK;
785 }
786 
787 
788 /*  We have the offset to a CU header.
789     Return thru outFileOffset the offset of the CU DIE.
790 
791     New June, 2001.
792     Used by SGI IRIX debuggers.
793     No error used to be possible.
794     As of May 2016 an error is possible if the DWARF is
795     corrupted! (IRIX debuggers are no longer built ...)
796 
797     See also dwarf_CU_dieoffset_given_die().
798 
799     This is assumed to never apply to data in .debug_types, it
800     only refers to .debug_info.
801 
802 */
803 
804 /* ARGSUSED */
805 int
dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,Dwarf_Off in_cu_header_offset,Dwarf_Off * out_cu_die_offset,UNUSEDARG Dwarf_Error * err)806 dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
807     Dwarf_Off in_cu_header_offset,
808     Dwarf_Off * out_cu_die_offset,
809     UNUSEDARG Dwarf_Error * err)
810 {
811     Dwarf_Off headerlen = 0;
812     int cres = 0;
813 
814     cres = _dwarf_length_of_cu_header(dbg, in_cu_header_offset,true,
815         &headerlen,err);
816     if (cres != DW_DLV_OK) {
817         return cres;
818     }
819     *out_cu_die_offset = in_cu_header_offset + headerlen;
820     return DW_DLV_OK;
821 }
822 
823 /*  The following version new in October 2011, does allow finding
824     the offset if one knows whether debug_info or debug_types.
825 
826     However, it is not accurate in DWARF5 because
827     there are two different header lengths (CU and TU)
828     in DWARF5 .debug_info.  In that case, pretend
829     that it's .debug_types (here) and pass is_info zero for
830     a TU (as if it was in .debug_types).
831     */
832 int
dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug dbg,Dwarf_Off in_cu_header_offset,Dwarf_Bool is_info,Dwarf_Off * out_cu_die_offset,UNUSEDARG Dwarf_Error * err)833 dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug dbg,
834     Dwarf_Off in_cu_header_offset,
835     Dwarf_Bool is_info,
836     Dwarf_Off * out_cu_die_offset,
837     UNUSEDARG Dwarf_Error * err)
838 {
839     Dwarf_Off headerlen = 0;
840     int cres = 0;
841 
842     cres = _dwarf_length_of_cu_header(dbg, in_cu_header_offset,is_info,
843         &headerlen,err);
844     if (cres != DW_DLV_OK) {
845         return cres;
846     }
847     *out_cu_die_offset = in_cu_header_offset + headerlen;
848     return DW_DLV_OK;
849 }
850 /*  dwarf_CU_dieoffset_given_die returns
851     the global debug_info section offset of the CU die
852     that is the CU containing the given (passed-in) die.
853     This information makes it possible for a consumer to
854     find and print context information for any die.
855 
856     Use dwarf_offdie() passing in the offset this returns
857     to get a die pointer to the CU die.  */
858 int
dwarf_CU_dieoffset_given_die(Dwarf_Die die,Dwarf_Off * return_offset,Dwarf_Error * error)859 dwarf_CU_dieoffset_given_die(Dwarf_Die die,
860     Dwarf_Off*       return_offset,
861     Dwarf_Error*     error)
862 {
863     Dwarf_Off  dieoff = 0;
864     Dwarf_CU_Context cucontext = 0;
865 
866     CHECK_DIE(die, DW_DLV_ERROR);
867     cucontext = die->di_cu_context;
868     dieoff =  cucontext->cc_debug_offset;
869     /*  The following call cannot fail, so no error check. */
870     dwarf_get_cu_die_offset_given_cu_header_offset_b(
871         cucontext->cc_dbg, dieoff,
872         die->di_is_info, return_offset,error);
873     return DW_DLV_OK;
874 }
875 
876 /*  We do not want to screw up error in case
877     it has something important.  So not touching it now. */
dwarf_return_empty_pubnames(Dwarf_Debug dbg,int flag,UNUSEDARG Dwarf_Error * err)878 int dwarf_return_empty_pubnames(Dwarf_Debug dbg,
879     int flag, UNUSEDARG Dwarf_Error *err )
880 {
881     if (dbg == NULL) {
882         return DW_DLV_OK;
883     }
884     if (flag && flag != 1) {
885         return DW_DLV_OK;
886     }
887     dbg->de_return_empty_pubnames = (unsigned char)flag;
888     return DW_DLV_OK;
889 }
890