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 if (segment == NULL) { 529 WARNING("No matching segment found for area %" B_PRIu64 " (ID %#" 530 B_PRIx32 " @ %#" B_PRIx64 ", name: '%s')", i, id, baseAddress, 531 name); 532 continue; 533 } 534 535 CoreFileAreaInfo* area = new(std::nothrow) CoreFileAreaInfo(segment, id, 536 baseAddress, size, ramSize, lock, protection, copiedName); 537 if (area == NULL || !fAreaInfos.AddItem(area)) { 538 delete area; 539 return B_NO_MEMORY; 540 } 541 } 542 543 return B_OK; 544 } 545 546 547 template<typename ElfClass> 548 status_t 549 CoreFile::_ReadImagesNote(const void* data, uint32 dataSize) 550 { 551 if (dataSize < 2 * sizeof(uint32)) { 552 WARNING("Images note too short\n"); 553 return B_BAD_DATA; 554 } 555 uint32 imageCount = _ReadValue<uint32>(data, dataSize); 556 uint32 entrySize = _ReadValue<uint32>(data, dataSize); 557 558 typedef typename ElfClass::NoteImageEntry Entry; 559 560 if (imageCount == 0) 561 return B_OK; 562 563 // check entry size and image count 564 if (entrySize == 0 || dataSize == 0 || imageCount > dataSize 565 || dataSize - 1 < entrySize || imageCount * entrySize >= dataSize) { 566 WARNING("Images note: too short or invalid entry size (%" B_PRIu32 567 ")\n", entrySize); 568 return B_BAD_DATA; 569 } 570 571 // check, if strings are null-terminated 572 const char* strings = (const char*)data + imageCount * entrySize; 573 size_t stringsSize = dataSize - imageCount * entrySize; 574 if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { 575 WARNING("Images note strings not terminated\n"); 576 return B_BAD_DATA; 577 } 578 579 for (uint64 i = 0; i < imageCount; i++) { 580 // get entry values 581 Entry entry = {}; 582 _ReadEntry(data, dataSize, entry, entrySize); 583 584 int32 id = Get(entry.ni_id); 585 int32 type = Get(entry.ni_type); 586 uint64 initRoutine = Get(entry.ni_init_routine); 587 uint64 termRoutine = Get(entry.ni_term_routine); 588 uint64 textBase = Get(entry.ni_text_base); 589 uint64 textSize = Get(entry.ni_text_size); 590 int64 textDelta = Get(entry.ni_text_delta); 591 uint64 dataBase = Get(entry.ni_data_base); 592 uint64 dataSize = Get(entry.ni_data_size); 593 int32 deviceId = Get(entry.ni_device); 594 int64 nodeId = Get(entry.ni_node); 595 uint64 symbolTable = Get(entry.ni_symbol_table); 596 uint64 symbolHash = Get(entry.ni_symbol_hash); 597 uint64 stringTable = Get(entry.ni_string_table); 598 599 // get name 600 if (stringsSize == 0) { 601 WARNING("Image %" B_PRIu64 " (ID %#" B_PRIx32 ") has no name\n", 602 i, id); 603 continue; 604 } 605 const char* name = strings; 606 size_t nameSize = strlen(name) + 1; 607 strings += nameSize; 608 stringsSize -= nameSize; 609 610 BString copiedName(name); 611 if (name[0] != '\0' && copiedName.Length() == 0) 612 return B_NO_MEMORY; 613 614 // create and add image 615 CoreFileAreaInfo* textArea = _FindArea(textBase); 616 CoreFileAreaInfo* dataArea = _FindArea(dataBase); 617 CoreFileImageInfo* image = new(std::nothrow) CoreFileImageInfo(id, type, 618 initRoutine, termRoutine, textBase, textSize, textDelta, dataBase, 619 dataSize, deviceId, nodeId, symbolTable, symbolHash, stringTable, 620 textArea, dataArea, copiedName); 621 if (image == NULL || !fImageInfos.AddItem(image)) { 622 delete image; 623 return B_NO_MEMORY; 624 } 625 } 626 627 return B_OK; 628 } 629 630 631 template<typename ElfClass> 632 status_t 633 CoreFile::_ReadSymbolsNote(const void* data, uint32 dataSize) 634 { 635 if (dataSize < 3 * sizeof(uint32)) { 636 WARNING("Symbols note too short\n"); 637 return B_BAD_DATA; 638 } 639 int32 imageId = _ReadValue<int32>(data, dataSize); 640 uint32 symbolCount = _ReadValue<uint32>(data, dataSize); 641 uint32 entrySize = _ReadValue<uint32>(data, dataSize); 642 643 typedef typename ElfClass::Sym Sym; 644 645 if (symbolCount == 0) 646 return B_OK; 647 648 // get the corresponding image 649 CoreFileImageInfo* imageInfo = _ImageInfoForId(imageId); 650 if (imageInfo == NULL) { 651 WARNING("Symbols note: image (ID %" B_PRId32 ") not found\n", 652 entrySize); 653 return B_BAD_DATA; 654 } 655 656 // check entry size and symbol count 657 if (entrySize < sizeof(Sym) || symbolCount > dataSize 658 || dataSize - 1 < entrySize 659 || symbolCount * entrySize >= dataSize - 1) { 660 WARNING("Symbols note: too short or invalid entry size (%" B_PRIu32 661 ")\n", entrySize); 662 return B_BAD_DATA; 663 } 664 665 uint32 symbolTableSize = symbolCount * entrySize; 666 uint32 stringTableSize = dataSize - symbolTableSize; 667 668 // check, if the string table is null-terminated 669 const char* stringTable = (const char*)data + symbolTableSize; 670 if (stringTableSize == 0 || stringTable[stringTableSize - 1] != '\0') { 671 WARNING("Symbols note string table not terminated\n"); 672 return B_BAD_DATA; 673 } 674 675 CoreFileSymbolsInfo* symbolsInfo = new(std::nothrow) CoreFileSymbolsInfo; 676 if (symbolsInfo == NULL 677 || !symbolsInfo->Init(data, symbolCount, entrySize, stringTable, 678 stringTableSize)) { 679 delete symbolsInfo; 680 return B_NO_MEMORY; 681 } 682 683 imageInfo->SetSymbolsInfo(symbolsInfo); 684 685 return B_OK; 686 } 687 688 689 template<typename ElfClass> 690 status_t 691 CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize) 692 { 693 if (dataSize < 3 * sizeof(uint32)) { 694 WARNING("Threads note too short\n"); 695 return B_BAD_DATA; 696 } 697 uint32 threadCount = _ReadValue<uint32>(data, dataSize); 698 uint32 entrySize = _ReadValue<uint32>(data, dataSize); 699 uint32 cpuStateSize = _ReadValue<uint32>(data, dataSize); 700 701 if (cpuStateSize > 1024 * 1024) { 702 WARNING("Threads note: unreasonable CPU state size: %" B_PRIu32 "\n", 703 cpuStateSize); 704 return B_BAD_DATA; 705 } 706 707 typedef typename ElfClass::NoteThreadEntry Entry; 708 709 if (threadCount == 0) 710 return B_OK; 711 712 size_t totalEntrySize = entrySize + cpuStateSize; 713 714 // check entry size and thread count 715 if (entrySize == 0 || dataSize == 0 || threadCount > dataSize 716 || entrySize > dataSize || cpuStateSize > dataSize 717 || dataSize - 1 < totalEntrySize 718 || threadCount * totalEntrySize >= dataSize) { 719 WARNING("Threads note: too short or invalid entry size (%" B_PRIu32 720 ")\n", entrySize); 721 return B_BAD_DATA; 722 } 723 724 // check, if strings are null-terminated 725 const char* strings = (const char*)data + threadCount * totalEntrySize; 726 size_t stringsSize = dataSize - threadCount * totalEntrySize; 727 if (stringsSize == 0 || strings[stringsSize - 1] != '\0') { 728 WARNING("Threads note strings not terminated\n"); 729 return B_BAD_DATA; 730 } 731 732 for (uint64 i = 0; i < threadCount; i++) { 733 // get entry values 734 Entry entry = {}; 735 _ReadEntry(data, dataSize, entry, entrySize); 736 737 int32 id = Get(entry.nth_id); 738 int32 state = Get(entry.nth_state); 739 int32 priority = Get(entry.nth_priority); 740 uint64 stackBase = Get(entry.nth_stack_base); 741 uint64 stackEnd = Get(entry.nth_stack_end); 742 743 // get name 744 if (stringsSize == 0) { 745 WARNING("Thread %" B_PRIu64 " (ID %#" B_PRIx32 ") has no name\n", 746 i, id); 747 continue; 748 } 749 const char* name = strings; 750 size_t nameSize = strlen(name) + 1; 751 strings += nameSize; 752 stringsSize -= nameSize; 753 754 BString copiedName(name); 755 if (name[0] != '\0' && copiedName.Length() == 0) 756 return B_NO_MEMORY; 757 758 // create and add thread 759 CoreFileThreadInfo* thread = new(std::nothrow) CoreFileThreadInfo(id, 760 state, priority, stackBase, stackEnd, copiedName); 761 if (thread == NULL || !fThreadInfos.AddItem(thread)) { 762 delete thread; 763 return B_NO_MEMORY; 764 } 765 766 // get CPU state 767 if (!thread->SetCpuState(data, cpuStateSize)) 768 return B_NO_MEMORY; 769 _Advance(data, dataSize, cpuStateSize); 770 } 771 772 return B_OK; 773 } 774 775 776 CoreFileAreaInfo* 777 CoreFile::_FindArea(uint64 address) const 778 { 779 int32 count = fAreaInfos.CountItems(); 780 for (int32 i = 0; i < count; i++) { 781 CoreFileAreaInfo* area = fAreaInfos.ItemAt(i); 782 if (address >= area->BaseAddress() 783 && address < area->EndAddress()) { 784 return area; 785 } 786 } 787 788 return NULL; 789 } 790 791 792 ElfSegment* 793 CoreFile::_FindAreaSegment(uint64 address) const 794 { 795 int32 count = fElfFile.CountSegments(); 796 for (int32 i = 0; i < count; i++) { 797 ElfSegment* segment = fElfFile.SegmentAt(i); 798 if (segment->Type() == PT_LOAD && segment->LoadAddress() == address) 799 return segment; 800 } 801 802 return NULL; 803 } 804 805 806 CoreFileImageInfo* 807 CoreFile::_ImageInfoForId(int32 id) const 808 { 809 int32 count = fImageInfos.CountItems(); 810 for (int32 i = 0; i < count; i++) { 811 CoreFileImageInfo* info = fImageInfos.ItemAt(i); 812 if (info->Id() == id) 813 return info; 814 } 815 816 return NULL; 817 } 818 819 820 template<typename Type> 821 Type 822 CoreFile::_ReadValue(const void*& data, uint32& dataSize) 823 { 824 Type value = Get(*(const Type*)data); 825 _Advance(data, dataSize, sizeof(Type)); 826 return value; 827 } 828 829 830 template<typename Entry> 831 void 832 CoreFile::_ReadEntry(const void*& data, uint32& dataSize, Entry& entry, 833 size_t entrySize) 834 { 835 memcpy(&entry, data, std::min(sizeof(entry), entrySize)); 836 _Advance(data, dataSize, entrySize); 837 } 838 839 840 void 841 CoreFile::_Advance(const void*& data, uint32& dataSize, size_t by) 842 { 843 data = (const uint8*)data + by; 844 dataSize -= by; 845 } 846