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