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 &region_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 &note : 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 &note : 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 &note : 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 &note : 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