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