1/* 2 3 Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it 6 under the terms of version 2.1 of the GNU Lesser General Public License 7 as published by the Free Software Foundation. 8 9 This program is distributed in the hope that it would be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 Further, this software is distributed without any warranty that it is 14 free of the rightful claim of any third person regarding infringement 15 or the like. Any license provided herein, whether implied or 16 otherwise, applies only to this software file. Patent licenses, if 17 any, provided herein do not apply to combinations of this program with 18 other software, or any other product whatsoever. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this program; if not, write the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 23 USA. 24 25 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, 26 Mountain View, CA 94043, or: 27 28 http://www.sgi.com 29 30 For further information regarding this notice, see: 31 32 http://oss.sgi.com/projects/GenInfo/NoticeExplan 33 34*/ 35 36 37 38 39#include "config.h" 40#include "dwarf_incl.h" 41#include <stdio.h> 42#include "dwarf_arange.h" 43#include "dwarf_global.h" /* for _dwarf_fixup_* */ 44 45 46/* 47 This function returns the count of the number of 48 aranges in the .debug_aranges section. It sets 49 aranges to point to a block of Dwarf_Arange's 50 describing the arange's. It returns DW_DLV_ERROR 51 on error. 52 53 Must be identical in most aspects to 54 dwarf_get_aranges_addr_offsets! 55*/ 56int 57dwarf_get_aranges(Dwarf_Debug dbg, 58 Dwarf_Arange ** aranges, 59 Dwarf_Signed * returned_count, Dwarf_Error * error) 60{ 61 /* Sweeps the .debug_aranges section. */ 62 Dwarf_Small *arange_ptr; 63 64 /* 65 Start of arange header. Used for rounding offset of arange_ptr 66 to twice the tuple size. Libdwarf requirement. */ 67 Dwarf_Small *header_ptr; 68 69 70 /* Version of .debug_aranges header. */ 71 Dwarf_Half version; 72 73 /* Offset of current set of aranges into .debug_info. */ 74 Dwarf_Off info_offset; 75 76 /* Size in bytes of addresses in target. */ 77 Dwarf_Small address_size; 78 79 /* Size in bytes of segment offsets in target. */ 80 Dwarf_Small segment_size; 81 82 Dwarf_Small remainder; 83 84 /* Count of total number of aranges. */ 85 Dwarf_Unsigned arange_count = 0; 86 87 /* Start address of arange. */ 88 Dwarf_Addr range_address; 89 90 /* Length of arange. */ 91 Dwarf_Unsigned range_length; 92 93 Dwarf_Arange arange, *arange_block; 94 95 Dwarf_Unsigned i; 96 97 /* Used to chain Dwarf_Aranges structs. */ 98 Dwarf_Chain curr_chain, prev_chain, head_chain = NULL; 99 100 int res; 101 102 /* ***** BEGIN CODE ***** */ 103 104 if (dbg == NULL) { 105 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); 106 return (DW_DLV_ERROR); 107 } 108 109 res = 110 _dwarf_load_section(dbg, 111 dbg->de_debug_aranges_index, 112 &dbg->de_debug_aranges, error); 113 if (res != DW_DLV_OK) { 114 return res; 115 } 116 117 arange_ptr = dbg->de_debug_aranges; 118 do { 119 /* Length of current set of aranges. */ 120 Dwarf_Unsigned length; 121 Dwarf_Small *arange_ptr_past_end = 0; 122 123 int local_length_size; 124 125 /*REFERENCED*/ /* Not used in this instance of the 126 macro */ 127 int local_extension_size; 128 129 header_ptr = arange_ptr; 130 131 /* READ_AREA_LENGTH updates arange_ptr for consumed bytes */ 132 READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, 133 arange_ptr, local_length_size, 134 local_extension_size); 135 arange_ptr_past_end = arange_ptr + length; 136 137 138 READ_UNALIGNED(dbg, version, Dwarf_Half, 139 arange_ptr, sizeof(Dwarf_Half)); 140 arange_ptr += sizeof(Dwarf_Half); 141 length = length - sizeof(Dwarf_Half); 142 if (version != CURRENT_VERSION_STAMP) { 143 _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); 144 return (DW_DLV_ERROR); 145 } 146 147 READ_UNALIGNED(dbg, info_offset, Dwarf_Off, 148 arange_ptr, local_length_size); 149 arange_ptr += local_length_size; 150 length = length - local_length_size; 151 if (info_offset >= dbg->de_debug_info_size) { 152 FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset, 153 "arange info offset.a"); 154 if (info_offset >= dbg->de_debug_info_size) { 155 _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD); 156 return (DW_DLV_ERROR); 157 } 158 } 159 160 address_size = *(Dwarf_Small *) arange_ptr; 161 if (address_size != dbg->de_pointer_size) { 162 /* Internal error of some kind */ 163 _dwarf_error(dbg, error, DW_DLE_BADBITC); 164 return (DW_DLV_ERROR); 165 } 166 arange_ptr = arange_ptr + sizeof(Dwarf_Small); 167 length = length - sizeof(Dwarf_Small); 168 169 segment_size = *(Dwarf_Small *) arange_ptr; 170 arange_ptr = arange_ptr + sizeof(Dwarf_Small); 171 length = length - sizeof(Dwarf_Small); 172 if (segment_size != 0) { 173 _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD); 174 return (DW_DLV_ERROR); 175 } 176 177 /* Round arange_ptr offset to next multiple of address_size. */ 178 remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) % 179 (2 * address_size); 180 if (remainder != 0) { 181 arange_ptr = arange_ptr + (2 * address_size) - remainder; 182 length = length - ((2 * address_size) - remainder); 183 } 184 185 do { 186 READ_UNALIGNED(dbg, range_address, Dwarf_Addr, 187 arange_ptr, address_size); 188 arange_ptr += address_size; 189 length = length - address_size; 190 191 READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned, 192 arange_ptr, address_size); 193 arange_ptr += address_size; 194 length = length - address_size; 195 196 if (range_address != 0 || range_length != 0) { 197 198 arange = (Dwarf_Arange) 199 _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); 200 if (arange == NULL) { 201 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 202 return (DW_DLV_ERROR); 203 } 204 205 arange->ar_address = range_address; 206 arange->ar_length = range_length; 207 arange->ar_info_offset = info_offset; 208 arange->ar_dbg = dbg; 209 arange_count++; 210 211 curr_chain = (Dwarf_Chain) 212 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); 213 if (curr_chain == NULL) { 214 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 215 return (DW_DLV_ERROR); 216 } 217 218 curr_chain->ch_item = arange; 219 if (head_chain == NULL) 220 head_chain = prev_chain = curr_chain; 221 else { 222 prev_chain->ch_next = curr_chain; 223 prev_chain = curr_chain; 224 } 225 } 226 } while (range_address != 0 || range_length != 0); 227 228 /* A compiler could emit some padding bytes here. dwarf2/3 229 (dwarf3 draft8 sec 7.20) does not clearly make extra padding 230 bytes illegal. */ 231 if (arange_ptr_past_end < arange_ptr) { 232 _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD); 233 return (DW_DLV_ERROR); 234 } 235 /* For most compilers, arange_ptr == arange_ptr_past_end at 236 this point. But not if there were padding bytes */ 237 arange_ptr = arange_ptr_past_end; 238 239 } while (arange_ptr < 240 dbg->de_debug_aranges + dbg->de_debug_aranges_size); 241 242 if (arange_ptr != 243 dbg->de_debug_aranges + dbg->de_debug_aranges_size) { 244 _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR); 245 return (DW_DLV_ERROR); 246 } 247 248 arange_block = (Dwarf_Arange *) 249 _dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count); 250 if (arange_block == NULL) { 251 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 252 return (DW_DLV_ERROR); 253 } 254 255 curr_chain = head_chain; 256 for (i = 0; i < arange_count; i++) { 257 *(arange_block + i) = curr_chain->ch_item; 258 prev_chain = curr_chain; 259 curr_chain = curr_chain->ch_next; 260 dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); 261 } 262 263 *aranges = arange_block; 264 *returned_count = (arange_count); 265 return DW_DLV_OK; 266} 267 268/* 269 This function returns DW_DLV_OK if it succeeds 270 and DW_DLV_ERR or DW_DLV_OK otherwise. 271 count is set to the number of addresses in the 272 .debug_aranges section. 273 For each address, the corresponding element in 274 an array is set to the address itself(aranges) and 275 the section offset (offsets). 276 Must be identical in most aspects to 277 dwarf_get_aranges! 278*/ 279int 280_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg, 281 Dwarf_Addr ** addrs, 282 Dwarf_Off ** offsets, 283 Dwarf_Signed * count, 284 Dwarf_Error * error) 285{ 286 /* Sweeps the .debug_aranges section. */ 287 Dwarf_Small *arange_ptr; 288 Dwarf_Small *arange_start_ptr; 289 290 /* 291 Start of arange header. Used for rounding offset of arange_ptr 292 to twice the tuple size. Libdwarf requirement. */ 293 Dwarf_Small *header_ptr; 294 295 /* Length of current set of aranges. */ 296 Dwarf_Unsigned length; 297 298 /* Version of .debug_aranges header. */ 299 Dwarf_Half version; 300 301 /* Offset of current set of aranges into .debug_info. */ 302 Dwarf_Off info_offset; 303 304 /* Size in bytes of addresses in target. */ 305 Dwarf_Small address_size; 306 307 /* Size in bytes of segment offsets in target. */ 308 Dwarf_Small segment_size; 309 310 Dwarf_Small remainder; 311 312 /* Count of total number of aranges. */ 313 Dwarf_Unsigned arange_count = 0; 314 315 /* Start address of arange. */ 316 Dwarf_Addr range_address; 317 318 /* Length of arange. */ 319 Dwarf_Unsigned range_length; 320 321 Dwarf_Arange arange; 322 323 Dwarf_Unsigned i; 324 325 /* Used to chain Dwarf_Aranges structs. */ 326 Dwarf_Chain curr_chain, prev_chain, head_chain = NULL; 327 328 Dwarf_Addr *arange_addrs; 329 Dwarf_Off *arange_offsets; 330 331 int res; 332 333 /* ***** BEGIN CODE ***** */ 334 335 if (error != NULL) 336 *error = NULL; 337 338 if (dbg == NULL) { 339 _dwarf_error(NULL, error, DW_DLE_DBG_NULL); 340 return (DW_DLV_ERROR); 341 } 342 343 res = 344 _dwarf_load_section(dbg, 345 dbg->de_debug_aranges_index, 346 &dbg->de_debug_aranges, error); 347 if (res != DW_DLV_OK) { 348 return res; 349 } 350 351 arange_ptr = dbg->de_debug_aranges; 352 do { 353 int local_length_size; 354 355 /*REFERENCED*/ /* not used in this instance of the 356 macro */ 357 int local_extension_size; 358 359 header_ptr = arange_ptr; 360 361 362 /* READ_AREA_LENGTH updates arange_ptr for consumed bytes */ 363 READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned, 364 arange_ptr, local_length_size, 365 local_extension_size); 366 367 368 READ_UNALIGNED(dbg, version, Dwarf_Half, 369 arange_ptr, sizeof(Dwarf_Half)); 370 arange_ptr += sizeof(Dwarf_Half); 371 length = length - sizeof(Dwarf_Half); 372 if (version != CURRENT_VERSION_STAMP) { 373 _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR); 374 return (DW_DLV_ERROR); 375 } 376 377 READ_UNALIGNED(dbg, info_offset, Dwarf_Off, 378 arange_ptr, local_length_size); 379 arange_ptr += local_length_size; 380 length = length - local_length_size; 381 if (info_offset >= dbg->de_debug_info_size) { 382 FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset, 383 "arange info offset.b"); 384 if (info_offset >= dbg->de_debug_info_size) { 385 386 _dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD); 387 return (DW_DLV_ERROR); 388 } 389 } 390 391 address_size = *(Dwarf_Small *) arange_ptr; 392 arange_ptr = arange_ptr + sizeof(Dwarf_Small); 393 length = length - sizeof(Dwarf_Small); 394 395 segment_size = *(Dwarf_Small *) arange_ptr; 396 arange_ptr = arange_ptr + sizeof(Dwarf_Small); 397 length = length - sizeof(Dwarf_Small); 398 if (segment_size != 0) { 399 _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD); 400 return (DW_DLV_ERROR); 401 } 402 403 /* Round arange_ptr offset to next multiple of address_size. */ 404 remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) % 405 (2 * address_size); 406 if (remainder != 0) { 407 arange_ptr = arange_ptr + (2 * address_size) - remainder; 408 length = length - ((2 * address_size) - remainder); 409 } 410 411 do { 412 arange_start_ptr = arange_ptr; 413 READ_UNALIGNED(dbg, range_address, Dwarf_Addr, 414 arange_ptr, dbg->de_pointer_size); 415 arange_ptr += dbg->de_pointer_size; 416 length = length - dbg->de_pointer_size; 417 418 READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned, 419 arange_ptr, local_length_size); 420 arange_ptr += local_length_size; 421 length = length - local_length_size; 422 423 if (range_address != 0 || range_length != 0) { 424 425 arange = (Dwarf_Arange) 426 _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1); 427 if (arange == NULL) { 428 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 429 return (DW_DLV_ERROR); 430 } 431 432 arange->ar_address = range_address; 433 arange->ar_length = range_length; 434 arange->ar_info_offset = 435 arange_start_ptr - dbg->de_debug_aranges; 436 arange->ar_dbg = dbg; 437 arange_count++; 438 439 curr_chain = (Dwarf_Chain) 440 _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); 441 if (curr_chain == NULL) { 442 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 443 return (DW_DLV_ERROR); 444 } 445 446 curr_chain->ch_item = arange; 447 if (head_chain == NULL) 448 head_chain = prev_chain = curr_chain; 449 else { 450 prev_chain->ch_next = curr_chain; 451 prev_chain = curr_chain; 452 } 453 } 454 } while (range_address != 0 || range_length != 0); 455 456 if (length != 0) { 457 _dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD); 458 return (DW_DLV_ERROR); 459 } 460 461 } while (arange_ptr < 462 dbg->de_debug_aranges + dbg->de_debug_aranges_size); 463 464 if (arange_ptr != 465 dbg->de_debug_aranges + dbg->de_debug_aranges_size) { 466 _dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR); 467 return (DW_DLV_ERROR); 468 } 469 470 arange_addrs = (Dwarf_Addr *) 471 _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); 472 if (arange_addrs == NULL) { 473 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 474 return (DW_DLV_ERROR); 475 } 476 arange_offsets = (Dwarf_Off *) 477 _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count); 478 if (arange_offsets == NULL) { 479 _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); 480 return (DW_DLV_ERROR); 481 } 482 483 curr_chain = head_chain; 484 for (i = 0; i < arange_count; i++) { 485 Dwarf_Arange ar = curr_chain->ch_item; 486 487 arange_addrs[i] = ar->ar_address; 488 arange_offsets[i] = ar->ar_info_offset; 489 prev_chain = curr_chain; 490 curr_chain = curr_chain->ch_next; 491 dwarf_dealloc(dbg, ar, DW_DLA_ARANGE); 492 dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); 493 } 494 *count = arange_count; 495 *offsets = arange_offsets; 496 *addrs = arange_addrs; 497 return (DW_DLV_OK); 498} 499 500 501/* 502 This function takes a pointer to a block 503 of Dwarf_Arange's, and a count of the 504 length of the block. It checks if the 505 given address is within the range of an 506 address range in the block. If yes, it 507 returns the appropriate Dwarf_Arange. 508 Otherwise, it returns DW_DLV_ERROR. 509*/ 510int 511dwarf_get_arange(Dwarf_Arange * aranges, 512 Dwarf_Unsigned arange_count, 513 Dwarf_Addr address, 514 Dwarf_Arange * returned_arange, Dwarf_Error * error) 515{ 516 Dwarf_Arange curr_arange; 517 Dwarf_Unsigned i; 518 519 if (aranges == NULL) { 520 _dwarf_error(NULL, error, DW_DLE_ARANGES_NULL); 521 return (DW_DLV_ERROR); 522 } 523 524 for (i = 0; i < arange_count; i++) { 525 curr_arange = *(aranges + i); 526 if (address >= curr_arange->ar_address && 527 address < 528 curr_arange->ar_address + curr_arange->ar_length) { 529 *returned_arange = curr_arange; 530 return (DW_DLV_OK); 531 } 532 } 533 534 return (DW_DLV_NO_ENTRY); 535} 536 537 538/* 539 This function takes an Dwarf_Arange, 540 and returns the offset of the first 541 die in the compilation-unit that the 542 arange belongs to. Returns DW_DLV_ERROR 543 on error. 544*/ 545int 546dwarf_get_cu_die_offset(Dwarf_Arange arange, 547 Dwarf_Off * returned_offset, 548 Dwarf_Error * error) 549{ 550 Dwarf_Debug dbg; 551 Dwarf_Off offset; 552 553 if (arange == NULL) { 554 _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); 555 return (DW_DLV_ERROR); 556 } 557 558 559 dbg = arange->ar_dbg; 560 561 562 offset = arange->ar_info_offset; 563 if (!dbg->de_debug_info) { 564 int res = _dwarf_load_debug_info(dbg, error); 565 566 if (res != DW_DLV_OK) { 567 return res; 568 } 569 } 570 571 *returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset); 572 return DW_DLV_OK; 573} 574 575/* 576 This function takes an Dwarf_Arange, 577 and returns the offset of the CU header 578 in the compilation-unit that the 579 arange belongs to. Returns DW_DLV_ERROR 580 on error. 581*/ 582int 583dwarf_get_arange_cu_header_offset(Dwarf_Arange arange, 584 Dwarf_Off * cu_header_offset_returned, 585 Dwarf_Error * error) 586{ 587 if (arange == NULL) { 588 _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); 589 return (DW_DLV_ERROR); 590 } 591 592 *cu_header_offset_returned = arange->ar_info_offset; 593 return DW_DLV_OK; 594} 595 596 597 598/* 599 This function takes a Dwarf_Arange, and returns 600 true if it is not NULL. It also stores the start 601 address of the range in *start, the length of the 602 range in *length, and the offset of the first die 603 in the compilation-unit in *cu_die_offset. It 604 returns false on error. 605*/ 606int 607dwarf_get_arange_info(Dwarf_Arange arange, 608 Dwarf_Addr * start, 609 Dwarf_Unsigned * length, 610 Dwarf_Off * cu_die_offset, Dwarf_Error * error) 611{ 612 if (arange == NULL) { 613 _dwarf_error(NULL, error, DW_DLE_ARANGE_NULL); 614 return (DW_DLV_ERROR); 615 } 616 617 if (start != NULL) 618 *start = arange->ar_address; 619 if (length != NULL) 620 *length = arange->ar_length; 621 if (cu_die_offset != NULL) { 622 Dwarf_Debug dbg = arange->ar_dbg; 623 Dwarf_Off offset = arange->ar_info_offset; 624 625 if (!dbg->de_debug_info) { 626 int res = _dwarf_load_debug_info(dbg, error); 627 628 if (res != DW_DLV_OK) { 629 return res; 630 } 631 } 632 633 *cu_die_offset = 634 offset + _dwarf_length_of_cu_header(dbg, offset); 635 } 636 return (DW_DLV_OK); 637} 638