ProcessElfCore.cpp revision 341825
1//===-- ProcessElfCore.cpp --------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10// C Includes 11#include <stdlib.h> 12 13// C++ Includes 14#include <mutex> 15 16// Other libraries and framework includes 17#include "lldb/Core/Module.h" 18#include "lldb/Core/ModuleSpec.h" 19#include "lldb/Core/PluginManager.h" 20#include "lldb/Core/Section.h" 21#include "lldb/Core/State.h" 22#include "lldb/Target/DynamicLoader.h" 23#include "lldb/Target/MemoryRegionInfo.h" 24#include "lldb/Target/Target.h" 25#include "lldb/Target/UnixSignals.h" 26#include "lldb/Utility/DataBufferHeap.h" 27#include "lldb/Utility/DataBufferLLVM.h" 28#include "lldb/Utility/Log.h" 29 30#include "llvm/BinaryFormat/ELF.h" 31#include "llvm/Support/Threading.h" 32 33#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" 34#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" 35#include "Plugins/Process/elf-core/RegisterUtilities.h" 36#include "ProcessElfCore.h" 37#include "ThreadElfCore.h" 38 39using namespace lldb_private; 40 41ConstString ProcessElfCore::GetPluginNameStatic() { 42 static ConstString g_name("elf-core"); 43 return g_name; 44} 45 46const char *ProcessElfCore::GetPluginDescriptionStatic() { 47 return "ELF core dump plug-in."; 48} 49 50void ProcessElfCore::Terminate() { 51 PluginManager::UnregisterPlugin(ProcessElfCore::CreateInstance); 52} 53 54lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp, 55 lldb::ListenerSP listener_sp, 56 const FileSpec *crash_file) { 57 lldb::ProcessSP process_sp; 58 if (crash_file) { 59 // Read enough data for a ELF32 header or ELF64 header Note: Here we care 60 // about e_type field only, so it is safe to ignore possible presence of 61 // the header extension. 62 const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); 63 64 auto data_sp = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), 65 header_size, 0); 66 if (data_sp && data_sp->GetByteSize() == header_size && 67 elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) { 68 elf::ELFHeader elf_header; 69 DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); 70 lldb::offset_t data_offset = 0; 71 if (elf_header.Parse(data, &data_offset)) { 72 if (elf_header.e_type == llvm::ELF::ET_CORE) 73 process_sp.reset( 74 new ProcessElfCore(target_sp, listener_sp, *crash_file)); 75 } 76 } 77 } 78 return process_sp; 79} 80 81bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp, 82 bool plugin_specified_by_name) { 83 // For now we are just making sure the file exists for a given module 84 if (!m_core_module_sp && m_core_file.Exists()) { 85 ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture()); 86 Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp, 87 NULL, NULL, NULL)); 88 if (m_core_module_sp) { 89 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); 90 if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile) 91 return true; 92 } 93 } 94 return false; 95} 96 97//---------------------------------------------------------------------- 98// ProcessElfCore constructor 99//---------------------------------------------------------------------- 100ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, 101 lldb::ListenerSP listener_sp, 102 const FileSpec &core_file) 103 : Process(target_sp, listener_sp), m_core_file(core_file) {} 104 105//---------------------------------------------------------------------- 106// Destructor 107//---------------------------------------------------------------------- 108ProcessElfCore::~ProcessElfCore() { 109 Clear(); 110 // We need to call finalize on the process before destroying ourselves to 111 // make sure all of the broadcaster cleanup goes as planned. If we destruct 112 // this class, then Process::~Process() might have problems trying to fully 113 // destroy the broadcaster. 114 Finalize(); 115} 116 117//---------------------------------------------------------------------- 118// PluginInterface 119//---------------------------------------------------------------------- 120ConstString ProcessElfCore::GetPluginName() { return GetPluginNameStatic(); } 121 122uint32_t ProcessElfCore::GetPluginVersion() { return 1; } 123 124lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment( 125 const elf::ELFProgramHeader *header) { 126 const lldb::addr_t addr = header->p_vaddr; 127 FileRange file_range(header->p_offset, header->p_filesz); 128 VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range); 129 130 VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); 131 if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && 132 last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() && 133 last_entry->GetByteSize() == last_entry->data.GetByteSize()) { 134 last_entry->SetRangeEnd(range_entry.GetRangeEnd()); 135 last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); 136 } else { 137 m_core_aranges.Append(range_entry); 138 } 139 140 // Keep a separate map of permissions that that isn't coalesced so all ranges 141 // are maintained. 142 const uint32_t permissions = 143 ((header->p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) | 144 ((header->p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) | 145 ((header->p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u); 146 147 m_core_range_infos.Append( 148 VMRangeToPermissions::Entry(addr, header->p_memsz, permissions)); 149 150 return addr; 151} 152 153//---------------------------------------------------------------------- 154// Process Control 155//---------------------------------------------------------------------- 156Status ProcessElfCore::DoLoadCore() { 157 Status error; 158 if (!m_core_module_sp) { 159 error.SetErrorString("invalid core module"); 160 return error; 161 } 162 163 ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); 164 if (core == NULL) { 165 error.SetErrorString("invalid core object file"); 166 return error; 167 } 168 169 const uint32_t num_segments = core->GetProgramHeaderCount(); 170 if (num_segments == 0) { 171 error.SetErrorString("core file has no segments"); 172 return error; 173 } 174 175 SetCanJIT(false); 176 177 m_thread_data_valid = true; 178 179 bool ranges_are_sorted = true; 180 lldb::addr_t vm_addr = 0; 181 /// Walk through segments and Thread and Address Map information. 182 /// PT_NOTE - Contains Thread and Register information 183 /// PT_LOAD - Contains a contiguous range of Process Address Space 184 for (uint32_t i = 1; i <= num_segments; i++) { 185 const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i); 186 assert(header != NULL); 187 188 DataExtractor data = core->GetSegmentDataByIndex(i); 189 190 // Parse thread contexts and auxv structure 191 if (header->p_type == llvm::ELF::PT_NOTE) { 192 if (llvm::Error error = ParseThreadContextsFromNoteSegment(header, data)) 193 return Status(std::move(error)); 194 } 195 // PT_LOAD segments contains address map 196 if (header->p_type == llvm::ELF::PT_LOAD) { 197 lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header); 198 if (vm_addr > last_addr) 199 ranges_are_sorted = false; 200 vm_addr = last_addr; 201 } 202 } 203 204 if (!ranges_are_sorted) { 205 m_core_aranges.Sort(); 206 m_core_range_infos.Sort(); 207 } 208 209 // Even if the architecture is set in the target, we need to override it to 210 // match the core file which is always single arch. 211 ArchSpec arch(m_core_module_sp->GetArchitecture()); 212 213 ArchSpec target_arch = GetTarget().GetArchitecture(); 214 ArchSpec core_arch(m_core_module_sp->GetArchitecture()); 215 target_arch.MergeFrom(core_arch); 216 GetTarget().SetArchitecture(target_arch); 217 218 SetUnixSignals(UnixSignals::Create(GetArchitecture())); 219 220 // Ensure we found at least one thread that was stopped on a signal. 221 bool siginfo_signal_found = false; 222 bool prstatus_signal_found = false; 223 // Check we found a signal in a SIGINFO note. 224 for (const auto &thread_data : m_thread_data) { 225 if (thread_data.signo != 0) 226 siginfo_signal_found = true; 227 if (thread_data.prstatus_sig != 0) 228 prstatus_signal_found = true; 229 } 230 if (!siginfo_signal_found) { 231 // If we don't have signal from SIGINFO use the signal from each threads 232 // PRSTATUS note. 233 if (prstatus_signal_found) { 234 for (auto &thread_data : m_thread_data) 235 thread_data.signo = thread_data.prstatus_sig; 236 } else if (m_thread_data.size() > 0) { 237 // If all else fails force the first thread to be SIGSTOP 238 m_thread_data.begin()->signo = 239 GetUnixSignals()->GetSignalNumberFromName("SIGSTOP"); 240 } 241 } 242 243 // Core files are useless without the main executable. See if we can locate 244 // the main executable using data we found in the core file notes. 245 lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); 246 if (!exe_module_sp) { 247 // The first entry in the NT_FILE might be our executable 248 if (!m_nt_file_entries.empty()) { 249 ModuleSpec exe_module_spec; 250 exe_module_spec.GetArchitecture() = arch; 251 exe_module_spec.GetFileSpec().SetFile( 252 m_nt_file_entries[0].path.GetCString(), false, 253 FileSpec::Style::native); 254 if (exe_module_spec.GetFileSpec()) { 255 exe_module_sp = GetTarget().GetSharedModule(exe_module_spec); 256 if (exe_module_sp) 257 GetTarget().SetExecutableModule(exe_module_sp, false); 258 } 259 } 260 } 261 return error; 262} 263 264lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() { 265 if (m_dyld_ap.get() == NULL) 266 m_dyld_ap.reset(DynamicLoader::FindPlugin( 267 this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic().GetCString())); 268 return m_dyld_ap.get(); 269} 270 271bool ProcessElfCore::UpdateThreadList(ThreadList &old_thread_list, 272 ThreadList &new_thread_list) { 273 const uint32_t num_threads = GetNumThreadContexts(); 274 if (!m_thread_data_valid) 275 return false; 276 277 for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { 278 const ThreadData &td = m_thread_data[tid]; 279 lldb::ThreadSP thread_sp(new ThreadElfCore(*this, td)); 280 new_thread_list.AddThread(thread_sp); 281 } 282 return new_thread_list.GetSize(false) > 0; 283} 284 285void ProcessElfCore::RefreshStateAfterStop() {} 286 287Status ProcessElfCore::DoDestroy() { return Status(); } 288 289//------------------------------------------------------------------ 290// Process Queries 291//------------------------------------------------------------------ 292 293bool ProcessElfCore::IsAlive() { return true; } 294 295//------------------------------------------------------------------ 296// Process Memory 297//------------------------------------------------------------------ 298size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size, 299 Status &error) { 300 // Don't allow the caching that lldb_private::Process::ReadMemory does since 301 // in core files we have it all cached our our core file anyway. 302 return DoReadMemory(addr, buf, size, error); 303} 304 305Status ProcessElfCore::GetMemoryRegionInfo(lldb::addr_t load_addr, 306 MemoryRegionInfo ®ion_info) { 307 region_info.Clear(); 308 const VMRangeToPermissions::Entry *permission_entry = 309 m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); 310 if (permission_entry) { 311 if (permission_entry->Contains(load_addr)) { 312 region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); 313 region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); 314 const Flags permissions(permission_entry->data); 315 region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable) 316 ? MemoryRegionInfo::eYes 317 : MemoryRegionInfo::eNo); 318 region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable) 319 ? MemoryRegionInfo::eYes 320 : MemoryRegionInfo::eNo); 321 region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable) 322 ? MemoryRegionInfo::eYes 323 : MemoryRegionInfo::eNo); 324 region_info.SetMapped(MemoryRegionInfo::eYes); 325 } else if (load_addr < permission_entry->GetRangeBase()) { 326 region_info.GetRange().SetRangeBase(load_addr); 327 region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); 328 region_info.SetReadable(MemoryRegionInfo::eNo); 329 region_info.SetWritable(MemoryRegionInfo::eNo); 330 region_info.SetExecutable(MemoryRegionInfo::eNo); 331 region_info.SetMapped(MemoryRegionInfo::eNo); 332 } 333 return Status(); 334 } 335 336 region_info.GetRange().SetRangeBase(load_addr); 337 region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); 338 region_info.SetReadable(MemoryRegionInfo::eNo); 339 region_info.SetWritable(MemoryRegionInfo::eNo); 340 region_info.SetExecutable(MemoryRegionInfo::eNo); 341 region_info.SetMapped(MemoryRegionInfo::eNo); 342 return Status(); 343} 344 345size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 346 Status &error) { 347 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); 348 349 if (core_objfile == NULL) 350 return 0; 351 352 // Get the address range 353 const VMRangeToFileOffset::Entry *address_range = 354 m_core_aranges.FindEntryThatContains(addr); 355 if (address_range == NULL || address_range->GetRangeEnd() < addr) { 356 error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64, 357 addr); 358 return 0; 359 } 360 361 // Convert the address into core file offset 362 const lldb::addr_t offset = addr - address_range->GetRangeBase(); 363 const lldb::addr_t file_start = address_range->data.GetRangeBase(); 364 const lldb::addr_t file_end = address_range->data.GetRangeEnd(); 365 size_t bytes_to_read = size; // Number of bytes to read from the core file 366 size_t bytes_copied = 0; // Number of bytes actually read from the core file 367 size_t zero_fill_size = 0; // Padding 368 lldb::addr_t bytes_left = 369 0; // Number of bytes available in the core file from the given address 370 371 // Don't proceed if core file doesn't contain the actual data for this 372 // address range. 373 if (file_start == file_end) 374 return 0; 375 376 // Figure out how many on-disk bytes remain in this segment starting at the 377 // given offset 378 if (file_end > file_start + offset) 379 bytes_left = file_end - (file_start + offset); 380 381 // Figure out how many bytes we need to zero-fill if we are reading more 382 // bytes than available in the on-disk segment 383 if (bytes_to_read > bytes_left) { 384 zero_fill_size = bytes_to_read - bytes_left; 385 bytes_to_read = bytes_left; 386 } 387 388 // If there is data available on the core file read it 389 if (bytes_to_read) 390 bytes_copied = 391 core_objfile->CopyData(offset + file_start, bytes_to_read, buf); 392 393 assert(zero_fill_size <= size); 394 // Pad remaining bytes 395 if (zero_fill_size) 396 memset(((char *)buf) + bytes_copied, 0, zero_fill_size); 397 398 return bytes_copied + zero_fill_size; 399} 400 401void ProcessElfCore::Clear() { 402 m_thread_list.Clear(); 403 404 SetUnixSignals(std::make_shared<UnixSignals>()); 405} 406 407void ProcessElfCore::Initialize() { 408 static llvm::once_flag g_once_flag; 409 410 llvm::call_once(g_once_flag, []() { 411 PluginManager::RegisterPlugin(GetPluginNameStatic(), 412 GetPluginDescriptionStatic(), CreateInstance); 413 }); 414} 415 416lldb::addr_t ProcessElfCore::GetImageInfoAddress() { 417 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); 418 Address addr = obj_file->GetImageInfoAddress(&GetTarget()); 419 420 if (addr.IsValid()) 421 return addr.GetLoadAddress(&GetTarget()); 422 return LLDB_INVALID_ADDRESS; 423} 424 425// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. 426static void ParseFreeBSDPrStatus(ThreadData &thread_data, 427 const DataExtractor &data, 428 const ArchSpec &arch) { 429 lldb::offset_t offset = 0; 430 bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || 431 arch.GetMachine() == llvm::Triple::mips64 || 432 arch.GetMachine() == llvm::Triple::ppc64 || 433 arch.GetMachine() == llvm::Triple::x86_64); 434 int pr_version = data.GetU32(&offset); 435 436 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 437 if (log) { 438 if (pr_version > 1) 439 log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); 440 } 441 442 // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate 443 if (lp64) 444 offset += 32; 445 else 446 offset += 16; 447 448 thread_data.signo = data.GetU32(&offset); // pr_cursig 449 thread_data.tid = data.GetU32(&offset); // pr_pid 450 if (lp64) 451 offset += 4; 452 453 size_t len = data.GetByteSize() - offset; 454 thread_data.gpregset = DataExtractor(data, offset, len); 455} 456 457static void ParseNetBSDProcInfo(ThreadData &thread_data, 458 const DataExtractor &data) { 459 lldb::offset_t offset = 0; 460 461 int version = data.GetU32(&offset); 462 if (version != 1) 463 return; 464 465 offset += 4; 466 thread_data.signo = data.GetU32(&offset); 467} 468 469static void ParseOpenBSDProcInfo(ThreadData &thread_data, 470 const DataExtractor &data) { 471 lldb::offset_t offset = 0; 472 473 int version = data.GetU32(&offset); 474 if (version != 1) 475 return; 476 477 offset += 4; 478 thread_data.signo = data.GetU32(&offset); 479} 480 481llvm::Expected<std::vector<CoreNote>> 482ProcessElfCore::parseSegment(const DataExtractor &segment) { 483 lldb::offset_t offset = 0; 484 std::vector<CoreNote> result; 485 486 while (offset < segment.GetByteSize()) { 487 ELFNote note = ELFNote(); 488 if (!note.Parse(segment, &offset)) 489 return llvm::make_error<llvm::StringError>( 490 "Unable to parse note segment", llvm::inconvertibleErrorCode()); 491 492 size_t note_start = offset; 493 size_t note_size = llvm::alignTo(note.n_descsz, 4); 494 DataExtractor note_data(segment, note_start, note_size); 495 496 result.push_back({note, note_data}); 497 offset += note_size; 498 } 499 500 return std::move(result); 501} 502 503llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { 504 bool have_prstatus = false; 505 bool have_prpsinfo = false; 506 ThreadData thread_data; 507 for (const auto ¬e : notes) { 508 if (note.info.n_name != "FreeBSD") 509 continue; 510 511 if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) || 512 (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) { 513 assert(thread_data.gpregset.GetByteSize() > 0); 514 // Add the new thread to thread list 515 m_thread_data.push_back(thread_data); 516 thread_data = ThreadData(); 517 have_prstatus = false; 518 have_prpsinfo = false; 519 } 520 521 switch (note.info.n_type) { 522 case FREEBSD::NT_PRSTATUS: 523 have_prstatus = true; 524 ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture()); 525 break; 526 case FREEBSD::NT_PRPSINFO: 527 have_prpsinfo = true; 528 break; 529 case FREEBSD::NT_THRMISC: { 530 lldb::offset_t offset = 0; 531 thread_data.name = note.data.GetCStr(&offset, 20); 532 break; 533 } 534 case FREEBSD::NT_PROCSTAT_AUXV: 535 // FIXME: FreeBSD sticks an int at the beginning of the note 536 m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4); 537 break; 538 default: 539 thread_data.notes.push_back(note); 540 break; 541 } 542 } 543 if (!have_prstatus) { 544 return llvm::make_error<llvm::StringError>( 545 "Could not find NT_PRSTATUS note in core file.", 546 llvm::inconvertibleErrorCode()); 547 } 548 m_thread_data.push_back(thread_data); 549 return llvm::Error::success(); 550} 551 552llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) { 553 ThreadData thread_data; 554 for (const auto ¬e : notes) { 555 // NetBSD per-thread information is stored in notes named "NetBSD-CORE@nnn" 556 // so match on the initial part of the string. 557 if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE")) 558 continue; 559 560 switch (note.info.n_type) { 561 case NETBSD::NT_PROCINFO: 562 ParseNetBSDProcInfo(thread_data, note.data); 563 break; 564 case NETBSD::NT_AUXV: 565 m_auxv = note.data; 566 break; 567 568 case NETBSD::NT_AMD64_REGS: 569 if (GetArchitecture().GetMachine() == llvm::Triple::x86_64) 570 thread_data.gpregset = note.data; 571 break; 572 default: 573 thread_data.notes.push_back(note); 574 break; 575 } 576 } 577 if (thread_data.gpregset.GetByteSize() == 0) { 578 return llvm::make_error<llvm::StringError>( 579 "Could not find general purpose registers note in core file.", 580 llvm::inconvertibleErrorCode()); 581 } 582 m_thread_data.push_back(thread_data); 583 return llvm::Error::success(); 584} 585 586llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) { 587 ThreadData thread_data; 588 for (const auto ¬e : notes) { 589 // OpenBSD per-thread information is stored in notes named "OpenBSD@nnn" so 590 // match on the initial part of the string. 591 if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD")) 592 continue; 593 594 switch (note.info.n_type) { 595 case OPENBSD::NT_PROCINFO: 596 ParseOpenBSDProcInfo(thread_data, note.data); 597 break; 598 case OPENBSD::NT_AUXV: 599 m_auxv = note.data; 600 break; 601 case OPENBSD::NT_REGS: 602 thread_data.gpregset = note.data; 603 break; 604 default: 605 thread_data.notes.push_back(note); 606 break; 607 } 608 } 609 if (thread_data.gpregset.GetByteSize() == 0) { 610 return llvm::make_error<llvm::StringError>( 611 "Could not find general purpose registers note in core file.", 612 llvm::inconvertibleErrorCode()); 613 } 614 m_thread_data.push_back(thread_data); 615 return llvm::Error::success(); 616} 617 618/// A description of a linux process usually contains the following NOTE 619/// entries: 620/// - NT_PRPSINFO - General process information like pid, uid, name, ... 621/// - NT_SIGINFO - Information about the signal that terminated the process 622/// - NT_AUXV - Process auxiliary vector 623/// - NT_FILE - Files mapped into memory 624/// 625/// Additionally, for each thread in the process the core file will contain at 626/// least the NT_PRSTATUS note, containing the thread id and general purpose 627/// registers. It may include additional notes for other register sets (floating 628/// point and vector registers, ...). The tricky part here is that some of these 629/// notes have "CORE" in their owner fields, while other set it to "LINUX". 630llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { 631 const ArchSpec &arch = GetArchitecture(); 632 bool have_prstatus = false; 633 bool have_prpsinfo = false; 634 ThreadData thread_data; 635 for (const auto ¬e : notes) { 636 if (note.info.n_name != "CORE" && note.info.n_name != "LINUX") 637 continue; 638 639 if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) || 640 (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) { 641 assert(thread_data.gpregset.GetByteSize() > 0); 642 // Add the new thread to thread list 643 m_thread_data.push_back(thread_data); 644 thread_data = ThreadData(); 645 have_prstatus = false; 646 have_prpsinfo = false; 647 } 648 649 switch (note.info.n_type) { 650 case LINUX::NT_PRSTATUS: { 651 have_prstatus = true; 652 ELFLinuxPrStatus prstatus; 653 Status status = prstatus.Parse(note.data, arch); 654 if (status.Fail()) 655 return status.ToError(); 656 thread_data.prstatus_sig = prstatus.pr_cursig; 657 thread_data.tid = prstatus.pr_pid; 658 uint32_t header_size = ELFLinuxPrStatus::GetSize(arch); 659 size_t len = note.data.GetByteSize() - header_size; 660 thread_data.gpregset = DataExtractor(note.data, header_size, len); 661 break; 662 } 663 case LINUX::NT_PRPSINFO: { 664 have_prpsinfo = true; 665 ELFLinuxPrPsInfo prpsinfo; 666 Status status = prpsinfo.Parse(note.data, arch); 667 if (status.Fail()) 668 return status.ToError(); 669 thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname))); 670 SetID(prpsinfo.pr_pid); 671 break; 672 } 673 case LINUX::NT_SIGINFO: { 674 ELFLinuxSigInfo siginfo; 675 Status status = siginfo.Parse(note.data, arch); 676 if (status.Fail()) 677 return status.ToError(); 678 thread_data.signo = siginfo.si_signo; 679 break; 680 } 681 case LINUX::NT_FILE: { 682 m_nt_file_entries.clear(); 683 lldb::offset_t offset = 0; 684 const uint64_t count = note.data.GetAddress(&offset); 685 note.data.GetAddress(&offset); // Skip page size 686 for (uint64_t i = 0; i < count; ++i) { 687 NT_FILE_Entry entry; 688 entry.start = note.data.GetAddress(&offset); 689 entry.end = note.data.GetAddress(&offset); 690 entry.file_ofs = note.data.GetAddress(&offset); 691 m_nt_file_entries.push_back(entry); 692 } 693 for (uint64_t i = 0; i < count; ++i) { 694 const char *path = note.data.GetCStr(&offset); 695 if (path && path[0]) 696 m_nt_file_entries[i].path.SetCString(path); 697 } 698 break; 699 } 700 case LINUX::NT_AUXV: 701 m_auxv = note.data; 702 break; 703 default: 704 thread_data.notes.push_back(note); 705 break; 706 } 707 } 708 // Add last entry in the note section 709 if (have_prstatus) 710 m_thread_data.push_back(thread_data); 711 return llvm::Error::success(); 712} 713 714/// Parse Thread context from PT_NOTE segment and store it in the thread list 715/// A note segment consists of one or more NOTE entries, but their types and 716/// meaning differ depending on the OS. 717llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment( 718 const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) { 719 assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); 720 721 auto notes_or_error = parseSegment(segment_data); 722 if(!notes_or_error) 723 return notes_or_error.takeError(); 724 switch (GetArchitecture().GetTriple().getOS()) { 725 case llvm::Triple::FreeBSD: 726 return parseFreeBSDNotes(*notes_or_error); 727 case llvm::Triple::Linux: 728 return parseLinuxNotes(*notes_or_error); 729 case llvm::Triple::NetBSD: 730 return parseNetBSDNotes(*notes_or_error); 731 case llvm::Triple::OpenBSD: 732 return parseOpenBSDNotes(*notes_or_error); 733 default: 734 return llvm::make_error<llvm::StringError>( 735 "Don't know how to parse core file. Unsupported OS.", 736 llvm::inconvertibleErrorCode()); 737 } 738} 739 740uint32_t ProcessElfCore::GetNumThreadContexts() { 741 if (!m_thread_data_valid) 742 DoLoadCore(); 743 return m_thread_data.size(); 744} 745 746ArchSpec ProcessElfCore::GetArchitecture() { 747 ArchSpec arch; 748 m_core_module_sp->GetObjectFile()->GetArchitecture(arch); 749 750 ArchSpec target_arch = GetTarget().GetArchitecture(); 751 arch.MergeFrom(target_arch); 752 753 // On MIPS there is no way to differentiate betwenn 32bit and 64bit core 754 // files and this information can't be merged in from the target arch so we 755 // fail back to unconditionally returning the target arch in this config. 756 if (target_arch.IsMIPS()) { 757 return target_arch; 758 } 759 760 return arch; 761} 762 763const lldb::DataBufferSP ProcessElfCore::GetAuxvData() { 764 const uint8_t *start = m_auxv.GetDataStart(); 765 size_t len = m_auxv.GetByteSize(); 766 lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len)); 767 return buffer; 768} 769 770bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) { 771 info.Clear(); 772 info.SetProcessID(GetID()); 773 info.SetArchitecture(GetArchitecture()); 774 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 775 if (module_sp) { 776 const bool add_exe_file_as_first_arg = false; 777 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 778 add_exe_file_as_first_arg); 779 } 780 return true; 781} 782