1 /* 2 * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "SymbolLookup.h" 7 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/mman.h> 13 #include <unistd.h> 14 15 #include <new> 16 17 #include <runtime_loader.h> 18 #include <syscalls.h> 19 20 21 #undef TRACE 22 //#define TRACE_DEBUG_SYMBOL_LOOKUP 23 #ifdef TRACE_DEBUG_SYMBOL_LOOKUP 24 # define TRACE(x) printf x 25 #else 26 # define TRACE(x) ; 27 #endif 28 29 30 using std::nothrow; 31 using namespace BPrivate; 32 33 34 // PrepareAddress 35 const void * 36 Area::PrepareAddress(const void *address) 37 { 38 TRACE(("Area::PrepareAddress(%p): area: %ld\n", address, fRemoteID)); 39 40 // clone the area, if not done already 41 if (fLocalID < 0) { 42 fLocalID = clone_area("cloned area", &fLocalAddress, B_ANY_ADDRESS, 43 B_READ_AREA, fRemoteID); 44 if (fLocalID < 0) { 45 TRACE(("Area::PrepareAddress(): Failed to clone area %ld: %s\n", 46 fRemoteID, strerror(fLocalID))); 47 throw Exception(fLocalID); 48 } 49 } 50 51 // translate the address 52 const void *result = (const void*)((addr_t)address - (addr_t)fRemoteAddress 53 + (addr_t)fLocalAddress); 54 55 TRACE(("Area::PrepareAddress(%p) done: %p\n", address, result)); 56 57 return result; 58 } 59 60 61 // #pragma mark - 62 63 // constructor 64 RemoteMemoryAccessor::RemoteMemoryAccessor(team_id team) 65 : fTeam(team), 66 fAreas() 67 { 68 } 69 70 // destructor 71 RemoteMemoryAccessor::~RemoteMemoryAccessor() 72 { 73 // delete the areas 74 while (Area *area = fAreas.Head()) { 75 fAreas.Remove(area); 76 delete area; 77 } 78 } 79 80 // Init 81 status_t 82 RemoteMemoryAccessor::Init() 83 { 84 // If the team is the kernel team, we don't try to clone the areas. Only 85 // SymbolLookup's image file functionality will be available. 86 if (fTeam == B_SYSTEM_TEAM) 87 return B_OK; 88 89 // get a list of the team's areas 90 area_info areaInfo; 91 int32 cookie = 0; 92 status_t error; 93 while ((error = get_next_area_info(fTeam, &cookie, &areaInfo)) == B_OK) { 94 TRACE(("area %ld: address: %p, size: %ld, name: %s\n", areaInfo.area, 95 areaInfo.address, areaInfo.size, areaInfo.name)); 96 97 Area *area = new(nothrow) Area(areaInfo.area, areaInfo.address, 98 areaInfo.size); 99 if (!area) 100 return B_NO_MEMORY; 101 102 fAreas.Add(area); 103 } 104 105 if (fAreas.IsEmpty()) 106 return error; 107 108 return B_OK; 109 } 110 111 // PrepareAddress 112 const void * 113 RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress, 114 int32 size) const 115 { 116 TRACE(("RemoteMemoryAccessor::PrepareAddress(%p, %ld)\n", remoteAddress, 117 size)); 118 119 if (!remoteAddress) { 120 TRACE(("RemoteMemoryAccessor::PrepareAddress(): Got null address!\n")); 121 throw Exception(B_BAD_VALUE); 122 } 123 124 return _FindArea(remoteAddress, size).PrepareAddress(remoteAddress); 125 } 126 127 128 const void * 129 RemoteMemoryAccessor::PrepareAddressNoThrow(const void *remoteAddress, 130 int32 size) const 131 { 132 if (remoteAddress == NULL) 133 return NULL; 134 135 Area* area = _FindAreaNoThrow(remoteAddress, size); 136 if (area == NULL) 137 return NULL; 138 139 return area->PrepareAddress(remoteAddress); 140 } 141 142 143 // AreaForLocalAddress 144 Area* 145 RemoteMemoryAccessor::AreaForLocalAddress(const void* address) const 146 { 147 if (address == NULL) 148 return NULL; 149 150 for (AreaList::ConstIterator it = fAreas.GetIterator(); it.HasNext();) { 151 Area* area = it.Next(); 152 if (area->ContainsLocalAddress(address)) 153 return area; 154 } 155 156 return NULL; 157 } 158 159 160 // _FindArea 161 Area & 162 RemoteMemoryAccessor::_FindArea(const void *address, int32 size) const 163 { 164 TRACE(("RemoteMemoryAccessor::_FindArea(%p, %ld)\n", address, size)); 165 166 for (AreaList::ConstIterator it = fAreas.GetIterator(); it.HasNext();) { 167 Area *area = it.Next(); 168 if (area->ContainsAddress(address, size)) 169 return *area; 170 } 171 172 TRACE(("RemoteMemoryAccessor::_FindArea(): No area found for address %p\n", 173 address)); 174 throw Exception(B_ENTRY_NOT_FOUND); 175 } 176 177 178 // _FindAreaNoThrow 179 Area* 180 RemoteMemoryAccessor::_FindAreaNoThrow(const void *address, int32 size) const 181 { 182 for (AreaList::ConstIterator it = fAreas.GetIterator(); it.HasNext();) { 183 Area *area = it.Next(); 184 if (area->ContainsAddress(address, size)) 185 return area; 186 } 187 188 return NULL; 189 } 190 191 192 // #pragma mark - 193 194 195 ImageFile::ImageFile(const image_info& info) 196 : 197 fInfo(info), 198 fFD(-1), 199 fFileSize(0), 200 fMappedFile((uint8*)MAP_FAILED), 201 fLoadDelta(0), 202 fSymbolTable(NULL), 203 fStringTable(NULL), 204 fSymbolCount(0), 205 fStringTableSize(0) 206 { 207 } 208 209 210 ImageFile::~ImageFile() 211 { 212 if (fMappedFile != MAP_FAILED) { 213 munmap(fMappedFile, fFileSize); 214 } else { 215 delete[] fSymbolTable; 216 delete[] fStringTable; 217 } 218 219 if (fFD >= 0) 220 close(fFD); 221 } 222 223 224 status_t 225 ImageFile::Load() 226 { 227 // open and stat() the file 228 fFD = open(fInfo.name, O_RDONLY); 229 if (fFD < 0) 230 return errno; 231 232 struct stat st; 233 if (fstat(fFD, &st) < 0) 234 return errno; 235 236 fFileSize = st.st_size; 237 if (fFileSize < sizeof(Elf32_Ehdr)) 238 return B_NOT_AN_EXECUTABLE; 239 240 // map it 241 fMappedFile = (uint8*)mmap(NULL, fFileSize, PROT_READ, MAP_PRIVATE, fFD, 0); 242 if (fMappedFile == MAP_FAILED) 243 return errno; 244 245 // examine the elf header 246 Elf32_Ehdr* elfHeader = (Elf32_Ehdr*)fMappedFile; 247 if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0) 248 return B_NOT_AN_EXECUTABLE; 249 250 if (elfHeader->e_ident[4] != ELFCLASS32) 251 return B_NOT_AN_EXECUTABLE; 252 253 // verify the location of the program headers 254 int32 programHeaderCount = elfHeader->e_phnum; 255 if (elfHeader->e_phoff < sizeof(Elf32_Ehdr) 256 || elfHeader->e_phentsize < sizeof(Elf32_Phdr) 257 || elfHeader->e_phoff + programHeaderCount * elfHeader->e_phentsize 258 > fFileSize) { 259 return B_NOT_AN_EXECUTABLE; 260 } 261 262 Elf32_Phdr* programHeaders 263 = (Elf32_Phdr*)(fMappedFile + elfHeader->e_phoff); 264 265 // verify the location of the section headers 266 int32 sectionCount = elfHeader->e_shnum; 267 if (elfHeader->e_shoff < sizeof(Elf32_Ehdr) 268 || elfHeader->e_shentsize < sizeof(Elf32_Shdr) 269 || elfHeader->e_shoff + sectionCount * elfHeader->e_shentsize 270 > fFileSize) { 271 return B_NOT_AN_EXECUTABLE; 272 } 273 274 Elf32_Shdr* sectionHeaders 275 = (Elf32_Shdr*)(fMappedFile + elfHeader->e_shoff); 276 277 // find the first segment -- we need its relative offset 278 for (int32 i = 0; i < programHeaderCount; i++) { 279 Elf32_Phdr* header = (Elf32_Phdr*) 280 ((uint8*)programHeaders + i * elfHeader->e_phentsize); 281 if (header->p_type == PT_LOAD) { 282 fLoadDelta = (addr_t)fInfo.text - header->p_vaddr; 283 break; 284 } 285 } 286 287 // find the symbol table 288 for (int32 i = 0; i < elfHeader->e_shnum; i++) { 289 Elf32_Shdr* sectionHeader = (Elf32_Shdr*) 290 ((uint8*)sectionHeaders + i * elfHeader->e_shentsize); 291 292 if (sectionHeader->sh_type == SHT_SYMTAB) { 293 Elf32_Shdr& stringHeader = *(Elf32_Shdr*) 294 ((uint8*)sectionHeaders 295 + sectionHeader->sh_link * elfHeader->e_shentsize); 296 297 if (stringHeader.sh_type != SHT_STRTAB) 298 return B_BAD_DATA; 299 300 if (sectionHeader->sh_offset + sectionHeader->sh_size > fFileSize 301 || stringHeader.sh_offset + stringHeader.sh_size > fFileSize) { 302 return B_BAD_DATA; 303 } 304 305 fSymbolTable = (Elf32_Sym*)(fMappedFile + sectionHeader->sh_offset); 306 fStringTable = (char*)(fMappedFile + stringHeader.sh_offset); 307 fSymbolCount = sectionHeader->sh_size / sizeof(Elf32_Sym); 308 fStringTableSize = stringHeader.sh_size; 309 310 return B_OK; 311 } 312 } 313 314 return B_BAD_DATA; 315 } 316 317 318 status_t 319 ImageFile::LoadKernel() 320 { 321 // get the table sizes 322 fSymbolCount = 0; 323 fStringTableSize = 0; 324 status_t error = _kern_read_kernel_image_symbols(fInfo.id, 325 NULL, &fSymbolCount, NULL, &fStringTableSize, NULL); 326 if (error != B_OK) 327 return error; 328 329 // allocate the tables 330 fSymbolTable = new(std::nothrow) Elf32_Sym[fSymbolCount]; 331 fStringTable = new(std::nothrow) char[fStringTableSize]; 332 if (fSymbolTable == NULL || fStringTable == NULL) 333 return B_NO_MEMORY; 334 335 // get the info 336 return _kern_read_kernel_image_symbols(fInfo.id, 337 fSymbolTable, &fSymbolCount, fStringTable, &fStringTableSize, 338 &fLoadDelta); 339 } 340 341 342 const Elf32_Sym* 343 ImageFile::LookupSymbol(addr_t address, addr_t* _baseAddress, 344 const char** _symbolName, size_t *_symbolNameLen, bool *_exactMatch) const 345 { 346 const Elf32_Sym* symbolFound = NULL; 347 const char* symbolName = NULL; 348 bool exactMatch = false; 349 addr_t deltaFound = ~(addr_t)0; 350 351 for (int32 i = 0; i < fSymbolCount; i++) { 352 const Elf32_Sym* symbol = &fSymbolTable[i]; 353 354 if (symbol->st_value == 0 355 || symbol->st_size >= (size_t)fInfo.text_size + fInfo.data_size) { 356 continue; 357 } 358 359 addr_t symbolAddress = symbol->st_value + fLoadDelta; 360 if (symbolAddress > address) 361 continue; 362 363 addr_t symbolDelta = address - symbolAddress; 364 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) 365 exactMatch = true; 366 367 if (exactMatch || symbolDelta < deltaFound) { 368 deltaFound = symbolDelta; 369 symbolFound = symbol; 370 symbolName = fStringTable + symbol->st_name; 371 372 if (exactMatch) 373 break; 374 } 375 } 376 377 if (symbolFound != NULL) { 378 if (_baseAddress != NULL) 379 *_baseAddress = symbolFound->st_value + fLoadDelta; 380 if (_symbolName != NULL) 381 *_symbolName = symbolName; 382 if (_exactMatch != NULL) 383 *_exactMatch = exactMatch; 384 if (_symbolNameLen != NULL) 385 *_symbolNameLen = _SymbolNameLen(symbolName); 386 } 387 388 return symbolFound; 389 } 390 391 392 status_t 393 ImageFile::NextSymbol(int32& iterator, const char** _symbolName, 394 size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize, 395 int32* _symbolType) const 396 { 397 while (true) { 398 if (++iterator >= fSymbolCount) 399 return B_ENTRY_NOT_FOUND; 400 401 const Elf32_Sym* symbol = &fSymbolTable[iterator]; 402 403 if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC 404 && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT) 405 || symbol->st_value == 0) { 406 continue; 407 } 408 409 *_symbolName = fStringTable + symbol->st_name; 410 *_symbolNameLen = _SymbolNameLen(*_symbolName); 411 *_symbolAddress = symbol->st_value + fLoadDelta; 412 *_symbolSize = symbol->st_size; 413 *_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC 414 ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; 415 416 return B_OK; 417 } 418 } 419 420 421 size_t 422 ImageFile::_SymbolNameLen(const char* symbolName) const 423 { 424 if (symbolName == NULL || (addr_t)symbolName < (addr_t)fStringTable 425 || (addr_t)symbolName >= (addr_t)fStringTable + fStringTableSize) { 426 return 0; 427 } 428 429 return strnlen(symbolName, 430 (addr_t)fStringTable + fStringTableSize - (addr_t)symbolName); 431 } 432 433 434 // #pragma mark - 435 436 437 // constructor 438 SymbolLookup::SymbolLookup(team_id team) 439 : 440 RemoteMemoryAccessor(team), 441 fDebugArea(NULL), 442 fImageFiles() 443 { 444 } 445 446 447 // destructor 448 SymbolLookup::~SymbolLookup() 449 { 450 while (ImageFile* imageFile = fImageFiles.RemoveHead()) 451 delete imageFile; 452 } 453 454 455 // Init 456 status_t 457 SymbolLookup::Init() 458 { 459 TRACE(("SymbolLookup::Init()\n")); 460 461 status_t error = RemoteMemoryAccessor::Init(); 462 if (error != B_OK) 463 return error; 464 465 if (fTeam != B_SYSTEM_TEAM) { 466 TRACE(("SymbolLookup::Init(): searching debug area...\n")); 467 468 // find the runtime loader debug area 469 runtime_loader_debug_area *remoteDebugArea = NULL; 470 int32 cookie = 0; 471 area_info areaInfo; 472 while (get_next_area_info(fTeam, &cookie, &areaInfo) == B_OK) { 473 if (strcmp(areaInfo.name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0) { 474 remoteDebugArea = (runtime_loader_debug_area*)areaInfo.address; 475 break; 476 } 477 } 478 479 if (remoteDebugArea) { 480 TRACE(("SymbolLookup::Init(): found debug area, translating " 481 "address...\n")); 482 } else { 483 TRACE(("SymbolLookup::Init(): Couldn't find debug area!\n")); 484 } 485 486 // translate the address 487 try { 488 if (remoteDebugArea != NULL) { 489 fDebugArea = &Read(*remoteDebugArea); 490 491 TRACE(("SymbolLookup::Init(): translated debug area is at: %p, " 492 "loaded_images: %p\n", fDebugArea, fDebugArea->loaded_images)); 493 } 494 } catch (Exception exception) { 495 // we can live without the debug area 496 } 497 } 498 499 // create a list of the team's images 500 image_info imageInfo; 501 int32 cookie = 0; 502 while (get_next_image_info(fTeam, &cookie, &imageInfo) == B_OK) { 503 ImageFile* imageFile = new(std::nothrow) ImageFile(imageInfo); 504 if (imageFile == NULL) 505 break; 506 507 error = fTeam == B_SYSTEM_TEAM 508 ? imageFile->LoadKernel() : imageFile->Load(); 509 if (error != B_OK) { 510 delete imageFile; 511 continue; 512 } 513 514 fImageFiles.Add(imageFile); 515 } 516 517 return B_OK; 518 } 519 520 521 // LookupSymbolAddress 522 status_t 523 SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress, 524 const char **_symbolName, size_t *_symbolNameLen, const char **_imageName, 525 bool *_exactMatch) const 526 { 527 TRACE(("SymbolLookup::LookupSymbolAddress(%p)\n", (void*)address)); 528 529 // Try the loaded image file first -- it also contains static symbols. 530 ImageFile* imageFile = _FindImageFileAtAddress(address); 531 if (imageFile != NULL) { 532 if (_imageName != NULL) 533 *_imageName = imageFile->Info().name; 534 const Elf32_Sym* symbol = imageFile->LookupSymbol(address, _baseAddress, 535 _symbolName, _symbolNameLen, _exactMatch); 536 if (symbol != NULL) 537 return B_OK; 538 } 539 540 // get the image for the address 541 const image_t *image = _FindImageAtAddress(address); 542 if (!image) 543 return B_ENTRY_NOT_FOUND; 544 545 TRACE(("SymbolLookup::LookupSymbolAddress(): found image: ID: %ld, text: " 546 "address: %p, size: %ld\n", 547 image->id, (void*)image->regions[0].vmstart, image->regions[0].size)); 548 549 // search the image for the symbol 550 const struct Elf32_Sym *symbolFound = NULL; 551 addr_t deltaFound = INT_MAX; 552 bool exactMatch = false; 553 const char *symbolName = NULL; 554 555 int32 symbolCount = Read(image->symhash[1]); 556 const elf_region_t *textRegion = image->regions; // local 557 558 for (int32 i = 0; i < symbolCount; i++) { 559 const struct Elf32_Sym *symbol = &Read(image->syms[i]); 560 561 // The symbol table contains not only symbols referring to functions 562 // and data symbols within the shared object, but also referenced 563 // symbols of other shared objects, as well as section and file 564 // references. We ignore everything but function and data symbols 565 // that have an st_value != 0 (0 seems to be an indication for a 566 // symbol defined elsewhere -- couldn't verify that in the specs 567 // though). 568 if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC 569 && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT) 570 || symbol->st_value == 0 571 || symbol->st_value + symbol->st_size + textRegion->delta 572 > textRegion->vmstart + textRegion->size) { 573 continue; 574 } 575 576 // skip symbols starting after the given address 577 addr_t symbolAddress = symbol->st_value + textRegion->delta; 578 579 if (symbolAddress > address) 580 continue; 581 addr_t symbolDelta = address - symbolAddress; 582 583 if (!symbolFound || symbolDelta < deltaFound) { 584 symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image, 585 symbol), 1); 586 if (symbolName == NULL) 587 continue; 588 589 deltaFound = symbolDelta; 590 symbolFound = symbol; 591 592 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) { 593 // exact match 594 exactMatch = true; 595 break; 596 } 597 } 598 } 599 600 TRACE(("SymbolLookup::LookupSymbolAddress(): done: symbol: %p, image name: " 601 "%s, exact match: %d\n", symbolFound, image->name, exactMatch)); 602 603 if (_baseAddress) { 604 if (symbolFound) 605 *_baseAddress = symbolFound->st_value + textRegion->delta; 606 else 607 *_baseAddress = textRegion->vmstart; 608 } 609 610 if (_imageName) 611 *_imageName = image->name; 612 613 if (_symbolName) 614 *_symbolName = symbolName; // remote address 615 616 if (_exactMatch) 617 *_exactMatch = exactMatch; 618 619 if (_symbolNameLen != NULL) 620 *_symbolNameLen = _SymbolNameLen(symbolName); 621 622 return B_OK; 623 } 624 625 626 // InitSymbolIterator 627 status_t 628 SymbolLookup::InitSymbolIterator(image_id imageID, 629 SymbolIterator& iterator) const 630 { 631 TRACE(("SymbolLookup::InitSymbolIterator(): image ID: %ld\n", imageID)); 632 633 // find the image file 634 iterator.imageFile = _FindImageFileByID(imageID); 635 636 // If that didn't work, find the image. 637 if (iterator.imageFile == NULL) { 638 const image_t* image = _FindImageByID(imageID); 639 if (image == NULL) { 640 TRACE(("SymbolLookup::InitSymbolIterator() done: image not " 641 "found\n")); 642 return B_ENTRY_NOT_FOUND; 643 } 644 645 iterator.image = image; 646 iterator.symbolCount = Read(image->symhash[1]); 647 iterator.textDelta = image->regions->delta; 648 } 649 650 iterator.currentIndex = -1; 651 652 return B_OK; 653 } 654 655 656 // InitSymbolIterator 657 status_t 658 SymbolLookup::InitSymbolIteratorByAddress(addr_t address, 659 SymbolIterator& iterator) const 660 { 661 TRACE(("SymbolLookup::InitSymbolIteratorByAddress(): base address: %#lx\n", 662 address)); 663 664 // find the image file 665 iterator.imageFile = _FindImageFileAtAddress(address); 666 667 // If that didn't work, find the image. 668 if (iterator.imageFile == NULL) { 669 const image_t *image = _FindImageAtAddress(address); 670 if (image == NULL) { 671 TRACE(("SymbolLookup::InitSymbolIteratorByAddress() done: image " 672 "not found\n")); 673 return B_ENTRY_NOT_FOUND; 674 } 675 676 iterator.image = image; 677 iterator.symbolCount = Read(image->symhash[1]); 678 iterator.textDelta = image->regions->delta; 679 } 680 681 iterator.currentIndex = -1; 682 683 return B_OK; 684 } 685 686 687 // NextSymbol 688 status_t 689 SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName, 690 size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize, 691 int32* _symbolType) const 692 { 693 // If we have an image file, get the next symbol from it. 694 const ImageFile* imageFile = iterator.imageFile; 695 if (imageFile != NULL) { 696 return imageFile->NextSymbol(iterator.currentIndex, _symbolName, 697 _symbolNameLen, _symbolAddress, _symbolSize, _symbolType); 698 } 699 700 // Otherwise we've to fall be to iterating through the image. 701 const image_t* image = iterator.image; 702 703 while (true) { 704 if (++iterator.currentIndex >= iterator.symbolCount) 705 return B_ENTRY_NOT_FOUND; 706 707 const struct Elf32_Sym* symbol = &Read(image->syms[ 708 iterator.currentIndex]); 709 if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC 710 && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT) 711 || symbol->st_value == 0) { 712 continue; 713 } 714 715 *_symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image, 716 symbol), 1); 717 *_symbolNameLen = _SymbolNameLen(*_symbolName); 718 *_symbolAddress = symbol->st_value + iterator.textDelta; 719 *_symbolSize = symbol->st_size; 720 *_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC 721 ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; 722 723 return B_OK; 724 } 725 } 726 727 728 // _FindImageAtAddress 729 const image_t * 730 SymbolLookup::_FindImageAtAddress(addr_t address) const 731 { 732 TRACE(("SymbolLookup::_FindImageAtAddress(%p)\n", (void*)address)); 733 734 if (fDebugArea == NULL) 735 return NULL; 736 737 // iterate through the images 738 for (const image_t *image = &Read(*Read(fDebugArea->loaded_images->head)); 739 image; 740 image = &Read(*image->next)) { 741 if (image->regions[0].vmstart <= address 742 && address < image->regions[0].vmstart + image->regions[0].size) { 743 return image; 744 } 745 } 746 747 return NULL; 748 } 749 750 751 // _FindImageByID 752 const image_t* 753 SymbolLookup::_FindImageByID(image_id id) const 754 { 755 if (fDebugArea == NULL) 756 return NULL; 757 758 // iterate through the images 759 for (const image_t *image = &Read(*Read(fDebugArea->loaded_images->head)); 760 image; 761 image = &Read(*image->next)) { 762 if (image->id == id) 763 return image; 764 } 765 766 return NULL; 767 } 768 769 770 // _FindImageFileAtAddress 771 ImageFile* 772 SymbolLookup::_FindImageFileAtAddress(addr_t address) const 773 { 774 DoublyLinkedList<ImageFile>::ConstIterator it = fImageFiles.GetIterator(); 775 while (ImageFile* imageFile = it.Next()) { 776 const image_info& info = imageFile->Info(); 777 if (address >= (addr_t)info.text 778 && address < (addr_t)info.text + info.text_size) { 779 return imageFile; 780 } 781 } 782 783 return NULL; 784 } 785 786 787 // _FindImageFileByID 788 ImageFile* 789 SymbolLookup::_FindImageFileByID(image_id id) const 790 { 791 DoublyLinkedList<ImageFile>::ConstIterator it = fImageFiles.GetIterator(); 792 while (ImageFile* imageFile = it.Next()) { 793 if (imageFile->Info().id == id) 794 return imageFile; 795 } 796 797 return NULL; 798 } 799 800 801 // _SymbolNameLen 802 size_t 803 SymbolLookup::_SymbolNameLen(const char* address) const 804 { 805 Area* area = AreaForLocalAddress(address); 806 if (area == NULL) 807 return 0; 808 809 return strnlen(address, (addr_t)area->LocalAddress() + area->Size() 810 - (addr_t)address); 811 } 812