ProcessElfCore.cpp revision 327952
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 60 // Note: Here we care about e_type field only, so it is safe 61 // to ignore possible presence of 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 111 // to make sure all of the broadcaster cleanup goes as planned. If we 112 // destruct this class, then Process::~Process() might have problems 113 // trying to fully 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 210 // it to 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 245 // executable using data we found in the core file notes. 246 lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); 247 if (!exe_module_sp) { 248 // The first entry in the NT_FILE might be our executable 249 if (!m_nt_file_entries.empty()) { 250 ModuleSpec exe_module_spec; 251 exe_module_spec.GetArchitecture() = arch; 252 exe_module_spec.GetFileSpec().SetFile( 253 m_nt_file_entries[0].path.GetCString(), false); 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 301 // since 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 address range. 372 if (file_start == file_end) 373 return 0; 374 375 // Figure out how many on-disk bytes remain in this segment 376 // starting at the given offset 377 if (file_end > file_start + offset) 378 bytes_left = file_end - (file_start + offset); 379 380 // Figure out how many bytes we need to zero-fill if we are 381 // reading more bytes than available in the on-disk segment 382 if (bytes_to_read > bytes_left) { 383 zero_fill_size = bytes_to_read - bytes_left; 384 bytes_to_read = bytes_left; 385 } 386 387 // If there is data available on the core file read it 388 if (bytes_to_read) 389 bytes_copied = 390 core_objfile->CopyData(offset + file_start, bytes_to_read, buf); 391 392 assert(zero_fill_size <= size); 393 // Pad remaining bytes 394 if (zero_fill_size) 395 memset(((char *)buf) + bytes_copied, 0, zero_fill_size); 396 397 return bytes_copied + zero_fill_size; 398} 399 400void ProcessElfCore::Clear() { 401 m_thread_list.Clear(); 402 403 SetUnixSignals(std::make_shared<UnixSignals>()); 404} 405 406void ProcessElfCore::Initialize() { 407 static llvm::once_flag g_once_flag; 408 409 llvm::call_once(g_once_flag, []() { 410 PluginManager::RegisterPlugin(GetPluginNameStatic(), 411 GetPluginDescriptionStatic(), CreateInstance); 412 }); 413} 414 415lldb::addr_t ProcessElfCore::GetImageInfoAddress() { 416 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); 417 Address addr = obj_file->GetImageInfoAddress(&GetTarget()); 418 419 if (addr.IsValid()) 420 return addr.GetLoadAddress(&GetTarget()); 421 return LLDB_INVALID_ADDRESS; 422} 423 424// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. 425static void ParseFreeBSDPrStatus(ThreadData &thread_data, 426 const DataExtractor &data, 427 const ArchSpec &arch) { 428 lldb::offset_t offset = 0; 429 bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || 430 arch.GetMachine() == llvm::Triple::mips64 || 431 arch.GetMachine() == llvm::Triple::ppc64 || 432 arch.GetMachine() == llvm::Triple::x86_64); 433 int pr_version = data.GetU32(&offset); 434 435 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 436 if (log) { 437 if (pr_version > 1) 438 log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); 439 } 440 441 // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate 442 if (lp64) 443 offset += 32; 444 else 445 offset += 16; 446 447 thread_data.signo = data.GetU32(&offset); // pr_cursig 448 thread_data.tid = data.GetU32(&offset); // pr_pid 449 if (lp64) 450 offset += 4; 451 452 size_t len = data.GetByteSize() - offset; 453 thread_data.gpregset = DataExtractor(data, offset, len); 454} 455 456static void ParseNetBSDProcInfo(ThreadData &thread_data, 457 const DataExtractor &data) { 458 lldb::offset_t offset = 0; 459 460 int version = data.GetU32(&offset); 461 if (version != 1) 462 return; 463 464 offset += 4; 465 thread_data.signo = data.GetU32(&offset); 466} 467 468static void ParseOpenBSDProcInfo(ThreadData &thread_data, 469 const DataExtractor &data) { 470 lldb::offset_t offset = 0; 471 472 int version = data.GetU32(&offset); 473 if (version != 1) 474 return; 475 476 offset += 4; 477 thread_data.signo = data.GetU32(&offset); 478} 479 480llvm::Expected<std::vector<CoreNote>> 481ProcessElfCore::parseSegment(const DataExtractor &segment) { 482 lldb::offset_t offset = 0; 483 std::vector<CoreNote> result; 484 485 while (offset < segment.GetByteSize()) { 486 ELFNote note = ELFNote(); 487 if (!note.Parse(segment, &offset)) 488 return llvm::make_error<llvm::StringError>( 489 "Unable to parse note segment", llvm::inconvertibleErrorCode()); 490 491 size_t note_start = offset; 492 size_t note_size = llvm::alignTo(note.n_descsz, 4); 493 DataExtractor note_data(segment, note_start, note_size); 494 495 result.push_back({note, note_data}); 496 offset += note_size; 497 } 498 499 return std::move(result); 500} 501 502llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { 503 bool have_prstatus = false; 504 bool have_prpsinfo = false; 505 ThreadData thread_data; 506 for (const auto ¬e : notes) { 507 if (note.info.n_name != "FreeBSD") 508 continue; 509 510 if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) || 511 (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) { 512 assert(thread_data.gpregset.GetByteSize() > 0); 513 // Add the new thread to thread list 514 m_thread_data.push_back(thread_data); 515 thread_data = ThreadData(); 516 have_prstatus = false; 517 have_prpsinfo = false; 518 } 519 520 switch (note.info.n_type) { 521 case FREEBSD::NT_PRSTATUS: 522 have_prstatus = true; 523 ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture()); 524 break; 525 case FREEBSD::NT_PRPSINFO: 526 have_prpsinfo = true; 527 break; 528 case FREEBSD::NT_THRMISC: { 529 lldb::offset_t offset = 0; 530 thread_data.name = note.data.GetCStr(&offset, 20); 531 break; 532 } 533 case FREEBSD::NT_PROCSTAT_AUXV: 534 // FIXME: FreeBSD sticks an int at the beginning of the note 535 m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4); 536 break; 537 default: 538 thread_data.notes.push_back(note); 539 break; 540 } 541 } 542 if (!have_prstatus) { 543 return llvm::make_error<llvm::StringError>( 544 "Could not find NT_PRSTATUS note in core file.", 545 llvm::inconvertibleErrorCode()); 546 } 547 m_thread_data.push_back(thread_data); 548 return llvm::Error::success(); 549} 550 551llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) { 552 ThreadData thread_data; 553 for (const auto ¬e : notes) { 554 // NetBSD per-thread information is stored in notes named 555 // "NetBSD-CORE@nnn" so match on the initial part of the string. 556 if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE")) 557 continue; 558 559 switch (note.info.n_type) { 560 case NETBSD::NT_PROCINFO: 561 ParseNetBSDProcInfo(thread_data, note.data); 562 break; 563 case NETBSD::NT_AUXV: 564 m_auxv = note.data; 565 break; 566 567 case NETBSD::NT_AMD64_REGS: 568 if (GetArchitecture().GetMachine() == llvm::Triple::x86_64) 569 thread_data.gpregset = note.data; 570 break; 571 default: 572 thread_data.notes.push_back(note); 573 break; 574 } 575 } 576 if (thread_data.gpregset.GetByteSize() == 0) { 577 return llvm::make_error<llvm::StringError>( 578 "Could not find general purpose registers note in core file.", 579 llvm::inconvertibleErrorCode()); 580 } 581 m_thread_data.push_back(thread_data); 582 return llvm::Error::success(); 583} 584 585llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) { 586 ThreadData thread_data; 587 for (const auto ¬e : notes) { 588 // OpenBSD per-thread information is stored in notes named 589 // "OpenBSD@nnn" so match on the initial part of the string. 590 if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD")) 591 continue; 592 593 switch (note.info.n_type) { 594 case OPENBSD::NT_PROCINFO: 595 ParseOpenBSDProcInfo(thread_data, note.data); 596 break; 597 case OPENBSD::NT_AUXV: 598 m_auxv = note.data; 599 break; 600 case OPENBSD::NT_REGS: 601 thread_data.gpregset = note.data; 602 break; 603 default: 604 thread_data.notes.push_back(note); 605 break; 606 } 607 } 608 if (thread_data.gpregset.GetByteSize() == 0) { 609 return llvm::make_error<llvm::StringError>( 610 "Could not find general purpose registers note in core file.", 611 llvm::inconvertibleErrorCode()); 612 } 613 m_thread_data.push_back(thread_data); 614 return llvm::Error::success(); 615} 616 617/// A description of a linux process usually contains the following NOTE 618/// entries: 619/// - NT_PRPSINFO - General process information like pid, uid, name, ... 620/// - NT_SIGINFO - Information about the signal that terminated the process 621/// - NT_AUXV - Process auxiliary vector 622/// - NT_FILE - Files mapped into memory 623/// 624/// Additionally, for each thread in the process the core file will contain at 625/// least the NT_PRSTATUS note, containing the thread id and general purpose 626/// registers. It may include additional notes for other register sets (floating 627/// point and vector registers, ...). The tricky part here is that some of these 628/// notes have "CORE" in their owner fields, while other set it to "LINUX". 629llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { 630 const ArchSpec &arch = GetArchitecture(); 631 bool have_prstatus = false; 632 bool have_prpsinfo = false; 633 ThreadData thread_data; 634 for (const auto ¬e : notes) { 635 if (note.info.n_name != "CORE" && note.info.n_name != "LINUX") 636 continue; 637 638 if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) || 639 (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) { 640 assert(thread_data.gpregset.GetByteSize() > 0); 641 // Add the new thread to thread list 642 m_thread_data.push_back(thread_data); 643 thread_data = ThreadData(); 644 have_prstatus = false; 645 have_prpsinfo = false; 646 } 647 648 switch (note.info.n_type) { 649 case LINUX::NT_PRSTATUS: { 650 have_prstatus = true; 651 ELFLinuxPrStatus prstatus; 652 Status status = prstatus.Parse(note.data, arch); 653 if (status.Fail()) 654 return status.ToError(); 655 thread_data.prstatus_sig = prstatus.pr_cursig; 656 thread_data.tid = prstatus.pr_pid; 657 uint32_t header_size = ELFLinuxPrStatus::GetSize(arch); 658 size_t len = note.data.GetByteSize() - header_size; 659 thread_data.gpregset = DataExtractor(note.data, header_size, len); 660 break; 661 } 662 case LINUX::NT_PRPSINFO: { 663 have_prpsinfo = true; 664 ELFLinuxPrPsInfo prpsinfo; 665 Status status = prpsinfo.Parse(note.data, arch); 666 if (status.Fail()) 667 return status.ToError(); 668 thread_data.name = prpsinfo.pr_fname; 669 SetID(prpsinfo.pr_pid); 670 break; 671 } 672 case LINUX::NT_SIGINFO: { 673 ELFLinuxSigInfo siginfo; 674 Status status = siginfo.Parse(note.data, arch); 675 if (status.Fail()) 676 return status.ToError(); 677 thread_data.signo = siginfo.si_signo; 678 break; 679 } 680 case LINUX::NT_FILE: { 681 m_nt_file_entries.clear(); 682 lldb::offset_t offset = 0; 683 const uint64_t count = note.data.GetAddress(&offset); 684 note.data.GetAddress(&offset); // Skip page size 685 for (uint64_t i = 0; i < count; ++i) { 686 NT_FILE_Entry entry; 687 entry.start = note.data.GetAddress(&offset); 688 entry.end = note.data.GetAddress(&offset); 689 entry.file_ofs = note.data.GetAddress(&offset); 690 m_nt_file_entries.push_back(entry); 691 } 692 for (uint64_t i = 0; i < count; ++i) { 693 const char *path = note.data.GetCStr(&offset); 694 if (path && path[0]) 695 m_nt_file_entries[i].path.SetCString(path); 696 } 697 break; 698 } 699 case LINUX::NT_AUXV: 700 m_auxv = note.data; 701 break; 702 default: 703 thread_data.notes.push_back(note); 704 break; 705 } 706 } 707 // Add last entry in the note section 708 if (have_prstatus) 709 m_thread_data.push_back(thread_data); 710 return llvm::Error::success(); 711} 712 713/// Parse Thread context from PT_NOTE segment and store it in the thread list 714/// A note segment consists of one or more NOTE entries, but their types and 715/// meaning differ depending on the OS. 716llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment( 717 const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) { 718 assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); 719 720 auto notes_or_error = parseSegment(segment_data); 721 if(!notes_or_error) 722 return notes_or_error.takeError(); 723 switch (GetArchitecture().GetTriple().getOS()) { 724 case llvm::Triple::FreeBSD: 725 return parseFreeBSDNotes(*notes_or_error); 726 case llvm::Triple::Linux: 727 return parseLinuxNotes(*notes_or_error); 728 case llvm::Triple::NetBSD: 729 return parseNetBSDNotes(*notes_or_error); 730 case llvm::Triple::OpenBSD: 731 return parseOpenBSDNotes(*notes_or_error); 732 default: 733 return llvm::make_error<llvm::StringError>( 734 "Don't know how to parse core file. Unsupported OS.", 735 llvm::inconvertibleErrorCode()); 736 } 737} 738 739uint32_t ProcessElfCore::GetNumThreadContexts() { 740 if (!m_thread_data_valid) 741 DoLoadCore(); 742 return m_thread_data.size(); 743} 744 745ArchSpec ProcessElfCore::GetArchitecture() { 746 ArchSpec arch; 747 m_core_module_sp->GetObjectFile()->GetArchitecture(arch); 748 749 ArchSpec target_arch = GetTarget().GetArchitecture(); 750 arch.MergeFrom(target_arch); 751 752 // On MIPS there is no way to differentiate betwenn 32bit and 64bit core files 753 // and this information can't be merged in from the target arch so we fail 754 // back to unconditionally returning the target arch in this config. 755 if (target_arch.IsMIPS()) { 756 return target_arch; 757 } 758 759 return arch; 760} 761 762const lldb::DataBufferSP ProcessElfCore::GetAuxvData() { 763 const uint8_t *start = m_auxv.GetDataStart(); 764 size_t len = m_auxv.GetByteSize(); 765 lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len)); 766 return buffer; 767} 768 769bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) { 770 info.Clear(); 771 info.SetProcessID(GetID()); 772 info.SetArchitecture(GetArchitecture()); 773 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 774 if (module_sp) { 775 const bool add_exe_file_as_first_arg = false; 776 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 777 add_exe_file_as_first_arg); 778 } 779 return true; 780} 781