<rdar://problem/10560053>

Fixed "target modules list" (aliased to "image list") to output more information
by default. Modified the "target modules list" to have a few new options:

"--header" or "-h" => show the image header address
"--offset" or "-o" => show the image header address offset from the address in the file (the slide applied to the shared library)

Removed the "--symfile-basename" or "-S" option, and repurposed it to 
"--symfile-unique" "-S" which will show the symbol file if it differs from
the executable file.

ObjectFile's can now be loaded from memory for cases where we don't have the
files cached locally in an SDK or net mounted root. ObjectFileMachO can now
read mach files from memory.

Moved the section data reading code into the ObjectFile so that the object
file can get the section data from Process memory if the file is only in
memory.

lldb_private::Module can now load its object file in a target with a rigid 
slide (very common operation for most dynamic linkers) by using:

bool 
Module::SetLoadAddress (Target &target, lldb::addr_t offset, bool &changed)

lldb::SBModule() now has a new constructor in the public interface:

SBModule::SBModule (lldb::SBProcess &process, lldb::addr_t header_addr);

This will find an appropriate ObjectFile plug-in to load an image from memory
where the object file header is at "header_addr".

llvm-svn: 149804
This commit is contained in:
Greg Clayton 2012-02-05 02:38:54 +00:00
parent 6987fdb620
commit c96605461c
28 changed files with 803 additions and 162 deletions

View File

@ -31,6 +31,9 @@ public:
operator = (const SBModule &rhs);
#endif
SBModule (lldb::SBProcess &process,
lldb::addr_t header_addr);
~SBModule ();
bool

View File

@ -193,6 +193,7 @@ protected:
friend class SBCommandInterpreter;
friend class SBDebugger;
friend class SBFunction;
friend class SBModule;
friend class SBTarget;
friend class SBThread;
friend class SBValue;

View File

@ -96,12 +96,51 @@ public:
const ConstString *object_name = NULL,
off_t object_offset = 0);
Module (const FileSpec& file_spec,
const lldb::ProcessSP &processSP,
lldb::addr_t header_addr);
//------------------------------------------------------------------
/// Destructor.
//------------------------------------------------------------------
virtual
~Module ();
//------------------------------------------------------------------
/// Set the load address for all sections in a module to be the
/// file address plus \a slide.
///
/// Many times a module will be loaded in a target with a constant
/// offset applied to all top level sections. This function can
/// set the load address for all top level sections to be the
/// section file address + offset.
///
/// @param[in] target
/// The target in which to apply the section load addresses.
///
/// @param[in] offset
/// The offset to apply to all file addresses for all top
/// level sections in the object file as each section load
/// address is being set.
///
/// @param[out] changed
/// If any section load addresses were changed in \a target,
/// then \a changed will be set to \b true. Else \a changed
/// will be set to false. This allows this function to be
/// called multiple times on the same module for the same
/// target. If the module hasn't moved, then \a changed will
/// be false and no module updated notification will need to
/// be sent out.
///
/// @returns
/// /b True if any sections were successfully loaded in \a target,
/// /b false otherwise.
//------------------------------------------------------------------
bool
SetLoadAddress (Target &target,
lldb::addr_t offset,
bool &changed);
//------------------------------------------------------------------
/// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*)
///

View File

@ -137,17 +137,24 @@ public:
static bool
RegisterPlugin (const char *name,
const char *description,
ObjectFileCreateInstance create_callback);
ObjectFileCreateInstance create_callback,
ObjectFileCreateMemoryInstance create_memory_callback);
static bool
UnregisterPlugin (ObjectFileCreateInstance create_callback);
static ObjectFileCreateInstance
GetObjectFileCreateCallbackAtIndex (uint32_t idx);
static ObjectFileCreateMemoryInstance
GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx);
static ObjectFileCreateInstance
GetObjectFileCreateCallbackForPluginName (const char *name);
static ObjectFileCreateMemoryInstance
GetObjectFileCreateMemoryCallbackForPluginName (const char *name);
//------------------------------------------------------------------
// ObjectContainer

View File

@ -226,15 +226,6 @@ public:
bool
IsDescendant (const Section *section);
size_t
MemoryMapSectionDataFromObjectFile (const ObjectFile* file, DataExtractor& section_data) const;
size_t
ReadSectionDataFromObjectFile (const ObjectFile* objfile, off_t section_offset, void *dst, size_t dst_len) const;
size_t
ReadSectionDataFromObjectFile (const ObjectFile* file, DataExtractor& section_data) const;
ConstString&
GetName ();

View File

@ -118,7 +118,7 @@ private:
GetCFIData();
ObjectFile& m_objfile;
lldb::SectionSP m_section;
lldb::SectionSP m_section_sp;
lldb::RegisterKind m_reg_kind;
Flags m_flags;
cie_map_t m_cie_map;

View File

@ -91,6 +91,11 @@ public:
lldb::addr_t length,
lldb::DataBufferSP& headerDataSP);
ObjectFile (Module* module,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr,
lldb::DataBufferSP& headerDataSP);
//------------------------------------------------------------------
/// Destructor.
///
@ -146,6 +151,29 @@ public:
lldb::addr_t file_size,
lldb::DataBufferSP &data_sp);
//------------------------------------------------------------------
/// Find a ObjectFile plug-in that can parse a file in memory.
///
/// Scans all loaded plug-in interfaces that implement versions of
/// the ObjectFile plug-in interface and returns the first
/// instance that can parse the file.
///
/// @param[in] module
/// The parent module that owns this object file.
///
/// @param[in] process_sp
/// A shared pointer to the process whose memory space contains
/// an object file. This will be stored as a std::weak_ptr.
///
/// @param[in] header_addr
/// The address of the header for the object file in memory.
//------------------------------------------------------------------
static lldb::ObjectFileSP
FindPlugin (Module* module,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr,
lldb::DataBufferSP &file_data_sp);
//------------------------------------------------------------------
/// Gets the address size in bytes for the current object file.
///
@ -371,6 +399,22 @@ public:
virtual lldb_private::Address
GetEntryPointAddress () { return Address();}
//------------------------------------------------------------------
/// Returns the address that represents the header of this object
/// file.
///
/// The header address is defined as where the header for the object
/// file is that describes the content of the file. If the header
/// doesn't appear in a section that is defined in the object file,
/// an address with no section is returned that has the file offset
/// set in the m_offset member of the lldb_private::Address object.
///
/// @return
/// Returns the entry address for this module.
//------------------------------------------------------------------
virtual lldb_private::Address
GetHeaderAddress () { return Address();}
//------------------------------------------------------------------
/// The object file should be able to calculate its type by looking
/// at its file header and possibly the sections or other data in
@ -421,12 +465,33 @@ public:
return m_strata;
}
// When an object file is in memory, subclasses should try and lock
// the process weak pointer. If the process weak pointer produces a
// valid ProcessSP, then subclasses can call this function to read
// memory.
static lldb::DataBufferSP
ReadMemory (const lldb::ProcessSP &process_sp,
lldb::addr_t addr,
size_t byte_size);
size_t
GetData (off_t offset, size_t length, DataExtractor &data) const;
size_t
CopyData (off_t offset, size_t length, void *dst) const;
size_t
ReadSectionData (const Section *section,
off_t section_offset,
void *dst,
size_t dst_len) const;
size_t
ReadSectionData (const Section *section,
DataExtractor& section_data) const;
size_t
MemoryMapSectionData (const Section *section,
DataExtractor& section_data) const;
protected:
//------------------------------------------------------------------
// Member variables.
@ -438,6 +503,8 @@ protected:
lldb::addr_t m_length; ///< The length of this object file if it is known (can be zero if length is unknown or can't be determined).
DataExtractor m_data; ///< The data for this object file so things can be parsed lazily.
lldb_private::UnwindTable m_unwind_table; /// < Table of FuncUnwinders objects created for this ObjectFile's functions
lldb::ProcessWP m_process_wp;
const bool m_in_memory;
//------------------------------------------------------------------
/// Sets the architecture for a module. At present the architecture

View File

@ -2574,6 +2574,10 @@ public:
return error;
}
lldb::ModuleSP
ReadModuleFromMemory (const FileSpec& file_spec,
lldb::addr_t header_addr);
//------------------------------------------------------------------
/// Attempt to get the attributes for a region of memory in the process.
///

View File

@ -21,6 +21,7 @@ namespace lldb_private
typedef DynamicLoader* (*DynamicLoaderCreateInstance) (Process* process, bool force);
typedef ObjectContainer* (*ObjectContainerCreateInstance) (Module* module, lldb::DataBufferSP& dataSP, const FileSpec *file, lldb::addr_t offset, lldb::addr_t length);
typedef ObjectFile* (*ObjectFileCreateInstance) (Module* module, lldb::DataBufferSP& dataSP, const FileSpec* file, lldb::addr_t offset, lldb::addr_t length);
typedef ObjectFile* (*ObjectFileCreateMemoryInstance) (Module* module, lldb::DataBufferSP& dataSP, const lldb::ProcessSP &process_sp, lldb::addr_t offset);
typedef LogChannel* (*LogChannelCreateInstance) ();
typedef EmulateInstruction * (*EmulateInstructionCreateInstance) (const ArchSpec &arch, InstructionType inst_type);
typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force);

View File

@ -98,6 +98,9 @@ public:
SBModule (const SBModule &rhs);
SBModule (lldb::SBProcess &process,
lldb::addr_t header_addr);
~SBModule ();
bool

View File

@ -10,6 +10,7 @@
#include "lldb/API/SBModule.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBSymbolContextList.h"
#include "lldb/Core/Module.h"
@ -40,6 +41,14 @@ SBModule::SBModule(const SBModule &rhs) :
{
}
SBModule::SBModule (lldb::SBProcess &process, lldb::addr_t header_addr) :
m_opaque_sp ()
{
ProcessSP process_sp (process.GetSP());
if (process_sp)
m_opaque_sp = process_sp->ReadModuleFromMemory (FileSpec(), header_addr);
}
const SBModule &
SBModule::operator = (const SBModule &rhs)
{

View File

@ -2760,7 +2760,7 @@ public:
Module *module = module_address.GetModulePtr();
if (module)
{
PrintModule (strm, module);
PrintModule (target, module, UINT32_MAX, 0, strm);
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
@ -2808,8 +2808,8 @@ public:
module = module_sp.get();
}
strm.Printf("[%3u] ", image_idx);
PrintModule (strm, module);
int indent = strm.Printf("[%3u] ", image_idx);
PrintModule (target, module, image_idx, indent, strm);
}
result.SetStatus (eReturnStatusSuccessFinishResult);
@ -2829,108 +2829,160 @@ public:
protected:
void
PrintModule (Stream &strm, Module *module)
PrintModule (Target *target, Module *module, uint32_t idx, int indent, Stream &strm)
{
bool dump_object_name = false;
if (m_options.m_format_array.empty())
{
DumpFullpath(strm, &module->GetFileSpec(), 0);
dump_object_name = true;
m_options.m_format_array.push_back(std::make_pair('u', 0));
m_options.m_format_array.push_back(std::make_pair('h', 0));
m_options.m_format_array.push_back(std::make_pair('f', 0));
m_options.m_format_array.push_back(std::make_pair('S', 0));
}
else
const size_t num_entries = m_options.m_format_array.size();
bool print_space = false;
for (size_t i=0; i<num_entries; ++i)
{
const size_t num_entries = m_options.m_format_array.size();
for (size_t i=0; i<num_entries; ++i)
if (print_space)
strm.PutChar(' ');
print_space = true;
const char format_char = m_options.m_format_array[i].first;
uint32_t width = m_options.m_format_array[i].second;
switch (format_char)
{
if (i > 0)
strm.PutChar(' ');
char format_char = m_options.m_format_array[i].first;
uint32_t width = m_options.m_format_array[i].second;
switch (format_char)
{
case 'A':
DumpModuleArchitecture (strm, module, false, width);
break;
case 't':
DumpModuleArchitecture (strm, module, true, width);
break;
case 'f':
DumpFullpath (strm, &module->GetFileSpec(), width);
dump_object_name = true;
break;
case 'd':
DumpDirectory (strm, &module->GetFileSpec(), width);
break;
case 'b':
DumpBasename (strm, &module->GetFileSpec(), width);
dump_object_name = true;
break;
case 'r':
{
uint32_t ref_count = 0;
ModuleSP module_sp (module->shared_from_this());
if (module_sp)
{
// Take one away to make sure we don't count our local "module_sp"
ref_count = module_sp.use_count() - 1;
}
if (width)
strm.Printf("{%*u}", width, ref_count);
else
strm.Printf("{%u}", ref_count);
}
break;
case 'A':
DumpModuleArchitecture (strm, module, false, width);
break;
case 't':
DumpModuleArchitecture (strm, module, true, width);
break;
case 'f':
DumpFullpath (strm, &module->GetFileSpec(), width);
dump_object_name = true;
break;
case 'd':
DumpDirectory (strm, &module->GetFileSpec(), width);
break;
case 'b':
DumpBasename (strm, &module->GetFileSpec(), width);
dump_object_name = true;
break;
case 'h':
case 'o':
// Image header address
{
uint32_t addr_nibble_width = target ? (target->GetArchitecture().GetAddressByteSize() * 2) : 16;
case 's':
case 'S':
ObjectFile *objfile = module->GetObjectFile ();
if (objfile)
{
SymbolVendor *symbol_vendor = module->GetSymbolVendor();
if (symbol_vendor)
Address header_addr(objfile->GetHeaderAddress());
if (header_addr.IsValid())
{
SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
if (symbol_file)
if (target && !target->GetSectionLoadList().IsEmpty())
{
if (format_char == 'S')
DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
lldb::addr_t header_load_addr = header_addr.GetLoadAddress (target);
if (header_load_addr == LLDB_INVALID_ADDRESS)
{
header_addr.Dump (&strm, target, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleFileAddress);
}
else
DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
dump_object_name = true;
{
if (format_char == 'o')
{
// Show the offset of slide for the image
strm.Printf ("0x%*.*llx", addr_nibble_width, addr_nibble_width, header_load_addr - header_addr.GetFileAddress());
}
else
{
// Show the load address of the image
strm.Printf ("0x%*.*llx", addr_nibble_width, addr_nibble_width, header_load_addr);
}
}
break;
}
// The address was valid, but the image isn't loaded, output the address in an appropriate format
header_addr.Dump (&strm, target, Address::DumpStyleFileAddress);
break;
}
strm.Printf("%.*s", width, "<NONE>");
}
break;
case 'm':
module->GetModificationTime().Dump(&strm, width);
break;
strm.Printf ("%*s", addr_nibble_width + 2, "");
}
break;
case 'r':
{
uint32_t ref_count = 0;
ModuleSP module_sp (module->shared_from_this());
if (module_sp)
{
// Take one away to make sure we don't count our local "module_sp"
ref_count = module_sp.use_count() - 1;
}
if (width)
strm.Printf("{%*u}", width, ref_count);
else
strm.Printf("{%u}", ref_count);
}
break;
case 'p':
strm.Printf("%p", module);
break;
case 's':
case 'S':
{
SymbolVendor *symbol_vendor = module->GetSymbolVendor();
if (symbol_vendor)
{
SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
if (symbol_file)
{
if (format_char == 'S')
{
FileSpec &symfile_spec = symbol_file->GetObjectFile()->GetFileSpec();
// Dump symbol file only if different from module file
if (!symfile_spec || symfile_spec == module->GetFileSpec())
{
print_space = false;
break;
}
// Add a newline and indent past the index
strm.Printf ("\n%*s", indent, "");
}
DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
dump_object_name = true;
break;
}
}
strm.Printf("%.*s", width, "<NONE>");
}
break;
case 'm':
module->GetModificationTime().Dump(&strm, width);
break;
case 'u':
DumpModuleUUID(strm, module);
break;
default:
break;
}
}
if (dump_object_name)
{
const char *object_name = module->GetObjectName().GetCString();
if (object_name)
strm.Printf ("(%s)", object_name);
case 'p':
strm.Printf("%p", module);
break;
case 'u':
DumpModuleUUID(strm, module);
break;
default:
break;
}
}
if (dump_object_name)
{
const char *object_name = module->GetObjectName().GetCString();
if (object_name)
strm.Printf ("(%s)", object_name);
}
strm.EOL();
}
@ -2944,12 +2996,14 @@ CommandObjectTargetModulesList::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_1, false, "address", 'a', required_argument, NULL, 0, eArgTypeAddress, "Display the image at this address."},
{ LLDB_OPT_SET_1, false, "arch", 'A', optional_argument, NULL, 0, eArgTypeWidth, "Display the architecture when listing images."},
{ LLDB_OPT_SET_1, false, "triple", 't', optional_argument, NULL, 0, eArgTypeWidth, "Display the triple when listing images."},
{ LLDB_OPT_SET_1, false, "header", 'h', no_argument, NULL, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise."},
{ LLDB_OPT_SET_1, false, "offset", 'o', no_argument, NULL, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)."},
{ LLDB_OPT_SET_1, false, "uuid", 'u', no_argument, NULL, 0, eArgTypeNone, "Display the UUID when listing images."},
{ LLDB_OPT_SET_1, false, "fullpath", 'f', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image object file."},
{ LLDB_OPT_SET_1, false, "directory", 'd', optional_argument, NULL, 0, eArgTypeWidth, "Display the directory with optional width for the image object file."},
{ LLDB_OPT_SET_1, false, "basename", 'b', optional_argument, NULL, 0, eArgTypeWidth, "Display the basename with optional width for the image object file."},
{ LLDB_OPT_SET_1, false, "symfile", 's', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width."},
{ LLDB_OPT_SET_1, false, "symfile-basename", 'S', optional_argument, NULL, 0, eArgTypeWidth, "Display the basename to the image symbol file with optional width."},
{ LLDB_OPT_SET_1, false, "symfile-unique", 'S', optional_argument, NULL, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file."},
{ LLDB_OPT_SET_1, false, "mod-time", 'm', optional_argument, NULL, 0, eArgTypeWidth, "Display the modification time with optional width of the module."},
{ LLDB_OPT_SET_1, false, "ref-count", 'r', optional_argument, NULL, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache."},
{ LLDB_OPT_SET_1, false, "pointer", 'p', optional_argument, NULL, 0, eArgTypeNone, "Display the module pointer."},

View File

@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/Module.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/RegularExpression.h"
@ -18,6 +20,8 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
@ -111,6 +115,61 @@ namespace lldb {
#endif
Module::Module(const FileSpec& file_spec, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) :
m_mutex (Mutex::eMutexTypeRecursive),
m_mod_time (),
m_arch (),
m_uuid (),
m_file (file_spec),
m_platform_file(),
m_object_name (),
m_object_offset (),
m_objfile_sp (),
m_symfile_ap (),
m_ast (),
m_did_load_objfile (false),
m_did_load_symbol_vendor (false),
m_did_parse_uuid (false),
m_did_init_ast (false),
m_is_dynamic_loader_module (false),
m_was_modified (false)
{
// Scope for locker below...
{
Mutex::Locker locker (GetAllocationModuleCollectionMutex());
GetModuleCollection().push_back(this);
}
StreamString s;
if (m_file.GetFilename())
s << m_file.GetFilename();
s.Printf("[0x%16.16llx]", header_addr);
m_file.GetFilename().SetCString (s.GetData());
Mutex::Locker locker (m_mutex);
DataBufferSP data_sp;
if (process_sp)
{
m_did_load_objfile = true;
std::auto_ptr<DataBufferHeap> data_ap (new DataBufferHeap (512, 0));
Error error;
const size_t bytes_read = process_sp->ReadMemory (header_addr,
data_ap->GetBytes(),
data_ap->GetByteSize(),
error);
if (bytes_read == 512)
{
data_sp.reset (data_ap.release());
m_objfile_sp = ObjectFile::FindPlugin(this, process_sp, header_addr, data_sp);
if (m_objfile_sp)
{
// Once we get the object file, update our module with the object file's
// architecture since it might differ in vendor/os if some parts were
// unknown.
m_objfile_sp->GetArchitecture (m_arch);
}
}
}
}
Module::Module(const FileSpec& file_spec, const ArchSpec& arch, const ConstString *object_name, off_t object_offset) :
m_mutex (Mutex::eMutexTypeRecursive),
m_mod_time (file_spec.GetModificationTime()),
@ -977,3 +1036,33 @@ Module::SetArchitecture (const ArchSpec &new_arch)
return m_arch == new_arch;
}
bool
Module::SetLoadAddress (Target &target, lldb::addr_t offset, bool &changed)
{
changed = false;
ObjectFile *image_object_file = GetObjectFile();
if (image_object_file)
{
SectionList *section_list = image_object_file->GetSectionList ();
if (section_list)
{
const size_t num_sections = section_list->GetSize();
size_t sect_idx = 0;
for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
{
// Iterate through the object file sections to find the
// first section that starts of file offset zero and that
// has bytes in the file...
Section *section = section_list->GetSectionAtIndex (sect_idx).get();
if (section)
{
if (target.GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress() + offset))
changed = true;
}
}
return sect_idx > 0;
}
}
return false;
}

View File

@ -860,6 +860,8 @@ ModuleList::GetSharedModule
{
error.SetErrorStringWithFormat("'%s' does not exist", path);
}
if (error.Fail())
module_sp.reset();
return error;
}

View File

@ -865,6 +865,8 @@ struct ObjectFileInstance
std::string name;
std::string description;
ObjectFileCreateInstance create_callback;
ObjectFileCreateMemoryInstance create_memory_callback;
};
typedef std::vector<ObjectFileInstance> ObjectFileInstances;
@ -889,7 +891,8 @@ PluginManager::RegisterPlugin
(
const char *name,
const char *description,
ObjectFileCreateInstance create_callback
ObjectFileCreateInstance create_callback,
ObjectFileCreateMemoryInstance create_memory_callback
)
{
if (create_callback)
@ -900,6 +903,7 @@ PluginManager::RegisterPlugin
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
instance.create_memory_callback = create_memory_callback;
Mutex::Locker locker (GetObjectFileMutex ());
GetObjectFileInstances ().push_back (instance);
}
@ -937,6 +941,17 @@ PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx)
return NULL;
}
ObjectFileCreateMemoryInstance
PluginManager::GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx)
{
Mutex::Locker locker (GetObjectFileMutex ());
ObjectFileInstances &instances = GetObjectFileInstances ();
if (idx < instances.size())
return instances[idx].create_memory_callback;
return NULL;
}
ObjectFileCreateInstance
PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
{
@ -957,6 +972,26 @@ PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name)
}
ObjectFileCreateMemoryInstance
PluginManager::GetObjectFileCreateMemoryCallbackForPluginName (const char *name)
{
if (name && name[0])
{
llvm::StringRef name_sref(name);
Mutex::Locker locker (GetObjectFileMutex ());
ObjectFileInstances &instances = GetObjectFileInstances ();
ObjectFileInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++ pos)
{
if (name_sref.equals (pos->name))
return pos->create_memory_callback;
}
}
return NULL;
}
#pragma mark ObjectContainer

View File

@ -307,35 +307,6 @@ Section::DumpName (Stream *s) const
m_name.Dump(s);
}
size_t
Section::ReadSectionDataFromObjectFile (const ObjectFile* objfile, off_t section_offset, void *dst, size_t dst_len) const
{
// The object file now contains a full mmap'ed copy of the object file data, so just use this
if (objfile)
return objfile->CopyData (GetFileOffset() + section_offset, dst_len, dst);
return 0;
}
//----------------------------------------------------------------------
// Get the section data the file on disk
//----------------------------------------------------------------------
size_t
Section::ReadSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
{
// The object file now contains a full mmap'ed copy of the object file data, so just use this
return MemoryMapSectionDataFromObjectFile (objfile, section_data);
}
size_t
Section::MemoryMapSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
{
// The object file now contains a full mmap'ed copy of the object file data, so just use this
if (objfile)
return objfile->GetData(GetFileOffset(), GetByteSize(), section_data);
section_data.Clear();
return 0;
}
bool
Section::IsDescendant (const Section *section)
{

View File

@ -286,6 +286,10 @@ DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &
module_sp = m_process->GetTarget().GetSharedModule (image_info.file_spec,
arch,
image_info_uuid_is_valid ? &image_info.uuid : NULL);
if (!module_sp || module_sp->GetObjectFile() == NULL)
module_sp = m_process->ReadModuleFromMemory (image_info.file_spec,
image_info.address);
if (did_create_ptr)
*did_create_ptr = module_sp;
}
@ -752,6 +756,11 @@ DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &i
NULL,
&commpage_dbstr,
objfile->GetOffset() + commpage_section->GetFileOffset());
if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL)
commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec,
image_infos[idx].address);
}
if (commpage_image_module_sp)
UpdateCommPageLoadAddress (commpage_image_module_sp.get());
@ -1216,6 +1225,9 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::co
exe_module_sp = m_process->GetTarget().GetSharedModule (image_infos[exe_idx].file_spec,
exe_arch_spec,
&image_infos[exe_idx].uuid);
if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
exe_module_sp = m_process->ReadModuleFromMemory (image_infos[exe_idx].file_spec,
image_infos[exe_idx].address);
}
if (exe_module_sp)

View File

@ -148,7 +148,8 @@ ObjectFileELF::Initialize()
{
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
CreateInstance,
CreateMemoryInstance);
}
void
@ -196,6 +197,13 @@ ObjectFileELF::CreateInstance(Module *module,
}
ObjectFile*
ObjectFileELF::CreateMemoryInstance(Module* module, DataBufferSP& data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr)
{
return NULL;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@ -428,8 +436,8 @@ ObjectFileELF::ParseDependentModules()
DataExtractor dynsym_data;
DataExtractor dynstr_data;
if (dynsym->ReadSectionDataFromObjectFile(this, dynsym_data) &&
dynstr->ReadSectionDataFromObjectFile(this, dynstr_data))
if (ReadSectionData(dynsym, dynsym_data) &&
ReadSectionData(dynstr, dynstr_data))
{
ELFDynamic symbol;
const unsigned section_size = dynsym_data.GetByteSize();
@ -812,8 +820,8 @@ ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id,
{
DataExtractor symtab_data;
DataExtractor strtab_data;
if (symtab->ReadSectionDataFromObjectFile(this, symtab_data) &&
strtab->ReadSectionDataFromObjectFile(this, strtab_data))
if (ReadSectionData(symtab, symtab_data) &&
ReadSectionData(strtab, strtab_data))
{
num_symbols = ParseSymbols(symbol_table, start_id,
section_list, symtab_hdr,
@ -844,7 +852,7 @@ ObjectFileELF::ParseDynamicSymbols()
ELFDynamic symbol;
DataExtractor dynsym_data;
if (dynsym->ReadSectionDataFromObjectFile(this, dynsym_data))
if (ReadSectionData(dynsym, dynsym_data))
{
const unsigned section_size = dynsym_data.GetByteSize();
@ -1034,15 +1042,15 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
return 0;
DataExtractor rel_data;
if (!rel_section->ReadSectionDataFromObjectFile(this, rel_data))
if (!ReadSectionData(rel_section, rel_data))
return 0;
DataExtractor symtab_data;
if (!symtab->ReadSectionDataFromObjectFile(this, symtab_data))
if (!ReadSectionData(symtab, symtab_data))
return 0;
DataExtractor strtab_data;
if (!strtab->ReadSectionDataFromObjectFile(this, strtab_data))
if (!ReadSectionData(strtab, strtab_data))
return 0;
unsigned rel_type = PLTRelocationType();

View File

@ -51,6 +51,12 @@ public:
lldb::addr_t offset,
lldb::addr_t length);
static lldb_private::ObjectFile *
CreateMemoryInstance (lldb_private::Module* module,
lldb::DataBufferSP& data_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------

View File

@ -26,6 +26,7 @@
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
using namespace lldb;
@ -39,7 +40,8 @@ ObjectFileMachO::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
CreateInstance,
CreateMemoryInstance);
}
void
@ -74,6 +76,58 @@ ObjectFileMachO::CreateInstance (Module* module, DataBufferSP& data_sp, const Fi
return NULL;
}
ObjectFile *
ObjectFileMachO::CreateMemoryInstance (Module* module,
DataBufferSP& data_sp,
const ProcessSP &process_sp,
lldb::addr_t header_addr)
{
if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
{
std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module, data_sp, process_sp, header_addr));
if (objfile_ap.get() && objfile_ap->ParseHeader())
return objfile_ap.release();
}
return NULL;
}
const ConstString &
ObjectFileMachO::GetSegmentNameTEXT()
{
static ConstString g_segment_name_TEXT ("__TEXT");
return g_segment_name_TEXT;
}
const ConstString &
ObjectFileMachO::GetSegmentNameDATA()
{
static ConstString g_segment_name_DATA ("__DATA");
return g_segment_name_DATA;
}
const ConstString &
ObjectFileMachO::GetSegmentNameOBJC()
{
static ConstString g_segment_name_OBJC ("__OBJC");
return g_segment_name_OBJC;
}
const ConstString &
ObjectFileMachO::GetSegmentNameLINKEDIT()
{
static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
return g_section_name_LINKEDIT;
}
const ConstString &
ObjectFileMachO::GetSectionNameEHFrame()
{
static ConstString g_section_name_eh_frame ("__eh_frame");
return g_section_name_eh_frame;
}
static uint32_t
MachHeaderSizeFromMagic(uint32_t magic)
@ -121,6 +175,20 @@ ObjectFileMachO::ObjectFileMachO(Module* module, DataBufferSP& data_sp, const Fi
::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
}
ObjectFileMachO::ObjectFileMachO (lldb_private::Module* module,
lldb::DataBufferSP& header_data_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr) :
ObjectFile(module, process_sp, header_addr, header_data_sp),
m_mutex (Mutex::eMutexTypeRecursive),
m_header(),
m_sections_ap(),
m_symtab_ap(),
m_entry_point_address ()
{
::memset (&m_header, 0, sizeof(m_header));
::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
}
ObjectFileMachO::~ObjectFileMachO()
{
@ -173,7 +241,28 @@ ObjectFileMachO::ParseHeader ()
ArchSpec mach_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
if (SetModulesArchitecture (mach_arch))
return true;
{
const size_t header_and_lc_size = m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic);
if (m_data.GetByteSize() < header_and_lc_size)
{
DataBufferSP data_sp;
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
{
data_sp = ReadMemory (process_sp, m_offset, header_and_lc_size);
}
else
{
// Read in all only the load command data from the file on disk
data_sp = m_file.ReadFileContents(m_offset, header_and_lc_size);
if (data_sp->GetByteSize() != header_and_lc_size)
return false;
}
if (data_sp)
m_data.SetData (data_sp);
}
}
return true;
}
else
{
@ -799,11 +888,45 @@ ObjectFileMachO::ParseSymtab (bool minimize)
if (section_list == NULL)
return 0;
ProcessSP process_sp (m_process_wp.lock());
const size_t addr_byte_size = m_data.GetAddressByteSize();
bool bit_width_32 = addr_byte_size == 4;
const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
DataExtractor nlist_data (m_data, symtab_load_command.symoff, symtab_load_command.nsyms * nlist_byte_size);
DataExtractor nlist_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
DataExtractor strtab_data (NULL, 0, m_data.GetByteOrder(), m_data.GetAddressByteSize());
const addr_t nlist_data_byte_size = symtab_load_command.nsyms * nlist_byte_size;
const addr_t strtab_data_byte_size = symtab_load_command.strsize;
if (process_sp)
{
Target &target = process_sp->GetTarget();
SectionSP linkedit_section_sp(section_list->FindSectionByName(GetSegmentNameLINKEDIT()));
// Reading mach file from memory in a process or core file...
if (linkedit_section_sp)
{
const addr_t linkedit_load_addr = linkedit_section_sp->GetLoadBaseAddress(&target);
const addr_t linkedit_file_offset = linkedit_section_sp->GetFileOffset();
const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset;
const addr_t stroff_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset;
DataBufferSP nlist_data_sp (ReadMemory (process_sp, symoff_addr, nlist_data_byte_size));
DataBufferSP strtab_data_sp (ReadMemory (process_sp, stroff_addr, strtab_data_byte_size));
nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize());
strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
}
}
else
{
nlist_data.SetData (m_data,
symtab_load_command.symoff,
nlist_data_byte_size);
strtab_data.SetData (m_data,
symtab_load_command.stroff,
strtab_data_byte_size);
}
if (nlist_data.GetByteSize() == 0)
{
@ -812,7 +935,6 @@ ObjectFileMachO::ParseSymtab (bool minimize)
return 0;
}
DataExtractor strtab_data (m_data, symtab_load_command.stroff, symtab_load_command.strsize);
if (strtab_data.GetByteSize() == 0)
{
@ -821,10 +943,10 @@ ObjectFileMachO::ParseSymtab (bool minimize)
return 0;
}
static ConstString g_segment_name_TEXT ("__TEXT");
static ConstString g_segment_name_DATA ("__DATA");
static ConstString g_segment_name_OBJC ("__OBJC");
static ConstString g_section_name_eh_frame ("__eh_frame");
const ConstString &g_segment_name_TEXT = GetSegmentNameTEXT();
const ConstString &g_segment_name_DATA = GetSegmentNameDATA();
const ConstString &g_segment_name_OBJC = GetSegmentNameOBJC();
const ConstString &g_section_name_eh_frame = GetSectionNameEHFrame();
SectionSP text_section_sp(section_list->FindSectionByName(g_segment_name_TEXT));
SectionSP data_section_sp(section_list->FindSectionByName(g_segment_name_DATA));
SectionSP objc_section_sp(section_list->FindSectionByName(g_segment_name_OBJC));
@ -1823,6 +1945,24 @@ ObjectFileMachO::GetEntryPointAddress ()
}
lldb_private::Address
ObjectFileMachO::GetHeaderAddress ()
{
lldb_private::Address header_addr;
SectionList *section_list = GetSectionList();
if (section_list)
{
SectionSP text_segment_sp (section_list->FindSectionByName (GetSegmentNameTEXT()));
if (text_segment_sp)
{
header_addr.SetSection (text_segment_sp.get());
header_addr.SetOffset (0);
}
}
return header_addr;
}
ObjectFile::Type
ObjectFileMachO::CalculateType()
{

View File

@ -40,13 +40,19 @@ public:
static const char *
GetPluginDescriptionStatic();
static ObjectFile *
static lldb_private::ObjectFile *
CreateInstance (lldb_private::Module* module,
lldb::DataBufferSP& dataSP,
const lldb_private::FileSpec* file,
lldb::addr_t offset,
lldb::addr_t length);
static lldb_private::ObjectFile *
CreateMemoryInstance (lldb_private::Module* module,
lldb::DataBufferSP& data_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
static bool
MagicBytesMatch (lldb::DataBufferSP& dataSP,
lldb::addr_t offset,
@ -61,6 +67,11 @@ public:
lldb::addr_t offset,
lldb::addr_t length);
ObjectFileMachO (lldb_private::Module* module,
lldb::DataBufferSP& dataSP,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
virtual
~ObjectFileMachO();
@ -111,7 +122,10 @@ public:
virtual lldb_private::Address
GetEntryPointAddress ();
virtual lldb_private::Address
GetHeaderAddress ();
virtual ObjectFile::Type
CalculateType();
@ -123,6 +137,11 @@ protected:
llvm::MachO::mach_header m_header;
mutable std::auto_ptr<lldb_private::SectionList> m_sections_ap;
mutable std::auto_ptr<lldb_private::Symtab> m_symtab_ap;
static const lldb_private::ConstString &GetSegmentNameTEXT();
static const lldb_private::ConstString &GetSegmentNameDATA();
static const lldb_private::ConstString &GetSegmentNameOBJC();
static const lldb_private::ConstString &GetSegmentNameLINKEDIT();
static const lldb_private::ConstString &GetSectionNameEHFrame();
llvm::MachO::dysymtab_command m_dysymtab;
std::vector<llvm::MachO::segment_command_64> m_mach_segments;

View File

@ -120,7 +120,8 @@ ObjectFilePECOFF::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
CreateInstance,
CreateMemoryInstance);
}
void
@ -155,6 +156,15 @@ ObjectFilePECOFF::CreateInstance (Module* module, DataBufferSP& dataSP, const Fi
return NULL;
}
ObjectFile *
ObjectFilePECOFF::CreateMemoryInstance (lldb_private::Module* module,
lldb::DataBufferSP& data_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr)
{
return NULL;
}
bool
ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& dataSP)
{

View File

@ -42,6 +42,11 @@ public:
lldb::addr_t offset,
lldb::addr_t length);
static lldb_private::ObjectFile *
CreateMemoryInstance (lldb_private::Module* module,
lldb::DataBufferSP& data_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr);
static bool
MagicBytesMatch (lldb::DataBufferSP& dataSP);

View File

@ -275,7 +275,7 @@ SymbolFileDWARF::InitializeObject()
// Memory map the DWARF mach-o segment so we have everything mmap'ed
// to keep our heap memory usage down.
if (section)
section->MemoryMapSectionDataFromObjectFile(m_obj_file, m_dwarf_data);
m_obj_file->MemoryMapSectionData(section, m_dwarf_data);
}
get_apple_names_data();
if (m_data_apple_names.GetByteSize() > 0)
@ -460,7 +460,7 @@ SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type,
}
else
{
if (section->ReadSectionDataFromObjectFile(m_obj_file, data) == 0)
if (m_obj_file->ReadSectionData (section, data) == 0)
data.Clear();
}
}

View File

@ -27,9 +27,9 @@
using namespace lldb;
using namespace lldb_private;
DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile& objfile, SectionSP& section, lldb::RegisterKind reg_kind, bool is_eh_frame) :
DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile& objfile, SectionSP& section_sp, lldb::RegisterKind reg_kind, bool is_eh_frame) :
m_objfile (objfile),
m_section (section),
m_section_sp (section_sp),
m_reg_kind (reg_kind), // The flavor of registers that the CFI data uses (enum RegisterKind)
m_flags (),
m_cie_map (),
@ -68,7 +68,7 @@ DWARFCallFrameInfo::GetUnwindPlan (Address addr, UnwindPlan& unwind_plan)
bool
DWARFCallFrameInfo::GetFDEEntryByAddress (Address addr, FDEEntry& fde_entry)
{
if (m_section.get() == NULL || m_section->IsEncrypted())
if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
return false;
GetFDEIndex();
@ -280,7 +280,7 @@ DWARFCallFrameInfo::GetCFIData()
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (log)
m_objfile.GetModule()->LogMessage(log.get(), "Reading EH frame info");
m_section->ReadSectionDataFromObjectFile (&m_objfile, m_cfi_data);
m_objfile.ReadSectionData (m_section_sp.get(), m_cfi_data);
m_cfi_data_initialized = true;
}
}
@ -291,7 +291,7 @@ DWARFCallFrameInfo::GetCFIData()
void
DWARFCallFrameInfo::GetFDEIndex ()
{
if (m_section.get() == NULL || m_section->IsEncrypted())
if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
return;
if (m_fde_index_initialized)
return;
@ -318,7 +318,7 @@ DWARFCallFrameInfo::GetFDEIndex ()
const CIE *cie = GetCIE (cie_offset);
if (cie)
{
const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
@ -348,7 +348,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t offset, Address startaddr, Unwi
{
dw_offset_t current_entry = offset;
if (m_section.get() == NULL || m_section->IsEncrypted())
if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
return false;
if (m_cfi_data_initialized == false)
@ -377,7 +377,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t offset, Address startaddr, Unwi
const dw_offset_t end_offset = current_entry + length + 4;
const lldb::addr_t pc_rel_addr = m_section->GetFileAddress();
const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);

View File

@ -10,6 +10,7 @@
#include "lldb/lldb-private.h"
#include "lldb/lldb-private-log.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
@ -18,6 +19,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/ObjectContainer.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Target/Process.h"
using namespace lldb;
using namespace lldb_private;
@ -106,6 +108,40 @@ ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset
return object_file_sp;
}
ObjectFileSP
ObjectFile::FindPlugin (Module* module,
const ProcessSP &process_sp,
lldb::addr_t header_addr,
DataBufferSP &file_data_sp)
{
Timer scoped_timer (__PRETTY_FUNCTION__,
"ObjectFile::FindPlugin (module = %s/%s, process = %p, header_addr = 0x%llx)",
module->GetFileSpec().GetDirectory().AsCString(),
module->GetFileSpec().GetFilename().AsCString(),
process_sp.get(), header_addr);
ObjectFileSP object_file_sp;
if (module != NULL)
{
uint32_t idx;
// Check if this is a normal object file by iterating through
// all object file plugin instances.
ObjectFileCreateMemoryInstance create_callback;
for (idx = 0; (create_callback = PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != NULL; ++idx)
{
object_file_sp.reset (create_callback(module, file_data_sp, process_sp, header_addr));
if (object_file_sp.get())
return object_file_sp;
}
}
// We didn't find it, so clear our shared pointer in case it
// contains anything and return an empty shared pointer
object_file_sp.reset();
return object_file_sp;
}
ObjectFile::ObjectFile (Module* module,
const FileSpec *file_spec_ptr,
addr_t file_offset,
@ -118,7 +154,9 @@ ObjectFile::ObjectFile (Module* module,
m_offset (file_offset),
m_length (file_size),
m_data (),
m_unwind_table (*this)
m_unwind_table (*this),
m_process_wp(),
m_in_memory (false)
{
if (file_spec_ptr)
m_file = *file_spec_ptr;
@ -150,6 +188,37 @@ ObjectFile::ObjectFile (Module* module,
}
}
ObjectFile::ObjectFile (Module* module,
const ProcessSP &process_sp,
lldb::addr_t header_addr,
DataBufferSP& header_data_sp) :
ModuleChild (module),
m_file (),
m_type (eTypeInvalid),
m_strata (eStrataInvalid),
m_offset (header_addr),
m_length (0),
m_data (),
m_unwind_table (*this),
m_process_wp (process_sp),
m_in_memory (true)
{
if (header_data_sp)
m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
{
log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, process = %p, header_addr = 0x%llx\n",
this,
m_module->GetFileSpec().GetDirectory().AsCString(),
m_module->GetFileSpec().GetFilename().AsCString(),
process_sp.get(),
m_offset);
}
}
ObjectFile::~ObjectFile()
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
@ -276,6 +345,24 @@ ObjectFile::GetAddressClass (addr_t file_addr)
return eAddressClassUnknown;
}
DataBufferSP
ObjectFile::ReadMemory (const ProcessSP &process_sp, lldb::addr_t addr, size_t byte_size)
{
DataBufferSP data_sp;
if (process_sp)
{
std::auto_ptr<DataBufferHeap> data_ap (new DataBufferHeap (byte_size, 0));
Error error;
const size_t bytes_read = process_sp->ReadMemory (addr,
data_ap->GetBytes(),
data_ap->GetByteSize(),
error);
if (bytes_read == byte_size)
data_sp.reset (data_ap.release());
}
return data_sp;
}
size_t
ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
{
@ -291,3 +378,69 @@ ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
}
size_t
ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const
{
if (m_in_memory)
{
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
{
Error error;
return process_sp->ReadMemory (section->GetLoadBaseAddress (&process_sp->GetTarget()) + section_offset, dst, dst_len, error);
}
}
else
{
return CopyData (section->GetFileOffset() + section_offset, dst_len, dst);
}
return 0;
}
//----------------------------------------------------------------------
// Get the section data the file on disk
//----------------------------------------------------------------------
size_t
ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const
{
if (m_in_memory)
{
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
{
DataBufferSP data_sp (ReadMemory (process_sp, section->GetLoadBaseAddress (&process_sp->GetTarget()), section->GetByteSize()));
if (data_sp)
{
section_data.SetData (data_sp, 0, data_sp->GetByteSize());
section_data.SetByteOrder (process_sp->GetByteOrder());
section_data.SetAddressByteSize (process_sp->GetAddressByteSize());
return section_data.GetByteSize();
}
}
}
else
{
// The object file now contains a full mmap'ed copy of the object file data, so just use this
return MemoryMapSectionData (section, section_data);
}
section_data.Clear();
return 0;
}
size_t
ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const
{
if (m_in_memory)
{
return ReadSectionData (section, section_data);
}
else
{
// The object file now contains a full mmap'ed copy of the object file data, so just use this
return GetData(section->GetFileOffset(), section->GetByteSize(), section_data);
}
section_data.Clear();
return 0;
}

View File

@ -2183,6 +2183,18 @@ Process::DeallocateMemory (addr_t ptr)
return error;
}
ModuleSP
Process::ReadModuleFromMemory (const FileSpec& file_spec, lldb::addr_t header_addr)
{
ModuleSP module_sp (new Module (file_spec, shared_from_this(), header_addr));
if (module_sp)
{
m_target.GetImages().Append(module_sp);
bool changed = false;
module_sp->SetLoadAddress (m_target, 0, changed);
}
return module_sp;
}
Error
Process::EnableWatchpoint (Watchpoint *watchpoint)

View File

@ -983,10 +983,10 @@ Target::ReadMemoryFromFileCache (const Address& addr, void *dst, size_t dst_len,
ObjectFile *objfile = section->GetModule()->GetObjectFile();
if (objfile)
{
size_t bytes_read = section->ReadSectionDataFromObjectFile (objfile,
addr.GetOffset(),
dst,
dst_len);
size_t bytes_read = objfile->ReadSectionData (section,
addr.GetOffset(),
dst,
dst_len);
if (bytes_read > 0)
return bytes_read;
else