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