[Lldb-commits] [lldb] r284422 - [lldb] Read modules from memory when a local copy is not available

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 17 13:28:20 PDT 2016


Author: wallace
Date: Mon Oct 17 15:28:19 2016
New Revision: 284422

URL: http://llvm.org/viewvc/llvm-project?rev=284422&view=rev
Log:
[lldb] Read modules from memory when a local copy is not available

Summary:
When the local lldb doesn't have access to a copy of the modules in the target, e.g. winphone, with this change now we read these modules from memory.

There are mainly 2 changes:
1. create pecoff object files from memory
2. read from memory when the local file is not available

Reviewers: sas, fjricci, zturner

Subscribers: #lldb

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D24284

Modified:
    lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
    lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h

Modified: lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp?rev=284422&r1=284421&r2=284422&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp Mon Oct 17 15:28:19 2016
@@ -14,6 +14,7 @@
 
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/FileSpecList.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -83,7 +84,14 @@ ObjectFile *ObjectFilePECOFF::CreateInst
 ObjectFile *ObjectFilePECOFF::CreateMemoryInstance(
     const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
     const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
-  return NULL;
+  if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp))
+    return nullptr;
+  auto objfile_ap = llvm::make_unique<ObjectFilePECOFF>(
+      module_sp, data_sp, process_sp, header_addr);
+  if (objfile_ap.get() && objfile_ap->ParseHeader()) {
+    return objfile_ap.release();
+  }
+  return nullptr;
 }
 
 size_t ObjectFilePECOFF::GetModuleSpecifications(
@@ -161,6 +169,18 @@ ObjectFilePECOFF::ObjectFilePECOFF(const
   ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt));
 }
 
+ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
+                                   DataBufferSP &header_data_sp,
+                                   const lldb::ProcessSP &process_sp,
+                                   addr_t header_addr)
+    : ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
+      m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
+      m_entry_point_address() {
+  ::memset(&m_dos_header, 0, sizeof(m_dos_header));
+  ::memset(&m_coff_header, 0, sizeof(m_coff_header));
+  ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt));
+}
+
 ObjectFilePECOFF::~ObjectFilePECOFF() {}
 
 bool ObjectFilePECOFF::ParseHeader() {
@@ -396,6 +416,27 @@ bool ObjectFilePECOFF::ParseCOFFOptional
   return success;
 }
 
+DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
+  if (m_file) {
+    DataBufferSP buffer_sp(m_file.ReadFileContents(offset, size));
+    return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize());
+  }
+  ProcessSP process_sp(m_process_wp.lock());
+  DataExtractor data;
+  if (process_sp) {
+    auto data_ap = llvm::make_unique<DataBufferHeap>(size, 0);
+    Error readmem_error;
+    size_t bytes_read =
+        process_sp->ReadMemory(m_image_base + offset, data_ap->GetBytes(),
+                               data_ap->GetByteSize(), readmem_error);
+    if (bytes_read == size) {
+      DataBufferSP buffer_sp(data_ap.release());
+      data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
+    }
+  }
+  return data;
+}
+
 //----------------------------------------------------------------------
 // ParseSectionHeaders
 //----------------------------------------------------------------------
@@ -405,12 +446,9 @@ bool ObjectFilePECOFF::ParseSectionHeade
   m_sect_headers.clear();
 
   if (nsects > 0) {
-    const uint32_t addr_byte_size = GetAddressByteSize();
     const size_t section_header_byte_size = nsects * sizeof(section_header_t);
-    DataBufferSP section_header_data_sp(m_file.ReadFileContents(
-        section_header_data_offset, section_header_byte_size));
-    DataExtractor section_header_data(section_header_data_sp, GetByteOrder(),
-                                      addr_byte_size);
+    DataExtractor section_header_data =
+        ReadImageData(section_header_data_offset, section_header_byte_size);
 
     lldb::offset_t offset = 0;
     if (section_header_data.ValidOffsetForDataOfSize(
@@ -470,68 +508,65 @@ Symtab *ObjectFilePECOFF::GetSymtab() {
 
       const uint32_t num_syms = m_coff_header.nsyms;
 
-      if (num_syms > 0 && m_coff_header.symoff > 0) {
+      if (m_file && num_syms > 0 && m_coff_header.symoff > 0) {
         const uint32_t symbol_size = 18;
-        const uint32_t addr_byte_size = GetAddressByteSize();
         const size_t symbol_data_size = num_syms * symbol_size;
         // Include the 4-byte string table size at the end of the symbols
-        DataBufferSP symtab_data_sp(m_file.ReadFileContents(
-            m_coff_header.symoff, symbol_data_size + 4));
-        DataExtractor symtab_data(symtab_data_sp, GetByteOrder(),
-                                  addr_byte_size);
+        DataExtractor symtab_data =
+            ReadImageData(m_coff_header.symoff, symbol_data_size + 4);
         lldb::offset_t offset = symbol_data_size;
         const uint32_t strtab_size = symtab_data.GetU32(&offset);
-        DataBufferSP strtab_data_sp(m_file.ReadFileContents(
-            m_coff_header.symoff + symbol_data_size, strtab_size));
-        DataExtractor strtab_data(strtab_data_sp, GetByteOrder(),
-                                  addr_byte_size);
-
-        // First 4 bytes should be zeroed after strtab_size has been read,
-        // because it is used as offset 0 to encode a NULL string.
-        uint32_t *strtab_data_start = (uint32_t *)strtab_data_sp->GetBytes();
-        strtab_data_start[0] = 0;
-
-        offset = 0;
-        std::string symbol_name;
-        Symbol *symbols = m_symtab_ap->Resize(num_syms);
-        for (uint32_t i = 0; i < num_syms; ++i) {
-          coff_symbol_t symbol;
-          const uint32_t symbol_offset = offset;
-          const char *symbol_name_cstr = NULL;
-          // If the first 4 bytes of the symbol string are zero, then they
-          // are followed by a 4-byte string table offset. Else these
-          // 8 bytes contain the symbol name
-          if (symtab_data.GetU32(&offset) == 0) {
-            // Long string that doesn't fit into the symbol table name,
-            // so now we must read the 4 byte string table offset
-            uint32_t strtab_offset = symtab_data.GetU32(&offset);
-            symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
-            symbol_name.assign(symbol_name_cstr);
-          } else {
-            // Short string that fits into the symbol table name which is 8
-            // bytes
-            offset += sizeof(symbol.name) - 4; // Skip remaining
-            symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
-            if (symbol_name_cstr == NULL)
-              break;
-            symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
-          }
-          symbol.value = symtab_data.GetU32(&offset);
-          symbol.sect = symtab_data.GetU16(&offset);
-          symbol.type = symtab_data.GetU16(&offset);
-          symbol.storage = symtab_data.GetU8(&offset);
-          symbol.naux = symtab_data.GetU8(&offset);
-          symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
-          if ((int16_t)symbol.sect >= 1) {
-            Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect - 1),
-                                symbol.value);
-            symbols[i].GetAddressRef() = symbol_addr;
-            symbols[i].SetType(MapSymbolType(symbol.type));
-          }
-
-          if (symbol.naux > 0) {
-            i += symbol.naux;
-            offset += symbol_size;
+        if (strtab_size > 0) {
+          DataExtractor strtab_data = ReadImageData(
+              m_coff_header.symoff + symbol_data_size, strtab_size);
+
+          // First 4 bytes should be zeroed after strtab_size has been read,
+          // because it is used as offset 0 to encode a NULL string.
+          uint32_t *strtab_data_start = (uint32_t *)strtab_data.GetDataStart();
+          strtab_data_start[0] = 0;
+
+          offset = 0;
+          std::string symbol_name;
+          Symbol *symbols = m_symtab_ap->Resize(num_syms);
+          for (uint32_t i = 0; i < num_syms; ++i) {
+            coff_symbol_t symbol;
+            const uint32_t symbol_offset = offset;
+            const char *symbol_name_cstr = NULL;
+            // If the first 4 bytes of the symbol string are zero, then they
+            // are followed by a 4-byte string table offset. Else these
+            // 8 bytes contain the symbol name
+            if (symtab_data.GetU32(&offset) == 0) {
+              // Long string that doesn't fit into the symbol table name,
+              // so now we must read the 4 byte string table offset
+              uint32_t strtab_offset = symtab_data.GetU32(&offset);
+              symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
+              symbol_name.assign(symbol_name_cstr);
+            } else {
+              // Short string that fits into the symbol table name which is 8
+              // bytes
+              offset += sizeof(symbol.name) - 4; // Skip remaining
+              symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
+              if (symbol_name_cstr == NULL)
+                break;
+              symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
+            }
+            symbol.value = symtab_data.GetU32(&offset);
+            symbol.sect = symtab_data.GetU16(&offset);
+            symbol.type = symtab_data.GetU16(&offset);
+            symbol.storage = symtab_data.GetU8(&offset);
+            symbol.naux = symtab_data.GetU8(&offset);
+            symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
+            if ((int16_t)symbol.sect >= 1) {
+              Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect - 1),
+                                  symbol.value);
+              symbols[i].GetAddressRef() = symbol_addr;
+              symbols[i].SetType(MapSymbolType(symbol.type));
+            }
+
+            if (symbol.naux > 0) {
+              i += symbol.naux;
+              offset += symbol_size;
+            }
           }
         }
       }
@@ -543,12 +578,15 @@ Symtab *ObjectFilePECOFF::GetSymtab() {
         export_directory_entry export_table;
         uint32_t data_start =
             m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
-        Address address(m_coff_header_opt.image_base + data_start, sect_list);
-        DataBufferSP symtab_data_sp(m_file.ReadFileContents(
-            address.GetSection()->GetFileOffset() + address.GetOffset(),
-            m_coff_header_opt.data_dirs[0].vmsize));
-        DataExtractor symtab_data(symtab_data_sp, GetByteOrder(),
-                                  GetAddressByteSize());
+
+        uint32_t address_rva = data_start;
+        if (m_file) {
+          Address address(m_coff_header_opt.image_base + data_start, sect_list);
+          address_rva =
+              address.GetSection()->GetFileOffset() + address.GetOffset();
+        }
+        DataExtractor symtab_data =
+            ReadImageData(address_rva, m_coff_header_opt.data_dirs[0].vmsize);
         lldb::offset_t offset = 0;
 
         // Read export_table header

Modified: lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h?rev=284422&r1=284421&r2=284422&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h Mon Oct 17 15:28:19 2016
@@ -50,6 +50,10 @@ public:
                    const lldb_private::FileSpec *file,
                    lldb::offset_t file_offset, lldb::offset_t length);
 
+  ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
+                   lldb::DataBufferSP &header_data_sp,
+                   const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
   ~ObjectFilePECOFF() override;
 
   //------------------------------------------------------------------
@@ -130,6 +134,8 @@ public:
 
   bool IsWindowsSubsystem();
 
+  lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size);
+
 protected:
   bool NeedsEndianSwap() const;
 




More information about the lldb-commits mailing list