180814287SRaphael Isemann //===-- ProcessElfCore.cpp ------------------------------------------------===//
24f01ff8bSAshok Thirumurthi //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64f01ff8bSAshok Thirumurthi //
74f01ff8bSAshok Thirumurthi //===----------------------------------------------------------------------===//
84f01ff8bSAshok Thirumurthi
976e47d48SRaphael Isemann #include <cstdlib>
104f01ff8bSAshok Thirumurthi
11796ac80bSJonas Devlieghere #include <memory>
123f69fa6fSBenjamin Kramer #include <mutex>
133f69fa6fSBenjamin Kramer
143385fa08SGreg Clayton #include "lldb/Core/Module.h"
153385fa08SGreg Clayton #include "lldb/Core/ModuleSpec.h"
163385fa08SGreg Clayton #include "lldb/Core/PluginManager.h"
173385fa08SGreg Clayton #include "lldb/Core/Section.h"
1800a12585SDavid Spickett #include "lldb/Target/ABI.h"
194f01ff8bSAshok Thirumurthi #include "lldb/Target/DynamicLoader.h"
203385fa08SGreg Clayton #include "lldb/Target/MemoryRegionInfo.h"
213385fa08SGreg Clayton #include "lldb/Target/Target.h"
224ceced3fSTodd Fiala #include "lldb/Target/UnixSignals.h"
23666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
24c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
256f9e6901SZachary Turner #include "lldb/Utility/Log.h"
26d821c997SPavel Labath #include "lldb/Utility/State.h"
279cbd3c62SGreg Clayton
28264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h"
29c5f28e2aSKamil Rytarowski #include "llvm/Support/Threading.h"
309cbd3c62SGreg Clayton
314f01ff8bSAshok Thirumurthi #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
32b9c1b51eSKate Stone #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
33bc8cc867SPavel Labath #include "Plugins/Process/elf-core/RegisterUtilities.h"
344f01ff8bSAshok Thirumurthi #include "ProcessElfCore.h"
354f01ff8bSAshok Thirumurthi #include "ThreadElfCore.h"
364f01ff8bSAshok Thirumurthi
374f01ff8bSAshok Thirumurthi using namespace lldb_private;
38b9f31b6fSPavel Labath namespace ELF = llvm::ELF;
394f01ff8bSAshok Thirumurthi
LLDB_PLUGIN_DEFINE(ProcessElfCore)40bba9ba8dSJonas Devlieghere LLDB_PLUGIN_DEFINE(ProcessElfCore)
41fbb4d1e4SJonas Devlieghere
425f4980f0SPavel Labath llvm::StringRef ProcessElfCore::GetPluginDescriptionStatic() {
434f01ff8bSAshok Thirumurthi return "ELF core dump plug-in.";
444f01ff8bSAshok Thirumurthi }
454f01ff8bSAshok Thirumurthi
Terminate()46b9c1b51eSKate Stone void ProcessElfCore::Terminate() {
474f01ff8bSAshok Thirumurthi PluginManager::UnregisterPlugin(ProcessElfCore::CreateInstance);
484f01ff8bSAshok Thirumurthi }
494f01ff8bSAshok Thirumurthi
CreateInstance(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp,const FileSpec * crash_file,bool can_connect)50b9c1b51eSKate Stone lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,
51b9c1b51eSKate Stone lldb::ListenerSP listener_sp,
5218e4272aSMichał Górny const FileSpec *crash_file,
5318e4272aSMichał Górny bool can_connect) {
544f01ff8bSAshok Thirumurthi lldb::ProcessSP process_sp;
5518e4272aSMichał Górny if (crash_file && !can_connect) {
5605097246SAdrian Prantl // Read enough data for a ELF32 header or ELF64 header Note: Here we care
5705097246SAdrian Prantl // about e_type field only, so it is safe to ignore possible presence of
5805097246SAdrian Prantl // the header extension.
599cbd3c62SGreg Clayton const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);
609cbd3c62SGreg Clayton
6187e403aaSJonas Devlieghere auto data_sp = FileSystem::Instance().CreateDataBuffer(
6287e403aaSJonas Devlieghere crash_file->GetPath(), header_size, 0);
632e940a11SEd Maste if (data_sp && data_sp->GetByteSize() == header_size &&
64b9c1b51eSKate Stone elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) {
659cbd3c62SGreg Clayton elf::ELFHeader elf_header;
669cbd3c62SGreg Clayton DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
679cbd3c62SGreg Clayton lldb::offset_t data_offset = 0;
68b9c1b51eSKate Stone if (elf_header.Parse(data, &data_offset)) {
69fdc1638bSMichał Górny // Check whether we're dealing with a raw FreeBSD "full memory dump"
70fdc1638bSMichał Górny // ELF vmcore that needs to be handled via FreeBSDKernel plugin instead.
71fdc1638bSMichał Górny if (elf_header.e_ident[7] == 0xFF && elf_header.e_version == 0)
72fdc1638bSMichał Górny return process_sp;
739cbd3c62SGreg Clayton if (elf_header.e_type == llvm::ELF::ET_CORE)
74796ac80bSJonas Devlieghere process_sp = std::make_shared<ProcessElfCore>(target_sp, listener_sp,
75796ac80bSJonas Devlieghere *crash_file);
769cbd3c62SGreg Clayton }
779cbd3c62SGreg Clayton }
789cbd3c62SGreg Clayton }
794f01ff8bSAshok Thirumurthi return process_sp;
804f01ff8bSAshok Thirumurthi }
814f01ff8bSAshok Thirumurthi
CanDebug(lldb::TargetSP target_sp,bool plugin_specified_by_name)82b9c1b51eSKate Stone bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp,
83b9c1b51eSKate Stone bool plugin_specified_by_name) {
844f01ff8bSAshok Thirumurthi // For now we are just making sure the file exists for a given module
85dbd7fabaSJonas Devlieghere if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {
867529df9aSZachary Turner ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());
8797206d57SZachary Turner Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
88248a1305SKonrad Kleine nullptr, nullptr, nullptr));
89b9c1b51eSKate Stone if (m_core_module_sp) {
904f01ff8bSAshok Thirumurthi ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
914f01ff8bSAshok Thirumurthi if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
924f01ff8bSAshok Thirumurthi return true;
934f01ff8bSAshok Thirumurthi }
944f01ff8bSAshok Thirumurthi }
954f01ff8bSAshok Thirumurthi return false;
964f01ff8bSAshok Thirumurthi }
974f01ff8bSAshok Thirumurthi
984f01ff8bSAshok Thirumurthi // ProcessElfCore constructor
ProcessElfCore(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp,const FileSpec & core_file)99b9c1b51eSKate Stone ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,
100b9c1b51eSKate Stone lldb::ListenerSP listener_sp,
101b9c1b51eSKate Stone const FileSpec &core_file)
102fb19f11eSWalter Erquinigo : PostMortemProcess(target_sp, listener_sp), m_core_file(core_file) {}
1034f01ff8bSAshok Thirumurthi
1044f01ff8bSAshok Thirumurthi // Destructor
~ProcessElfCore()105b9c1b51eSKate Stone ProcessElfCore::~ProcessElfCore() {
1064f01ff8bSAshok Thirumurthi Clear();
10705097246SAdrian Prantl // We need to call finalize on the process before destroying ourselves to
10805097246SAdrian Prantl // make sure all of the broadcaster cleanup goes as planned. If we destruct
10905097246SAdrian Prantl // this class, then Process::~Process() might have problems trying to fully
11005097246SAdrian Prantl // destroy the broadcaster.
1114f01ff8bSAshok Thirumurthi Finalize();
1124f01ff8bSAshok Thirumurthi }
1134f01ff8bSAshok Thirumurthi
AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader & header)114b9c1b51eSKate Stone lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment(
1155ea7ecdbSPavel Labath const elf::ELFProgramHeader &header) {
1165ea7ecdbSPavel Labath const lldb::addr_t addr = header.p_vaddr;
1175ea7ecdbSPavel Labath FileRange file_range(header.p_offset, header.p_filesz);
1185ea7ecdbSPavel Labath VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range);
1194f01ff8bSAshok Thirumurthi
1204f68c226SGreg Clayton // Only add to m_core_aranges if the file size is non zero. Some core files
1214f68c226SGreg Clayton // have PT_LOAD segments for all address ranges, but set f_filesz to zero for
1224f68c226SGreg Clayton // the .text sections since they can be retrieved from the object files.
1234f68c226SGreg Clayton if (header.p_filesz > 0) {
1244f01ff8bSAshok Thirumurthi VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
125b9c1b51eSKate Stone if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
126729c001eSTodd Fiala last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
127b9c1b51eSKate Stone last_entry->GetByteSize() == last_entry->data.GetByteSize()) {
1284f01ff8bSAshok Thirumurthi last_entry->SetRangeEnd(range_entry.GetRangeEnd());
1294f01ff8bSAshok Thirumurthi last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
130b9c1b51eSKate Stone } else {
1314f01ff8bSAshok Thirumurthi m_core_aranges.Append(range_entry);
1324f01ff8bSAshok Thirumurthi }
1334f68c226SGreg Clayton }
1343385fa08SGreg Clayton // Keep a separate map of permissions that that isn't coalesced so all ranges
1353385fa08SGreg Clayton // are maintained.
136b9c1b51eSKate Stone const uint32_t permissions =
1375ea7ecdbSPavel Labath ((header.p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) |
1385ea7ecdbSPavel Labath ((header.p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) |
1395ea7ecdbSPavel Labath ((header.p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u);
1403385fa08SGreg Clayton
141b9c1b51eSKate Stone m_core_range_infos.Append(
1425ea7ecdbSPavel Labath VMRangeToPermissions::Entry(addr, header.p_memsz, permissions));
1433385fa08SGreg Clayton
1444f01ff8bSAshok Thirumurthi return addr;
1454f01ff8bSAshok Thirumurthi }
1464f01ff8bSAshok Thirumurthi
AddAddressRangeFromMemoryTagSegment(const elf::ELFProgramHeader & header)147*2f9fa9efSDavid Spickett lldb::addr_t ProcessElfCore::AddAddressRangeFromMemoryTagSegment(
148*2f9fa9efSDavid Spickett const elf::ELFProgramHeader &header) {
149*2f9fa9efSDavid Spickett // If lldb understood multiple kinds of tag segments we would record the type
150*2f9fa9efSDavid Spickett // of the segment here also. As long as there is only 1 type lldb looks for,
151*2f9fa9efSDavid Spickett // there is no need.
152*2f9fa9efSDavid Spickett FileRange file_range(header.p_offset, header.p_filesz);
153*2f9fa9efSDavid Spickett m_core_tag_ranges.Append(
154*2f9fa9efSDavid Spickett VMRangeToFileOffset::Entry(header.p_vaddr, header.p_memsz, file_range));
155*2f9fa9efSDavid Spickett
156*2f9fa9efSDavid Spickett return header.p_vaddr;
157*2f9fa9efSDavid Spickett }
158*2f9fa9efSDavid Spickett
1594f01ff8bSAshok Thirumurthi // Process Control
DoLoadCore()16097206d57SZachary Turner Status ProcessElfCore::DoLoadCore() {
16197206d57SZachary Turner Status error;
162b9c1b51eSKate Stone if (!m_core_module_sp) {
1634f01ff8bSAshok Thirumurthi error.SetErrorString("invalid core module");
1644f01ff8bSAshok Thirumurthi return error;
1654f01ff8bSAshok Thirumurthi }
1664f01ff8bSAshok Thirumurthi
1674f01ff8bSAshok Thirumurthi ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
168248a1305SKonrad Kleine if (core == nullptr) {
1694f01ff8bSAshok Thirumurthi error.SetErrorString("invalid core object file");
1704f01ff8bSAshok Thirumurthi return error;
1714f01ff8bSAshok Thirumurthi }
1724f01ff8bSAshok Thirumurthi
1735ea7ecdbSPavel Labath llvm::ArrayRef<elf::ELFProgramHeader> segments = core->ProgramHeaders();
1745ea7ecdbSPavel Labath if (segments.size() == 0) {
175aec14038SEd Maste error.SetErrorString("core file has no segments");
1764f01ff8bSAshok Thirumurthi return error;
1774f01ff8bSAshok Thirumurthi }
1784f01ff8bSAshok Thirumurthi
1794f01ff8bSAshok Thirumurthi SetCanJIT(false);
1804f01ff8bSAshok Thirumurthi
1814f01ff8bSAshok Thirumurthi m_thread_data_valid = true;
1824f01ff8bSAshok Thirumurthi
1834f01ff8bSAshok Thirumurthi bool ranges_are_sorted = true;
1844f01ff8bSAshok Thirumurthi lldb::addr_t vm_addr = 0;
185*2f9fa9efSDavid Spickett lldb::addr_t tag_addr = 0;
1864f01ff8bSAshok Thirumurthi /// Walk through segments and Thread and Address Map information.
1874f01ff8bSAshok Thirumurthi /// PT_NOTE - Contains Thread and Register information
1884f01ff8bSAshok Thirumurthi /// PT_LOAD - Contains a contiguous range of Process Address Space
189*2f9fa9efSDavid Spickett /// PT_AARCH64_MEMTAG_MTE - Contains AArch64 MTE memory tags for a range of
190*2f9fa9efSDavid Spickett /// Process Address Space.
1915ea7ecdbSPavel Labath for (const elf::ELFProgramHeader &H : segments) {
1925ea7ecdbSPavel Labath DataExtractor data = core->GetSegmentData(H);
1934f01ff8bSAshok Thirumurthi
1944f01ff8bSAshok Thirumurthi // Parse thread contexts and auxv structure
1955ea7ecdbSPavel Labath if (H.p_type == llvm::ELF::PT_NOTE) {
1965ea7ecdbSPavel Labath if (llvm::Error error = ParseThreadContextsFromNoteSegment(H, data))
197cef4119cSPavel Labath return Status(std::move(error));
198023dd64fSDimitar Vlahovski }
1994f01ff8bSAshok Thirumurthi // PT_LOAD segments contains address map
2005ea7ecdbSPavel Labath if (H.p_type == llvm::ELF::PT_LOAD) {
2015ea7ecdbSPavel Labath lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(H);
2024f01ff8bSAshok Thirumurthi if (vm_addr > last_addr)
2034f01ff8bSAshok Thirumurthi ranges_are_sorted = false;
2044f01ff8bSAshok Thirumurthi vm_addr = last_addr;
205*2f9fa9efSDavid Spickett } else if (H.p_type == llvm::ELF::PT_AARCH64_MEMTAG_MTE) {
206*2f9fa9efSDavid Spickett lldb::addr_t last_addr = AddAddressRangeFromMemoryTagSegment(H);
207*2f9fa9efSDavid Spickett if (tag_addr > last_addr)
208*2f9fa9efSDavid Spickett ranges_are_sorted = false;
209*2f9fa9efSDavid Spickett tag_addr = last_addr;
2104f01ff8bSAshok Thirumurthi }
2114f01ff8bSAshok Thirumurthi }
2124f01ff8bSAshok Thirumurthi
213b9c1b51eSKate Stone if (!ranges_are_sorted) {
2144f01ff8bSAshok Thirumurthi m_core_aranges.Sort();
2153385fa08SGreg Clayton m_core_range_infos.Sort();
216*2f9fa9efSDavid Spickett m_core_tag_ranges.Sort();
2173385fa08SGreg Clayton }
2184f01ff8bSAshok Thirumurthi
21905097246SAdrian Prantl // Even if the architecture is set in the target, we need to override it to
22005097246SAdrian Prantl // match the core file which is always single arch.
2214f01ff8bSAshok Thirumurthi ArchSpec arch(m_core_module_sp->GetArchitecture());
222706c5205SNitesh Jain
223706c5205SNitesh Jain ArchSpec target_arch = GetTarget().GetArchitecture();
224706c5205SNitesh Jain ArchSpec core_arch(m_core_module_sp->GetArchitecture());
225706c5205SNitesh Jain target_arch.MergeFrom(core_arch);
226706c5205SNitesh Jain GetTarget().SetArchitecture(target_arch);
2274f01ff8bSAshok Thirumurthi
22898d0a4b3SChaoren Lin SetUnixSignals(UnixSignals::Create(GetArchitecture()));
22994ba3689SEd Maste
2301a2ac9bdSHoward Hellyer // Ensure we found at least one thread that was stopped on a signal.
2311a2ac9bdSHoward Hellyer bool siginfo_signal_found = false;
2321a2ac9bdSHoward Hellyer bool prstatus_signal_found = false;
2331a2ac9bdSHoward Hellyer // Check we found a signal in a SIGINFO note.
2341a2ac9bdSHoward Hellyer for (const auto &thread_data : m_thread_data) {
2351a2ac9bdSHoward Hellyer if (thread_data.signo != 0)
2361a2ac9bdSHoward Hellyer siginfo_signal_found = true;
2371a2ac9bdSHoward Hellyer if (thread_data.prstatus_sig != 0)
2381a2ac9bdSHoward Hellyer prstatus_signal_found = true;
2391a2ac9bdSHoward Hellyer }
2401a2ac9bdSHoward Hellyer if (!siginfo_signal_found) {
2411a2ac9bdSHoward Hellyer // If we don't have signal from SIGINFO use the signal from each threads
2421a2ac9bdSHoward Hellyer // PRSTATUS note.
2431a2ac9bdSHoward Hellyer if (prstatus_signal_found) {
2441a2ac9bdSHoward Hellyer for (auto &thread_data : m_thread_data)
2451a2ac9bdSHoward Hellyer thread_data.signo = thread_data.prstatus_sig;
2461a2ac9bdSHoward Hellyer } else if (m_thread_data.size() > 0) {
2471a2ac9bdSHoward Hellyer // If all else fails force the first thread to be SIGSTOP
2481a2ac9bdSHoward Hellyer m_thread_data.begin()->signo =
2491a2ac9bdSHoward Hellyer GetUnixSignals()->GetSignalNumberFromName("SIGSTOP");
2501a2ac9bdSHoward Hellyer }
2511a2ac9bdSHoward Hellyer }
2521a2ac9bdSHoward Hellyer
253b9c1b51eSKate Stone // Core files are useless without the main executable. See if we can locate
25405097246SAdrian Prantl // the main executable using data we found in the core file notes.
255b704b69eSGreg Clayton lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
256b9c1b51eSKate Stone if (!exe_module_sp) {
257b704b69eSGreg Clayton // The first entry in the NT_FILE might be our executable
258b9c1b51eSKate Stone if (!m_nt_file_entries.empty()) {
259b704b69eSGreg Clayton ModuleSpec exe_module_spec;
260b704b69eSGreg Clayton exe_module_spec.GetArchitecture() = arch;
261b9c1b51eSKate Stone exe_module_spec.GetFileSpec().SetFile(
2628f3be7a3SJonas Devlieghere m_nt_file_entries[0].path.GetCString(), FileSpec::Style::native);
263b9c1b51eSKate Stone if (exe_module_spec.GetFileSpec()) {
2641724a179SJason Molenda exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec,
2651724a179SJason Molenda true /* notify */);
266b704b69eSGreg Clayton if (exe_module_sp)
267f9a07e9fSJonas Devlieghere GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
268b704b69eSGreg Clayton }
269b704b69eSGreg Clayton }
270b704b69eSGreg Clayton }
2714f01ff8bSAshok Thirumurthi return error;
2724f01ff8bSAshok Thirumurthi }
2734f01ff8bSAshok Thirumurthi
GetDynamicLoader()274b9c1b51eSKate Stone lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
275248a1305SKonrad Kleine if (m_dyld_up.get() == nullptr)
276d5b44036SJonas Devlieghere m_dyld_up.reset(DynamicLoader::FindPlugin(
2776fa1b4ffSPavel Labath this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic()));
278d5b44036SJonas Devlieghere return m_dyld_up.get();
2794f01ff8bSAshok Thirumurthi }
2804f01ff8bSAshok Thirumurthi
DoUpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)2814bb62448SWalter Erquinigo bool ProcessElfCore::DoUpdateThreadList(ThreadList &old_thread_list,
282b9c1b51eSKate Stone ThreadList &new_thread_list) {
2834f01ff8bSAshok Thirumurthi const uint32_t num_threads = GetNumThreadContexts();
2844f01ff8bSAshok Thirumurthi if (!m_thread_data_valid)
2854f01ff8bSAshok Thirumurthi return false;
2864f01ff8bSAshok Thirumurthi
287b9c1b51eSKate Stone for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
2884f01ff8bSAshok Thirumurthi const ThreadData &td = m_thread_data[tid];
289343ad623SEd Maste lldb::ThreadSP thread_sp(new ThreadElfCore(*this, td));
2904f01ff8bSAshok Thirumurthi new_thread_list.AddThread(thread_sp);
2914f01ff8bSAshok Thirumurthi }
2924f01ff8bSAshok Thirumurthi return new_thread_list.GetSize(false) > 0;
2934f01ff8bSAshok Thirumurthi }
2944f01ff8bSAshok Thirumurthi
RefreshStateAfterStop()295b9c1b51eSKate Stone void ProcessElfCore::RefreshStateAfterStop() {}
2964f01ff8bSAshok Thirumurthi
DoDestroy()29797206d57SZachary Turner Status ProcessElfCore::DoDestroy() { return Status(); }
2984f01ff8bSAshok Thirumurthi
2994f01ff8bSAshok Thirumurthi // Process Queries
3004f01ff8bSAshok Thirumurthi
IsAlive()301b9c1b51eSKate Stone bool ProcessElfCore::IsAlive() { return true; }
3024f01ff8bSAshok Thirumurthi
3034f01ff8bSAshok Thirumurthi // Process Memory
ReadMemory(lldb::addr_t addr,void * buf,size_t size,Status & error)304b9c1b51eSKate Stone size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
30597206d57SZachary Turner Status &error) {
30600a12585SDavid Spickett if (lldb::ABISP abi_sp = GetABI())
30700a12585SDavid Spickett addr = abi_sp->FixAnyAddress(addr);
30800a12585SDavid Spickett
30905097246SAdrian Prantl // Don't allow the caching that lldb_private::Process::ReadMemory does since
31005097246SAdrian Prantl // in core files we have it all cached our our core file anyway.
3114f01ff8bSAshok Thirumurthi return DoReadMemory(addr, buf, size, error);
3124f01ff8bSAshok Thirumurthi }
3134f01ff8bSAshok Thirumurthi
DoGetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & region_info)3142937b282SDavid Spickett Status ProcessElfCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
315b9c1b51eSKate Stone MemoryRegionInfo ®ion_info) {
3163385fa08SGreg Clayton region_info.Clear();
317b9c1b51eSKate Stone const VMRangeToPermissions::Entry *permission_entry =
318b9c1b51eSKate Stone m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
319b9c1b51eSKate Stone if (permission_entry) {
320b9c1b51eSKate Stone if (permission_entry->Contains(load_addr)) {
3213385fa08SGreg Clayton region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
3223385fa08SGreg Clayton region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
3233385fa08SGreg Clayton const Flags permissions(permission_entry->data);
324b9c1b51eSKate Stone region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable)
325b9c1b51eSKate Stone ? MemoryRegionInfo::eYes
3263385fa08SGreg Clayton : MemoryRegionInfo::eNo);
327b9c1b51eSKate Stone region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable)
328b9c1b51eSKate Stone ? MemoryRegionInfo::eYes
3293385fa08SGreg Clayton : MemoryRegionInfo::eNo);
330b9c1b51eSKate Stone region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable)
331b9c1b51eSKate Stone ? MemoryRegionInfo::eYes
3323385fa08SGreg Clayton : MemoryRegionInfo::eNo);
333ad007563SHoward Hellyer region_info.SetMapped(MemoryRegionInfo::eYes);
334*2f9fa9efSDavid Spickett
335*2f9fa9efSDavid Spickett // A region is memory tagged if there is a memory tag segment that covers
336*2f9fa9efSDavid Spickett // the exact same range.
337*2f9fa9efSDavid Spickett region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
338*2f9fa9efSDavid Spickett const VMRangeToFileOffset::Entry *tag_entry =
339*2f9fa9efSDavid Spickett m_core_tag_ranges.FindEntryStartsAt(permission_entry->GetRangeBase());
340*2f9fa9efSDavid Spickett if (tag_entry &&
341*2f9fa9efSDavid Spickett tag_entry->GetRangeEnd() == permission_entry->GetRangeEnd())
342*2f9fa9efSDavid Spickett region_info.SetMemoryTagged(MemoryRegionInfo::eYes);
343b9c1b51eSKate Stone } else if (load_addr < permission_entry->GetRangeBase()) {
3443385fa08SGreg Clayton region_info.GetRange().SetRangeBase(load_addr);
3453385fa08SGreg Clayton region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
3463385fa08SGreg Clayton region_info.SetReadable(MemoryRegionInfo::eNo);
3473385fa08SGreg Clayton region_info.SetWritable(MemoryRegionInfo::eNo);
3483385fa08SGreg Clayton region_info.SetExecutable(MemoryRegionInfo::eNo);
349ad007563SHoward Hellyer region_info.SetMapped(MemoryRegionInfo::eNo);
350*2f9fa9efSDavid Spickett region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
3513385fa08SGreg Clayton }
35297206d57SZachary Turner return Status();
3533385fa08SGreg Clayton }
354ad007563SHoward Hellyer
355ad007563SHoward Hellyer region_info.GetRange().SetRangeBase(load_addr);
356ad007563SHoward Hellyer region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
357ad007563SHoward Hellyer region_info.SetReadable(MemoryRegionInfo::eNo);
358ad007563SHoward Hellyer region_info.SetWritable(MemoryRegionInfo::eNo);
359ad007563SHoward Hellyer region_info.SetExecutable(MemoryRegionInfo::eNo);
360ad007563SHoward Hellyer region_info.SetMapped(MemoryRegionInfo::eNo);
361*2f9fa9efSDavid Spickett region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
36297206d57SZachary Turner return Status();
3633385fa08SGreg Clayton }
3643385fa08SGreg Clayton
DoReadMemory(lldb::addr_t addr,void * buf,size_t size,Status & error)365b9c1b51eSKate Stone size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
36697206d57SZachary Turner Status &error) {
3674f01ff8bSAshok Thirumurthi ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
3684f01ff8bSAshok Thirumurthi
369248a1305SKonrad Kleine if (core_objfile == nullptr)
3704f01ff8bSAshok Thirumurthi return 0;
3714f01ff8bSAshok Thirumurthi
3724f01ff8bSAshok Thirumurthi // Get the address range
373b9c1b51eSKate Stone const VMRangeToFileOffset::Entry *address_range =
374b9c1b51eSKate Stone m_core_aranges.FindEntryThatContains(addr);
375248a1305SKonrad Kleine if (address_range == nullptr || address_range->GetRangeEnd() < addr) {
376b9c1b51eSKate Stone error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64,
377b9c1b51eSKate Stone addr);
3784f01ff8bSAshok Thirumurthi return 0;
3794f01ff8bSAshok Thirumurthi }
3804f01ff8bSAshok Thirumurthi
3814f01ff8bSAshok Thirumurthi // Convert the address into core file offset
3824f01ff8bSAshok Thirumurthi const lldb::addr_t offset = addr - address_range->GetRangeBase();
3834f01ff8bSAshok Thirumurthi const lldb::addr_t file_start = address_range->data.GetRangeBase();
3844f01ff8bSAshok Thirumurthi const lldb::addr_t file_end = address_range->data.GetRangeEnd();
3854f01ff8bSAshok Thirumurthi size_t bytes_to_read = size; // Number of bytes to read from the core file
3864f01ff8bSAshok Thirumurthi size_t bytes_copied = 0; // Number of bytes actually read from the core file
387b9c1b51eSKate Stone lldb::addr_t bytes_left =
388b9c1b51eSKate Stone 0; // Number of bytes available in the core file from the given address
3894f01ff8bSAshok Thirumurthi
39005097246SAdrian Prantl // Don't proceed if core file doesn't contain the actual data for this
39105097246SAdrian Prantl // address range.
392706c5205SNitesh Jain if (file_start == file_end)
393706c5205SNitesh Jain return 0;
394706c5205SNitesh Jain
39505097246SAdrian Prantl // Figure out how many on-disk bytes remain in this segment starting at the
39605097246SAdrian Prantl // given offset
397729c001eSTodd Fiala if (file_end > file_start + offset)
398729c001eSTodd Fiala bytes_left = file_end - (file_start + offset);
3994f01ff8bSAshok Thirumurthi
4009abd8c1aSDjordje Todorovic if (bytes_to_read > bytes_left)
4014f01ff8bSAshok Thirumurthi bytes_to_read = bytes_left;
4024f01ff8bSAshok Thirumurthi
4034f01ff8bSAshok Thirumurthi // If there is data available on the core file read it
4044f01ff8bSAshok Thirumurthi if (bytes_to_read)
405b9c1b51eSKate Stone bytes_copied =
406b9c1b51eSKate Stone core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
4074f01ff8bSAshok Thirumurthi
4089abd8c1aSDjordje Todorovic return bytes_copied;
4094f01ff8bSAshok Thirumurthi }
4104f01ff8bSAshok Thirumurthi
411*2f9fa9efSDavid Spickett llvm::Expected<std::vector<lldb::addr_t>>
ReadMemoryTags(lldb::addr_t addr,size_t len)412*2f9fa9efSDavid Spickett ProcessElfCore::ReadMemoryTags(lldb::addr_t addr, size_t len) {
413*2f9fa9efSDavid Spickett ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
414*2f9fa9efSDavid Spickett if (core_objfile == nullptr)
415*2f9fa9efSDavid Spickett return llvm::createStringError(llvm::inconvertibleErrorCode(),
416*2f9fa9efSDavid Spickett "No core object file.");
417*2f9fa9efSDavid Spickett
418*2f9fa9efSDavid Spickett llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
419*2f9fa9efSDavid Spickett GetMemoryTagManager();
420*2f9fa9efSDavid Spickett if (!tag_manager_or_err)
421*2f9fa9efSDavid Spickett return tag_manager_or_err.takeError();
422*2f9fa9efSDavid Spickett
423*2f9fa9efSDavid Spickett // LLDB only supports AArch64 MTE tag segments so we do not need to worry
424*2f9fa9efSDavid Spickett // about the segment type here. If you got here then you must have a tag
425*2f9fa9efSDavid Spickett // manager (meaning you are debugging AArch64) and all the segments in this
426*2f9fa9efSDavid Spickett // list will have had type PT_AARCH64_MEMTAG_MTE.
427*2f9fa9efSDavid Spickett const VMRangeToFileOffset::Entry *tag_entry =
428*2f9fa9efSDavid Spickett m_core_tag_ranges.FindEntryThatContains(addr);
429*2f9fa9efSDavid Spickett // If we don't have a tag segment or the range asked for extends outside the
430*2f9fa9efSDavid Spickett // segment.
431*2f9fa9efSDavid Spickett if (!tag_entry || (addr + len) >= tag_entry->GetRangeEnd())
432*2f9fa9efSDavid Spickett return llvm::createStringError(llvm::inconvertibleErrorCode(),
433*2f9fa9efSDavid Spickett "No tag segment that covers this range.");
434*2f9fa9efSDavid Spickett
435*2f9fa9efSDavid Spickett const MemoryTagManager *tag_manager = *tag_manager_or_err;
436*2f9fa9efSDavid Spickett return tag_manager->UnpackTagsFromCoreFileSegment(
437*2f9fa9efSDavid Spickett [core_objfile](lldb::offset_t offset, size_t length, void *dst) {
438*2f9fa9efSDavid Spickett return core_objfile->CopyData(offset, length, dst);
439*2f9fa9efSDavid Spickett },
440*2f9fa9efSDavid Spickett tag_entry->GetRangeBase(), tag_entry->data.GetRangeBase(), addr, len);
441*2f9fa9efSDavid Spickett }
442*2f9fa9efSDavid Spickett
Clear()443b9c1b51eSKate Stone void ProcessElfCore::Clear() {
4444f01ff8bSAshok Thirumurthi m_thread_list.Clear();
4454ceced3fSTodd Fiala
446c963a222SChaoren Lin SetUnixSignals(std::make_shared<UnixSignals>());
4474f01ff8bSAshok Thirumurthi }
4484f01ff8bSAshok Thirumurthi
Initialize()449b9c1b51eSKate Stone void ProcessElfCore::Initialize() {
450c5f28e2aSKamil Rytarowski static llvm::once_flag g_once_flag;
4514f01ff8bSAshok Thirumurthi
452c5f28e2aSKamil Rytarowski llvm::call_once(g_once_flag, []() {
453c8d69828SDavide Italiano PluginManager::RegisterPlugin(GetPluginNameStatic(),
454c8d69828SDavide Italiano GetPluginDescriptionStatic(), CreateInstance);
455c8d69828SDavide Italiano });
4564f01ff8bSAshok Thirumurthi }
4574f01ff8bSAshok Thirumurthi
GetImageInfoAddress()458b9c1b51eSKate Stone lldb::addr_t ProcessElfCore::GetImageInfoAddress() {
4597529df9aSZachary Turner ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
4607529df9aSZachary Turner Address addr = obj_file->GetImageInfoAddress(&GetTarget());
4614f01ff8bSAshok Thirumurthi
4624f01ff8bSAshok Thirumurthi if (addr.IsValid())
4637529df9aSZachary Turner return addr.GetLoadAddress(&GetTarget());
4644f01ff8bSAshok Thirumurthi return LLDB_INVALID_ADDRESS;
4654f01ff8bSAshok Thirumurthi }
4664f01ff8bSAshok Thirumurthi
467197af31aSEd Maste // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
ParseFreeBSDPrStatus(ThreadData & thread_data,const DataExtractor & data,bool lp64)468cef4119cSPavel Labath static void ParseFreeBSDPrStatus(ThreadData &thread_data,
469cef4119cSPavel Labath const DataExtractor &data,
47071e66da0SMichał Górny bool lp64) {
471197af31aSEd Maste lldb::offset_t offset = 0;
472197af31aSEd Maste int pr_version = data.GetU32(&offset);
473262b8dd7SEd Maste
474a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Process);
475b9c1b51eSKate Stone if (log) {
476197af31aSEd Maste if (pr_version > 1)
47763e5fb76SJonas Devlieghere LLDB_LOGF(log, "FreeBSD PRSTATUS unexpected version %d", pr_version);
478197af31aSEd Maste }
479197af31aSEd Maste
4808b4a2832SEd Maste // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
4818b4a2832SEd Maste if (lp64)
4828b4a2832SEd Maste offset += 32;
4838b4a2832SEd Maste else
4848b4a2832SEd Maste offset += 16;
4858b4a2832SEd Maste
486ff8e5f25SEd Maste thread_data.signo = data.GetU32(&offset); // pr_cursig
487343ad623SEd Maste thread_data.tid = data.GetU32(&offset); // pr_pid
4888b4a2832SEd Maste if (lp64)
489197af31aSEd Maste offset += 4;
490197af31aSEd Maste
491197af31aSEd Maste size_t len = data.GetByteSize() - offset;
492ff8e5f25SEd Maste thread_data.gpregset = DataExtractor(data, offset, len);
493262b8dd7SEd Maste }
494262b8dd7SEd Maste
49571e66da0SMichał Górny // Parse a FreeBSD NT_PRPSINFO note - see FreeBSD sys/procfs.h for details.
ParseFreeBSDPrPsInfo(ProcessElfCore & process,const DataExtractor & data,bool lp64)49671e66da0SMichał Górny static void ParseFreeBSDPrPsInfo(ProcessElfCore &process,
49771e66da0SMichał Górny const DataExtractor &data,
49871e66da0SMichał Górny bool lp64) {
49971e66da0SMichał Górny lldb::offset_t offset = 0;
50071e66da0SMichał Górny int pr_version = data.GetU32(&offset);
50171e66da0SMichał Górny
502a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Process);
50371e66da0SMichał Górny if (log) {
50471e66da0SMichał Górny if (pr_version > 1)
50571e66da0SMichał Górny LLDB_LOGF(log, "FreeBSD PRPSINFO unexpected version %d", pr_version);
50671e66da0SMichał Górny }
50771e66da0SMichał Górny
50871e66da0SMichał Górny // Skip pr_psinfosz, pr_fname, pr_psargs
50971e66da0SMichał Górny offset += 108;
51071e66da0SMichał Górny if (lp64)
51171e66da0SMichał Górny offset += 4;
51271e66da0SMichał Górny
51371e66da0SMichał Górny process.SetID(data.GetU32(&offset)); // pr_pid
51471e66da0SMichał Górny }
51571e66da0SMichał Górny
ParseNetBSDProcInfo(const DataExtractor & data,uint32_t & cpi_nlwps,uint32_t & cpi_signo,uint32_t & cpi_siglwp,uint32_t & cpi_pid)516c12f1597SMichal Gorny static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data,
517c12f1597SMichal Gorny uint32_t &cpi_nlwps,
518c12f1597SMichal Gorny uint32_t &cpi_signo,
519c12f1597SMichal Gorny uint32_t &cpi_siglwp,
520c12f1597SMichal Gorny uint32_t &cpi_pid) {
5213eef2b5eSKamil Rytarowski lldb::offset_t offset = 0;
5223eef2b5eSKamil Rytarowski
523c12f1597SMichal Gorny uint32_t version = data.GetU32(&offset);
5243eef2b5eSKamil Rytarowski if (version != 1)
525c12f1597SMichal Gorny return llvm::make_error<llvm::StringError>(
526c12f1597SMichal Gorny "Error parsing NetBSD core(5) notes: Unsupported procinfo version",
527c12f1597SMichal Gorny llvm::inconvertibleErrorCode());
5283eef2b5eSKamil Rytarowski
529c12f1597SMichal Gorny uint32_t cpisize = data.GetU32(&offset);
530c12f1597SMichal Gorny if (cpisize != NETBSD::NT_PROCINFO_SIZE)
531c12f1597SMichal Gorny return llvm::make_error<llvm::StringError>(
532c12f1597SMichal Gorny "Error parsing NetBSD core(5) notes: Unsupported procinfo size",
533c12f1597SMichal Gorny llvm::inconvertibleErrorCode());
534c12f1597SMichal Gorny
535c12f1597SMichal Gorny cpi_signo = data.GetU32(&offset); /* killing signal */
536c12f1597SMichal Gorny
537c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SIGCODE_SIZE;
538c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SIGPEND_SIZE;
539c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SIGMASK_SIZE;
540c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SIGIGNORE_SIZE;
541c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SIGCATCH_SIZE;
542c12f1597SMichal Gorny cpi_pid = data.GetU32(&offset);
543c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_PPID_SIZE;
544c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_PGRP_SIZE;
545c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SID_SIZE;
546c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_RUID_SIZE;
547c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_EUID_SIZE;
548c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SVUID_SIZE;
549c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_RGID_SIZE;
550c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_EGID_SIZE;
551c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_SVGID_SIZE;
552c12f1597SMichal Gorny cpi_nlwps = data.GetU32(&offset); /* number of LWPs */
553c12f1597SMichal Gorny
554c12f1597SMichal Gorny offset += NETBSD::NT_PROCINFO_CPI_NAME_SIZE;
555c12f1597SMichal Gorny cpi_siglwp = data.GetU32(&offset); /* LWP target of killing signal */
556c12f1597SMichal Gorny
557c12f1597SMichal Gorny return llvm::Error::success();
5583eef2b5eSKamil Rytarowski }
5593eef2b5eSKamil Rytarowski
ParseOpenBSDProcInfo(ThreadData & thread_data,const DataExtractor & data)560cef4119cSPavel Labath static void ParseOpenBSDProcInfo(ThreadData &thread_data,
561cef4119cSPavel Labath const DataExtractor &data) {
56212801f1eSKamil Rytarowski lldb::offset_t offset = 0;
56312801f1eSKamil Rytarowski
56412801f1eSKamil Rytarowski int version = data.GetU32(&offset);
56512801f1eSKamil Rytarowski if (version != 1)
56612801f1eSKamil Rytarowski return;
56712801f1eSKamil Rytarowski
56812801f1eSKamil Rytarowski offset += 4;
56912801f1eSKamil Rytarowski thread_data.signo = data.GetU32(&offset);
57012801f1eSKamil Rytarowski }
57112801f1eSKamil Rytarowski
572cef4119cSPavel Labath llvm::Expected<std::vector<CoreNote>>
parseSegment(const DataExtractor & segment)573cef4119cSPavel Labath ProcessElfCore::parseSegment(const DataExtractor &segment) {
5744f01ff8bSAshok Thirumurthi lldb::offset_t offset = 0;
575cef4119cSPavel Labath std::vector<CoreNote> result;
576cef4119cSPavel Labath
577cef4119cSPavel Labath while (offset < segment.GetByteSize()) {
578cef4119cSPavel Labath ELFNote note = ELFNote();
579cef4119cSPavel Labath if (!note.Parse(segment, &offset))
580cef4119cSPavel Labath return llvm::make_error<llvm::StringError>(
581cef4119cSPavel Labath "Unable to parse note segment", llvm::inconvertibleErrorCode());
582cef4119cSPavel Labath
583cef4119cSPavel Labath size_t note_start = offset;
584cef4119cSPavel Labath size_t note_size = llvm::alignTo(note.n_descsz, 4);
585cef4119cSPavel Labath
58614f44303SJan Kratochvil result.push_back({note, DataExtractor(segment, note_start, note_size)});
587cef4119cSPavel Labath offset += note_size;
588cef4119cSPavel Labath }
589cef4119cSPavel Labath
590cef4119cSPavel Labath return std::move(result);
591cef4119cSPavel Labath }
592cef4119cSPavel Labath
parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes)593cef4119cSPavel Labath llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
59471e66da0SMichał Górny ArchSpec arch = GetArchitecture();
59571e66da0SMichał Górny bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
59671e66da0SMichał Górny arch.GetMachine() == llvm::Triple::mips64 ||
59771e66da0SMichał Górny arch.GetMachine() == llvm::Triple::ppc64 ||
59871e66da0SMichał Górny arch.GetMachine() == llvm::Triple::x86_64);
59935f091ddSEd Maste bool have_prstatus = false;
60035f091ddSEd Maste bool have_prpsinfo = false;
601cef4119cSPavel Labath ThreadData thread_data;
602cef4119cSPavel Labath for (const auto ¬e : notes) {
603cef4119cSPavel Labath if (note.info.n_name != "FreeBSD")
604cef4119cSPavel Labath continue;
6054f01ff8bSAshok Thirumurthi
606b9f31b6fSPavel Labath if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) ||
607b9f31b6fSPavel Labath (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) {
608cef4119cSPavel Labath assert(thread_data.gpregset.GetByteSize() > 0);
6094f01ff8bSAshok Thirumurthi // Add the new thread to thread list
610cef4119cSPavel Labath m_thread_data.push_back(thread_data);
611cef4119cSPavel Labath thread_data = ThreadData();
61235f091ddSEd Maste have_prstatus = false;
61335f091ddSEd Maste have_prpsinfo = false;
6144f01ff8bSAshok Thirumurthi }
6154f01ff8bSAshok Thirumurthi
616cef4119cSPavel Labath switch (note.info.n_type) {
617b9f31b6fSPavel Labath case ELF::NT_PRSTATUS:
61876859d6cSEd Maste have_prstatus = true;
61971e66da0SMichał Górny ParseFreeBSDPrStatus(thread_data, note.data, lp64);
62076859d6cSEd Maste break;
621b9f31b6fSPavel Labath case ELF::NT_PRPSINFO:
62276859d6cSEd Maste have_prpsinfo = true;
62371e66da0SMichał Górny ParseFreeBSDPrPsInfo(*this, note.data, lp64);
624c05ae522SEd Maste break;
625b9f31b6fSPavel Labath case ELF::NT_FREEBSD_THRMISC: {
626cef4119cSPavel Labath lldb::offset_t offset = 0;
627cef4119cSPavel Labath thread_data.name = note.data.GetCStr(&offset, 20);
628c05ae522SEd Maste break;
629cef4119cSPavel Labath }
630b9f31b6fSPavel Labath case ELF::NT_FREEBSD_PROCSTAT_AUXV:
631c05ae522SEd Maste // FIXME: FreeBSD sticks an int at the beginning of the note
632cef4119cSPavel Labath m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4);
633f9ec0d1eSJustin Hibbits break;
63476859d6cSEd Maste default:
635bc8cc867SPavel Labath thread_data.notes.push_back(note);
63676859d6cSEd Maste break;
63776859d6cSEd Maste }
638cef4119cSPavel Labath }
639cef4119cSPavel Labath if (!have_prstatus) {
640cef4119cSPavel Labath return llvm::make_error<llvm::StringError>(
641cef4119cSPavel Labath "Could not find NT_PRSTATUS note in core file.",
642cef4119cSPavel Labath llvm::inconvertibleErrorCode());
643cef4119cSPavel Labath }
644cef4119cSPavel Labath m_thread_data.push_back(thread_data);
645cef4119cSPavel Labath return llvm::Error::success();
646cef4119cSPavel Labath }
647cef4119cSPavel Labath
648c12f1597SMichal Gorny /// NetBSD specific Thread context from PT_NOTE segment
649c12f1597SMichal Gorny ///
650c12f1597SMichal Gorny /// NetBSD ELF core files use notes to provide information about
651c12f1597SMichal Gorny /// the process's state. The note name is "NetBSD-CORE" for
652c12f1597SMichal Gorny /// information that is global to the process, and "NetBSD-CORE@nn",
653c12f1597SMichal Gorny /// where "nn" is the lwpid of the LWP that the information belongs
654c12f1597SMichal Gorny /// to (such as register state).
655c12f1597SMichal Gorny ///
656c12f1597SMichal Gorny /// NetBSD uses the following note identifiers:
657c12f1597SMichal Gorny ///
658c12f1597SMichal Gorny /// ELF_NOTE_NETBSD_CORE_PROCINFO (value 1)
659c12f1597SMichal Gorny /// Note is a "netbsd_elfcore_procinfo" structure.
660c12f1597SMichal Gorny /// ELF_NOTE_NETBSD_CORE_AUXV (value 2; since NetBSD 8.0)
661c12f1597SMichal Gorny /// Note is an array of AuxInfo structures.
662c12f1597SMichal Gorny ///
663c12f1597SMichal Gorny /// NetBSD also uses ptrace(2) request numbers (the ones that exist in
664c12f1597SMichal Gorny /// machine-dependent space) to identify register info notes. The
665c12f1597SMichal Gorny /// info in such notes is in the same format that ptrace(2) would
666c12f1597SMichal Gorny /// export that information.
667c12f1597SMichal Gorny ///
668c12f1597SMichal Gorny /// For more information see /usr/include/sys/exec_elf.h
669c12f1597SMichal Gorny ///
parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes)670cef4119cSPavel Labath llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
671cef4119cSPavel Labath ThreadData thread_data;
672c12f1597SMichal Gorny bool had_nt_regs = false;
673c12f1597SMichal Gorny
674c12f1597SMichal Gorny // To be extracted from struct netbsd_elfcore_procinfo
675c12f1597SMichal Gorny // Used to sanity check of the LWPs of the process
676c12f1597SMichal Gorny uint32_t nlwps = 0;
6774871dfc6SSlava Gurevich uint32_t signo = 0; // killing signal
6784871dfc6SSlava Gurevich uint32_t siglwp = 0; // LWP target of killing signal
6794871dfc6SSlava Gurevich uint32_t pr_pid = 0;
680c12f1597SMichal Gorny
681cef4119cSPavel Labath for (const auto ¬e : notes) {
682c12f1597SMichal Gorny llvm::StringRef name = note.info.n_name;
683cef4119cSPavel Labath
684c12f1597SMichal Gorny if (name == "NetBSD-CORE") {
685c12f1597SMichal Gorny if (note.info.n_type == NETBSD::NT_PROCINFO) {
686c12f1597SMichal Gorny llvm::Error error = ParseNetBSDProcInfo(note.data, nlwps, signo,
687c12f1597SMichal Gorny siglwp, pr_pid);
688c12f1597SMichal Gorny if (error)
689c12f1597SMichal Gorny return error;
690c12f1597SMichal Gorny SetID(pr_pid);
691c12f1597SMichal Gorny } else if (note.info.n_type == NETBSD::NT_AUXV) {
692bc8cc867SPavel Labath m_auxv = note.data;
693c12f1597SMichal Gorny }
694c12f1597SMichal Gorny } else if (name.consume_front("NetBSD-CORE@")) {
695c12f1597SMichal Gorny lldb::tid_t tid;
696c12f1597SMichal Gorny if (name.getAsInteger(10, tid))
697c12f1597SMichal Gorny return llvm::make_error<llvm::StringError>(
698c12f1597SMichal Gorny "Error parsing NetBSD core(5) notes: Cannot convert LWP ID "
699c12f1597SMichal Gorny "to integer",
700c12f1597SMichal Gorny llvm::inconvertibleErrorCode());
701bc8cc867SPavel Labath
702c12f1597SMichal Gorny switch (GetArchitecture().GetMachine()) {
703d8519f4aSMichal Gorny case llvm::Triple::aarch64: {
704d8519f4aSMichal Gorny // Assume order PT_GETREGS, PT_GETFPREGS
705d8519f4aSMichal Gorny if (note.info.n_type == NETBSD::AARCH64::NT_REGS) {
706d8519f4aSMichal Gorny // If this is the next thread, push the previous one first.
707d8519f4aSMichal Gorny if (had_nt_regs) {
708d8519f4aSMichal Gorny m_thread_data.push_back(thread_data);
709d8519f4aSMichal Gorny thread_data = ThreadData();
710d8519f4aSMichal Gorny had_nt_regs = false;
711d8519f4aSMichal Gorny }
712d8519f4aSMichal Gorny
713d8519f4aSMichal Gorny thread_data.gpregset = note.data;
714d8519f4aSMichal Gorny thread_data.tid = tid;
715d8519f4aSMichal Gorny if (thread_data.gpregset.GetByteSize() == 0)
716d8519f4aSMichal Gorny return llvm::make_error<llvm::StringError>(
717d8519f4aSMichal Gorny "Could not find general purpose registers note in core file.",
718d8519f4aSMichal Gorny llvm::inconvertibleErrorCode());
719d8519f4aSMichal Gorny had_nt_regs = true;
720d8519f4aSMichal Gorny } else if (note.info.n_type == NETBSD::AARCH64::NT_FPREGS) {
721d8519f4aSMichal Gorny if (!had_nt_regs || tid != thread_data.tid)
722d8519f4aSMichal Gorny return llvm::make_error<llvm::StringError>(
723d8519f4aSMichal Gorny "Error parsing NetBSD core(5) notes: Unexpected order "
724d8519f4aSMichal Gorny "of NOTEs PT_GETFPREG before PT_GETREG",
725d8519f4aSMichal Gorny llvm::inconvertibleErrorCode());
726d8519f4aSMichal Gorny thread_data.notes.push_back(note);
727d8519f4aSMichal Gorny }
728d8519f4aSMichal Gorny } break;
729d4c437c4SMichał Górny case llvm::Triple::x86: {
730d4c437c4SMichał Górny // Assume order PT_GETREGS, PT_GETFPREGS
731d4c437c4SMichał Górny if (note.info.n_type == NETBSD::I386::NT_REGS) {
732d4c437c4SMichał Górny // If this is the next thread, push the previous one first.
733d4c437c4SMichał Górny if (had_nt_regs) {
734d4c437c4SMichał Górny m_thread_data.push_back(thread_data);
735d4c437c4SMichał Górny thread_data = ThreadData();
736d4c437c4SMichał Górny had_nt_regs = false;
737d4c437c4SMichał Górny }
738d4c437c4SMichał Górny
739d4c437c4SMichał Górny thread_data.gpregset = note.data;
740d4c437c4SMichał Górny thread_data.tid = tid;
741d4c437c4SMichał Górny if (thread_data.gpregset.GetByteSize() == 0)
742d4c437c4SMichał Górny return llvm::make_error<llvm::StringError>(
743d4c437c4SMichał Górny "Could not find general purpose registers note in core file.",
744d4c437c4SMichał Górny llvm::inconvertibleErrorCode());
745d4c437c4SMichał Górny had_nt_regs = true;
746d4c437c4SMichał Górny } else if (note.info.n_type == NETBSD::I386::NT_FPREGS) {
747d4c437c4SMichał Górny if (!had_nt_regs || tid != thread_data.tid)
748d4c437c4SMichał Górny return llvm::make_error<llvm::StringError>(
749d4c437c4SMichał Górny "Error parsing NetBSD core(5) notes: Unexpected order "
750d4c437c4SMichał Górny "of NOTEs PT_GETFPREG before PT_GETREG",
751d4c437c4SMichał Górny llvm::inconvertibleErrorCode());
752d4c437c4SMichał Górny thread_data.notes.push_back(note);
753d4c437c4SMichał Górny }
754d4c437c4SMichał Górny } break;
755c12f1597SMichal Gorny case llvm::Triple::x86_64: {
756c12f1597SMichal Gorny // Assume order PT_GETREGS, PT_GETFPREGS
757c12f1597SMichal Gorny if (note.info.n_type == NETBSD::AMD64::NT_REGS) {
758c12f1597SMichal Gorny // If this is the next thread, push the previous one first.
759c12f1597SMichal Gorny if (had_nt_regs) {
760c12f1597SMichal Gorny m_thread_data.push_back(thread_data);
761c12f1597SMichal Gorny thread_data = ThreadData();
762c12f1597SMichal Gorny had_nt_regs = false;
763c12f1597SMichal Gorny }
764c12f1597SMichal Gorny
765cef4119cSPavel Labath thread_data.gpregset = note.data;
766c12f1597SMichal Gorny thread_data.tid = tid;
767c12f1597SMichal Gorny if (thread_data.gpregset.GetByteSize() == 0)
768cef4119cSPavel Labath return llvm::make_error<llvm::StringError>(
769cef4119cSPavel Labath "Could not find general purpose registers note in core file.",
770cef4119cSPavel Labath llvm::inconvertibleErrorCode());
771c12f1597SMichal Gorny had_nt_regs = true;
772c12f1597SMichal Gorny } else if (note.info.n_type == NETBSD::AMD64::NT_FPREGS) {
773c12f1597SMichal Gorny if (!had_nt_regs || tid != thread_data.tid)
774c12f1597SMichal Gorny return llvm::make_error<llvm::StringError>(
775c12f1597SMichal Gorny "Error parsing NetBSD core(5) notes: Unexpected order "
776c12f1597SMichal Gorny "of NOTEs PT_GETFPREG before PT_GETREG",
777c12f1597SMichal Gorny llvm::inconvertibleErrorCode());
778c12f1597SMichal Gorny thread_data.notes.push_back(note);
779cef4119cSPavel Labath }
780c12f1597SMichal Gorny } break;
781c12f1597SMichal Gorny default:
782c12f1597SMichal Gorny break;
783c12f1597SMichal Gorny }
784c12f1597SMichal Gorny }
785c12f1597SMichal Gorny }
786c12f1597SMichal Gorny
787c12f1597SMichal Gorny // Push the last thread.
788c12f1597SMichal Gorny if (had_nt_regs)
789cef4119cSPavel Labath m_thread_data.push_back(thread_data);
790c12f1597SMichal Gorny
791c12f1597SMichal Gorny if (m_thread_data.empty())
792c12f1597SMichal Gorny return llvm::make_error<llvm::StringError>(
793c12f1597SMichal Gorny "Error parsing NetBSD core(5) notes: No threads information "
794c12f1597SMichal Gorny "specified in notes",
795c12f1597SMichal Gorny llvm::inconvertibleErrorCode());
796c12f1597SMichal Gorny
797c12f1597SMichal Gorny if (m_thread_data.size() != nlwps)
798c12f1597SMichal Gorny return llvm::make_error<llvm::StringError>(
799c12f1597SMichal Gorny "Error parsing NetBSD core(5) notes: Mismatch between the number "
800c12f1597SMichal Gorny "of LWPs in netbsd_elfcore_procinfo and the number of LWPs specified "
801c12f1597SMichal Gorny "by MD notes",
802c12f1597SMichal Gorny llvm::inconvertibleErrorCode());
803c12f1597SMichal Gorny
804c12f1597SMichal Gorny // Signal targeted at the whole process.
805c12f1597SMichal Gorny if (siglwp == 0) {
806c12f1597SMichal Gorny for (auto &data : m_thread_data)
807c12f1597SMichal Gorny data.signo = signo;
808c12f1597SMichal Gorny }
809c12f1597SMichal Gorny // Signal destined for a particular LWP.
810c12f1597SMichal Gorny else {
811c12f1597SMichal Gorny bool passed = false;
812c12f1597SMichal Gorny
813c12f1597SMichal Gorny for (auto &data : m_thread_data) {
814c12f1597SMichal Gorny if (data.tid == siglwp) {
815c12f1597SMichal Gorny data.signo = signo;
816c12f1597SMichal Gorny passed = true;
817c12f1597SMichal Gorny break;
818c12f1597SMichal Gorny }
819c12f1597SMichal Gorny }
820c12f1597SMichal Gorny
821c12f1597SMichal Gorny if (!passed)
822c12f1597SMichal Gorny return llvm::make_error<llvm::StringError>(
823c12f1597SMichal Gorny "Error parsing NetBSD core(5) notes: Signal passed to unknown LWP",
824c12f1597SMichal Gorny llvm::inconvertibleErrorCode());
825c12f1597SMichal Gorny }
826c12f1597SMichal Gorny
827cef4119cSPavel Labath return llvm::Error::success();
828cef4119cSPavel Labath }
829cef4119cSPavel Labath
parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes)830cef4119cSPavel Labath llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {
8314871dfc6SSlava Gurevich ThreadData thread_data = {};
832cef4119cSPavel Labath for (const auto ¬e : notes) {
83305097246SAdrian Prantl // OpenBSD per-thread information is stored in notes named "OpenBSD@nnn" so
83405097246SAdrian Prantl // match on the initial part of the string.
835cef4119cSPavel Labath if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD"))
836cef4119cSPavel Labath continue;
837cef4119cSPavel Labath
838cef4119cSPavel Labath switch (note.info.n_type) {
839fd2c8d65SPavel Labath case OPENBSD::NT_PROCINFO:
840cef4119cSPavel Labath ParseOpenBSDProcInfo(thread_data, note.data);
84112801f1eSKamil Rytarowski break;
842fd2c8d65SPavel Labath case OPENBSD::NT_AUXV:
843cef4119cSPavel Labath m_auxv = note.data;
84412801f1eSKamil Rytarowski break;
845fd2c8d65SPavel Labath case OPENBSD::NT_REGS:
846cef4119cSPavel Labath thread_data.gpregset = note.data;
84712801f1eSKamil Rytarowski break;
848bc8cc867SPavel Labath default:
849bc8cc867SPavel Labath thread_data.notes.push_back(note);
85012801f1eSKamil Rytarowski break;
85112801f1eSKamil Rytarowski }
852cef4119cSPavel Labath }
853cef4119cSPavel Labath if (thread_data.gpregset.GetByteSize() == 0) {
854cef4119cSPavel Labath return llvm::make_error<llvm::StringError>(
855cef4119cSPavel Labath "Could not find general purpose registers note in core file.",
856cef4119cSPavel Labath llvm::inconvertibleErrorCode());
857cef4119cSPavel Labath }
858cef4119cSPavel Labath m_thread_data.push_back(thread_data);
859cef4119cSPavel Labath return llvm::Error::success();
860cef4119cSPavel Labath }
861fd2c8d65SPavel Labath
862cef4119cSPavel Labath /// A description of a linux process usually contains the following NOTE
863cef4119cSPavel Labath /// entries:
864cef4119cSPavel Labath /// - NT_PRPSINFO - General process information like pid, uid, name, ...
865cef4119cSPavel Labath /// - NT_SIGINFO - Information about the signal that terminated the process
866cef4119cSPavel Labath /// - NT_AUXV - Process auxiliary vector
867cef4119cSPavel Labath /// - NT_FILE - Files mapped into memory
868cef4119cSPavel Labath ///
869cef4119cSPavel Labath /// Additionally, for each thread in the process the core file will contain at
870cef4119cSPavel Labath /// least the NT_PRSTATUS note, containing the thread id and general purpose
871cef4119cSPavel Labath /// registers. It may include additional notes for other register sets (floating
872cef4119cSPavel Labath /// point and vector registers, ...). The tricky part here is that some of these
873cef4119cSPavel Labath /// notes have "CORE" in their owner fields, while other set it to "LINUX".
parseLinuxNotes(llvm::ArrayRef<CoreNote> notes)874cef4119cSPavel Labath llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
875cef4119cSPavel Labath const ArchSpec &arch = GetArchitecture();
876cef4119cSPavel Labath bool have_prstatus = false;
877cef4119cSPavel Labath bool have_prpsinfo = false;
878cef4119cSPavel Labath ThreadData thread_data;
879cef4119cSPavel Labath for (const auto ¬e : notes) {
880cef4119cSPavel Labath if (note.info.n_name != "CORE" && note.info.n_name != "LINUX")
881cef4119cSPavel Labath continue;
882cef4119cSPavel Labath
883b9f31b6fSPavel Labath if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) ||
884b9f31b6fSPavel Labath (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) {
885cef4119cSPavel Labath assert(thread_data.gpregset.GetByteSize() > 0);
886cef4119cSPavel Labath // Add the new thread to thread list
887cef4119cSPavel Labath m_thread_data.push_back(thread_data);
888cef4119cSPavel Labath thread_data = ThreadData();
889cef4119cSPavel Labath have_prstatus = false;
890cef4119cSPavel Labath have_prpsinfo = false;
891cef4119cSPavel Labath }
892cef4119cSPavel Labath
893cef4119cSPavel Labath switch (note.info.n_type) {
894b9f31b6fSPavel Labath case ELF::NT_PRSTATUS: {
895cef4119cSPavel Labath have_prstatus = true;
896cef4119cSPavel Labath ELFLinuxPrStatus prstatus;
897cef4119cSPavel Labath Status status = prstatus.Parse(note.data, arch);
898cef4119cSPavel Labath if (status.Fail())
899cef4119cSPavel Labath return status.ToError();
900cef4119cSPavel Labath thread_data.prstatus_sig = prstatus.pr_cursig;
901cef4119cSPavel Labath thread_data.tid = prstatus.pr_pid;
902cef4119cSPavel Labath uint32_t header_size = ELFLinuxPrStatus::GetSize(arch);
903cef4119cSPavel Labath size_t len = note.data.GetByteSize() - header_size;
904cef4119cSPavel Labath thread_data.gpregset = DataExtractor(note.data, header_size, len);
905cef4119cSPavel Labath break;
906cef4119cSPavel Labath }
907b9f31b6fSPavel Labath case ELF::NT_PRPSINFO: {
908cef4119cSPavel Labath have_prpsinfo = true;
909cef4119cSPavel Labath ELFLinuxPrPsInfo prpsinfo;
910cef4119cSPavel Labath Status status = prpsinfo.Parse(note.data, arch);
911cef4119cSPavel Labath if (status.Fail())
912cef4119cSPavel Labath return status.ToError();
91337713073SJason Molenda thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname)));
914cef4119cSPavel Labath SetID(prpsinfo.pr_pid);
915cef4119cSPavel Labath break;
916cef4119cSPavel Labath }
917b9f31b6fSPavel Labath case ELF::NT_SIGINFO: {
918cef4119cSPavel Labath ELFLinuxSigInfo siginfo;
919cef4119cSPavel Labath Status status = siginfo.Parse(note.data, arch);
920cef4119cSPavel Labath if (status.Fail())
921cef4119cSPavel Labath return status.ToError();
922cef4119cSPavel Labath thread_data.signo = siginfo.si_signo;
923cef4119cSPavel Labath break;
924cef4119cSPavel Labath }
925b9f31b6fSPavel Labath case ELF::NT_FILE: {
926cef4119cSPavel Labath m_nt_file_entries.clear();
927cef4119cSPavel Labath lldb::offset_t offset = 0;
928cef4119cSPavel Labath const uint64_t count = note.data.GetAddress(&offset);
929cef4119cSPavel Labath note.data.GetAddress(&offset); // Skip page size
930cef4119cSPavel Labath for (uint64_t i = 0; i < count; ++i) {
931cef4119cSPavel Labath NT_FILE_Entry entry;
932cef4119cSPavel Labath entry.start = note.data.GetAddress(&offset);
933cef4119cSPavel Labath entry.end = note.data.GetAddress(&offset);
934cef4119cSPavel Labath entry.file_ofs = note.data.GetAddress(&offset);
935cef4119cSPavel Labath m_nt_file_entries.push_back(entry);
936cef4119cSPavel Labath }
937cef4119cSPavel Labath for (uint64_t i = 0; i < count; ++i) {
938cef4119cSPavel Labath const char *path = note.data.GetCStr(&offset);
939cef4119cSPavel Labath if (path && path[0])
940cef4119cSPavel Labath m_nt_file_entries[i].path.SetCString(path);
941cef4119cSPavel Labath }
942cef4119cSPavel Labath break;
943cef4119cSPavel Labath }
944b9f31b6fSPavel Labath case ELF::NT_AUXV:
945cef4119cSPavel Labath m_auxv = note.data;
9464f01ff8bSAshok Thirumurthi break;
947bc8cc867SPavel Labath default:
948bc8cc867SPavel Labath thread_data.notes.push_back(note);
949fd2c8d65SPavel Labath break;
950a228c46cSDimitar Vlahovski }
95176859d6cSEd Maste }
9524f01ff8bSAshok Thirumurthi // Add last entry in the note section
953cef4119cSPavel Labath if (have_prstatus)
954cef4119cSPavel Labath m_thread_data.push_back(thread_data);
955cef4119cSPavel Labath return llvm::Error::success();
9564f01ff8bSAshok Thirumurthi }
957023dd64fSDimitar Vlahovski
958cef4119cSPavel Labath /// Parse Thread context from PT_NOTE segment and store it in the thread list
959cef4119cSPavel Labath /// A note segment consists of one or more NOTE entries, but their types and
960cef4119cSPavel Labath /// meaning differ depending on the OS.
ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader & segment_header,const DataExtractor & segment_data)961cef4119cSPavel Labath llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
96214f44303SJan Kratochvil const elf::ELFProgramHeader &segment_header,
96314f44303SJan Kratochvil const DataExtractor &segment_data) {
9645ea7ecdbSPavel Labath assert(segment_header.p_type == llvm::ELF::PT_NOTE);
965cef4119cSPavel Labath
966cef4119cSPavel Labath auto notes_or_error = parseSegment(segment_data);
967cef4119cSPavel Labath if(!notes_or_error)
968cef4119cSPavel Labath return notes_or_error.takeError();
969cef4119cSPavel Labath switch (GetArchitecture().GetTriple().getOS()) {
970cef4119cSPavel Labath case llvm::Triple::FreeBSD:
971cef4119cSPavel Labath return parseFreeBSDNotes(*notes_or_error);
972cef4119cSPavel Labath case llvm::Triple::Linux:
973cef4119cSPavel Labath return parseLinuxNotes(*notes_or_error);
974cef4119cSPavel Labath case llvm::Triple::NetBSD:
975cef4119cSPavel Labath return parseNetBSDNotes(*notes_or_error);
976cef4119cSPavel Labath case llvm::Triple::OpenBSD:
977cef4119cSPavel Labath return parseOpenBSDNotes(*notes_or_error);
978cef4119cSPavel Labath default:
979cef4119cSPavel Labath return llvm::make_error<llvm::StringError>(
980cef4119cSPavel Labath "Don't know how to parse core file. Unsupported OS.",
981cef4119cSPavel Labath llvm::inconvertibleErrorCode());
982cef4119cSPavel Labath }
9834f01ff8bSAshok Thirumurthi }
9844f01ff8bSAshok Thirumurthi
GetNumThreadContexts()985b9c1b51eSKate Stone uint32_t ProcessElfCore::GetNumThreadContexts() {
9864f01ff8bSAshok Thirumurthi if (!m_thread_data_valid)
9874f01ff8bSAshok Thirumurthi DoLoadCore();
9884f01ff8bSAshok Thirumurthi return m_thread_data.size();
9894f01ff8bSAshok Thirumurthi }
9904f01ff8bSAshok Thirumurthi
GetArchitecture()991b9c1b51eSKate Stone ArchSpec ProcessElfCore::GetArchitecture() {
992f760f5aeSPavel Labath ArchSpec arch = m_core_module_sp->GetObjectFile()->GetArchitecture();
993706c5205SNitesh Jain
994706c5205SNitesh Jain ArchSpec target_arch = GetTarget().GetArchitecture();
9957cb7df2bSTamas Berghammer arch.MergeFrom(target_arch);
996706c5205SNitesh Jain
99705097246SAdrian Prantl // On MIPS there is no way to differentiate betwenn 32bit and 64bit core
99805097246SAdrian Prantl // files and this information can't be merged in from the target arch so we
99905097246SAdrian Prantl // fail back to unconditionally returning the target arch in this config.
10007cb7df2bSTamas Berghammer if (target_arch.IsMIPS()) {
1001706c5205SNitesh Jain return target_arch;
10027cb7df2bSTamas Berghammer }
1003706c5205SNitesh Jain
10044f01ff8bSAshok Thirumurthi return arch;
10054f01ff8bSAshok Thirumurthi }
10064f01ff8bSAshok Thirumurthi
GetAuxvData()1007943faef1SAntonio Afonso DataExtractor ProcessElfCore::GetAuxvData() {
10084f01ff8bSAshok Thirumurthi const uint8_t *start = m_auxv.GetDataStart();
10094f01ff8bSAshok Thirumurthi size_t len = m_auxv.GetByteSize();
10104f01ff8bSAshok Thirumurthi lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len));
1011943faef1SAntonio Afonso return DataExtractor(buffer, GetByteOrder(), GetAddressByteSize());
10124f01ff8bSAshok Thirumurthi }
1013a933d517SPavel Labath
GetProcessInfo(ProcessInstanceInfo & info)1014b9c1b51eSKate Stone bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
1015a933d517SPavel Labath info.Clear();
1016a933d517SPavel Labath info.SetProcessID(GetID());
1017a933d517SPavel Labath info.SetArchitecture(GetArchitecture());
1018a933d517SPavel Labath lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
1019b9c1b51eSKate Stone if (module_sp) {
1020a933d517SPavel Labath const bool add_exe_file_as_first_arg = false;
1021b9c1b51eSKate Stone info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
1022b9c1b51eSKate Stone add_exe_file_as_first_arg);
1023a933d517SPavel Labath }
1024a933d517SPavel Labath return true;
1025a933d517SPavel Labath }
1026