1254721Semaste//===-- ProcessElfCore.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste// C Includes
11254721Semaste#include <stdlib.h>
12254721Semaste
13254721Semaste// Other libraries and framework includes
14254721Semaste#include "lldb/Core/PluginManager.h"
15254721Semaste#include "lldb/Core/Module.h"
16254721Semaste#include "lldb/Core/ModuleSpec.h"
17254721Semaste#include "lldb/Core/Section.h"
18254721Semaste#include "lldb/Core/State.h"
19254721Semaste#include "lldb/Core/DataBufferHeap.h"
20254721Semaste#include "lldb/Target/Target.h"
21254721Semaste#include "lldb/Target/DynamicLoader.h"
22254721Semaste#include "ProcessPOSIXLog.h"
23254721Semaste
24254721Semaste#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
25254721Semaste#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
26254721Semaste
27254721Semaste// Project includes
28254721Semaste#include "ProcessElfCore.h"
29254721Semaste#include "ThreadElfCore.h"
30254721Semaste
31254721Semasteusing namespace lldb_private;
32254721Semaste
33254721SemasteConstString
34254721SemasteProcessElfCore::GetPluginNameStatic()
35254721Semaste{
36254721Semaste    static ConstString g_name("elf-core");
37254721Semaste    return g_name;
38254721Semaste}
39254721Semaste
40254721Semasteconst char *
41254721SemasteProcessElfCore::GetPluginDescriptionStatic()
42254721Semaste{
43254721Semaste    return "ELF core dump plug-in.";
44254721Semaste}
45254721Semaste
46254721Semastevoid
47254721SemasteProcessElfCore::Terminate()
48254721Semaste{
49254721Semaste    PluginManager::UnregisterPlugin (ProcessElfCore::CreateInstance);
50254721Semaste}
51254721Semaste
52254721Semaste
53254721Semastelldb::ProcessSP
54254721SemasteProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
55254721Semaste{
56254721Semaste    lldb::ProcessSP process_sp;
57254721Semaste    if (crash_file)
58254721Semaste        process_sp.reset(new ProcessElfCore (target, listener, *crash_file));
59254721Semaste    return process_sp;
60254721Semaste}
61254721Semaste
62254721Semastebool
63254721SemasteProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
64254721Semaste{
65254721Semaste    // For now we are just making sure the file exists for a given module
66254721Semaste    if (!m_core_module_sp && m_core_file.Exists())
67254721Semaste    {
68254721Semaste        ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
69254721Semaste        Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp,
70254721Semaste                                                  NULL, NULL, NULL));
71254721Semaste        if (m_core_module_sp)
72254721Semaste        {
73254721Semaste            ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
74254721Semaste            if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
75254721Semaste                return true;
76254721Semaste        }
77254721Semaste    }
78254721Semaste    return false;
79254721Semaste}
80254721Semaste
81254721Semaste//----------------------------------------------------------------------
82254721Semaste// ProcessElfCore constructor
83254721Semaste//----------------------------------------------------------------------
84254721SemasteProcessElfCore::ProcessElfCore(Target& target, Listener &listener,
85254721Semaste                               const FileSpec &core_file) :
86254721Semaste    Process (target, listener),
87254721Semaste    m_core_module_sp (),
88254721Semaste    m_core_file (core_file),
89254721Semaste    m_dyld_plugin_name (),
90254721Semaste    m_thread_data_valid(false),
91254721Semaste    m_thread_data(),
92254721Semaste    m_core_aranges ()
93254721Semaste{
94254721Semaste}
95254721Semaste
96254721Semaste//----------------------------------------------------------------------
97254721Semaste// Destructor
98254721Semaste//----------------------------------------------------------------------
99254721SemasteProcessElfCore::~ProcessElfCore()
100254721Semaste{
101254721Semaste    Clear();
102254721Semaste    // We need to call finalize on the process before destroying ourselves
103254721Semaste    // to make sure all of the broadcaster cleanup goes as planned. If we
104254721Semaste    // destruct this class, then Process::~Process() might have problems
105254721Semaste    // trying to fully destroy the broadcaster.
106254721Semaste    Finalize();
107254721Semaste}
108254721Semaste
109254721Semaste//----------------------------------------------------------------------
110254721Semaste// PluginInterface
111254721Semaste//----------------------------------------------------------------------
112254721SemasteConstString
113254721SemasteProcessElfCore::GetPluginName()
114254721Semaste{
115254721Semaste    return GetPluginNameStatic();
116254721Semaste}
117254721Semaste
118254721Semasteuint32_t
119254721SemasteProcessElfCore::GetPluginVersion()
120254721Semaste{
121254721Semaste    return 1;
122254721Semaste}
123254721Semaste
124254721Semastelldb::addr_t
125254721SemasteProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header)
126254721Semaste{
127254721Semaste    lldb::addr_t addr = header->p_vaddr;
128254721Semaste    FileRange file_range (header->p_offset, header->p_filesz);
129254721Semaste    VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range);
130254721Semaste
131254721Semaste    VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
132254721Semaste    if (last_entry &&
133254721Semaste        last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
134269024Semaste        last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
135269024Semaste        last_entry->GetByteSize() == last_entry->data.GetByteSize())
136254721Semaste    {
137254721Semaste        last_entry->SetRangeEnd (range_entry.GetRangeEnd());
138254721Semaste        last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
139254721Semaste    }
140254721Semaste    else
141254721Semaste    {
142254721Semaste        m_core_aranges.Append(range_entry);
143254721Semaste    }
144254721Semaste
145254721Semaste    return addr;
146254721Semaste}
147254721Semaste
148254721Semaste//----------------------------------------------------------------------
149254721Semaste// Process Control
150254721Semaste//----------------------------------------------------------------------
151254721SemasteError
152254721SemasteProcessElfCore::DoLoadCore ()
153254721Semaste{
154254721Semaste    Error error;
155254721Semaste    if (!m_core_module_sp)
156254721Semaste    {
157254721Semaste        error.SetErrorString ("invalid core module");
158254721Semaste        return error;
159254721Semaste    }
160254721Semaste
161254721Semaste    ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
162254721Semaste    if (core == NULL)
163254721Semaste    {
164254721Semaste        error.SetErrorString ("invalid core object file");
165254721Semaste        return error;
166254721Semaste    }
167254721Semaste
168254721Semaste    const uint32_t num_segments = core->GetProgramHeaderCount();
169254721Semaste    if (num_segments == 0)
170254721Semaste    {
171254721Semaste        error.SetErrorString ("core file has no sections");
172254721Semaste        return error;
173254721Semaste    }
174254721Semaste
175254721Semaste    SetCanJIT(false);
176254721Semaste
177254721Semaste    m_thread_data_valid = true;
178254721Semaste
179254721Semaste    bool ranges_are_sorted = true;
180254721Semaste    lldb::addr_t vm_addr = 0;
181254721Semaste    /// Walk through segments and Thread and Address Map information.
182254721Semaste    /// PT_NOTE - Contains Thread and Register information
183254721Semaste    /// PT_LOAD - Contains a contiguous range of Process Address Space
184254721Semaste    for(uint32_t i = 1; i <= num_segments; i++)
185254721Semaste    {
186254721Semaste        const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i);
187254721Semaste        assert(header != NULL);
188254721Semaste
189254721Semaste        DataExtractor data = core->GetSegmentDataByIndex(i);
190254721Semaste
191254721Semaste        // Parse thread contexts and auxv structure
192254721Semaste        if (header->p_type == llvm::ELF::PT_NOTE)
193254721Semaste            ParseThreadContextsFromNoteSegment(header, data);
194254721Semaste
195254721Semaste        // PT_LOAD segments contains address map
196254721Semaste        if (header->p_type == llvm::ELF::PT_LOAD)
197254721Semaste        {
198254721Semaste            lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header);
199254721Semaste            if (vm_addr > last_addr)
200254721Semaste                ranges_are_sorted = false;
201254721Semaste            vm_addr = last_addr;
202254721Semaste        }
203254721Semaste    }
204254721Semaste
205254721Semaste    if (!ranges_are_sorted)
206254721Semaste        m_core_aranges.Sort();
207254721Semaste
208254721Semaste    // Even if the architecture is set in the target, we need to override
209254721Semaste    // it to match the core file which is always single arch.
210254721Semaste    ArchSpec arch (m_core_module_sp->GetArchitecture());
211254721Semaste    if (arch.IsValid())
212254721Semaste        m_target.SetArchitecture(arch);
213254721Semaste
214254721Semaste    return error;
215254721Semaste}
216254721Semaste
217254721Semastelldb_private::DynamicLoader *
218254721SemasteProcessElfCore::GetDynamicLoader ()
219254721Semaste{
220254721Semaste    if (m_dyld_ap.get() == NULL)
221254721Semaste        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic().GetCString()));
222254721Semaste    return m_dyld_ap.get();
223254721Semaste}
224254721Semaste
225254721Semastebool
226254721SemasteProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
227254721Semaste{
228254721Semaste    const uint32_t num_threads = GetNumThreadContexts ();
229254721Semaste    if (!m_thread_data_valid)
230254721Semaste        return false;
231254721Semaste
232254721Semaste    for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
233254721Semaste    {
234254721Semaste        const ThreadData &td = m_thread_data[tid];
235254721Semaste        lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td));
236254721Semaste        new_thread_list.AddThread (thread_sp);
237254721Semaste    }
238254721Semaste    return new_thread_list.GetSize(false) > 0;
239254721Semaste}
240254721Semaste
241254721Semastevoid
242254721SemasteProcessElfCore::RefreshStateAfterStop ()
243254721Semaste{
244254721Semaste}
245254721Semaste
246254721SemasteError
247254721SemasteProcessElfCore::DoDestroy ()
248254721Semaste{
249254721Semaste    return Error();
250254721Semaste}
251254721Semaste
252254721Semaste//------------------------------------------------------------------
253254721Semaste// Process Queries
254254721Semaste//------------------------------------------------------------------
255254721Semaste
256254721Semastebool
257254721SemasteProcessElfCore::IsAlive ()
258254721Semaste{
259254721Semaste    return true;
260254721Semaste}
261254721Semaste
262254721Semaste//------------------------------------------------------------------
263254721Semaste// Process Memory
264254721Semaste//------------------------------------------------------------------
265254721Semastesize_t
266254721SemasteProcessElfCore::ReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error)
267254721Semaste{
268254721Semaste    // Don't allow the caching that lldb_private::Process::ReadMemory does
269254721Semaste    // since in core files we have it all cached our our core file anyway.
270254721Semaste    return DoReadMemory (addr, buf, size, error);
271254721Semaste}
272254721Semaste
273254721Semastesize_t
274254721SemasteProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error)
275254721Semaste{
276254721Semaste    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
277254721Semaste
278254721Semaste    if (core_objfile == NULL)
279254721Semaste        return 0;
280254721Semaste
281254721Semaste    // Get the address range
282254721Semaste    const VMRangeToFileOffset::Entry *address_range = m_core_aranges.FindEntryThatContains (addr);
283254721Semaste    if (address_range == NULL || address_range->GetRangeEnd() < addr)
284254721Semaste    {
285254721Semaste        error.SetErrorStringWithFormat ("core file does not contain 0x%" PRIx64, addr);
286254721Semaste        return 0;
287254721Semaste    }
288254721Semaste
289254721Semaste    // Convert the address into core file offset
290254721Semaste    const lldb::addr_t offset = addr - address_range->GetRangeBase();
291254721Semaste    const lldb::addr_t file_start = address_range->data.GetRangeBase();
292254721Semaste    const lldb::addr_t file_end = address_range->data.GetRangeEnd();
293254721Semaste    size_t bytes_to_read = size; // Number of bytes to read from the core file
294254721Semaste    size_t bytes_copied = 0;     // Number of bytes actually read from the core file
295254721Semaste    size_t zero_fill_size = 0;   // Padding
296254721Semaste    lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address
297254721Semaste
298269024Semaste    // Figure out how many on-disk bytes remain in this segment
299269024Semaste    // starting at the given offset
300269024Semaste    if (file_end > file_start + offset)
301269024Semaste        bytes_left = file_end - (file_start + offset);
302254721Semaste
303269024Semaste    // Figure out how many bytes we need to zero-fill if we are
304269024Semaste    // reading more bytes than available in the on-disk segment
305254721Semaste    if (bytes_to_read > bytes_left)
306254721Semaste    {
307254721Semaste        zero_fill_size = bytes_to_read - bytes_left;
308254721Semaste        bytes_to_read = bytes_left;
309254721Semaste    }
310254721Semaste
311254721Semaste    // If there is data available on the core file read it
312254721Semaste    if (bytes_to_read)
313254721Semaste        bytes_copied = core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
314254721Semaste
315254721Semaste    assert(zero_fill_size <= size);
316254721Semaste    // Pad remaining bytes
317254721Semaste    if (zero_fill_size)
318254721Semaste        memset(((char *)buf) + bytes_copied, 0, zero_fill_size);
319254721Semaste
320254721Semaste    return bytes_copied + zero_fill_size;
321254721Semaste}
322254721Semaste
323254721Semastevoid
324254721SemasteProcessElfCore::Clear()
325254721Semaste{
326254721Semaste    m_thread_list.Clear();
327254721Semaste}
328254721Semaste
329254721Semastevoid
330254721SemasteProcessElfCore::Initialize()
331254721Semaste{
332254721Semaste    static bool g_initialized = false;
333254721Semaste
334254721Semaste    if (g_initialized == false)
335254721Semaste    {
336254721Semaste        g_initialized = true;
337254721Semaste        PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance);
338254721Semaste    }
339254721Semaste}
340254721Semaste
341254721Semastelldb::addr_t
342254721SemasteProcessElfCore::GetImageInfoAddress()
343254721Semaste{
344254721Semaste    Target *target = &GetTarget();
345254721Semaste    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
346263363Semaste    Address addr = obj_file->GetImageInfoAddress(target);
347254721Semaste
348263363Semaste    if (addr.IsValid())
349254721Semaste        return addr.GetLoadAddress(target);
350254721Semaste    return LLDB_INVALID_ADDRESS;
351254721Semaste}
352254721Semaste
353254721Semaste/// Core files PT_NOTE segment descriptor types
354254721Semasteenum {
355254721Semaste    NT_PRSTATUS     = 1,
356254721Semaste    NT_FPREGSET,
357254721Semaste    NT_PRPSINFO,
358254721Semaste    NT_TASKSTRUCT,
359254721Semaste    NT_PLATFORM,
360254721Semaste    NT_AUXV
361254721Semaste};
362254721Semaste
363254721Semasteenum {
364254721Semaste    NT_FREEBSD_PRSTATUS      = 1,
365254721Semaste    NT_FREEBSD_FPREGSET,
366254721Semaste    NT_FREEBSD_PRPSINFO,
367254721Semaste    NT_FREEBSD_THRMISC       = 7,
368254721Semaste    NT_FREEBSD_PROCSTAT_AUXV = 16
369254721Semaste};
370254721Semaste
371254721Semaste// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
372254721Semastestatic void
373269024SemasteParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
374254721Semaste                     ArchSpec &arch)
375254721Semaste{
376254721Semaste    lldb::offset_t offset = 0;
377269024Semaste    bool lp64 = (arch.GetMachine() == llvm::Triple::mips64 ||
378269024Semaste                 arch.GetMachine() == llvm::Triple::x86_64);
379254721Semaste    int pr_version = data.GetU32(&offset);
380254721Semaste
381254721Semaste    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
382254721Semaste    if (log)
383254721Semaste    {
384254721Semaste        if (pr_version > 1)
385254721Semaste            log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version);
386254721Semaste    }
387254721Semaste
388269024Semaste    // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
389269024Semaste    if (lp64)
390269024Semaste        offset += 32;
391269024Semaste    else
392269024Semaste        offset += 16;
393269024Semaste
394269024Semaste    thread_data.signo = data.GetU32(&offset); // pr_cursig
395254721Semaste    offset += 4;        // pr_pid
396269024Semaste    if (lp64)
397254721Semaste        offset += 4;
398254721Semaste
399254721Semaste    size_t len = data.GetByteSize() - offset;
400269024Semaste    thread_data.gpregset = DataExtractor(data, offset, len);
401254721Semaste}
402254721Semaste
403254721Semastestatic void
404269024SemasteParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data)
405254721Semaste{
406254721Semaste    lldb::offset_t offset = 0;
407269024Semaste    thread_data.name = data.GetCStr(&offset, 20);
408254721Semaste}
409254721Semaste
410254721Semaste/// Parse Thread context from PT_NOTE segment and store it in the thread list
411254721Semaste/// Notes:
412254721Semaste/// 1) A PT_NOTE segment is composed of one or more NOTE entries.
413254721Semaste/// 2) NOTE Entry contains a standard header followed by variable size data.
414254721Semaste///   (see ELFNote structure)
415254721Semaste/// 3) A Thread Context in a core file usually described by 3 NOTE entries.
416254721Semaste///    a) NT_PRSTATUS - Register context
417254721Semaste///    b) NT_PRPSINFO - Process info(pid..)
418254721Semaste///    c) NT_FPREGSET - Floating point registers
419254721Semaste/// 4) The NOTE entries can be in any order
420254721Semaste/// 5) If a core file contains multiple thread contexts then there is two data forms
421254721Semaste///    a) Each thread context(2 or more NOTE entries) contained in its own segment (PT_NOTE)
422254721Semaste///    b) All thread context is stored in a single segment(PT_NOTE).
423254721Semaste///        This case is little tricker since while parsing we have to find where the
424254721Semaste///        new thread starts. The current implementation marks beginning of
425254721Semaste///        new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry.
426254721Semaste///    For case (b) there may be either one NT_PRPSINFO per thread, or a single
427254721Semaste///    one that applies to all threads (depending on the platform type).
428254721Semastevoid
429269024SemasteProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header,
430254721Semaste                                                   DataExtractor segment_data)
431254721Semaste{
432254721Semaste    assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
433254721Semaste
434254721Semaste    lldb::offset_t offset = 0;
435269024Semaste    std::unique_ptr<ThreadData> thread_data(new ThreadData);
436254721Semaste    bool have_prstatus = false;
437254721Semaste    bool have_prpsinfo = false;
438254721Semaste
439254721Semaste    ArchSpec arch = GetArchitecture();
440254721Semaste    ELFLinuxPrPsInfo prpsinfo;
441254721Semaste    ELFLinuxPrStatus prstatus;
442254721Semaste    size_t header_size;
443254721Semaste    size_t len;
444254721Semaste
445254721Semaste    // Loop through the NOTE entires in the segment
446254721Semaste    while (offset < segment_header->p_filesz)
447254721Semaste    {
448254721Semaste        ELFNote note = ELFNote();
449254721Semaste        note.Parse(segment_data, &offset);
450254721Semaste
451254721Semaste        // Beginning of new thread
452254721Semaste        if ((note.n_type == NT_PRSTATUS && have_prstatus) ||
453254721Semaste            (note.n_type == NT_PRPSINFO && have_prpsinfo))
454254721Semaste        {
455254721Semaste            assert(thread_data->gpregset.GetByteSize() > 0);
456254721Semaste            // Add the new thread to thread list
457254721Semaste            m_thread_data.push_back(*thread_data);
458269024Semaste            *thread_data = ThreadData();
459254721Semaste            have_prstatus = false;
460254721Semaste            have_prpsinfo = false;
461254721Semaste        }
462254721Semaste
463254721Semaste        size_t note_start, note_size;
464254721Semaste        note_start = offset;
465263363Semaste        note_size = llvm::RoundUpToAlignment(note.n_descsz, 4);
466254721Semaste
467254721Semaste        // Store the NOTE information in the current thread
468254721Semaste        DataExtractor note_data (segment_data, note_start, note_size);
469254721Semaste        if (note.n_name == "FreeBSD")
470254721Semaste        {
471254721Semaste            switch (note.n_type)
472254721Semaste            {
473254721Semaste                case NT_FREEBSD_PRSTATUS:
474254721Semaste                    have_prstatus = true;
475269024Semaste                    ParseFreeBSDPrStatus(*thread_data, note_data, arch);
476254721Semaste                    break;
477254721Semaste                case NT_FREEBSD_FPREGSET:
478254721Semaste                    thread_data->fpregset = note_data;
479254721Semaste                    break;
480254721Semaste                case NT_FREEBSD_PRPSINFO:
481254721Semaste                    have_prpsinfo = true;
482254721Semaste                    break;
483254721Semaste                case NT_FREEBSD_THRMISC:
484269024Semaste                    ParseFreeBSDThrMisc(*thread_data, note_data);
485254721Semaste                    break;
486254721Semaste                case NT_FREEBSD_PROCSTAT_AUXV:
487254721Semaste                    // FIXME: FreeBSD sticks an int at the beginning of the note
488254721Semaste                    m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4);
489254721Semaste                    break;
490254721Semaste                default:
491254721Semaste                    break;
492254721Semaste            }
493254721Semaste        }
494254721Semaste        else
495254721Semaste        {
496254721Semaste            switch (note.n_type)
497254721Semaste            {
498254721Semaste                case NT_PRSTATUS:
499254721Semaste                    have_prstatus = true;
500254721Semaste                    prstatus.Parse(note_data, arch);
501254721Semaste                    thread_data->signo = prstatus.pr_cursig;
502254721Semaste                    header_size = ELFLinuxPrStatus::GetSize(arch);
503254721Semaste                    len = note_data.GetByteSize() - header_size;
504254721Semaste                    thread_data->gpregset = DataExtractor(note_data, header_size, len);
505254721Semaste                    break;
506254721Semaste                case NT_FPREGSET:
507254721Semaste                    thread_data->fpregset = note_data;
508254721Semaste                    break;
509254721Semaste                case NT_PRPSINFO:
510254721Semaste                    have_prpsinfo = true;
511254721Semaste                    prpsinfo.Parse(note_data, arch);
512254721Semaste                    thread_data->name = prpsinfo.pr_fname;
513254721Semaste                    break;
514254721Semaste                case NT_AUXV:
515254721Semaste                    m_auxv = DataExtractor(note_data);
516254721Semaste                    break;
517254721Semaste                default:
518254721Semaste                    break;
519254721Semaste            }
520254721Semaste        }
521254721Semaste
522254721Semaste        offset += note_size;
523254721Semaste    }
524254721Semaste    // Add last entry in the note section
525254721Semaste    if (thread_data && thread_data->gpregset.GetByteSize() > 0)
526254721Semaste    {
527254721Semaste        m_thread_data.push_back(*thread_data);
528254721Semaste    }
529254721Semaste}
530254721Semaste
531254721Semasteuint32_t
532254721SemasteProcessElfCore::GetNumThreadContexts ()
533254721Semaste{
534254721Semaste    if (!m_thread_data_valid)
535254721Semaste        DoLoadCore();
536254721Semaste    return m_thread_data.size();
537254721Semaste}
538254721Semaste
539254721SemasteArchSpec
540254721SemasteProcessElfCore::GetArchitecture()
541254721Semaste{
542254721Semaste    ObjectFileELF *core_file = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
543254721Semaste    ArchSpec arch;
544254721Semaste    core_file->GetArchitecture(arch);
545254721Semaste    return arch;
546254721Semaste}
547254721Semaste
548254721Semasteconst lldb::DataBufferSP
549254721SemasteProcessElfCore::GetAuxvData()
550254721Semaste{
551254721Semaste    const uint8_t *start = m_auxv.GetDataStart();
552254721Semaste    size_t len = m_auxv.GetByteSize();
553254721Semaste    lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len));
554254721Semaste    return buffer;
555254721Semaste}
556254721Semaste
557