8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / tools / ctf / dwarf / common / dwarf_global.c
blobd1c090fa4362a04ae85a00da368a6e78c0141b84
1 /*
3 Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
4 Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
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.
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.
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.
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.
26 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
27 Mountain View, CA 94043, or:
29 http://www.sgi.com
31 For further information regarding this notice, see:
33 http://oss.sgi.com/projects/GenInfo/NoticeExplan
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.
45 #include "config.h"
46 #include "dwarf_incl.h"
47 #include <stdio.h>
48 #include "dwarf_global.h"
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..
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).
65 void
66 _dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
67 Dwarf_Unsigned * varp, char *caller_site_name)
70 Dwarf_Unsigned var = *varp;
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;
81 #undef UPPER33
82 #undef LOWER32
83 return;
85 #endif
88 int
89 dwarf_get_globals(Dwarf_Debug dbg,
90 Dwarf_Global ** globals,
91 Dwarf_Signed * return_count, Dwarf_Error * error)
93 int res = _dwarf_load_section(dbg, &dbg->de_debug_pubnames,error);
94 if (res != DW_DLV_OK) {
95 return res;
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);
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.
116 void
117 dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
118 Dwarf_Signed count)
120 _dwarf_internal_globals_dealloc(dbg, dwgl,
121 count,
122 DW_DLA_GLOBAL_CONTEXT,
123 DW_DLA_GLOBAL, DW_DLA_LIST);
124 return;
127 void
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)
133 Dwarf_Signed i;
134 struct Dwarf_Global_Context_s *gcp = 0;
135 struct Dwarf_Global_Context_s *lastgcp = 0;
137 for (i = 0; i < count; i++) {
138 Dwarf_Global dgb = dwgl[i];
140 gcp = dgb->gl_context;
142 if (lastgcp != gcp) {
143 lastgcp = gcp;
144 dwarf_dealloc(dbg, gcp, context_code);
146 dwarf_dealloc(dbg, dgb, global_code);
148 dwarf_dealloc(dbg, dwgl, list_code);
149 return;
153 /* Sweeps the complete section.
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)
169 Dwarf_Small *pubnames_like_ptr = 0;
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;
178 Dwarf_Half version = 0;
181 Offset from the start of compilation-unit for the current
182 global. */
183 Dwarf_Off die_offset_in_cu = 0;
185 Dwarf_Unsigned global_count = 0;
187 /* Points to the current global read. */
188 Dwarf_Global global = 0;
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;
196 /* Points to contiguous block of Dwarf_Global's to be returned. */
197 Dwarf_Global *ret_globals = 0;
199 /* Temporary counter. */
200 Dwarf_Unsigned i = 0;
205 if (dbg == NULL) {
206 _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
207 return (DW_DLV_ERROR);
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);
213 if (res != DW_DLV_OK) {
214 return res;
218 if (section_data_ptr == NULL) {
219 return (DW_DLV_NO_ENTRY);
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;
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;
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);
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;
253 pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
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);
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;
269 FIX_UP_OFFSET_IRIX_BUG(dbg,
270 pubnames_context->pu_offset_of_cu_header,
271 "pubnames cu header offset");
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;
279 if (pubnames_like_ptr > (section_data_ptr + section_length)) {
280 _dwarf_error(dbg, error, length_err_num);
281 return (DW_DLV_ERROR);
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");
293 /* Loop thru pairs. DIE off with CU followed by string. */
294 while (die_offset_in_cu != 0) {
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);
304 global_count++;
306 global->gl_context = pubnames_context;
308 global->gl_named_die_offset_within_cu = die_offset_in_cu;
310 global->gl_name = pubnames_like_ptr;
312 pubnames_like_ptr = pubnames_like_ptr +
313 strlen((char *) pubnames_like_ptr) + 1;
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);
324 /* Put current global on singly_linked list. */
325 curr_chain->ch_item = (Dwarf_Global) global;
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;
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);
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");
344 if (pubnames_like_ptr > (section_data_ptr + section_length)) {
345 _dwarf_error(dbg, error, length_err_num);
346 return (DW_DLV_ERROR);
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);
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;
364 } while (pubnames_like_ptr < (section_data_ptr + section_length));
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);
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);
385 *globals = ret_globals;
386 *return_count = (Dwarf_Signed) global_count;
387 return DW_DLV_OK;
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.
398 dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
400 if (glob == NULL) {
401 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
402 return (DW_DLV_ERROR);
405 *ret_name = (char *) (glob->gl_name);
406 return DW_DLV_OK;
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.
418 dwarf_global_die_offset(Dwarf_Global global,
419 Dwarf_Off * ret_off, Dwarf_Error * error)
421 if (global == NULL) {
422 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
423 return (DW_DLV_ERROR);
426 if (global->gl_context == NULL) {
427 _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
428 return (DW_DLV_ERROR);
431 *ret_off = (global->gl_named_die_offset_within_cu +
432 global->gl_context->pu_offset_of_cu_header);
433 return DW_DLV_OK;
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.
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).
451 dwarf_global_cu_offset(Dwarf_Global global,
452 Dwarf_Off * cu_header_offset,
453 Dwarf_Error * error)
455 Dwarf_Global_Context con = 0;
457 if (global == NULL) {
458 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
459 return (DW_DLV_ERROR);
462 con = global->gl_context;
464 if (con == NULL) {
465 _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
466 return (DW_DLV_ERROR);
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;
473 return DW_DLV_OK;
477 Give back the pubnames entry (or any other like section)
478 name, symbol DIE offset, and the cu-DIE offset.
480 Various errors are possible.
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.
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)
494 Dwarf_Global_Context con = 0;
495 Dwarf_Debug dbg = 0;
496 Dwarf_Off off = 0;
498 if (global == NULL) {
499 _dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
500 return (DW_DLV_ERROR);
503 con = global->gl_context;
505 if (con == NULL) {
506 _dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
507 return (DW_DLV_ERROR);
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);
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);
529 #undef MIN_CU_HDR_SIZE
530 if (die_offset != NULL) {
531 *die_offset = global->gl_named_die_offset_within_cu + off;
534 *ret_name = (char *) global->gl_name;
536 if (cu_die_offset != NULL) {
537 int res = _dwarf_load_debug_info(dbg, error);
539 if (res != DW_DLV_OK) {
540 return res;
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);
550 *cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
554 return DW_DLV_OK;
558 We have the offset to a CU header.
559 Return thru outFileOffset the offset of the CU DIE.
561 New June, 2001.
562 Used by SGI debuggers.
563 No error is possible.
565 See also dwarf_CU_dieoffset_given_die().
568 /* ARGSUSED */
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)
575 Dwarf_Off len =
576 _dwarf_length_of_cu_header(dbg, in_cu_header_offset);
578 Dwarf_Off newoff = in_cu_header_offset + len;
580 *out_cu_die_offset = newoff;
581 return DW_DLV_OK;
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.
589 Use dwarf_offdie() passing in the offset this returns
590 to get a die pointer to the CU die.
592 int
593 dwarf_CU_dieoffset_given_die(Dwarf_Die die,
594 Dwarf_Off* return_offset,
595 Dwarf_Error* error)
597 Dwarf_Off dieoff = 0;
598 Dwarf_CU_Context cucontext = 0;
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;