1 /* 2 * Copyright 2016, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "CoreFile.h" 8 9 #include <errno.h> 10 11 #include <algorithm> 12 13 #include <OS.h> 14 15 #include <AutoDeleter.h> 16 17 #include "ElfSymbolLookup.h" 18 #include "Tracing.h" 19 20 21 static const size_t kMaxNotesSize = 10 * 1024 * 1024; 22 23 24 // pragma mark - CoreFileTeamInfo 25 26 27 CoreFileTeamInfo::CoreFileTeamInfo() 28 : 29 fId(-1), 30 fUid(-1), 31 fGid(-1), 32 fArgs() 33 { 34 } 35 36 37 void 38 CoreFileTeamInfo::Init(int32 id, int32 uid, int32 gid, const BString& args) 39 { 40 fId = id; 41 fUid = uid; 42 fGid = gid; 43 fArgs = args; 44 } 45 46 47 // pragma mark - CoreFileAreaInfo 48 49 50 CoreFileAreaInfo::CoreFileAreaInfo(ElfSegment* segment, int32 id, 51 uint64 baseAddress, uint64 size, uint64 ramSize, uint32 locking, 52 uint32 protection, const BString& name) 53 : 54 fSegment(segment), 55 fBaseAddress(baseAddress), 56 fSize(size), 57 fRamSize(ramSize), 58 fLocking(locking), 59 fProtection(protection), 60 fId(-1) 61 { 62 } 63 64 65 // pragma mark - CoreFileImageInfo 66 67 68 CoreFileImageInfo::CoreFileImageInfo(int32 id, int32 type, uint64 initRoutine, 69 uint64 termRoutine, uint64 textBase, uint64 textSize, int64 textDelta, 70 uint64 dataBase, uint64 dataSize, int32 deviceId, int64 nodeId, 71 uint64 symbolTable, uint64 symbolHash, uint64 stringTable, 72 CoreFileAreaInfo* textArea, CoreFileAreaInfo* dataArea, const BString& name) 73 : 74 fId(id), 75 fType(type), 76 fInitRoutine(initRoutine), 77 fTermRoutine(termRoutine), 78 fTextBase(textBase), 79 fTextSize(textSize), 80 fTextDelta(textDelta), 81 fDataBase(dataBase), 82 fDataSize(dataSize), 83 fDeviceId(deviceId), 84 fNodeId(nodeId), 85 fSymbolTable(symbolTable), 86 fSymbolHash(symbolHash), 87 fStringTable(stringTable), 88 fTextArea(textArea), 89 fDataArea(dataArea), 90 fName(name), 91 fSymbolsInfo(NULL) 92 { 93 } 94 95 96 CoreFileImageInfo::~CoreFileImageInfo() 97 { 98 SetSymbolsInfo(NULL); 99 } 100 101 102 void 103 CoreFileImageInfo::SetSymbolsInfo(CoreFileSymbolsInfo* symbolsInfo) 104 { 105 if (fSymbolsInfo != NULL) 106 delete fSymbolsInfo; 107 108 fSymbolsInfo = symbolsInfo; 109 } 110 111 112 // pragma mark - CoreFileSymbolsInfo 113 114 CoreFileSymbolsInfo::CoreFileSymbolsInfo() 115 : 116 fSymbolTable(NULL), 117 fStringTable(NULL), 118 fSymbolCount(0), 119 fSymbolTableEntrySize(0), 120 fStringTableSize(0) 121 { 122 } 123 124 125 CoreFileSymbolsInfo::~CoreFileSymbolsInfo() 126 { 127 free(fSymbolTable); 128 free(fStringTable); 129 } 130 131 132 bool 133 CoreFileSymbolsInfo::Init(const void* symbolTable, uint32 symbolCount, 134 uint32 symbolTableEntrySize, const char* stringTable, 135 uint32 stringTableSize) 136 { 137 fSymbolTable = malloc(symbolCount * symbolTableEntrySize); 138 fStringTable = (char*)malloc(stringTableSize); 139 140 if (fSymbolTable == NULL || fStringTable == NULL) 141 return false; 142 143 memcpy(fSymbolTable, symbolTable, symbolCount * symbolTableEntrySize); 144 memcpy(fStringTable, stringTable, stringTableSize); 145 146 fSymbolCount = symbolCount; 147 fSymbolTableEntrySize = symbolTableEntrySize; 148 fStringTableSize = stringTableSize; 149 150 return true; 151 } 152 153 154 // pragma mark - CoreFileThreadInfo 155 156 157 CoreFileThreadInfo::CoreFileThreadInfo(int32 id, int32 state, int32 priority, 158 uint64 stackBase, uint64 stackEnd, const BString& name) 159 : 160 fId(id), 161 fState(state), 162 fPriority(priority), 163 fStackBase(stackBase), 164 fStackEnd(stackEnd), 165 fName(name), 166 fCpuState(NULL), 167 fCpuStateSize(0) 168 { 169 } 170 171 172 CoreFileThreadInfo::~CoreFileThreadInfo() 173 { 174 free(fCpuState); 175 } 176 177 178 bool 179 CoreFileThreadInfo::SetCpuState(const void* state, size_t size) 180 { 181 free(fCpuState); 182 fCpuState = NULL; 183 fCpuStateSize = 0; 184 185 if (state != NULL) { 186 fCpuState = malloc(size); 187 if (fCpuState == NULL) 188 return false; 189 memcpy(fCpuState, state, size); 190 fCpuStateSize = size; 191 } 192 193 return true; 194 } 195 196 197 // pragma mark - CoreFile 198 199 200 CoreFile::CoreFile() 201 : 202 fElfFile(), 203 fTeamInfo(), 204 fAreaInfos(32, true), 205 fImageInfos(32, true), 206 fThreadInfos(32, true) 207 { 208 } 209 210 211 CoreFile::~CoreFile() 212 { 213 } 214 215 216 status_t 217 CoreFile::Init(const char* fileName) 218 { 219 status_t error = fElfFile.Init(fileName); 220 if (error != B_OK) 221 return error; 222 223 if (fElfFile.Is64Bit()) 224 return _Init<ElfClass64>(); 225 return _Init<ElfClass32>(); 226 } 227 228 229 const CoreFileThreadInfo* 230 CoreFile::ThreadInfoForId(int32 id) const 231 { 232 int32 count = fThreadInfos.CountItems(); 233 for (int32 i = 0; i < count; i++) { 234 CoreFileThreadInfo* info = fThreadInfos.ItemAt(i); 235 if (info->Id() == id) 236 return info; 237 } 238 239 return NULL; 240 } 241 242 243 status_t 244 CoreFile::CreateSymbolLookup(const CoreFileImageInfo* imageInfo, 245 ElfSymbolLookup*& _lookup) 246 { 247 // get the needed data 248 uint64 textDelta = imageInfo->TextDelta(); 249 uint64 symbolTable = imageInfo->SymbolTable(); 250 uint64 symbolHash = imageInfo->SymbolHash(); 251 uint64 stringTable = imageInfo->StringTable(); 252 CoreFileAreaInfo* textArea = imageInfo->TextArea(); 253 ElfSegment* textSegment = textArea != NULL ? textArea->Segment() : NULL; 254 255 if (symbolTable == 0 || symbolHash == 0 || stringTable == 0 256 || textSegment == NULL) { 257 return B_UNSUPPORTED; 258 } 259 260 // create a data source for the text segment 261 ElfSymbolLookupSource* source = fElfFile.CreateSymbolLookupSource( 262 textSegment->FileOffset(), textSegment->FileSize(), 263 textSegment->LoadAddress()); 264 if (source == NULL) 265 return B_NO_MEMORY; 266 267 // get the symbol table entry size 268 // TODO: This is not actually correct, since at least theoretically the 269 // entry size may differ (cf. DT_SYMENT in the dynamic segment). 270 size_t symbolTableEntrySize = fElfFile.Is64Bit() 271 ? sizeof(ElfClass64::Sym) : sizeof(ElfClass32::Sym); 272 273 // create the symbol lookup 274 return ElfSymbolLookup::Create(source, symbolTable, symbolHash, stringTable, 275 ElfSymbolLookup::kGetSymbolCountFromHash, symbolTableEntrySize, 276 textDelta, fElfFile.Is64Bit(), fElfFile.IsByteOrderSwapped(), true, 277 _lookup); 278 } 279 280 281 template<typename ElfClass> 282 status_t 283 CoreFile::_Init() 284 { 285 status_t error = _ReadNotes<ElfClass>(); 286 if (error != B_OK) 287 return error; 288 printf("CoreFile::_Init(): got %" B_PRId32 " areas, %" B_PRId32 " images, %" 289 B_PRId32 " threads\n", CountAreaInfos(), CountImageInfos(), CountThreadInfos()); 290 // TODO: Verify that we actually read something! 291 return B_OK; 292 } 293 294 295 template<typename ElfClass> 296 status_t 297 CoreFile::_ReadNotes() 298 { 299 int32 count = fElfFile.CountSegments(); 300 for (int32 i = 0; i < count; i++) { 301 ElfSegment* segment = fElfFile.SegmentAt(i); 302 if (segment->Type() == PT_NOTE) { 303 status_t error = _ReadNotes<ElfClass>(segment); 304 if (error != B_OK) 305 return error; 306 } 307 } 308 309 return B_OK; 310 } 311 312 313 template<typename ElfClass> 314 status_t 315 CoreFile::_ReadNotes(ElfSegment* segment) 316 { 317 // read the whole segment into memory 318 if ((uint64)segment->FileSize() > kMaxNotesSize) { 319 WARNING("Notes segment too large (%" B_PRIdOFF ")\n", 320 segment->FileSize()); 321 return B_UNSUPPORTED; 322 } 323 324 size_t notesSize = (size_t)segment->FileSize(); 325 uint8* notes = (uint8*)malloc(notesSize); 326 if (notes == NULL) 327 return B_NO_MEMORY; 328 MemoryDeleter notesDeleter(notes); 329 330 ssize_t bytesRead = pread(fElfFile.FD(), notes, notesSize, 331 (off_t)segment->FileOffset()); 332 if (bytesRead < 0) { 333 WARNING("Failed to read notes segment: %s\n", strerror(errno)); 334 return errno; 335 } 336 if ((size_t)bytesRead != notesSize) { 337 WARNING("Failed to read whole notes segment\n"); 338 return B_IO_ERROR; 339 } 340 341 // iterate through notes 342 typedef typename ElfClass::Nhdr Nhdr; 343 while (notesSize > 0) { 344 if (notesSize < sizeof(Nhdr)) { 345 WARNING("Remaining bytes in notes segment too short for header\n"); 346 return B_BAD_DATA; 347 } 348 349 const Nhdr* header = (const Nhdr*)notes; 350 uint32 nameSize = Get(header->n_namesz); 351 uint32 dataSize = Get(header->n_descsz); 352 uint32 type = Get(header->n_type); 353 354 notes += sizeof(Nhdr); 355 notesSize -= sizeof(Nhdr); 356 357 size_t alignedNameSize = (nameSize + 3) / 4 * 4; 358 if (alignedNameSize > notesSize) { 359 WARNING("Not enough bytes remaining in notes segment for note " 360 "name (%zu / %zu)\n", notesSize, alignedNameSize); 361 return B_BAD_DATA; 362 } 363 364 const char* name = (const char*)notes; 365 size_t nameLen = strnlen(name, nameSize); 366 if (nameLen == nameSize) { 367 WARNING("Unterminated note name\n"); 368 return B_BAD_DATA; 369 } 370 371 notes += alignedNameSize; 372 notesSize -= alignedNameSize; 373 374 size_t alignedDataSize = (dataSize + 3) / 4 * 4; 375 if (alignedDataSize > notesSize) { 376 WARNING("Not enough bytes remaining in notes segment for note " 377 "data\n"); 378 return B_BAD_DATA; 379 } 380 381 _ReadNote<ElfClass>(name, type, notes, dataSize); 382 383 notes += alignedDataSize; 384 notesSize -= alignedDataSize; 385 } 386 387 return B_OK; 388 } 389 390 391 template<typename ElfClass> 392 status_t 393 CoreFile::_ReadNote(const char* name, uint32 type, const void* data, 394 uint32 dataSize) 395 { 396 if (strcmp(name, ELF_NOTE_CORE) == 0) { 397 switch (type) { 398 case NT_FILE: 399 // not needed 400 return B_OK; 401 } 402 } else if (strcmp(name, ELF_NOTE_HAIKU) == 0) { 403 switch (type) { 404 case NT_TEAM: 405 return _ReadTeamNote<ElfClass>(data, dataSize); 406 case NT_AREAS: 407 return _ReadAreasNote<ElfClass>(data, dataSize); 408 case NT_IMAGES: 409 return _ReadImagesNote<ElfClass>(data, dataSize); 410 case NT_SYMBOLS: 411 return _ReadSymbolsNote<ElfClass>(data, dataSize); 412 case NT_THREADS: 413 return _ReadThreadsNote<ElfClass>(data, dataSize); 414 break; 415 } 416 } 417 418 WARNING("Unsupported note type %s/%#" B_PRIx32 "\n", name, type); 419 return B_OK; 420 } 421 422 423 template<typename ElfClass> 424 status_t 425 CoreFile::_ReadTeamNote(const void* data, uint32 dataSize) 426 { 427 typedef typename ElfClass::NoteTeam NoteTeam; 428 429 if (dataSize < sizeof(uint32)) { 430 WARNING("Team note too short\n"); 431 return B_BAD_DATA; 432 } 433 uint32 entrySize = Get(*(const uint32*)data); 434 data = (const uint32*)data + 1; 435 dataSize -= sizeof(uint32); 436 437 if (entrySize == 0 || dataSize == 0 || dataSize - 1 < entrySize) { 438 WARNING("Team note: too short or invalid entry size (%" B_PRIu32 ")\n", 439 entrySize); 440 return B_BAD_DATA; 441 } 442 443 NoteTeam note = {}; 444 _ReadEntry(data, dataSize, note, entrySize); 445 446 // check, if args are null-terminated 447 const char* args = (const char*)data; 448 size_t argsSize = dataSize; 449 if (args[argsSize - 1] != '\0') { 450 WARNING("Team note args not terminated\n"); 451 return B_BAD_DATA; 452 } 453 454 int32 id = Get(note.nt_id); 455 int32 uid = Get(note.nt_uid); 456 int32 gid = Get(note.nt_gid); 457 458 BString copiedArgs(args); 459 if (args[0] != '\0' && copiedArgs.Length() == 0) 460 return B_NO_MEMORY; 461 462 fTeamInfo.Init(id, uid, gid, copiedArgs); 463 return B_OK; 464 } 465 466 467 template<typename ElfClass> 468 status_t 469 CoreFile::_ReadAreasNote(const void* data, uint32 dataSize) 470 { 471 if (dataSize < 2 * sizeof(uint32)) { 472 WARNING("Areas note too short\n"); 473 return B_BAD_DATA; 474 } 475 uint32 areaCount = _ReadValue<uint32>(data, dataSize); 476 uint32 entrySize = _ReadValue<uint32>(data, dataSize); 477 478 typedef typename ElfClass::NoteAreaEntry Entry; 479 480 if (areaCount == 0) 481 return B_OK; 482 483 // check entry size and area count 484 if (entrySize == 0 || dataSize == 0 || areaCount > dataSize 485 || dataSize - 1 < entrySize || areaCount * entrySize >= dataSize) { 486 WARNING("Areas note: too short or invalid entry size (%" B_PRIu32 ")\n", 487 entrySize); 488 return B_BAD_DATA; 489 } 490 491 // check, if strings are null-terminated 492 const char* strings = (const char*)data + areaCount * entrySize; 493 size_t stringsSize = dataSize - areaCount * entrySize; 494 if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { 495 WARNING("Areas note strings not terminated\n"); 496 return B_BAD_DATA; 497 } 498 499 for (uint64 i = 0; i < areaCount; i++) { 500 // get entry values 501 Entry entry = {}; 502 _ReadEntry(data, dataSize, entry, entrySize); 503 504 int32 id = Get(entry.na_id); 505 uint64 baseAddress = Get(entry.na_base); 506 uint64 size = Get(entry.na_size); 507 uint64 ramSize = Get(entry.na_ram_size); 508 uint32 lock = Get(entry.na_lock); 509 uint32 protection = Get(entry.na_protection); 510 511 // get name 512 if (stringsSize == 0) { 513 WARNING("Area %" B_PRIu64 " (ID %#" B_PRIx32 " @ %#" B_PRIx64 514 ") has no name\n", i, id, baseAddress); 515 continue; 516 } 517 const char* name = strings; 518 size_t nameSize = strlen(name) + 1; 519 strings += nameSize; 520 stringsSize -= nameSize; 521 522 BString copiedName(name); 523 if (name[0] != '\0' && copiedName.Length() == 0) 524 return B_NO_MEMORY; 525 526 // create and add area 527 ElfSegment* segment = _FindAreaSegment(baseAddress); 528 CoreFileAreaInfo* area = new(std::nothrow) CoreFileAreaInfo(segment, id, 529 baseAddress, size, ramSize, lock, protection, copiedName); 530 if (area == NULL || !fAreaInfos.AddItem(area)) { 531 delete area; 532 return B_NO_MEMORY; 533 } 534 } 535 536 return B_OK; 537 } 538 539 540 template<typename ElfClass> 541 status_t 542 CoreFile::_ReadImagesNote(const void* data, uint32 dataSize) 543 { 544 if (dataSize < 2 * sizeof(uint32)) { 545 WARNING("Images note too short\n"); 546 return B_BAD_DATA; 547 } 548 uint32 imageCount = _ReadValue<uint32>(data, dataSize); 549 uint32 entrySize = _ReadValue<uint32>(data, dataSize); 550 551 typedef typename ElfClass::NoteImageEntry Entry; 552 553 if (imageCount == 0) 554 return B_OK; 555 556 // check entry size and image count 557 if (entrySize == 0 || dataSize == 0 || imageCount > dataSize 558 || dataSize - 1 < entrySize || imageCount * entrySize >= dataSize) { 559 WARNING("Images note: too short or invalid entry size (%" B_PRIu32 560 ")\n", entrySize); 561 return B_BAD_DATA; 562 } 563 564 // check, if strings are null-terminated 565 const char* strings = (const char*)data + imageCount * entrySize; 566 size_t stringsSize = dataSize - imageCount * entrySize; 567 if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { 568 WARNING("Images note strings not terminated\n"); 569 return B_BAD_DATA; 570 } 571 572 for (uint64 i = 0; i < imageCount; i++) { 573 // get entry values 574 Entry entry = {}; 575 _ReadEntry(data, dataSize, entry, entrySize); 576 577 int32 id = Get(entry.ni_id); 578 int32 type = Get(entry.ni_type); 579 uint64 initRoutine = Get(entry.ni_init_routine); 580 uint64 termRoutine = Get(entry.ni_term_routine); 581 uint64 textBase = Get(entry.ni_text_base); 582 uint64 textSize = Get(entry.ni_text_size); 583 int64 textDelta = Get(entry.ni_text_delta); 584 uint64 dataBase = Get(entry.ni_data_base); 585 uint64 dataSize = Get(entry.ni_data_size); 586 int32 deviceId = Get(entry.ni_device); 587 int64 nodeId = Get(entry.ni_node); 588 uint64 symbolTable = Get(entry.ni_symbol_table); 589 uint64 symbolHash = Get(entry.ni_symbol_hash); 590 uint64 stringTable = Get(entry.ni_string_table); 591 592 // get name 593 if (stringsSize == 0) { 594 WARNING("Image %" B_PRIu64 " (ID %#" B_PRIx32 ") has no name\n", 595 i, id); 596 continue; 597 } 598 const char* name = strings; 599 size_t nameSize = strlen(name) + 1; 600 strings += nameSize; 601 stringsSize -= nameSize; 602 603 BString copiedName(name); 604 if (name[0] != '\0' && copiedName.Length() == 0) 605 return B_NO_MEMORY; 606 607 // create and add image 608 CoreFileAreaInfo* textArea = _FindArea(textBase); 609 CoreFileAreaInfo* dataArea = _FindArea(dataBase); 610 CoreFileImageInfo* image = new(std::nothrow) CoreFileImageInfo(id, type, 611 initRoutine, termRoutine, textBase, textSize, textDelta, dataBase, 612 dataSize, deviceId, nodeId, symbolTable, symbolHash, stringTable, 613 textArea, dataArea, copiedName); 614 if (image == NULL || !fImageInfos.AddItem(image)) { 615 delete image; 616 return B_NO_MEMORY; 617 } 618 } 619 620 return B_OK; 621 } 622 623 624 template<typename ElfClass> 625 status_t 626 CoreFile::_ReadSymbolsNote(const void* data, uint32 dataSize) 627 { 628 if (dataSize < 3 * sizeof(uint32)) { 629 WARNING("Symbols note too short\n"); 630 return B_BAD_DATA; 631 } 632 int32 imageId = _ReadValue<int32>(data, dataSize); 633 uint32 symbolCount = _ReadValue<uint32>(data, dataSize); 634 uint32 entrySize = _ReadValue<uint32>(data, dataSize); 635 636 typedef typename ElfClass::Sym Sym; 637 638 if (symbolCount == 0) 639 return B_OK; 640 641 // get the corresponding image 642 CoreFileImageInfo* imageInfo = _ImageInfoForId(imageId); 643 if (imageInfo == NULL) { 644 WARNING("Symbols note: image (ID %" B_PRId32 ") not found\n", 645 entrySize); 646 return B_BAD_DATA; 647 } 648 649 // check entry size and symbol count 650 if (entrySize < sizeof(Sym) || symbolCount > dataSize 651 || dataSize - 1 < entrySize 652 || symbolCount * entrySize >= dataSize - 1) { 653 WARNING("Symbols note: too short or invalid entry size (%" B_PRIu32 654 ")\n", entrySize); 655 return B_BAD_DATA; 656 } 657 658 uint32 symbolTableSize = symbolCount * entrySize; 659 uint32 stringTableSize = dataSize - symbolTableSize; 660 661 // check, if the string table is null-terminated 662 const char* stringTable = (const char*)data + symbolTableSize; 663 if (stringTableSize == 0 || stringTable[stringTableSize - 1] != '\0') { 664 WARNING("Symbols note string table not terminated\n"); 665 return B_BAD_DATA; 666 } 667 668 CoreFileSymbolsInfo* symbolsInfo = new(std::nothrow) CoreFileSymbolsInfo; 669 if (symbolsInfo == NULL 670 || !symbolsInfo->Init(data, symbolCount, entrySize, stringTable, 671 stringTableSize)) { 672 delete symbolsInfo; 673 return B_NO_MEMORY; 674 } 675 676 imageInfo->SetSymbolsInfo(symbolsInfo); 677 678 return B_OK; 679 } 680 681 682 template<typename ElfClass> 683 status_t 684 CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize) 685 { 686 if (dataSize < 3 * sizeof(uint32)) { 687 WARNING("Threads note too short\n"); 688 return B_BAD_DATA; 689 } 690 uint32 threadCount = _ReadValue<uint32>(data, dataSize); 691 uint32 entrySize = _ReadValue<uint32>(data, dataSize); 692 uint32 cpuStateSize = _ReadValue<uint32>(data, dataSize); 693 694 if (cpuStateSize > 1024 * 1024) { 695 WARNING("Threads note: unreasonable CPU state size: %" B_PRIu32 "\n", 696 cpuStateSize); 697 return B_BAD_DATA; 698 } 699 700 typedef typename ElfClass::NoteThreadEntry Entry; 701 702 if (threadCount == 0) 703 return B_OK; 704 705 size_t totalEntrySize = entrySize + cpuStateSize; 706 707 // check entry size and thread count 708 if (entrySize == 0 || dataSize == 0 || threadCount > dataSize 709 || entrySize > dataSize || cpuStateSize > dataSize 710 || dataSize - 1 < totalEntrySize 711 || threadCount * totalEntrySize >= dataSize) { 712 WARNING("Threads note: too short or invalid entry size (%" B_PRIu32 713 ")\n", entrySize); 714 return B_BAD_DATA; 715 } 716 717 // check, if strings are null-terminated 718 const char* strings = (const char*)data + threadCount * totalEntrySize; 719 size_t stringsSize = dataSize - threadCount * totalEntrySize; 720 if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { 721 WARNING("Threads note strings not terminated\n"); 722 return B_BAD_DATA; 723 } 724 725 for (uint64 i = 0; i < threadCount; i++) { 726 // get entry values 727 Entry entry = {}; 728 _ReadEntry(data, dataSize, entry, entrySize); 729 730 int32 id = Get(entry.nth_id); 731 int32 state = Get(entry.nth_state); 732 int32 priority = Get(entry.nth_priority); 733 uint64 stackBase = Get(entry.nth_stack_base); 734 uint64 stackEnd = Get(entry.nth_stack_end); 735 736 // get name 737 if (stringsSize == 0) { 738 WARNING("Thread %" B_PRIu64 " (ID %#" B_PRIx32 ") has no name\n", 739 i, id); 740 continue; 741 } 742 const char* name = strings; 743 size_t nameSize = strlen(name) + 1; 744 strings += nameSize; 745 stringsSize -= nameSize; 746 747 BString copiedName(name); 748 if (name[0] != '\0' && copiedName.Length() == 0) 749 return B_NO_MEMORY; 750 751 // create and add thread 752 CoreFileThreadInfo* thread = new(std::nothrow) CoreFileThreadInfo(id, 753 state, priority, stackBase, stackEnd, copiedName); 754 if (thread == NULL || !fThreadInfos.AddItem(thread)) { 755 delete thread; 756 return B_NO_MEMORY; 757 } 758 759 // get CPU state 760 if (!thread->SetCpuState(data, cpuStateSize)) 761 return B_NO_MEMORY; 762 _Advance(data, dataSize, cpuStateSize); 763 } 764 765 return B_OK; 766 } 767 768 769 CoreFileAreaInfo* 770 CoreFile::_FindArea(uint64 address) const 771 { 772 int32 count = fAreaInfos.CountItems(); 773 for (int32 i = 0; i < count; i++) { 774 CoreFileAreaInfo* area = fAreaInfos.ItemAt(i); 775 if (address >= area->BaseAddress() 776 && address < area->EndAddress()) { 777 return area; 778 } 779 } 780 781 return NULL; 782 } 783 784 785 ElfSegment* 786 CoreFile::_FindAreaSegment(uint64 address) const 787 { 788 int32 count = fElfFile.CountSegments(); 789 for (int32 i = 0; i < count; i++) { 790 ElfSegment* segment = fElfFile.SegmentAt(i); 791 if (segment->Type() == PT_LOAD && segment->LoadAddress() == address) 792 return segment; 793 } 794 795 return NULL; 796 } 797 798 799 CoreFileImageInfo* 800 CoreFile::_ImageInfoForId(int32 id) const 801 { 802 int32 count = fImageInfos.CountItems(); 803 for (int32 i = 0; i < count; i++) { 804 CoreFileImageInfo* info = fImageInfos.ItemAt(i); 805 if (info->Id() == id) 806 return info; 807 } 808 809 return NULL; 810 } 811 812 813 template<typename Type> 814 Type 815 CoreFile::_ReadValue(const void*& data, uint32& dataSize) 816 { 817 Type value = Get(*(const Type*)data); 818 _Advance(data, dataSize, sizeof(Type)); 819 return value; 820 } 821 822 823 template<typename Entry> 824 void 825 CoreFile::_ReadEntry(const void*& data, uint32& dataSize, Entry& entry, 826 size_t entrySize) 827 { 828 memcpy(&entry, data, std::min(sizeof(entry), entrySize)); 829 _Advance(data, dataSize, entrySize); 830 } 831 832 833 void 834 CoreFile::_Advance(const void*& data, uint32& dataSize, size_t by) 835 { 836 data = (const uint8*)data + by; 837 dataSize -= by; 838 } 839