Home | History | Annotate | Download | only in elf-core
      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 // Other libraries and framework includes
     14 #include "lldb/Core/PluginManager.h"
     15 #include "lldb/Core/Module.h"
     16 #include "lldb/Core/ModuleSpec.h"
     17 #include "lldb/Core/Section.h"
     18 #include "lldb/Core/State.h"
     19 #include "lldb/Core/DataBufferHeap.h"
     20 #include "lldb/Target/Target.h"
     21 #include "lldb/Target/DynamicLoader.h"
     22 #include "ProcessPOSIXLog.h"
     23 
     24 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
     25 #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
     26 
     27 // Project includes
     28 #include "ProcessElfCore.h"
     29 #include "ThreadElfCore.h"
     30 
     31 using namespace lldb_private;
     32 
     33 ConstString
     34 ProcessElfCore::GetPluginNameStatic()
     35 {
     36     static ConstString g_name("elf-core");
     37     return g_name;
     38 }
     39 
     40 const char *
     41 ProcessElfCore::GetPluginDescriptionStatic()
     42 {
     43     return "ELF core dump plug-in.";
     44 }
     45 
     46 void
     47 ProcessElfCore::Terminate()
     48 {
     49     PluginManager::UnregisterPlugin (ProcessElfCore::CreateInstance);
     50 }
     51 
     52 
     53 lldb::ProcessSP
     54 ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
     55 {
     56     lldb::ProcessSP process_sp;
     57     if (crash_file)
     58         process_sp.reset(new ProcessElfCore (target, listener, *crash_file));
     59     return process_sp;
     60 }
     61 
     62 bool
     63 ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
     64 {
     65     // For now we are just making sure the file exists for a given module
     66     if (!m_core_module_sp && m_core_file.Exists())
     67     {
     68         ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
     69         Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp,
     70                                                   NULL, NULL, NULL));
     71         if (m_core_module_sp)
     72         {
     73             ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
     74             if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
     75                 return true;
     76         }
     77     }
     78     return false;
     79 }
     80 
     81 //----------------------------------------------------------------------
     82 // ProcessElfCore constructor
     83 //----------------------------------------------------------------------
     84 ProcessElfCore::ProcessElfCore(Target& target, Listener &listener,
     85                                const FileSpec &core_file) :
     86     Process (target, listener),
     87     m_core_module_sp (),
     88     m_core_file (core_file),
     89     m_dyld_plugin_name (),
     90     m_thread_data_valid(false),
     91     m_thread_data(),
     92     m_core_aranges ()
     93 {
     94 }
     95 
     96 //----------------------------------------------------------------------
     97 // Destructor
     98 //----------------------------------------------------------------------
     99 ProcessElfCore::~ProcessElfCore()
    100 {
    101     Clear();
    102     // We need to call finalize on the process before destroying ourselves
    103     // to make sure all of the broadcaster cleanup goes as planned. If we
    104     // destruct this class, then Process::~Process() might have problems
    105     // trying to fully destroy the broadcaster.
    106     Finalize();
    107 }
    108 
    109 //----------------------------------------------------------------------
    110 // PluginInterface
    111 //----------------------------------------------------------------------
    112 ConstString
    113 ProcessElfCore::GetPluginName()
    114 {
    115     return GetPluginNameStatic();
    116 }
    117 
    118 uint32_t
    119 ProcessElfCore::GetPluginVersion()
    120 {
    121     return 1;
    122 }
    123 
    124 lldb::addr_t
    125 ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header)
    126 {
    127     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 &&
    133         last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
    134         last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
    135     {
    136         last_entry->SetRangeEnd (range_entry.GetRangeEnd());
    137         last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
    138     }
    139     else
    140     {
    141         m_core_aranges.Append(range_entry);
    142     }
    143 
    144     return addr;
    145 }
    146 
    147 //----------------------------------------------------------------------
    148 // Process Control
    149 //----------------------------------------------------------------------
    150 Error
    151 ProcessElfCore::DoLoadCore ()
    152 {
    153     Error error;
    154     if (!m_core_module_sp)
    155     {
    156         error.SetErrorString ("invalid core module");
    157         return error;
    158     }
    159 
    160     ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
    161     if (core == NULL)
    162     {
    163         error.SetErrorString ("invalid core object file");
    164         return error;
    165     }
    166 
    167     const uint32_t num_segments = core->GetProgramHeaderCount();
    168     if (num_segments == 0)
    169     {
    170         error.SetErrorString ("core file has no sections");
    171         return error;
    172     }
    173 
    174     SetCanJIT(false);
    175 
    176     m_thread_data_valid = true;
    177 
    178     bool ranges_are_sorted = true;
    179     lldb::addr_t vm_addr = 0;
    180     /// Walk through segments and Thread and Address Map information.
    181     /// PT_NOTE - Contains Thread and Register information
    182     /// PT_LOAD - Contains a contiguous range of Process Address Space
    183     for(uint32_t i = 1; i <= num_segments; i++)
    184     {
    185         const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i);
    186         assert(header != NULL);
    187 
    188         DataExtractor data = core->GetSegmentDataByIndex(i);
    189 
    190         // Parse thread contexts and auxv structure
    191         if (header->p_type == llvm::ELF::PT_NOTE)
    192             ParseThreadContextsFromNoteSegment(header, data);
    193 
    194         // PT_LOAD segments contains address map
    195         if (header->p_type == llvm::ELF::PT_LOAD)
    196         {
    197             lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header);
    198             if (vm_addr > last_addr)
    199                 ranges_are_sorted = false;
    200             vm_addr = last_addr;
    201         }
    202     }
    203 
    204     if (!ranges_are_sorted)
    205         m_core_aranges.Sort();
    206 
    207     // Even if the architecture is set in the target, we need to override
    208     // it to match the core file which is always single arch.
    209     ArchSpec arch (m_core_module_sp->GetArchitecture());
    210     if (arch.IsValid())
    211         m_target.SetArchitecture(arch);
    212 
    213     return error;
    214 }
    215 
    216 lldb_private::DynamicLoader *
    217 ProcessElfCore::GetDynamicLoader ()
    218 {
    219     if (m_dyld_ap.get() == NULL)
    220         m_dyld_ap.reset (DynamicLoader::FindPlugin(this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic().GetCString()));
    221     return m_dyld_ap.get();
    222 }
    223 
    224 bool
    225 ProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
    226 {
    227     const uint32_t num_threads = GetNumThreadContexts ();
    228     if (!m_thread_data_valid)
    229         return false;
    230 
    231     for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
    232     {
    233         const ThreadData &td = m_thread_data[tid];
    234         lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td));
    235         new_thread_list.AddThread (thread_sp);
    236     }
    237     return new_thread_list.GetSize(false) > 0;
    238 }
    239 
    240 void
    241 ProcessElfCore::RefreshStateAfterStop ()
    242 {
    243 }
    244 
    245 Error
    246 ProcessElfCore::DoDestroy ()
    247 {
    248     return Error();
    249 }
    250 
    251 //------------------------------------------------------------------
    252 // Process Queries
    253 //------------------------------------------------------------------
    254 
    255 bool
    256 ProcessElfCore::IsAlive ()
    257 {
    258     return true;
    259 }
    260 
    261 //------------------------------------------------------------------
    262 // Process Memory
    263 //------------------------------------------------------------------
    264 size_t
    265 ProcessElfCore::ReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error)
    266 {
    267     // Don't allow the caching that lldb_private::Process::ReadMemory does
    268     // since in core files we have it all cached our our core file anyway.
    269     return DoReadMemory (addr, buf, size, error);
    270 }
    271 
    272 size_t
    273 ProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error)
    274 {
    275     ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
    276 
    277     if (core_objfile == NULL)
    278         return 0;
    279 
    280     // Get the address range
    281     const VMRangeToFileOffset::Entry *address_range = m_core_aranges.FindEntryThatContains (addr);
    282     if (address_range == NULL || address_range->GetRangeEnd() < addr)
    283     {
    284         error.SetErrorStringWithFormat ("core file does not contain 0x%" PRIx64, addr);
    285         return 0;
    286     }
    287 
    288     // Convert the address into core file offset
    289     const lldb::addr_t offset = addr - address_range->GetRangeBase();
    290     const lldb::addr_t file_start = address_range->data.GetRangeBase();
    291     const lldb::addr_t file_end = address_range->data.GetRangeEnd();
    292     size_t bytes_to_read = size; // Number of bytes to read from the core file
    293     size_t bytes_copied = 0;     // Number of bytes actually read from the core file
    294     size_t zero_fill_size = 0;   // Padding
    295     lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address
    296 
    297     if (file_end > offset)
    298         bytes_left = file_end - offset;
    299 
    300     if (bytes_to_read > bytes_left)
    301     {
    302         zero_fill_size = bytes_to_read - bytes_left;
    303         bytes_to_read = bytes_left;
    304     }
    305 
    306     // If there is data available on the core file read it
    307     if (bytes_to_read)
    308         bytes_copied = core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
    309 
    310     assert(zero_fill_size <= size);
    311     // Pad remaining bytes
    312     if (zero_fill_size)
    313         memset(((char *)buf) + bytes_copied, 0, zero_fill_size);
    314 
    315     return bytes_copied + zero_fill_size;
    316 }
    317 
    318 void
    319 ProcessElfCore::Clear()
    320 {
    321     m_thread_list.Clear();
    322 }
    323 
    324 void
    325 ProcessElfCore::Initialize()
    326 {
    327     static bool g_initialized = false;
    328 
    329     if (g_initialized == false)
    330     {
    331         g_initialized = true;
    332         PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance);
    333     }
    334 }
    335 
    336 lldb::addr_t
    337 ProcessElfCore::GetImageInfoAddress()
    338 {
    339     Target *target = &GetTarget();
    340     ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
    341     Address addr = obj_file->GetImageInfoAddress();
    342 
    343     if (addr.IsValid())
    344         return addr.GetLoadAddress(target);
    345     return LLDB_INVALID_ADDRESS;
    346 }
    347 
    348 /// Core files PT_NOTE segment descriptor types
    349 enum {
    350     NT_PRSTATUS     = 1,
    351     NT_FPREGSET,
    352     NT_PRPSINFO,
    353     NT_TASKSTRUCT,
    354     NT_PLATFORM,
    355     NT_AUXV
    356 };
    357 
    358 enum {
    359     NT_FREEBSD_PRSTATUS      = 1,
    360     NT_FREEBSD_FPREGSET,
    361     NT_FREEBSD_PRPSINFO,
    362     NT_FREEBSD_THRMISC       = 7,
    363     NT_FREEBSD_PROCSTAT_AUXV = 16
    364 };
    365 
    366 /// Align the given value to next boundary specified by the alignment bytes
    367 static uint32_t
    368 AlignToNext(uint32_t value, int alignment_bytes)
    369 {
    370     return (value + alignment_bytes - 1) & ~(alignment_bytes - 1);
    371 }
    372 
    373 /// Note Structure found in ELF core dumps.
    374 /// This is PT_NOTE type program/segments in the core file.
    375 struct ELFNote
    376 {
    377     elf::elf_word n_namesz;
    378     elf::elf_word n_descsz;
    379     elf::elf_word n_type;
    380 
    381     std::string n_name;
    382 
    383     ELFNote() : n_namesz(0), n_descsz(0), n_type(0)
    384     {
    385     }
    386 
    387     /// Parse an ELFNote entry from the given DataExtractor starting at position
    388     /// \p offset.
    389     ///
    390     /// @param[in] data
    391     ///    The DataExtractor to read from.
    392     ///
    393     /// @param[in,out] offset
    394     ///    Pointer to an offset in the data.  On return the offset will be
    395     ///    advanced by the number of bytes read.
    396     ///
    397     /// @return
    398     ///    True if the ELFRel entry was successfully read and false otherwise.
    399     bool
    400     Parse(const DataExtractor &data, lldb::offset_t *offset)
    401     {
    402         // Read all fields.
    403         if (data.GetU32(offset, &n_namesz, 3) == NULL)
    404             return false;
    405 
    406         // The name field is required to be nul-terminated, and n_namesz
    407         // includes the terminating nul in observed implementations (contrary
    408         // to the ELF-64 spec).  A special case is needed for cores generated
    409         // by some older Linux versions, which write a note named "CORE"
    410         // without a nul terminator and n_namesz = 4.
    411         if (n_namesz == 4)
    412         {
    413             char buf[4];
    414             if (data.ExtractBytes (*offset, 4, data.GetByteOrder(), buf) != 4)
    415                 return false;
    416             if (strncmp (buf, "CORE", 4) == 0)
    417             {
    418                 n_name = "CORE";
    419                 *offset += 4;
    420                 return true;
    421             }
    422         }
    423 
    424         const char *cstr = data.GetCStr(offset, AlignToNext(n_namesz, 4));
    425         if (cstr == NULL)
    426         {
    427             Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    428             if (log)
    429                 log->Printf("Failed to parse note name lacking nul terminator");
    430 
    431             return false;
    432         }
    433         n_name = cstr;
    434         return true;
    435     }
    436 };
    437 
    438 // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
    439 static void
    440 ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
    441                      ArchSpec &arch)
    442 {
    443     lldb::offset_t offset = 0;
    444     bool have_padding = (arch.GetMachine() == llvm::Triple::x86_64);
    445     int pr_version = data.GetU32(&offset);
    446 
    447     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
    448     if (log)
    449     {
    450         if (pr_version > 1)
    451             log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version);
    452     }
    453 
    454     if (have_padding)
    455         offset += 4;
    456     offset += 28;       // pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
    457     thread_data->signo = data.GetU32(&offset); // pr_cursig
    458     offset += 4;        // pr_pid
    459     if (have_padding)
    460         offset += 4;
    461 
    462     size_t len = data.GetByteSize() - offset;
    463     thread_data->gpregset = DataExtractor(data, offset, len);
    464 }
    465 
    466 static void
    467 ParseFreeBSDThrMisc(ThreadData *thread_data, DataExtractor &data)
    468 {
    469     lldb::offset_t offset = 0;
    470     thread_data->name = data.GetCStr(&offset, 20);
    471 }
    472 
    473 /// Parse Thread context from PT_NOTE segment and store it in the thread list
    474 /// Notes:
    475 /// 1) A PT_NOTE segment is composed of one or more NOTE entries.
    476 /// 2) NOTE Entry contains a standard header followed by variable size data.
    477 ///   (see ELFNote structure)
    478 /// 3) A Thread Context in a core file usually described by 3 NOTE entries.
    479 ///    a) NT_PRSTATUS - Register context
    480 ///    b) NT_PRPSINFO - Process info(pid..)
    481 ///    c) NT_FPREGSET - Floating point registers
    482 /// 4) The NOTE entries can be in any order
    483 /// 5) If a core file contains multiple thread contexts then there is two data forms
    484 ///    a) Each thread context(2 or more NOTE entries) contained in its own segment (PT_NOTE)
    485 ///    b) All thread context is stored in a single segment(PT_NOTE).
    486 ///        This case is little tricker since while parsing we have to find where the
    487 ///        new thread starts. The current implementation marks beginning of
    488 ///        new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry.
    489 ///    For case (b) there may be either one NT_PRPSINFO per thread, or a single
    490 ///    one that applies to all threads (depending on the platform type).
    491 void
    492 ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header,
    493                                                    DataExtractor segment_data)
    494 {
    495     assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
    496 
    497     lldb::offset_t offset = 0;
    498     ThreadData *thread_data = new ThreadData();
    499     bool have_prstatus = false;
    500     bool have_prpsinfo = false;
    501 
    502     ArchSpec arch = GetArchitecture();
    503     ELFLinuxPrPsInfo prpsinfo;
    504     ELFLinuxPrStatus prstatus;
    505     size_t header_size;
    506     size_t len;
    507 
    508     // Loop through the NOTE entires in the segment
    509     while (offset < segment_header->p_filesz)
    510     {
    511         ELFNote note = ELFNote();
    512         note.Parse(segment_data, &offset);
    513 
    514         // Beginning of new thread
    515         if ((note.n_type == NT_PRSTATUS && have_prstatus) ||
    516             (note.n_type == NT_PRPSINFO && have_prpsinfo))
    517         {
    518             assert(thread_data->gpregset.GetByteSize() > 0);
    519             // Add the new thread to thread list
    520             m_thread_data.push_back(*thread_data);
    521             thread_data = new ThreadData();
    522             have_prstatus = false;
    523             have_prpsinfo = false;
    524         }
    525 
    526         size_t note_start, note_size;
    527         note_start = offset;
    528         note_size = AlignToNext(note.n_descsz, 4);
    529 
    530         // Store the NOTE information in the current thread
    531         DataExtractor note_data (segment_data, note_start, note_size);
    532         if (note.n_name == "FreeBSD")
    533         {
    534             switch (note.n_type)
    535             {
    536                 case NT_FREEBSD_PRSTATUS:
    537                     have_prstatus = true;
    538                     ParseFreeBSDPrStatus(thread_data, note_data, arch);
    539                     break;
    540                 case NT_FREEBSD_FPREGSET:
    541                     thread_data->fpregset = note_data;
    542                     break;
    543                 case NT_FREEBSD_PRPSINFO:
    544                     have_prpsinfo = true;
    545                     break;
    546                 case NT_FREEBSD_THRMISC:
    547                     ParseFreeBSDThrMisc(thread_data, note_data);
    548                     break;
    549                 case NT_FREEBSD_PROCSTAT_AUXV:
    550                     // FIXME: FreeBSD sticks an int at the beginning of the note
    551                     m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4);
    552                     break;
    553                 default:
    554                     break;
    555             }
    556         }
    557         else
    558         {
    559             switch (note.n_type)
    560             {
    561                 case NT_PRSTATUS:
    562                     have_prstatus = true;
    563                     prstatus.Parse(note_data, arch);
    564                     thread_data->signo = prstatus.pr_cursig;
    565                     header_size = ELFLinuxPrStatus::GetSize(arch);
    566                     len = note_data.GetByteSize() - header_size;
    567                     thread_data->gpregset = DataExtractor(note_data, header_size, len);
    568                     break;
    569                 case NT_FPREGSET:
    570                     thread_data->fpregset = note_data;
    571                     break;
    572                 case NT_PRPSINFO:
    573                     have_prpsinfo = true;
    574                     prpsinfo.Parse(note_data, arch);
    575                     thread_data->name = prpsinfo.pr_fname;
    576                     break;
    577                 case NT_AUXV:
    578                     m_auxv = DataExtractor(note_data);
    579                     break;
    580                 default:
    581                     break;
    582             }
    583         }
    584 
    585         offset += note_size;
    586     }
    587     // Add last entry in the note section
    588     if (thread_data && thread_data->gpregset.GetByteSize() > 0)
    589     {
    590         m_thread_data.push_back(*thread_data);
    591     }
    592 }
    593 
    594 uint32_t
    595 ProcessElfCore::GetNumThreadContexts ()
    596 {
    597     if (!m_thread_data_valid)
    598         DoLoadCore();
    599     return m_thread_data.size();
    600 }
    601 
    602 ArchSpec
    603 ProcessElfCore::GetArchitecture()
    604 {
    605     ObjectFileELF *core_file = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
    606     ArchSpec arch;
    607     core_file->GetArchitecture(arch);
    608     return arch;
    609 }
    610 
    611 const lldb::DataBufferSP
    612 ProcessElfCore::GetAuxvData()
    613 {
    614     const uint8_t *start = m_auxv.GetDataStart();
    615     size_t len = m_auxv.GetByteSize();
    616     lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len));
    617     return buffer;
    618 }
    619 
    620