1147 lines · cpp
1//===-- ProcessElfCore.cpp ------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <cstdlib>10 11#include <memory>12#include <mutex>13 14#include "lldb/Core/Module.h"15#include "lldb/Core/ModuleSpec.h"16#include "lldb/Core/PluginManager.h"17#include "lldb/Core/Section.h"18#include "lldb/Target/ABI.h"19#include "lldb/Target/DynamicLoader.h"20#include "lldb/Target/MemoryRegionInfo.h"21#include "lldb/Target/Target.h"22#include "lldb/Target/UnixSignals.h"23#include "lldb/Utility/DataBufferHeap.h"24#include "lldb/Utility/LLDBLog.h"25#include "lldb/Utility/Log.h"26#include "lldb/Utility/State.h"27 28#include "llvm/BinaryFormat/ELF.h"29#include "llvm/Support/Threading.h"30 31#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"32#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"33#include "Plugins/Process/elf-core/RegisterUtilities.h"34#include "ProcessElfCore.h"35#include "ThreadElfCore.h"36 37using namespace lldb_private;38namespace ELF = llvm::ELF;39 40LLDB_PLUGIN_DEFINE(ProcessElfCore)41 42llvm::StringRef ProcessElfCore::GetPluginDescriptionStatic() {43 return "ELF core dump plug-in.";44}45 46void ProcessElfCore::Terminate() {47 PluginManager::UnregisterPlugin(ProcessElfCore::CreateInstance);48}49 50lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,51 lldb::ListenerSP listener_sp,52 const FileSpec *crash_file,53 bool can_connect) {54 lldb::ProcessSP process_sp;55 if (crash_file && !can_connect) {56 // Read enough data for an ELF32 header or ELF64 header Note: Here we care57 // about e_type field only, so it is safe to ignore possible presence of58 // the header extension.59 const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);60 61 auto data_sp = FileSystem::Instance().CreateDataBuffer(62 crash_file->GetPath(), header_size, 0);63 if (data_sp && data_sp->GetByteSize() == header_size &&64 elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) {65 elf::ELFHeader elf_header;66 DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);67 lldb::offset_t data_offset = 0;68 if (elf_header.Parse(data, &data_offset)) {69 // Check whether we're dealing with a raw FreeBSD "full memory dump"70 // ELF vmcore that needs to be handled via FreeBSDKernel plugin instead.71 if (elf_header.e_ident[7] == 0xFF && elf_header.e_version == 0)72 return process_sp;73 if (elf_header.e_type == llvm::ELF::ET_CORE)74 process_sp = std::make_shared<ProcessElfCore>(target_sp, listener_sp,75 *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 module85 if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {86 ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());87 core_module_spec.SetTarget(target_sp);88 Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,89 nullptr, nullptr));90 if (m_core_module_sp) {91 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();92 if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)93 return true;94 }95 }96 return false;97}98 99// ProcessElfCore constructor100ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,101 lldb::ListenerSP listener_sp,102 const FileSpec &core_file)103 : PostMortemProcess(target_sp, listener_sp, core_file), m_uuids() {}104 105// Destructor106ProcessElfCore::~ProcessElfCore() {107 Clear();108 // We need to call finalize on the process before destroying ourselves to109 // make sure all of the broadcaster cleanup goes as planned. If we destruct110 // this class, then Process::~Process() might have problems trying to fully111 // destroy the broadcaster.112 Finalize(true /* destructing */);113}114 115lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment(116 const elf::ELFProgramHeader &header) {117 const lldb::addr_t addr = header.p_vaddr;118 FileRange file_range(header.p_offset, header.p_filesz);119 VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range);120 121 // Only add to m_core_aranges if the file size is non zero. Some core files122 // have PT_LOAD segments for all address ranges, but set f_filesz to zero for123 // the .text sections since they can be retrieved from the object files.124 if (header.p_filesz > 0) {125 VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();126 if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&127 last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&128 last_entry->GetByteSize() == last_entry->data.GetByteSize()) {129 last_entry->SetRangeEnd(range_entry.GetRangeEnd());130 last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());131 } else {132 m_core_aranges.Append(range_entry);133 }134 }135 // Keep a separate map of permissions that isn't coalesced so all ranges136 // are maintained.137 const uint32_t permissions =138 ((header.p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) |139 ((header.p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) |140 ((header.p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u);141 142 m_core_range_infos.Append(143 VMRangeToPermissions::Entry(addr, header.p_memsz, permissions));144 145 return addr;146}147 148lldb::addr_t ProcessElfCore::AddAddressRangeFromMemoryTagSegment(149 const elf::ELFProgramHeader &header) {150 // If lldb understood multiple kinds of tag segments we would record the type151 // of the segment here also. As long as there is only 1 type lldb looks for,152 // there is no need.153 FileRange file_range(header.p_offset, header.p_filesz);154 m_core_tag_ranges.Append(155 VMRangeToFileOffset::Entry(header.p_vaddr, header.p_memsz, file_range));156 157 return header.p_vaddr;158}159 160// Process Control161Status ProcessElfCore::DoLoadCore() {162 Status error;163 if (!m_core_module_sp) {164 error = Status::FromErrorString("invalid core module");165 return error;166 }167 168 ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());169 if (core == nullptr) {170 error = Status::FromErrorString("invalid core object file");171 return error;172 }173 174 llvm::ArrayRef<elf::ELFProgramHeader> segments = core->ProgramHeaders();175 if (segments.size() == 0) {176 error = Status::FromErrorString("core file has no segments");177 return error;178 }179 180 // Even if the architecture is set in the target, we need to override it to181 // match the core file which is always single arch.182 ArchSpec arch(m_core_module_sp->GetArchitecture());183 184 ArchSpec target_arch = GetTarget().GetArchitecture();185 ArchSpec core_arch(m_core_module_sp->GetArchitecture());186 target_arch.MergeFrom(core_arch);187 GetTarget().SetArchitecture(target_arch, /*set_platform*/ true);188 189 SetUnixSignals(UnixSignals::Create(GetArchitecture()));190 191 SetCanJIT(false);192 193 m_thread_data_valid = true;194 195 bool ranges_are_sorted = true;196 lldb::addr_t vm_addr = 0;197 lldb::addr_t tag_addr = 0;198 /// Walk through segments and Thread and Address Map information.199 /// PT_NOTE - Contains Thread and Register information200 /// PT_LOAD - Contains a contiguous range of Process Address Space201 /// PT_AARCH64_MEMTAG_MTE - Contains AArch64 MTE memory tags for a range of202 /// Process Address Space.203 for (const elf::ELFProgramHeader &H : segments) {204 DataExtractor data = core->GetSegmentData(H);205 206 // Parse thread contexts and auxv structure207 if (H.p_type == llvm::ELF::PT_NOTE) {208 if (llvm::Error error = ParseThreadContextsFromNoteSegment(H, data))209 return Status::FromError(std::move(error));210 }211 // PT_LOAD segments contains address map212 if (H.p_type == llvm::ELF::PT_LOAD) {213 lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(H);214 if (vm_addr > last_addr)215 ranges_are_sorted = false;216 vm_addr = last_addr;217 } else if (H.p_type == llvm::ELF::PT_AARCH64_MEMTAG_MTE) {218 lldb::addr_t last_addr = AddAddressRangeFromMemoryTagSegment(H);219 if (tag_addr > last_addr)220 ranges_are_sorted = false;221 tag_addr = last_addr;222 }223 }224 225 if (!ranges_are_sorted) {226 m_core_aranges.Sort();227 m_core_range_infos.Sort();228 m_core_tag_ranges.Sort();229 }230 231 // Ensure we found at least one thread that was stopped on a signal.232 bool siginfo_signal_found = false;233 bool prstatus_signal_found = false;234 // Check we found a signal in a SIGINFO note.235 for (const auto &thread_data : m_thread_data) {236 if (!thread_data.siginfo_bytes.empty() || thread_data.signo != 0)237 siginfo_signal_found = true;238 if (thread_data.prstatus_sig != 0)239 prstatus_signal_found = true;240 }241 if (!siginfo_signal_found) {242 // If we don't have signal from SIGINFO use the signal from each threads243 // PRSTATUS note.244 if (prstatus_signal_found) {245 for (auto &thread_data : m_thread_data)246 thread_data.signo = thread_data.prstatus_sig;247 } else if (m_thread_data.size() > 0) {248 // If all else fails force the first thread to be SIGSTOP249 m_thread_data.begin()->signo =250 GetUnixSignals()->GetSignalNumberFromName("SIGSTOP");251 }252 }253 254 // Try to find gnu build id before we load the executable.255 UpdateBuildIdForNTFileEntries();256 257 // Core files are useless without the main executable. See if we can locate258 // the main executable using data we found in the core file notes.259 lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();260 if (!exe_module_sp) {261 if (!m_nt_file_entries.empty()) {262 llvm::StringRef executable_path = GetMainExecutablePath();263 ModuleSpec exe_module_spec;264 exe_module_spec.GetArchitecture() = arch;265 exe_module_spec.GetUUID() = FindModuleUUID(executable_path);266 exe_module_spec.GetFileSpec().SetFile(executable_path,267 FileSpec::Style::native);268 if (exe_module_spec.GetFileSpec()) {269 exe_module_sp =270 GetTarget().GetOrCreateModule(exe_module_spec, true /* notify */);271 if (exe_module_sp)272 GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);273 }274 }275 }276 return error;277}278 279void ProcessElfCore::UpdateBuildIdForNTFileEntries() {280 Log *log = GetLog(LLDBLog::Process);281 m_uuids.clear();282 for (NT_FILE_Entry &entry : m_nt_file_entries) {283 UUID uuid = FindBuidIdInCoreMemory(entry.start);284 if (uuid.IsValid()) {285 // Assert that either the path is not in the map or the UUID matches286 assert(m_uuids.count(entry.path) == 0 || m_uuids[entry.path] == uuid);287 m_uuids[entry.path] = uuid;288 if (log)289 LLDB_LOGF(log, "%s found UUID @ %16.16" PRIx64 ": %s \"%s\"",290 __FUNCTION__, entry.start, uuid.GetAsString().c_str(),291 entry.path.c_str());292 }293 }294}295 296llvm::StringRef ProcessElfCore::GetMainExecutablePath() {297 if (m_nt_file_entries.empty())298 return "";299 300 // The first entry in the NT_FILE might be our executable301 llvm::StringRef executable_path = m_nt_file_entries[0].path;302 // Prefer the NT_FILE entry matching m_executable_name as main executable.303 for (const NT_FILE_Entry &file_entry : m_nt_file_entries)304 if (llvm::StringRef(file_entry.path).ends_with("/" + m_executable_name)) {305 executable_path = file_entry.path;306 break;307 }308 return executable_path;309}310 311UUID ProcessElfCore::FindModuleUUID(const llvm::StringRef path) {312 // Lookup the UUID for the given path in the map.313 // Note that this could be called by multiple threads so make sure314 // we access the map in a thread safe way (i.e. don't use operator[]).315 auto it = m_uuids.find(std::string(path));316 if (it != m_uuids.end())317 return it->second;318 return UUID();319}320 321lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {322 if (m_dyld_up.get() == nullptr)323 m_dyld_up.reset(DynamicLoader::FindPlugin(324 this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic()));325 return m_dyld_up.get();326}327 328bool ProcessElfCore::DoUpdateThreadList(ThreadList &old_thread_list,329 ThreadList &new_thread_list) {330 const uint32_t num_threads = GetNumThreadContexts();331 if (!m_thread_data_valid)332 return false;333 334 for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {335 const ThreadData &td = m_thread_data[tid];336 lldb::ThreadSP thread_sp(new ThreadElfCore(*this, td));337 new_thread_list.AddThread(thread_sp);338 }339 return new_thread_list.GetSize(false) > 0;340}341 342void ProcessElfCore::RefreshStateAfterStop() {}343 344Status ProcessElfCore::DoDestroy() { return Status(); }345 346// Process Queries347 348bool ProcessElfCore::IsAlive() { return true; }349 350// Process Memory351size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,352 Status &error) {353 if (lldb::ABISP abi_sp = GetABI())354 addr = abi_sp->FixAnyAddress(addr);355 356 // Don't allow the caching that lldb_private::Process::ReadMemory does since357 // in core files we have it all cached our our core file anyway.358 return DoReadMemory(addr, buf, size, error);359}360 361Status ProcessElfCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr,362 MemoryRegionInfo ®ion_info) {363 region_info.Clear();364 const VMRangeToPermissions::Entry *permission_entry =365 m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);366 if (permission_entry) {367 if (permission_entry->Contains(load_addr)) {368 region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());369 region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());370 const Flags permissions(permission_entry->data);371 region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable)372 ? MemoryRegionInfo::eYes373 : MemoryRegionInfo::eNo);374 region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable)375 ? MemoryRegionInfo::eYes376 : MemoryRegionInfo::eNo);377 region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable)378 ? MemoryRegionInfo::eYes379 : MemoryRegionInfo::eNo);380 region_info.SetMapped(MemoryRegionInfo::eYes);381 382 // A region is memory tagged if there is a memory tag segment that covers383 // the exact same range.384 region_info.SetMemoryTagged(MemoryRegionInfo::eNo);385 const VMRangeToFileOffset::Entry *tag_entry =386 m_core_tag_ranges.FindEntryStartsAt(permission_entry->GetRangeBase());387 if (tag_entry &&388 tag_entry->GetRangeEnd() == permission_entry->GetRangeEnd())389 region_info.SetMemoryTagged(MemoryRegionInfo::eYes);390 } else if (load_addr < permission_entry->GetRangeBase()) {391 region_info.GetRange().SetRangeBase(load_addr);392 region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());393 region_info.SetReadable(MemoryRegionInfo::eNo);394 region_info.SetWritable(MemoryRegionInfo::eNo);395 region_info.SetExecutable(MemoryRegionInfo::eNo);396 region_info.SetMapped(MemoryRegionInfo::eNo);397 region_info.SetMemoryTagged(MemoryRegionInfo::eNo);398 }399 return Status();400 }401 402 region_info.GetRange().SetRangeBase(load_addr);403 region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);404 region_info.SetReadable(MemoryRegionInfo::eNo);405 region_info.SetWritable(MemoryRegionInfo::eNo);406 region_info.SetExecutable(MemoryRegionInfo::eNo);407 region_info.SetMapped(MemoryRegionInfo::eNo);408 region_info.SetMemoryTagged(MemoryRegionInfo::eNo);409 return Status();410}411 412size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,413 Status &error) {414 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();415 416 if (core_objfile == nullptr)417 return 0;418 419 // Get the address range420 const VMRangeToFileOffset::Entry *address_range =421 m_core_aranges.FindEntryThatContains(addr);422 if (address_range == nullptr || address_range->GetRangeEnd() < addr) {423 error = Status::FromErrorStringWithFormat(424 "core file does not contain 0x%" PRIx64, addr);425 return 0;426 }427 428 // Convert the address into core file offset429 const lldb::addr_t offset = addr - address_range->GetRangeBase();430 const lldb::addr_t file_start = address_range->data.GetRangeBase();431 const lldb::addr_t file_end = address_range->data.GetRangeEnd();432 size_t bytes_to_read = size; // Number of bytes to read from the core file433 size_t bytes_copied = 0; // Number of bytes actually read from the core file434 lldb::addr_t bytes_left =435 0; // Number of bytes available in the core file from the given address436 437 // Don't proceed if core file doesn't contain the actual data for this438 // address range.439 if (file_start == file_end)440 return 0;441 442 // Figure out how many on-disk bytes remain in this segment starting at the443 // given offset444 if (file_end > file_start + offset)445 bytes_left = file_end - (file_start + offset);446 447 if (bytes_to_read > bytes_left)448 bytes_to_read = bytes_left;449 450 // If there is data available on the core file read it451 if (bytes_to_read)452 bytes_copied =453 core_objfile->CopyData(offset + file_start, bytes_to_read, buf);454 455 return bytes_copied;456}457 458llvm::Expected<std::vector<lldb::addr_t>>459ProcessElfCore::ReadMemoryTags(lldb::addr_t addr, size_t len) {460 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();461 if (core_objfile == nullptr)462 return llvm::createStringError(llvm::inconvertibleErrorCode(),463 "No core object file.");464 465 llvm::Expected<const MemoryTagManager *> tag_manager_or_err =466 GetMemoryTagManager();467 if (!tag_manager_or_err)468 return tag_manager_or_err.takeError();469 470 // LLDB only supports AArch64 MTE tag segments so we do not need to worry471 // about the segment type here. If you got here then you must have a tag472 // manager (meaning you are debugging AArch64) and all the segments in this473 // list will have had type PT_AARCH64_MEMTAG_MTE.474 const VMRangeToFileOffset::Entry *tag_entry =475 m_core_tag_ranges.FindEntryThatContains(addr);476 // If we don't have a tag segment or the range asked for extends outside the477 // segment.478 if (!tag_entry || (addr + len) >= tag_entry->GetRangeEnd())479 return llvm::createStringError(llvm::inconvertibleErrorCode(),480 "No tag segment that covers this range.");481 482 const MemoryTagManager *tag_manager = *tag_manager_or_err;483 return tag_manager->UnpackTagsFromCoreFileSegment(484 [core_objfile](lldb::offset_t offset, size_t length, void *dst) {485 return core_objfile->CopyData(offset, length, dst);486 },487 tag_entry->GetRangeBase(), tag_entry->data.GetRangeBase(), addr, len);488}489 490void ProcessElfCore::Clear() {491 m_thread_list.Clear();492 493 SetUnixSignals(std::make_shared<UnixSignals>());494}495 496void ProcessElfCore::Initialize() {497 static llvm::once_flag g_once_flag;498 499 llvm::call_once(g_once_flag, []() {500 PluginManager::RegisterPlugin(GetPluginNameStatic(),501 GetPluginDescriptionStatic(), CreateInstance);502 });503}504 505lldb::addr_t ProcessElfCore::GetImageInfoAddress() {506 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();507 Address addr = obj_file->GetImageInfoAddress(&GetTarget());508 509 if (addr.IsValid())510 return addr.GetLoadAddress(&GetTarget());511 return LLDB_INVALID_ADDRESS;512}513 514// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.515static void ParseFreeBSDPrStatus(ThreadData &thread_data,516 const DataExtractor &data,517 bool lp64) {518 lldb::offset_t offset = 0;519 int pr_version = data.GetU32(&offset);520 521 Log *log = GetLog(LLDBLog::Process);522 if (log) {523 if (pr_version > 1)524 LLDB_LOGF(log, "FreeBSD PRSTATUS unexpected version %d", pr_version);525 }526 527 // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate528 if (lp64)529 offset += 32;530 else531 offset += 16;532 533 thread_data.signo = data.GetU32(&offset); // pr_cursig534 thread_data.tid = data.GetU32(&offset); // pr_pid535 if (lp64)536 offset += 4;537 538 size_t len = data.GetByteSize() - offset;539 thread_data.gpregset = DataExtractor(data, offset, len);540}541 542// Parse a FreeBSD NT_PRPSINFO note - see FreeBSD sys/procfs.h for details.543static void ParseFreeBSDPrPsInfo(ProcessElfCore &process,544 const DataExtractor &data,545 bool lp64) {546 lldb::offset_t offset = 0;547 int pr_version = data.GetU32(&offset);548 549 Log *log = GetLog(LLDBLog::Process);550 if (log) {551 if (pr_version > 1)552 LLDB_LOGF(log, "FreeBSD PRPSINFO unexpected version %d", pr_version);553 }554 555 // Skip pr_psinfosz, pr_fname, pr_psargs556 offset += 108;557 if (lp64)558 offset += 4;559 560 process.SetID(data.GetU32(&offset)); // pr_pid561}562 563static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data,564 uint32_t &cpi_nlwps,565 uint32_t &cpi_signo,566 uint32_t &cpi_siglwp,567 uint32_t &cpi_pid) {568 lldb::offset_t offset = 0;569 570 uint32_t version = data.GetU32(&offset);571 if (version != 1)572 return llvm::make_error<llvm::StringError>(573 "Error parsing NetBSD core(5) notes: Unsupported procinfo version",574 llvm::inconvertibleErrorCode());575 576 uint32_t cpisize = data.GetU32(&offset);577 if (cpisize != NETBSD::NT_PROCINFO_SIZE)578 return llvm::make_error<llvm::StringError>(579 "Error parsing NetBSD core(5) notes: Unsupported procinfo size",580 llvm::inconvertibleErrorCode());581 582 cpi_signo = data.GetU32(&offset); /* killing signal */583 584 offset += NETBSD::NT_PROCINFO_CPI_SIGCODE_SIZE;585 offset += NETBSD::NT_PROCINFO_CPI_SIGPEND_SIZE;586 offset += NETBSD::NT_PROCINFO_CPI_SIGMASK_SIZE;587 offset += NETBSD::NT_PROCINFO_CPI_SIGIGNORE_SIZE;588 offset += NETBSD::NT_PROCINFO_CPI_SIGCATCH_SIZE;589 cpi_pid = data.GetU32(&offset);590 offset += NETBSD::NT_PROCINFO_CPI_PPID_SIZE;591 offset += NETBSD::NT_PROCINFO_CPI_PGRP_SIZE;592 offset += NETBSD::NT_PROCINFO_CPI_SID_SIZE;593 offset += NETBSD::NT_PROCINFO_CPI_RUID_SIZE;594 offset += NETBSD::NT_PROCINFO_CPI_EUID_SIZE;595 offset += NETBSD::NT_PROCINFO_CPI_SVUID_SIZE;596 offset += NETBSD::NT_PROCINFO_CPI_RGID_SIZE;597 offset += NETBSD::NT_PROCINFO_CPI_EGID_SIZE;598 offset += NETBSD::NT_PROCINFO_CPI_SVGID_SIZE;599 cpi_nlwps = data.GetU32(&offset); /* number of LWPs */600 601 offset += NETBSD::NT_PROCINFO_CPI_NAME_SIZE;602 cpi_siglwp = data.GetU32(&offset); /* LWP target of killing signal */603 604 return llvm::Error::success();605}606 607static void ParseOpenBSDProcInfo(ThreadData &thread_data,608 const DataExtractor &data) {609 lldb::offset_t offset = 0;610 611 int version = data.GetU32(&offset);612 if (version != 1)613 return;614 615 offset += 4;616 thread_data.signo = data.GetU32(&offset);617}618 619llvm::Expected<std::vector<CoreNote>>620ProcessElfCore::parseSegment(const DataExtractor &segment) {621 lldb::offset_t offset = 0;622 std::vector<CoreNote> result;623 624 while (offset < segment.GetByteSize()) {625 ELFNote note = ELFNote();626 if (!note.Parse(segment, &offset))627 return llvm::make_error<llvm::StringError>(628 "Unable to parse note segment", llvm::inconvertibleErrorCode());629 630 size_t note_start = offset;631 size_t note_size = llvm::alignTo(note.n_descsz, 4);632 633 result.push_back({note, DataExtractor(segment, note_start, note_size)});634 offset += note_size;635 }636 637 return std::move(result);638}639 640llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {641 ArchSpec arch = GetArchitecture();642 bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||643 arch.GetMachine() == llvm::Triple::mips64 ||644 arch.GetMachine() == llvm::Triple::ppc64 ||645 arch.GetMachine() == llvm::Triple::x86_64);646 bool have_prstatus = false;647 bool have_prpsinfo = false;648 ThreadData thread_data;649 for (const auto ¬e : notes) {650 if (note.info.n_name != "FreeBSD")651 continue;652 653 if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) ||654 (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) {655 assert(thread_data.gpregset.GetByteSize() > 0);656 // Add the new thread to thread list657 m_thread_data.push_back(thread_data);658 thread_data = ThreadData();659 have_prstatus = false;660 have_prpsinfo = false;661 }662 663 switch (note.info.n_type) {664 case ELF::NT_PRSTATUS:665 have_prstatus = true;666 ParseFreeBSDPrStatus(thread_data, note.data, lp64);667 break;668 case ELF::NT_PRPSINFO:669 have_prpsinfo = true;670 ParseFreeBSDPrPsInfo(*this, note.data, lp64);671 break;672 case ELF::NT_FREEBSD_THRMISC: {673 lldb::offset_t offset = 0;674 thread_data.name = note.data.GetCStr(&offset, 20);675 break;676 }677 case ELF::NT_FREEBSD_PROCSTAT_AUXV:678 // FIXME: FreeBSD sticks an int at the beginning of the note679 m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4);680 break;681 default:682 thread_data.notes.push_back(note);683 break;684 }685 }686 if (!have_prstatus) {687 return llvm::make_error<llvm::StringError>(688 "Could not find NT_PRSTATUS note in core file.",689 llvm::inconvertibleErrorCode());690 }691 m_thread_data.push_back(thread_data);692 return llvm::Error::success();693}694 695/// NetBSD specific Thread context from PT_NOTE segment696///697/// NetBSD ELF core files use notes to provide information about698/// the process's state. The note name is "NetBSD-CORE" for699/// information that is global to the process, and "NetBSD-CORE@nn",700/// where "nn" is the lwpid of the LWP that the information belongs701/// to (such as register state).702///703/// NetBSD uses the following note identifiers:704///705/// ELF_NOTE_NETBSD_CORE_PROCINFO (value 1)706/// Note is a "netbsd_elfcore_procinfo" structure.707/// ELF_NOTE_NETBSD_CORE_AUXV (value 2; since NetBSD 8.0)708/// Note is an array of AuxInfo structures.709///710/// NetBSD also uses ptrace(2) request numbers (the ones that exist in711/// machine-dependent space) to identify register info notes. The712/// info in such notes is in the same format that ptrace(2) would713/// export that information.714///715/// For more information see /usr/include/sys/exec_elf.h716///717llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {718 ThreadData thread_data;719 bool had_nt_regs = false;720 721 // To be extracted from struct netbsd_elfcore_procinfo722 // Used to sanity check of the LWPs of the process723 uint32_t nlwps = 0;724 uint32_t signo = 0; // killing signal725 uint32_t siglwp = 0; // LWP target of killing signal726 uint32_t pr_pid = 0;727 728 for (const auto ¬e : notes) {729 llvm::StringRef name = note.info.n_name;730 731 if (name == "NetBSD-CORE") {732 if (note.info.n_type == NETBSD::NT_PROCINFO) {733 llvm::Error error = ParseNetBSDProcInfo(note.data, nlwps, signo,734 siglwp, pr_pid);735 if (error)736 return error;737 SetID(pr_pid);738 } else if (note.info.n_type == NETBSD::NT_AUXV) {739 m_auxv = note.data;740 }741 } else if (name.consume_front("NetBSD-CORE@")) {742 lldb::tid_t tid;743 if (name.getAsInteger(10, tid))744 return llvm::make_error<llvm::StringError>(745 "Error parsing NetBSD core(5) notes: Cannot convert LWP ID "746 "to integer",747 llvm::inconvertibleErrorCode());748 749 switch (GetArchitecture().GetMachine()) {750 case llvm::Triple::aarch64: {751 // Assume order PT_GETREGS, PT_GETFPREGS752 if (note.info.n_type == NETBSD::AARCH64::NT_REGS) {753 // If this is the next thread, push the previous one first.754 if (had_nt_regs) {755 m_thread_data.push_back(thread_data);756 thread_data = ThreadData();757 had_nt_regs = false;758 }759 760 thread_data.gpregset = note.data;761 thread_data.tid = tid;762 if (thread_data.gpregset.GetByteSize() == 0)763 return llvm::make_error<llvm::StringError>(764 "Could not find general purpose registers note in core file.",765 llvm::inconvertibleErrorCode());766 had_nt_regs = true;767 } else if (note.info.n_type == NETBSD::AARCH64::NT_FPREGS) {768 if (!had_nt_regs || tid != thread_data.tid)769 return llvm::make_error<llvm::StringError>(770 "Error parsing NetBSD core(5) notes: Unexpected order "771 "of NOTEs PT_GETFPREG before PT_GETREG",772 llvm::inconvertibleErrorCode());773 thread_data.notes.push_back(note);774 }775 } break;776 case llvm::Triple::x86: {777 // Assume order PT_GETREGS, PT_GETFPREGS778 if (note.info.n_type == NETBSD::I386::NT_REGS) {779 // If this is the next thread, push the previous one first.780 if (had_nt_regs) {781 m_thread_data.push_back(thread_data);782 thread_data = ThreadData();783 had_nt_regs = false;784 }785 786 thread_data.gpregset = note.data;787 thread_data.tid = tid;788 if (thread_data.gpregset.GetByteSize() == 0)789 return llvm::make_error<llvm::StringError>(790 "Could not find general purpose registers note in core file.",791 llvm::inconvertibleErrorCode());792 had_nt_regs = true;793 } else if (note.info.n_type == NETBSD::I386::NT_FPREGS) {794 if (!had_nt_regs || tid != thread_data.tid)795 return llvm::make_error<llvm::StringError>(796 "Error parsing NetBSD core(5) notes: Unexpected order "797 "of NOTEs PT_GETFPREG before PT_GETREG",798 llvm::inconvertibleErrorCode());799 thread_data.notes.push_back(note);800 }801 } break;802 case llvm::Triple::x86_64: {803 // Assume order PT_GETREGS, PT_GETFPREGS804 if (note.info.n_type == NETBSD::AMD64::NT_REGS) {805 // If this is the next thread, push the previous one first.806 if (had_nt_regs) {807 m_thread_data.push_back(thread_data);808 thread_data = ThreadData();809 had_nt_regs = false;810 }811 812 thread_data.gpregset = note.data;813 thread_data.tid = tid;814 if (thread_data.gpregset.GetByteSize() == 0)815 return llvm::make_error<llvm::StringError>(816 "Could not find general purpose registers note in core file.",817 llvm::inconvertibleErrorCode());818 had_nt_regs = true;819 } else if (note.info.n_type == NETBSD::AMD64::NT_FPREGS) {820 if (!had_nt_regs || tid != thread_data.tid)821 return llvm::make_error<llvm::StringError>(822 "Error parsing NetBSD core(5) notes: Unexpected order "823 "of NOTEs PT_GETFPREG before PT_GETREG",824 llvm::inconvertibleErrorCode());825 thread_data.notes.push_back(note);826 }827 } break;828 default:829 break;830 }831 }832 }833 834 // Push the last thread.835 if (had_nt_regs)836 m_thread_data.push_back(thread_data);837 838 if (m_thread_data.empty())839 return llvm::make_error<llvm::StringError>(840 "Error parsing NetBSD core(5) notes: No threads information "841 "specified in notes",842 llvm::inconvertibleErrorCode());843 844 if (m_thread_data.size() != nlwps)845 return llvm::make_error<llvm::StringError>(846 "Error parsing NetBSD core(5) notes: Mismatch between the number "847 "of LWPs in netbsd_elfcore_procinfo and the number of LWPs specified "848 "by MD notes",849 llvm::inconvertibleErrorCode());850 851 // Signal targeted at the whole process.852 if (siglwp == 0) {853 for (auto &data : m_thread_data)854 data.signo = signo;855 }856 // Signal destined for a particular LWP.857 else {858 bool passed = false;859 860 for (auto &data : m_thread_data) {861 if (data.tid == siglwp) {862 data.signo = signo;863 passed = true;864 break;865 }866 }867 868 if (!passed)869 return llvm::make_error<llvm::StringError>(870 "Error parsing NetBSD core(5) notes: Signal passed to unknown LWP",871 llvm::inconvertibleErrorCode());872 }873 874 return llvm::Error::success();875}876 877llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {878 ThreadData thread_data = {};879 for (const auto ¬e : notes) {880 // OpenBSD per-thread information is stored in notes named "OpenBSD@nnn" so881 // match on the initial part of the string.882 if (!llvm::StringRef(note.info.n_name).starts_with("OpenBSD"))883 continue;884 885 switch (note.info.n_type) {886 case OPENBSD::NT_PROCINFO:887 ParseOpenBSDProcInfo(thread_data, note.data);888 break;889 case OPENBSD::NT_AUXV:890 m_auxv = note.data;891 break;892 case OPENBSD::NT_REGS:893 thread_data.gpregset = note.data;894 break;895 default:896 thread_data.notes.push_back(note);897 break;898 }899 }900 if (thread_data.gpregset.GetByteSize() == 0) {901 return llvm::make_error<llvm::StringError>(902 "Could not find general purpose registers note in core file.",903 llvm::inconvertibleErrorCode());904 }905 m_thread_data.push_back(thread_data);906 return llvm::Error::success();907}908 909/// A description of a linux process usually contains the following NOTE910/// entries:911/// - NT_PRPSINFO - General process information like pid, uid, name, ...912/// - NT_SIGINFO - Information about the signal that terminated the process913/// - NT_AUXV - Process auxiliary vector914/// - NT_FILE - Files mapped into memory915///916/// Additionally, for each thread in the process the core file will contain at917/// least the NT_PRSTATUS note, containing the thread id and general purpose918/// registers. It may include additional notes for other register sets (floating919/// point and vector registers, ...). The tricky part here is that some of these920/// notes have "CORE" in their owner fields, while other set it to "LINUX".921llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {922 const ArchSpec &arch = GetArchitecture();923 bool have_prstatus = false;924 bool have_prpsinfo = false;925 ThreadData thread_data;926 for (const auto ¬e : notes) {927 if (note.info.n_name != "CORE" && note.info.n_name != "LINUX")928 continue;929 930 if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) ||931 (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) {932 assert(thread_data.gpregset.GetByteSize() > 0);933 // Add the new thread to thread list934 m_thread_data.push_back(thread_data);935 thread_data = ThreadData();936 have_prstatus = false;937 have_prpsinfo = false;938 }939 940 switch (note.info.n_type) {941 case ELF::NT_PRSTATUS: {942 have_prstatus = true;943 ELFLinuxPrStatus prstatus;944 Status status = prstatus.Parse(note.data, arch);945 if (status.Fail())946 return status.ToError();947 thread_data.prstatus_sig = prstatus.pr_cursig;948 thread_data.tid = prstatus.pr_pid;949 uint32_t header_size = ELFLinuxPrStatus::GetSize(arch);950 size_t len = note.data.GetByteSize() - header_size;951 thread_data.gpregset = DataExtractor(note.data, header_size, len);952 break;953 }954 case ELF::NT_PRPSINFO: {955 have_prpsinfo = true;956 ELFLinuxPrPsInfo prpsinfo;957 Status status = prpsinfo.Parse(note.data, arch);958 if (status.Fail())959 return status.ToError();960 thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname)));961 SetID(prpsinfo.pr_pid);962 m_executable_name = thread_data.name;963 break;964 }965 case ELF::NT_SIGINFO: {966 lldb::offset_t size = note.data.GetByteSize();967 lldb::offset_t offset = 0;968 const char *bytes =969 static_cast<const char *>(note.data.GetData(&offset, size));970 thread_data.siginfo_bytes = llvm::StringRef(bytes, size);971 break;972 }973 case ELF::NT_FILE: {974 m_nt_file_entries.clear();975 lldb::offset_t offset = 0;976 const uint64_t count = note.data.GetAddress(&offset);977 note.data.GetAddress(&offset); // Skip page size978 for (uint64_t i = 0; i < count; ++i) {979 NT_FILE_Entry entry;980 entry.start = note.data.GetAddress(&offset);981 entry.end = note.data.GetAddress(&offset);982 entry.file_ofs = note.data.GetAddress(&offset);983 m_nt_file_entries.push_back(entry);984 }985 for (uint64_t i = 0; i < count; ++i) {986 const char *path = note.data.GetCStr(&offset);987 if (path && path[0])988 m_nt_file_entries[i].path.assign(path);989 }990 break;991 }992 case ELF::NT_AUXV:993 m_auxv = note.data;994 break;995 default:996 thread_data.notes.push_back(note);997 break;998 }999 }1000 // Add last entry in the note section1001 if (have_prstatus)1002 m_thread_data.push_back(thread_data);1003 return llvm::Error::success();1004}1005 1006/// Parse Thread context from PT_NOTE segment and store it in the thread list1007/// A note segment consists of one or more NOTE entries, but their types and1008/// meaning differ depending on the OS.1009llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(1010 const elf::ELFProgramHeader &segment_header,1011 const DataExtractor &segment_data) {1012 assert(segment_header.p_type == llvm::ELF::PT_NOTE);1013 1014 auto notes_or_error = parseSegment(segment_data);1015 if(!notes_or_error)1016 return notes_or_error.takeError();1017 switch (GetArchitecture().GetTriple().getOS()) {1018 case llvm::Triple::FreeBSD:1019 return parseFreeBSDNotes(*notes_or_error);1020 case llvm::Triple::Linux:1021 return parseLinuxNotes(*notes_or_error);1022 case llvm::Triple::NetBSD:1023 return parseNetBSDNotes(*notes_or_error);1024 case llvm::Triple::OpenBSD:1025 return parseOpenBSDNotes(*notes_or_error);1026 default:1027 return llvm::make_error<llvm::StringError>(1028 "Don't know how to parse core file. Unsupported OS.",1029 llvm::inconvertibleErrorCode());1030 }1031}1032 1033UUID ProcessElfCore::FindBuidIdInCoreMemory(lldb::addr_t address) {1034 UUID invalid_uuid;1035 const uint32_t addr_size = GetAddressByteSize();1036 const size_t elf_header_size = addr_size == 4 ? sizeof(llvm::ELF::Elf32_Ehdr)1037 : sizeof(llvm::ELF::Elf64_Ehdr);1038 1039 std::vector<uint8_t> elf_header_bytes;1040 elf_header_bytes.resize(elf_header_size);1041 Status error;1042 size_t byte_read =1043 ReadMemory(address, elf_header_bytes.data(), elf_header_size, error);1044 if (byte_read != elf_header_size ||1045 !elf::ELFHeader::MagicBytesMatch(elf_header_bytes.data()))1046 return invalid_uuid;1047 DataExtractor elf_header_data(elf_header_bytes.data(), elf_header_size,1048 GetByteOrder(), addr_size);1049 lldb::offset_t offset = 0;1050 1051 elf::ELFHeader elf_header;1052 elf_header.Parse(elf_header_data, &offset);1053 1054 const lldb::addr_t ph_addr = address + elf_header.e_phoff;1055 1056 std::vector<uint8_t> ph_bytes;1057 ph_bytes.resize(elf_header.e_phentsize);1058 lldb::addr_t base_addr = 0;1059 bool found_first_load_segment = false;1060 for (unsigned int i = 0; i < elf_header.e_phnum; ++i) {1061 byte_read = ReadMemory(ph_addr + i * elf_header.e_phentsize,1062 ph_bytes.data(), elf_header.e_phentsize, error);1063 if (byte_read != elf_header.e_phentsize)1064 break;1065 DataExtractor program_header_data(ph_bytes.data(), elf_header.e_phentsize,1066 GetByteOrder(), addr_size);1067 offset = 0;1068 elf::ELFProgramHeader program_header;1069 program_header.Parse(program_header_data, &offset);1070 if (program_header.p_type == llvm::ELF::PT_LOAD &&1071 !found_first_load_segment) {1072 base_addr = program_header.p_vaddr;1073 found_first_load_segment = true;1074 }1075 if (program_header.p_type != llvm::ELF::PT_NOTE)1076 continue;1077 1078 std::vector<uint8_t> note_bytes;1079 note_bytes.resize(program_header.p_memsz);1080 1081 // We need to slide the address of the p_vaddr as these values don't get1082 // relocated in memory.1083 const lldb::addr_t vaddr = program_header.p_vaddr + address - base_addr;1084 byte_read =1085 ReadMemory(vaddr, note_bytes.data(), program_header.p_memsz, error);1086 if (byte_read != program_header.p_memsz)1087 continue;1088 DataExtractor segment_data(note_bytes.data(), note_bytes.size(),1089 GetByteOrder(), addr_size);1090 auto notes_or_error = parseSegment(segment_data);1091 if (!notes_or_error) {1092 llvm::consumeError(notes_or_error.takeError());1093 return invalid_uuid;1094 }1095 for (const CoreNote ¬e : *notes_or_error) {1096 if (note.info.n_namesz == 4 &&1097 note.info.n_type == llvm::ELF::NT_GNU_BUILD_ID &&1098 "GNU" == note.info.n_name &&1099 note.data.ValidOffsetForDataOfSize(0, note.info.n_descsz))1100 return UUID(note.data.GetData().take_front(note.info.n_descsz));1101 }1102 }1103 return invalid_uuid;1104}1105 1106uint32_t ProcessElfCore::GetNumThreadContexts() {1107 if (!m_thread_data_valid)1108 DoLoadCore();1109 return m_thread_data.size();1110}1111 1112ArchSpec ProcessElfCore::GetArchitecture() {1113 ArchSpec arch = m_core_module_sp->GetObjectFile()->GetArchitecture();1114 1115 ArchSpec target_arch = GetTarget().GetArchitecture();1116 arch.MergeFrom(target_arch);1117 1118 // On MIPS there is no way to differentiate betwenn 32bit and 64bit core1119 // files and this information can't be merged in from the target arch so we1120 // fail back to unconditionally returning the target arch in this config.1121 if (target_arch.IsMIPS()) {1122 return target_arch;1123 }1124 1125 return arch;1126}1127 1128DataExtractor ProcessElfCore::GetAuxvData() {1129 assert(m_auxv.GetByteSize() == 0 ||1130 (m_auxv.GetByteOrder() == GetByteOrder() &&1131 m_auxv.GetAddressByteSize() == GetAddressByteSize()));1132 return DataExtractor(m_auxv);1133}1134 1135bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {1136 info.Clear();1137 info.SetProcessID(GetID());1138 info.SetArchitecture(GetArchitecture());1139 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();1140 if (module_sp) {1141 const bool add_exe_file_as_first_arg = false;1142 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),1143 add_exe_file_as_first_arg);1144 }1145 return true;1146}1147