ProcessElfCore.cpp revision 321369
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
40using namespace lldb_private;
41
42ConstString ProcessElfCore::GetPluginNameStatic() {
43  static ConstString g_name("elf-core");
44  return g_name;
45}
46
47const char *ProcessElfCore::GetPluginDescriptionStatic() {
48  return "ELF core dump plug-in.";
49}
50
51void ProcessElfCore::Terminate() {
52  PluginManager::UnregisterPlugin(ProcessElfCore::CreateInstance);
53}
54
55lldb::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
82bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp,
83                              bool plugin_specified_by_name) {
84  // For now we are just making sure the file exists for a given 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//----------------------------------------------------------------------
101ProcessElfCore::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//----------------------------------------------------------------------
112ProcessElfCore::~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//----------------------------------------------------------------------
124ConstString ProcessElfCore::GetPluginName() { return GetPluginNameStatic(); }
125
126uint32_t ProcessElfCore::GetPluginVersion() { return 1; }
127
128lldb::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//----------------------------------------------------------------------
160Status 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
269lldb_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
276bool 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
290void ProcessElfCore::RefreshStateAfterStop() {}
291
292Status ProcessElfCore::DoDestroy() { return Status(); }
293
294//------------------------------------------------------------------
295// Process Queries
296//------------------------------------------------------------------
297
298bool ProcessElfCore::IsAlive() { return true; }
299
300//------------------------------------------------------------------
301// Process Memory
302//------------------------------------------------------------------
303size_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
310Status 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
350size_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
405void ProcessElfCore::Clear() {
406  m_thread_list.Clear();
407  m_os = llvm::Triple::UnknownOS;
408
409  SetUnixSignals(std::make_shared<UnixSignals>());
410}
411
412void 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
421lldb::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
431enum {
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
447namespace FREEBSD {
448
449enum {
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
459namespace NETBSD {
460
461enum { 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.
465static 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
495static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) {
496  lldb::offset_t offset = 0;
497  thread_data.name = data.GetCStr(&offset, 20);
498}
499
500static 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
511static 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).
543Status 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
720uint32_t ProcessElfCore::GetNumThreadContexts() {
721  if (!m_thread_data_valid)
722    DoLoadCore();
723  return m_thread_data.size();
724}
725
726ArchSpec 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
740const 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
747bool 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