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