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