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 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 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 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 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 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 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 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 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 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 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 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