1 /*
2
3 Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
4 Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of version 2.1 of the GNU Lesser General Public License
8 as published by the Free Software Foundation.
9
10 This program is distributed in the hope that it would be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 Further, this software is distributed without any warranty that it is
15 free of the rightful claim of any third person regarding infringement
16 or the like. Any license provided herein, whether implied or
17 otherwise, applies only to this software file. Patent licenses, if
18 any, provided herein do not apply to combinations of this program with
19 other software, or any other product whatsoever.
20
21 You should have received a copy of the GNU Lesser General Public
22 License along with this program; if not, write the Free Software
23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
24 USA.
25
26 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
27 Mountain View, CA 94043, or:
28
29 http://www.sgi.com
30
31 For further information regarding this notice, see:
32
33 http://oss.sgi.com/projects/GenInfo/NoticeExplan
34
35 */
36 /* The address of the Free Software Foundation is
37 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
38 Boston, MA 02110-1301, USA.
39 SGI has moved from the Crittenden Lane address.
40 */
41
42
43
44
45 #include "config.h"
46 #include "dwarf_incl.h"
47 #include <stdio.h>
48 #include "dwarf_global.h"
49
50
51 #ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */
52 /* The 'fixup' here intended for IRIX targets only.
53 With a 2+GB Elf64 IRIX executable (under 4GB in size),
54 some DIE offsets wrongly
55 got the 32bit upper bit sign extended. For the cu-header
56 offset in the .debug_pubnames section and in the
57 .debug_aranges section.
58 the 'varp' here is a pointer to an offset into .debug_info.
59 We fix up the offset here if it seems advisable..
60
61 As of June 2005 we have identified a series of mistakes
62 in ldx64 that can cause this (64 bit values getting passed
63 thru 32-bit signed knothole).
64 */
65 void
_dwarf_fix_up_offset_irix(Dwarf_Debug dbg,Dwarf_Unsigned * varp,char * caller_site_name)66 _dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
67 Dwarf_Unsigned * varp, char *caller_site_name)
68 {
69
70 Dwarf_Unsigned var = *varp;
71
72 #define UPPER33 0xffffffff80000000LL
73 #define LOWER32 0xffffffffLL
74 /* Restrict the hack to the known case. Upper 32 bits erroneously
75 sign extended from lower 32 upper bit. */
76 if ((var & UPPER33) == UPPER33) {
77 var &= LOWER32;
78 /* Apply the fix. Dreadful hack. */
79 *varp = var;
80 }
81 #undef UPPER33
82 #undef LOWER32
83 return;
84 }
85 #endif
86
87
88 int
dwarf_get_globals(Dwarf_Debug dbg,Dwarf_Global ** globals,Dwarf_Signed * return_count,Dwarf_Error * error)89 dwarf_get_globals(Dwarf_Debug dbg,
90 Dwarf_Global ** globals,
91 Dwarf_Signed * return_count, Dwarf_Error * error)
92 {
93 int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error);
94 if (res != DW_DLV_OK) {
95 return res;
96 }
97
98 return _dwarf_internal_get_pubnames_like_data(dbg,
99 dbg->de_debug_pubnames.dss_data,
100 dbg->de_debug_pubnames.dss_size,
101 globals,
102 return_count,
103 error,
104 DW_DLA_GLOBAL_CONTEXT,
105 DW_DLA_GLOBAL,
106 DW_DLE_PUBNAMES_LENGTH_BAD,
107 DW_DLE_PUBNAMES_VERSION_ERROR);
108
109 }
110
111 /* Deallocating fully requires deallocating the list
112 and all entries. But some internal data is
113 not exposed, so we need a function with internal knowledge.
114 */
115
116 void
dwarf_globals_dealloc(Dwarf_Debug dbg,Dwarf_Global * dwgl,Dwarf_Signed count)117 dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
118 Dwarf_Signed count)
119 {
120 _dwarf_internal_globals_dealloc(dbg, dwgl,
121 count,
122 DW_DLA_GLOBAL_CONTEXT,
123 DW_DLA_GLOBAL, DW_DLA_LIST);
124 return;
125 }
126
127 void
_dwarf_internal_globals_dealloc(Dwarf_Debug dbg,Dwarf_Global * dwgl,Dwarf_Signed count,int context_code,int global_code,int list_code)128 _dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
129 Dwarf_Signed count,
130 int context_code,
131 int global_code, int list_code)
132 {
133 Dwarf_Signed i;
134 struct Dwarf_Global_Context_s *gcp = 0;
135 struct Dwarf_Global_Context_s *lastgcp = 0;
136
137 for (i = 0; i < count; i++) {
138 Dwarf_Global dgb = dwgl[i];
139
140 gcp = dgb->gl_context;
141
142 if (lastgcp != gcp) {
143 lastgcp = gcp;
144 dwarf_dealloc(dbg, gcp, context_code);
145 }
146 dwarf_dealloc(dbg, dgb, global_code);
147 }
148 dwarf_dealloc(dbg, dwgl, list_code);
149 return;
150 }
151
152
153 /* Sweeps the complete section.
154 */
155 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_code,int global_code,int length_err_num,int version_err_num)156 _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
157 Dwarf_Small * section_data_ptr,
158 Dwarf_Unsigned section_length,
159 Dwarf_Global ** globals,
160 Dwarf_Signed * return_count,
161 Dwarf_Error * error,
162 int context_code,
163 int global_code,
164 int length_err_num,
165 int version_err_num)
166 {
167
168
169 Dwarf_Small *pubnames_like_ptr = 0;
170
171
172
173 /* Points to the context for the current set of global names, and
174 contains information to identify the compilation-unit that the
175 set refers to. */
176 Dwarf_Global_Context pubnames_context = 0;
177
178 Dwarf_Half version = 0;
179
180 /*
181 Offset from the start of compilation-unit for the current
182 global. */
183 Dwarf_Off die_offset_in_cu = 0;
184
185 Dwarf_Unsigned global_count = 0;
186
187 /* Points to the current global read. */
188 Dwarf_Global global = 0;
189
190 /* Used to chain the Dwarf_Global_s structs for creating contiguous
191 list of pointers to the structs. */
192 Dwarf_Chain curr_chain = 0;
193 Dwarf_Chain prev_chain = 0;
194 Dwarf_Chain head_chain = 0;
195
196 /* Points to contiguous block of Dwarf_Global's to be returned. */
197 Dwarf_Global *ret_globals = 0;
198
199 /* Temporary counter. */
200 Dwarf_Unsigned i = 0;
201
202
203
204
205 if (dbg == NULL) {
206 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
207 return (DW_DLV_ERROR);
208 }
209 /* We will eventually need the .debug_info data. Load it now. */
210 if (!dbg->de_debug_info.dss_data) {
211 int res = _dwarf_load_debug_info(dbg, error);
212
213 if (res != DW_DLV_OK) {
214 return res;
215 }
216 }
217
218 if (section_data_ptr == NULL) {
219 return (DW_DLV_NO_ENTRY);
220 }
221
222 pubnames_like_ptr = section_data_ptr;
223 do {
224 Dwarf_Unsigned length = 0;
225 int local_extension_size = 0;
226 int local_length_size = 0;
227
228 /* Some compilers emit padding at the end of each cu's area.
229 pubnames_ptr_past_end_cu records the true area end for this
230 cu's data. Essentially the length in the header and the 0
231 terminator of the data are redundant information. The
232 dwarf2/3 spec does not mention what to do if the length is
233 past the 0 terminator. So we take any bytes left after the 0
234 as padding and ignore them. */
235 Dwarf_Small *pubnames_ptr_past_end_cu = 0;
236
237
238 pubnames_context = (Dwarf_Global_Context)
239 _dwarf_get_alloc(dbg, context_code, 1);
240 if (pubnames_context == NULL) {
241 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
242 return (DW_DLV_ERROR);
243 }
244 /* READ_AREA_LENGTH updates pubnames_like_ptr for consumed
245 bytes. */
246 READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
247 pubnames_like_ptr, local_length_size,
248 local_extension_size);
249 pubnames_context->pu_length_size = local_length_size;
250 pubnames_context->pu_extension_size = local_extension_size;
251 pubnames_context->pu_dbg = dbg;
252
253 pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
254
255 READ_UNALIGNED(dbg, version, Dwarf_Half,
256 pubnames_like_ptr, sizeof(Dwarf_Half));
257 pubnames_like_ptr += sizeof(Dwarf_Half);
258 if (version != CURRENT_VERSION_STAMP) {
259 _dwarf_error(dbg, error, version_err_num);
260 return (DW_DLV_ERROR);
261 }
262
263 /* Offset of CU header in debug section. */
264 READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header,
265 Dwarf_Off, pubnames_like_ptr,
266 pubnames_context->pu_length_size);
267 pubnames_like_ptr += pubnames_context->pu_length_size;
268
269 FIX_UP_OFFSET_IRIX_BUG(dbg,
270 pubnames_context->pu_offset_of_cu_header,
271 "pubnames cu header offset");
272
273
274 READ_UNALIGNED(dbg, pubnames_context->pu_info_length,
275 Dwarf_Unsigned, pubnames_like_ptr,
276 pubnames_context->pu_length_size);
277 pubnames_like_ptr += pubnames_context->pu_length_size;
278
279 if (pubnames_like_ptr > (section_data_ptr + section_length)) {
280 _dwarf_error(dbg, error, length_err_num);
281 return (DW_DLV_ERROR);
282 }
283
284 /* Read initial offset (of DIE within CU) of a pubname, final
285 entry is not a pair, just a zero offset. */
286 READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
287 pubnames_like_ptr,
288 pubnames_context->pu_length_size);
289 pubnames_like_ptr += pubnames_context->pu_length_size;
290 FIX_UP_OFFSET_IRIX_BUG(dbg,
291 die_offset_in_cu, "offset of die in cu");
292
293 /* Loop thru pairs. DIE off with CU followed by string. */
294 while (die_offset_in_cu != 0) {
295
296 /* Already read offset, pubnames_like_ptr now points to the
297 string. */
298 global =
299 (Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1);
300 if (global == NULL) {
301 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
302 return (DW_DLV_ERROR);
303 }
304 global_count++;
305
306 global->gl_context = pubnames_context;
307
308 global->gl_named_die_offset_within_cu = die_offset_in_cu;
309
310 global->gl_name = pubnames_like_ptr;
311
312 pubnames_like_ptr = pubnames_like_ptr +
313 strlen((char *) pubnames_like_ptr) + 1;
314
315
316 /* finish off current entry chain */
317 curr_chain =
318 (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
319 if (curr_chain == NULL) {
320 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
321 return (DW_DLV_ERROR);
322 }
323
324 /* Put current global on singly_linked list. */
325 curr_chain->ch_item = (Dwarf_Global) global;
326
327 if (head_chain == NULL)
328 head_chain = prev_chain = curr_chain;
329 else {
330 prev_chain->ch_next = curr_chain;
331 prev_chain = curr_chain;
332 }
333
334 /* read offset for the *next* entry */
335 READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
336 pubnames_like_ptr,
337 pubnames_context->pu_length_size);
338
339 pubnames_like_ptr += pubnames_context->pu_length_size;
340 FIX_UP_OFFSET_IRIX_BUG(dbg,
341 die_offset_in_cu,
342 "offset of next die in cu");
343
344 if (pubnames_like_ptr > (section_data_ptr + section_length)) {
345 _dwarf_error(dbg, error, length_err_num);
346 return (DW_DLV_ERROR);
347 }
348 }
349 /* ASSERT: die_offset_in_cu == 0 */
350 if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
351 /* This is some kind of error. This simply cannot happen.
352 The encoding is wrong or the length in the header for
353 this cu's contribution is wrong. */
354 _dwarf_error(dbg, error, length_err_num);
355 return (DW_DLV_ERROR);
356 }
357 /* If there is some kind of padding at the end of the section,
358 as emitted by some compilers, skip over that padding and
359 simply ignore the bytes thus passed-over. With most
360 compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at
361 this point */
362 pubnames_like_ptr = pubnames_ptr_past_end_cu;
363
364 } while (pubnames_like_ptr < (section_data_ptr + section_length));
365
366 /* Points to contiguous block of Dwarf_Global's. */
367 ret_globals = (Dwarf_Global *)
368 _dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
369 if (ret_globals == NULL) {
370 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
371 return (DW_DLV_ERROR);
372 }
373
374 /*
375 Store pointers to Dwarf_Global_s structs in contiguous block,
376 and deallocate the chain. */
377 curr_chain = head_chain;
378 for (i = 0; i < global_count; i++) {
379 *(ret_globals + i) = curr_chain->ch_item;
380 prev_chain = curr_chain;
381 curr_chain = curr_chain->ch_next;
382 dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
383 }
384
385 *globals = ret_globals;
386 *return_count = (Dwarf_Signed) global_count;
387 return DW_DLV_OK;
388 }
389
390
391 /*
392 Given a pubnames entry (or other like section entry)
393 return thru the ret_name pointer
394 a pointer to the string which is the entry name.
395
396 */
397 int
dwarf_globname(Dwarf_Global glob,char ** ret_name,Dwarf_Error * error)398 dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
399 {
400 if (glob == NULL) {
401 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
402 return (DW_DLV_ERROR);
403 }
404
405 *ret_name = (char *) (glob->gl_name);
406 return DW_DLV_OK;
407 }
408
409
410 /*
411 Given a pubnames entry (or other like section entry)
412 return thru the ret_off pointer the
413 global offset of the DIE for this entry.
414 The global offset is the offset within the .debug_info
415 section as a whole.
416 */
417 int
dwarf_global_die_offset(Dwarf_Global global,Dwarf_Off * ret_off,Dwarf_Error * error)418 dwarf_global_die_offset(Dwarf_Global global,
419 Dwarf_Off * ret_off, Dwarf_Error * error)
420 {
421 if (global == NULL) {
422 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
423 return (DW_DLV_ERROR);
424 }
425
426 if (global->gl_context == NULL) {
427 _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
428 return (DW_DLV_ERROR);
429 }
430
431 *ret_off = (global->gl_named_die_offset_within_cu +
432 global->gl_context->pu_offset_of_cu_header);
433 return DW_DLV_OK;
434 }
435
436 /*
437 Given a pubnames entry (or other like section entry)
438 return thru the ret_off pointer the
439 offset of the compilation unit header of the
440 compilation unit the global is part of.
441
442 In early versions of this, the value returned was
443 the offset of the compilation unit die, and
444 other cu-local die offsets were faked so adding this to
445 such a cu-local offset got a true section offset.
446 Now things do as they say (adding *cu_header_offset to
447 a cu-local offset gets the section offset).
448
449 */
450 int
dwarf_global_cu_offset(Dwarf_Global global,Dwarf_Off * cu_header_offset,Dwarf_Error * error)451 dwarf_global_cu_offset(Dwarf_Global global,
452 Dwarf_Off * cu_header_offset,
453 Dwarf_Error * error)
454 {
455 Dwarf_Global_Context con = 0;
456
457 if (global == NULL) {
458 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
459 return (DW_DLV_ERROR);
460 }
461
462 con = global->gl_context;
463
464 if (con == NULL) {
465 _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
466 return (DW_DLV_ERROR);
467 }
468
469 /* In early libdwarf, this incorrectly returned the offset of the
470 CU DIE. Now correctly returns the header offset. */
471 *cu_header_offset = con->pu_offset_of_cu_header;
472
473 return DW_DLV_OK;
474 }
475
476 /*
477 Give back the pubnames entry (or any other like section)
478 name, symbol DIE offset, and the cu-DIE offset.
479
480 Various errors are possible.
481
482 The string pointer returned thru ret_name is not
483 dwarf_get_alloc()ed, so no dwarf_dealloc()
484 DW_DLA_STRING should be applied to it.
485
486 */
487 int
dwarf_global_name_offsets(Dwarf_Global global,char ** ret_name,Dwarf_Off * die_offset,Dwarf_Off * cu_die_offset,Dwarf_Error * error)488 dwarf_global_name_offsets(Dwarf_Global global,
489 char **ret_name,
490 Dwarf_Off * die_offset,
491 Dwarf_Off * cu_die_offset,
492 Dwarf_Error * error)
493 {
494 Dwarf_Global_Context con = 0;
495 Dwarf_Debug dbg = 0;
496 Dwarf_Off off = 0;
497
498 if (global == NULL) {
499 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
500 return (DW_DLV_ERROR);
501 }
502
503 con = global->gl_context;
504
505 if (con == NULL) {
506 _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
507 return (DW_DLV_ERROR);
508 }
509
510 off = con->pu_offset_of_cu_header;
511 /* The offset had better not be too close to the end. If it is,
512 _dwarf_length_of_cu_header() will step off the end and therefore
513 must not be used. 10 is a meaningless heuristic, but no CU
514 header is that small so it is safe. An erroneous offset is due
515 to a bug in the tool chain. A bug like this has been seen on
516 IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and
517 with 2 million pubnames entries. */
518 #define MIN_CU_HDR_SIZE 10
519 dbg = con->pu_dbg;
520 if (dbg == NULL) {
521 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
522 return (DW_DLV_ERROR);
523 }
524 if (dbg->de_debug_info.dss_size &&
525 ((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info.dss_size)) {
526 _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
527 return (DW_DLV_ERROR);
528 }
529 #undef MIN_CU_HDR_SIZE
530 if (die_offset != NULL) {
531 *die_offset = global->gl_named_die_offset_within_cu + off;
532 }
533
534 *ret_name = (char *) global->gl_name;
535
536 if (cu_die_offset != NULL) {
537 int res = _dwarf_load_debug_info(dbg, error);
538
539 if (res != DW_DLV_OK) {
540 return res;
541 }
542 /* The offset had better not be too close to the end. If it is,
543 _dwarf_length_of_cu_header() will step off the end and
544 therefore must not be used. 10 is a meaningless heuristic,
545 but no CU header is that small so it is safe. */
546 if ((off + 10) >= dbg->de_debug_info.dss_size) {
547 _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
548 return (DW_DLV_ERROR);
549 }
550 *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
551 }
552
553
554 return DW_DLV_OK;
555 }
556
557 /*
558 We have the offset to a CU header.
559 Return thru outFileOffset the offset of the CU DIE.
560
561 New June, 2001.
562 Used by SGI debuggers.
563 No error is possible.
564
565 See also dwarf_CU_dieoffset_given_die().
566 */
567
568 /* ARGSUSED */
569 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,Dwarf_Error * err)570 dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
571 Dwarf_Off in_cu_header_offset,
572 Dwarf_Off * out_cu_die_offset,
573 Dwarf_Error * err)
574 {
575 Dwarf_Off len =
576 _dwarf_length_of_cu_header(dbg, in_cu_header_offset);
577
578 Dwarf_Off newoff = in_cu_header_offset + len;
579
580 *out_cu_die_offset = newoff;
581 return DW_DLV_OK;
582 }
583 /* dwarf_CU_dieoffset_given_die returns
584 the global debug_info section offset of the CU die
585 that is the CU containing the given (passed-in) die.
586 This information makes it possible for a consumer to
587 find and print context information for any die.
588
589 Use dwarf_offdie() passing in the offset this returns
590 to get a die pointer to the CU die.
591 */
592 int
dwarf_CU_dieoffset_given_die(Dwarf_Die die,Dwarf_Off * return_offset,Dwarf_Error * error)593 dwarf_CU_dieoffset_given_die(Dwarf_Die die,
594 Dwarf_Off* return_offset,
595 Dwarf_Error* error)
596 {
597 Dwarf_Off dieoff = 0;
598 Dwarf_CU_Context cucontext = 0;
599
600 CHECK_DIE(die, DW_DLV_ERROR);
601 cucontext = die->di_cu_context;
602 dieoff = cucontext->cc_debug_info_offset;
603 /* The following call cannot fail, so no error check. */
604 dwarf_get_cu_die_offset_given_cu_header_offset(
605 cucontext->cc_dbg, dieoff, return_offset,error);
606 return DW_DLV_OK;
607 }
608