forked from OSchip/llvm-project
Big change in the way ObjectFile file contents are managed. We now
mmap() the entire object file contents into memory with MAP_PRIVATE. We do this because object file contents can change on us and currently this helps alleviate this situation. It also make the code for accessing object file data much easier to manage and we don't end up opening the file, reading some data and closing the file over and over. llvm-svn: 148017
This commit is contained in:
parent
c7f03b6155
commit
44435ed07a
|
@ -199,9 +199,6 @@ public:
|
|||
m_byte_size = byte_size;
|
||||
}
|
||||
|
||||
size_t
|
||||
GetSectionDataFromImage (const DataExtractor& image_data, DataExtractor& section_data) const;
|
||||
|
||||
bool
|
||||
IsFake() const
|
||||
{
|
||||
|
|
|
@ -49,17 +49,19 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
ObjectContainer (Module* module,
|
||||
const FileSpec *file,
|
||||
lldb::addr_t offset,
|
||||
lldb::addr_t length,
|
||||
lldb::DataBufferSP& headerDataSP) :
|
||||
lldb::addr_t file_offset,
|
||||
lldb::addr_t file_size,
|
||||
lldb::DataBufferSP& file_data_sp) :
|
||||
ModuleChild (module),
|
||||
m_file (), // This file can be different than the module's file spec
|
||||
m_offset (offset),
|
||||
m_length (length),
|
||||
m_data (headerDataSP, lldb::endian::InlHostByteOrder(), 4)
|
||||
m_offset (file_offset),
|
||||
m_length (file_size),
|
||||
m_data ()
|
||||
{
|
||||
if (file)
|
||||
m_file = *file;
|
||||
if (file_data_sp)
|
||||
m_data.SetData (file_data_sp, file_offset, file_size);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -146,7 +146,8 @@ public:
|
|||
FindPlugin (Module* module,
|
||||
const FileSpec* file_spec,
|
||||
lldb::addr_t file_offset,
|
||||
lldb::addr_t file_size);
|
||||
lldb::addr_t file_size,
|
||||
lldb::DataBufferSP &data_sp);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Gets the address size in bytes for the current object file.
|
||||
|
@ -423,7 +424,12 @@ public:
|
|||
return m_strata;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
GetData (off_t offset, size_t length, DataExtractor &data) const;
|
||||
|
||||
size_t
|
||||
CopyData (off_t offset, size_t length, void *dst) const;
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
// Member variables.
|
||||
|
|
|
@ -782,7 +782,8 @@ Module::GetObjectFile()
|
|||
m_did_load_objfile = true;
|
||||
Timer scoped_timer(__PRETTY_FUNCTION__,
|
||||
"Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString(""));
|
||||
m_objfile_sp = ObjectFile::FindPlugin(this, &m_file, m_object_offset, m_file.GetByteSize());
|
||||
DataBufferSP file_data_sp;
|
||||
m_objfile_sp = ObjectFile::FindPlugin(this, &m_file, m_object_offset, m_file.GetByteSize(), file_data_sp);
|
||||
if (m_objfile_sp)
|
||||
{
|
||||
// Once we get the object file, update our module with the object file's
|
||||
|
|
|
@ -878,6 +878,8 @@ ModuleList::GetSharedModule
|
|||
if (!file_spec.Exists())
|
||||
{
|
||||
file_spec.GetPath(path, sizeof(path));
|
||||
if (path[0] == '\0')
|
||||
in_file_spec.GetPath(path, sizeof(path));
|
||||
if (file_spec.Exists())
|
||||
{
|
||||
if (uuid_ptr && uuid_ptr->IsValid())
|
||||
|
|
|
@ -228,7 +228,7 @@ Section::Dump (Stream *s, Target *target, uint32_t depth) const
|
|||
{
|
||||
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
|
||||
s->Indent();
|
||||
s->Printf("0x%8.8llx %-14s ", GetID(), GetSectionTypeAsCString (m_type));
|
||||
s->Printf("0x%8.8llx %-16s ", GetID(), GetSectionTypeAsCString (m_type));
|
||||
bool resolved = true;
|
||||
addr_t addr = LLDB_INVALID_ADDRESS;
|
||||
|
||||
|
@ -307,53 +307,12 @@ Section::DumpName (Stream *s) const
|
|||
m_name.Dump(s);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Get the section data from a complete contiguous copy of the
|
||||
// entire executable image.
|
||||
//----------------------------------------------------------------------
|
||||
size_t
|
||||
Section::GetSectionDataFromImage (const DataExtractor& image_data, DataExtractor& section_data) const
|
||||
{
|
||||
size_t file_size = GetByteSize();
|
||||
if (file_size > 0)
|
||||
{
|
||||
off_t file_offset = GetFileOffset();
|
||||
if (section_data.SetData (image_data, file_offset, file_size) == file_size)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
Section::ReadSectionDataFromObjectFile (const ObjectFile* objfile, off_t section_offset, void *dst, size_t dst_len) const
|
||||
{
|
||||
if (objfile && dst && dst_len)
|
||||
{
|
||||
const FileSpec& file = objfile->GetFileSpec();
|
||||
|
||||
if (file)
|
||||
{
|
||||
size_t bytes_left = dst_len;
|
||||
size_t bytes_read = 0;
|
||||
const uint64_t file_size = GetFileSize();
|
||||
if (section_offset < file_size)
|
||||
{
|
||||
off_t section_file_offset = objfile->GetOffset() + GetFileOffset() + section_offset;
|
||||
bytes_read = file.ReadFileContents (section_file_offset, dst, dst_len, NULL);
|
||||
if (bytes_read >= dst_len)
|
||||
return bytes_read;
|
||||
bytes_left -= bytes_read;
|
||||
}
|
||||
|
||||
const uint64_t byte_size = GetByteSize();
|
||||
if (section_offset + bytes_read < byte_size)
|
||||
{
|
||||
memset ((uint8_t*)dst + bytes_read, 0, bytes_left);
|
||||
bytes_read += bytes_left;
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -363,47 +322,17 @@ Section::ReadSectionDataFromObjectFile (const ObjectFile* objfile, off_t section
|
|||
size_t
|
||||
Section::ReadSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
|
||||
{
|
||||
if (objfile == NULL)
|
||||
return 0;
|
||||
|
||||
const FileSpec& file = objfile->GetFileSpec();
|
||||
|
||||
if (file)
|
||||
{
|
||||
size_t section_file_size = GetByteSize();
|
||||
if (section_file_size > 0)
|
||||
{
|
||||
off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
|
||||
DataBufferSP section_data_sp(file.ReadFileContents(section_file_offset, section_file_size));
|
||||
|
||||
section_data.SetByteOrder(objfile->GetByteOrder());
|
||||
section_data.SetAddressByteSize(objfile->GetAddressByteSize());
|
||||
return section_data.SetData (section_data_sp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
// 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
|
||||
{
|
||||
if (objfile == NULL)
|
||||
return 0;
|
||||
|
||||
const FileSpec& file = objfile->GetFileSpec();
|
||||
|
||||
if (file)
|
||||
{
|
||||
size_t section_file_size = GetFileSize();
|
||||
if (section_file_size > 0)
|
||||
{
|
||||
off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
|
||||
DataBufferSP section_data_sp(file.MemoryMapFileContents(section_file_offset, section_file_size));
|
||||
section_data.SetByteOrder(objfile->GetByteOrder());
|
||||
section_data.SetAddressByteSize(objfile->GetAddressByteSize());
|
||||
return section_data.SetData (section_data_sp);
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -691,16 +620,10 @@ SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth)
|
|||
bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty();
|
||||
if (show_header && !m_sections.empty())
|
||||
{
|
||||
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
|
||||
// s->Indent();
|
||||
// s->PutCString( "SectionList\n");
|
||||
// s->IndentMore();
|
||||
// s->Printf("%*s", 2*(sizeof(void *) + 2), "");
|
||||
s->Indent();
|
||||
s->Printf("SectID Type %s Address File Off. File Size Flags Section Name\n", target_has_loaded_sections ? "Load" : "File");
|
||||
// s->Printf("%*s", 2*(sizeof(void *) + 2), "");
|
||||
s->Printf( "SectID Type %s Address File Off. File Size Flags Section Name\n", target_has_loaded_sections ? "Load" : "File");
|
||||
s->Indent();
|
||||
s->PutCString("---------- -------------- --------------------------------------- ---------- ---------- ---------- ----------------------------\n");
|
||||
s->PutCString("---------- ---------------- --------------------------------------- ---------- ---------- ---------- ----------------------------\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -450,7 +450,7 @@ LocateDSYMInVincinityOfExecutable (const FileSpec *exec_fspec, const ArchSpec* a
|
|||
|
||||
dsym_fspec.SetFile(path, false);
|
||||
|
||||
if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
|
||||
if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ LocateDSYMInVincinityOfExecutable (const FileSpec *exec_fspec, const ArchSpec* a
|
|||
strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
|
||||
strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
|
||||
dsym_fspec.SetFile(path, false);
|
||||
if (dsym_fspec.Exists())
|
||||
if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
|
|
|
@ -269,7 +269,9 @@ ObjectContainerBSDArchive::CreateInstance
|
|||
addr_t offset,
|
||||
addr_t length)
|
||||
{
|
||||
if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data_sp))
|
||||
DataExtractor data;
|
||||
data.SetData (data_sp, offset, length);
|
||||
if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
|
||||
{
|
||||
Timer scoped_timer (__PRETTY_FUNCTION__,
|
||||
"ObjectContainerBSDArchive::CreateInstance (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
|
||||
|
@ -278,25 +280,20 @@ ObjectContainerBSDArchive::CreateInstance
|
|||
file, offset, length);
|
||||
|
||||
Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module->GetArchitecture(), module->GetModificationTime()));
|
||||
|
||||
if (archive_sp)
|
||||
|
||||
std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module, data_sp, file, offset, length));
|
||||
|
||||
if (container_ap.get())
|
||||
{
|
||||
// We already have this archive in our cache, use it
|
||||
std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module, data_sp, file, offset, length));
|
||||
if (container_ap.get())
|
||||
if (archive_sp)
|
||||
{
|
||||
// We already have this archive in our cache, use it
|
||||
container_ap->SetArchive (archive_sp);
|
||||
return container_ap.release();
|
||||
}
|
||||
else if (container_ap->ParseHeader())
|
||||
return container_ap.release();
|
||||
}
|
||||
|
||||
// Read everything since we need that in order to index all the
|
||||
// objects in the archive
|
||||
data_sp = file->MemoryMapFileContents (offset, length);
|
||||
|
||||
std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module, data_sp, file, offset, length));
|
||||
if (container_ap->ParseHeader())
|
||||
return container_ap.release();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -304,9 +301,8 @@ ObjectContainerBSDArchive::CreateInstance
|
|||
|
||||
|
||||
bool
|
||||
ObjectContainerBSDArchive::MagicBytesMatch (DataBufferSP& dataSP)
|
||||
ObjectContainerBSDArchive::MagicBytesMatch (const DataExtractor &data)
|
||||
{
|
||||
DataExtractor data(dataSP, lldb::endian::InlHostByteOrder(), 4);
|
||||
uint32_t offset = 0;
|
||||
const char* armag = (const char* )data.PeekData (offset, sizeof(ar_hdr));
|
||||
if (armag && ::strncmp(armag, ARMAG, SARMAG) == 0)
|
||||
|
@ -353,11 +349,6 @@ ObjectContainerBSDArchive::ParseHeader ()
|
|||
m_module->GetArchitecture(),
|
||||
m_module->GetModificationTime(),
|
||||
m_data);
|
||||
// The archive might be huge, so clear "m_data" to free up the
|
||||
// memory since it will contain the entire file (possibly more than
|
||||
// one architecture slice). We already have an index of all objects
|
||||
// in the file, so we will be ready to serve up those objects.
|
||||
m_data.Clear();
|
||||
}
|
||||
}
|
||||
return m_archive_sp.get() != NULL;
|
||||
|
@ -396,7 +387,11 @@ ObjectContainerBSDArchive::GetObjectFile (const FileSpec *file)
|
|||
{
|
||||
Object *object = m_archive_sp->FindObject (m_module->GetObjectName());
|
||||
if (object)
|
||||
return ObjectFile::FindPlugin (m_module, file, m_offset + object->ar_file_offset, object->ar_file_size);
|
||||
return ObjectFile::FindPlugin (m_module,
|
||||
file,
|
||||
object->ar_file_offset,
|
||||
object->ar_file_size,
|
||||
m_data.GetSharedDataBuffer());
|
||||
}
|
||||
return ObjectFileSP();
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
lldb::addr_t length);
|
||||
|
||||
static bool
|
||||
MagicBytesMatch (lldb::DataBufferSP& dataSP);
|
||||
MagicBytesMatch (const lldb_private::DataExtractor &data);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Member Functions
|
||||
|
|
|
@ -51,15 +51,17 @@ ObjectContainer *
|
|||
ObjectContainerUniversalMachO::CreateInstance
|
||||
(
|
||||
Module* module,
|
||||
DataBufferSP& dataSP,
|
||||
DataBufferSP& data_sp,
|
||||
const FileSpec *file,
|
||||
addr_t offset,
|
||||
addr_t length
|
||||
)
|
||||
{
|
||||
if (ObjectContainerUniversalMachO::MagicBytesMatch(dataSP))
|
||||
DataExtractor data;
|
||||
data.SetData (data_sp, offset, length);
|
||||
if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
|
||||
{
|
||||
std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, dataSP, file, offset, length));
|
||||
std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, data_sp, file, offset, length));
|
||||
if (container_ap->ParseHeader())
|
||||
{
|
||||
return container_ap.release();
|
||||
|
@ -71,9 +73,8 @@ ObjectContainerUniversalMachO::CreateInstance
|
|||
|
||||
|
||||
bool
|
||||
ObjectContainerUniversalMachO::MagicBytesMatch (DataBufferSP& dataSP)
|
||||
ObjectContainerUniversalMachO::MagicBytesMatch (const DataExtractor &data)
|
||||
{
|
||||
DataExtractor data(dataSP, lldb::endian::InlHostByteOrder(), 4);
|
||||
uint32_t offset = 0;
|
||||
uint32_t magic = data.GetU32(&offset);
|
||||
return magic == UniversalMagic || magic == UniversalMagicSwapped;
|
||||
|
@ -115,17 +116,6 @@ ObjectContainerUniversalMachO::ParseHeader ()
|
|||
|
||||
m_header.nfat_arch = m_data.GetU32(&offset);
|
||||
|
||||
const size_t nfat_arch_size = sizeof(fat_arch) * m_header.nfat_arch;
|
||||
// See if the current data we have is enough for all of the fat headers?
|
||||
if (!m_data.ValidOffsetForDataOfSize(offset, nfat_arch_size))
|
||||
{
|
||||
// The fat headers are larger than the number of bytes we have been
|
||||
// given when this class was constructed. We will read the exact number
|
||||
// of bytes that we need.
|
||||
DataBufferSP data_sp(m_file.ReadFileContents(m_offset, nfat_arch_size + sizeof(fat_header)));
|
||||
m_data.SetData (data_sp);
|
||||
}
|
||||
|
||||
// Now we should have enough data for all of the fat headers, so lets index
|
||||
// them so we know how many architectures that this universal binary contains.
|
||||
uint32_t arch_idx = 0;
|
||||
|
@ -140,9 +130,6 @@ ObjectContainerUniversalMachO::ParseHeader ()
|
|||
}
|
||||
}
|
||||
}
|
||||
// Now that we have indexed the universal headers, we no longer need any cached data.
|
||||
m_data.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -222,7 +209,8 @@ ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
|
|||
return ObjectFile::FindPlugin (m_module,
|
||||
file,
|
||||
m_offset + m_fat_archs[arch_idx].offset,
|
||||
m_fat_archs[arch_idx].size);
|
||||
m_fat_archs[arch_idx].size,
|
||||
m_data.GetSharedDataBuffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
lldb::addr_t length);
|
||||
|
||||
static bool
|
||||
MagicBytesMatch (lldb::DataBufferSP& dataSP);
|
||||
MagicBytesMatch (const lldb_private::DataExtractor &data);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Member Functions
|
||||
|
|
|
@ -473,15 +473,11 @@ ObjectFileELF::ParseProgramHeaders()
|
|||
return 0;
|
||||
|
||||
const size_t ph_size = m_header.e_phnum * m_header.e_phentsize;
|
||||
const elf_off ph_offset = m_offset + m_header.e_phoff;
|
||||
DataBufferSP buffer_sp(m_file.ReadFileContents(ph_offset, ph_size));
|
||||
|
||||
if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != ph_size)
|
||||
const elf_off ph_offset = m_header.e_phoff;
|
||||
DataExtractor data;
|
||||
if (GetData (ph_offset, ph_size, data) != ph_size)
|
||||
return 0;
|
||||
|
||||
DataExtractor data(buffer_sp, m_data.GetByteOrder(),
|
||||
m_data.GetAddressByteSize());
|
||||
|
||||
uint32_t idx;
|
||||
uint32_t offset;
|
||||
for (idx = 0, offset = 0; idx < m_header.e_phnum; ++idx)
|
||||
|
@ -515,16 +511,11 @@ ObjectFileELF::ParseSectionHeaders()
|
|||
return 0;
|
||||
|
||||
const size_t sh_size = m_header.e_shnum * m_header.e_shentsize;
|
||||
const elf_off sh_offset = m_offset + m_header.e_shoff;
|
||||
DataBufferSP buffer_sp(m_file.ReadFileContents(sh_offset, sh_size));
|
||||
|
||||
if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != sh_size)
|
||||
const elf_off sh_offset = m_header.e_shoff;
|
||||
DataExtractor data;
|
||||
if (GetData (sh_offset, sh_size, data) != sh_size)
|
||||
return 0;
|
||||
|
||||
DataExtractor data(buffer_sp,
|
||||
m_data.GetByteOrder(),
|
||||
m_data.GetAddressByteSize());
|
||||
|
||||
uint32_t idx;
|
||||
uint32_t offset;
|
||||
for (idx = 0, offset = 0; idx < m_header.e_shnum; ++idx)
|
||||
|
@ -549,13 +540,11 @@ ObjectFileELF::GetSectionHeaderStringTable()
|
|||
{
|
||||
const ELFSectionHeader &sheader = m_section_headers[strtab_idx];
|
||||
const size_t byte_size = sheader.sh_size;
|
||||
const Elf64_Off offset = m_offset + sheader.sh_offset;
|
||||
DataBufferSP buffer_sp(m_file.ReadFileContents(offset, byte_size));
|
||||
const Elf64_Off offset = sheader.sh_offset;
|
||||
m_shstr_data.SetData (m_data, offset, byte_size);
|
||||
|
||||
if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
|
||||
if (m_shstr_data.GetByteSize() != byte_size)
|
||||
return 0;
|
||||
|
||||
m_shstr_data.SetData(buffer_sp);
|
||||
}
|
||||
}
|
||||
return m_shstr_data.GetByteSize();
|
||||
|
|
|
@ -63,11 +63,11 @@ ObjectFileMachO::GetPluginDescriptionStatic()
|
|||
|
||||
|
||||
ObjectFile *
|
||||
ObjectFileMachO::CreateInstance (Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
|
||||
ObjectFileMachO::CreateInstance (Module* module, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length)
|
||||
{
|
||||
if (ObjectFileMachO::MagicBytesMatch(dataSP))
|
||||
if (ObjectFileMachO::MagicBytesMatch(data_sp, offset, length))
|
||||
{
|
||||
std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module, dataSP, file, offset, length));
|
||||
std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module, data_sp, file, offset, length));
|
||||
if (objfile_ap.get() && objfile_ap->ParseHeader())
|
||||
return objfile_ap.release();
|
||||
}
|
||||
|
@ -97,17 +97,20 @@ MachHeaderSizeFromMagic(uint32_t magic)
|
|||
|
||||
|
||||
bool
|
||||
ObjectFileMachO::MagicBytesMatch (DataBufferSP& dataSP)
|
||||
ObjectFileMachO::MagicBytesMatch (DataBufferSP& data_sp,
|
||||
lldb::addr_t data_offset,
|
||||
lldb::addr_t data_length)
|
||||
{
|
||||
DataExtractor data(dataSP, lldb::endian::InlHostByteOrder(), 4);
|
||||
DataExtractor data;
|
||||
data.SetData (data_sp, data_offset, data_length);
|
||||
uint32_t offset = 0;
|
||||
uint32_t magic = data.GetU32(&offset);
|
||||
return MachHeaderSizeFromMagic(magic) != 0;
|
||||
}
|
||||
|
||||
|
||||
ObjectFileMachO::ObjectFileMachO(Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length) :
|
||||
ObjectFile(module, file, offset, length, dataSP),
|
||||
ObjectFileMachO::ObjectFileMachO(Module* module, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length) :
|
||||
ObjectFile(module, file, offset, length, data_sp),
|
||||
m_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_header(),
|
||||
m_sections_ap(),
|
||||
|
@ -170,12 +173,7 @@ ObjectFileMachO::ParseHeader ()
|
|||
ArchSpec mach_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
|
||||
|
||||
if (SetModulesArchitecture (mach_arch))
|
||||
{
|
||||
// Read in all only the load command data
|
||||
DataBufferSP data_sp(m_file.ReadFileContents(m_offset, m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic)));
|
||||
m_data.SetData (data_sp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -802,37 +800,27 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
return 0;
|
||||
|
||||
const size_t addr_byte_size = m_data.GetAddressByteSize();
|
||||
const ByteOrder byte_order = m_data.GetByteOrder();
|
||||
bool bit_width_32 = addr_byte_size == 4;
|
||||
const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
|
||||
|
||||
DataBufferSP symtab_data_sp(m_file.ReadFileContents (m_offset + symtab_load_command.symoff,
|
||||
symtab_load_command.nsyms * nlist_byte_size));
|
||||
DataExtractor nlist_data (m_data, symtab_load_command.symoff, symtab_load_command.nsyms * nlist_byte_size);
|
||||
|
||||
if (symtab_data_sp.get() == NULL ||
|
||||
symtab_data_sp->GetBytes() == NULL ||
|
||||
symtab_data_sp->GetByteSize() == 0)
|
||||
if (nlist_data.GetByteSize() == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "failed to read nlist data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataBufferSP strtab_data_sp(m_file.ReadFileContents (m_offset + symtab_load_command.stroff,
|
||||
symtab_load_command.strsize));
|
||||
DataExtractor strtab_data (m_data, symtab_load_command.stroff, symtab_load_command.strsize);
|
||||
|
||||
if (strtab_data_sp.get() == NULL ||
|
||||
strtab_data_sp->GetBytes() == NULL ||
|
||||
strtab_data_sp->GetByteSize() == 0)
|
||||
if (strtab_data.GetByteSize() == 0)
|
||||
{
|
||||
if (log)
|
||||
GetModule()->LogMessage(log.get(), "failed to read strtab data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *strtab_data = (const char *)strtab_data_sp->GetBytes();
|
||||
const size_t strtab_data_len = strtab_data_sp->GetByteSize();
|
||||
|
||||
static ConstString g_segment_name_TEXT ("__TEXT");
|
||||
static ConstString g_segment_name_DATA ("__DATA");
|
||||
static ConstString g_segment_name_OBJC ("__OBJC");
|
||||
|
@ -847,11 +835,8 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame);
|
||||
|
||||
uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NListSectionNoSection;
|
||||
//uint32_t symtab_offset = 0;
|
||||
assert (symtab_data_sp->GetByteSize()/nlist_byte_size >= symtab_load_command.nsyms);
|
||||
|
||||
uint32_t nlist_data_offset = 0;
|
||||
DataExtractor nlist_data (symtab_data_sp, byte_order, addr_byte_size);
|
||||
|
||||
uint32_t N_SO_index = UINT32_MAX;
|
||||
|
||||
|
@ -889,7 +874,8 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
nlist.n_value = nlist_data.GetAddress_unchecked (&nlist_data_offset);
|
||||
|
||||
SymbolType type = eSymbolTypeInvalid;
|
||||
if (nlist.n_strx >= strtab_data_len)
|
||||
const char *symbol_name = strtab_data.PeekCStr(nlist.n_strx);
|
||||
if (symbol_name == NULL)
|
||||
{
|
||||
// No symbol should be NULL, even the symbols with no
|
||||
// string values should have an offset zero which points
|
||||
|
@ -902,7 +888,6 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
m_module->GetFileSpec().GetFilename().GetCString());
|
||||
continue;
|
||||
}
|
||||
const char *symbol_name = &strtab_data[nlist.n_strx];
|
||||
const char *symbol_name_non_abi_mangled = NULL;
|
||||
|
||||
if (symbol_name[0] == '\0')
|
||||
|
@ -1517,12 +1502,11 @@ ObjectFileMachO::ParseSymtab (bool minimize)
|
|||
// Now synthesize indirect symbols
|
||||
if (m_dysymtab.nindirectsyms != 0)
|
||||
{
|
||||
DataBufferSP indirect_symbol_indexes_sp(m_file.ReadFileContents(m_offset + m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4));
|
||||
DataExtractor indirect_symbol_index_data (m_data, m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4);
|
||||
|
||||
if (indirect_symbol_indexes_sp && indirect_symbol_indexes_sp->GetByteSize())
|
||||
if (indirect_symbol_index_data.GetByteSize())
|
||||
{
|
||||
NListIndexToSymbolIndexMap::const_iterator end_index_pos = m_nlist_idx_to_sym_idx.end();
|
||||
DataExtractor indirect_symbol_index_data (indirect_symbol_indexes_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
|
||||
|
||||
for (uint32_t sect_idx = 1; sect_idx < m_mach_sections.size(); ++sect_idx)
|
||||
{
|
||||
|
|
|
@ -48,7 +48,9 @@ public:
|
|||
lldb::addr_t length);
|
||||
|
||||
static bool
|
||||
MagicBytesMatch (lldb::DataBufferSP& dataSP);
|
||||
MagicBytesMatch (lldb::DataBufferSP& dataSP,
|
||||
lldb::addr_t offset,
|
||||
lldb::addr_t length);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Member Functions
|
||||
|
|
|
@ -148,7 +148,8 @@ SymbolVendorMacOSX::CreateInstance(Module* module)
|
|||
|
||||
if (dsym_fspec)
|
||||
{
|
||||
dsym_objfile_sp = ObjectFile::FindPlugin(module, &dsym_fspec, 0, dsym_fspec.GetByteSize());
|
||||
DataBufferSP dsym_file_data_sp;
|
||||
dsym_objfile_sp = ObjectFile::FindPlugin(module, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp);
|
||||
if (UUIDsMatch(module, dsym_objfile_sp.get()))
|
||||
{
|
||||
ReplaceDSYMSectionsWithExecutableSections (obj_file, dsym_objfile_sp.get());
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/lldb-private-log.h"
|
||||
#include "lldb/Core/DataBuffer.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
|
@ -22,7 +23,7 @@ using namespace lldb;
|
|||
using namespace lldb_private;
|
||||
|
||||
ObjectFileSP
|
||||
ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset, addr_t file_size)
|
||||
ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset, addr_t file_size, DataBufferSP &file_data_sp)
|
||||
{
|
||||
Timer scoped_timer (__PRETTY_FUNCTION__,
|
||||
"ObjectFile::FindPlugin (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
|
||||
|
@ -35,10 +36,14 @@ ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset
|
|||
{
|
||||
if (file)
|
||||
{
|
||||
if (file_size == 0)
|
||||
file_size = file->GetByteSize();
|
||||
// Memory map the entire file contents
|
||||
if (!file_data_sp)
|
||||
{
|
||||
assert (file_offset == 0);
|
||||
file_data_sp = file->MemoryMapFileContents(file_offset, file_size);
|
||||
}
|
||||
|
||||
if (file_size == 0)
|
||||
if (!file_data_sp || file_data_sp->GetByteSize() == 0)
|
||||
{
|
||||
// Check for archive file with format "/path/to/archive.a(object.o)"
|
||||
char path_with_object[PATH_MAX*2];
|
||||
|
@ -56,42 +61,42 @@ ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset
|
|||
archive_file.SetFile (path.c_str(), false);
|
||||
file_size = archive_file.GetByteSize();
|
||||
if (file_size > 0)
|
||||
{
|
||||
module->SetFileSpecAndObjectName (archive_file, ConstString(object.c_str()));
|
||||
file_data_sp = archive_file.MemoryMapFileContents(file_offset, file_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No need to delegate further if (file_offset, file_size) exceeds the total file size.
|
||||
// This is the base case.
|
||||
// if (file_offset + file_size > file->GetByteSize())
|
||||
// return NULL;
|
||||
|
||||
DataBufferSP file_header_data_sp(file->ReadFileContents(file_offset, 512));
|
||||
uint32_t idx;
|
||||
|
||||
// Check if this is a normal object file by iterating through
|
||||
// all object file plugin instances.
|
||||
ObjectFileCreateInstance create_object_file_callback;
|
||||
for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
|
||||
if (file_data_sp && file_data_sp->GetByteSize() > 0)
|
||||
{
|
||||
object_file_sp.reset (create_object_file_callback(module, file_header_data_sp, file, file_offset, file_size));
|
||||
if (object_file_sp.get())
|
||||
return object_file_sp;
|
||||
}
|
||||
uint32_t idx;
|
||||
|
||||
// Check if this is a object container by iterating through
|
||||
// all object container plugin instances and then trying to get
|
||||
// an object file from the container.
|
||||
ObjectContainerCreateInstance create_object_container_callback;
|
||||
for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
|
||||
{
|
||||
std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module, file_header_data_sp, file, file_offset, file_size));
|
||||
// Check if this is a normal object file by iterating through
|
||||
// all object file plugin instances.
|
||||
ObjectFileCreateInstance create_object_file_callback;
|
||||
for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
|
||||
{
|
||||
object_file_sp.reset (create_object_file_callback(module, file_data_sp, file, file_offset, file_size));
|
||||
if (object_file_sp.get())
|
||||
return object_file_sp;
|
||||
}
|
||||
|
||||
if (object_container_ap.get())
|
||||
object_file_sp = object_container_ap->GetObjectFile(file);
|
||||
// Check if this is a object container by iterating through
|
||||
// all object container plugin instances and then trying to get
|
||||
// an object file from the container.
|
||||
ObjectContainerCreateInstance create_object_container_callback;
|
||||
for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
|
||||
{
|
||||
std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module, file_data_sp, file, file_offset, file_size));
|
||||
|
||||
if (object_file_sp.get())
|
||||
return object_file_sp;
|
||||
if (object_container_ap.get())
|
||||
object_file_sp = object_container_ap->GetObjectFile(file);
|
||||
|
||||
if (object_file_sp.get())
|
||||
return object_file_sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,20 +108,22 @@ ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset
|
|||
|
||||
ObjectFile::ObjectFile (Module* module,
|
||||
const FileSpec *file_spec_ptr,
|
||||
addr_t offset,
|
||||
addr_t length,
|
||||
DataBufferSP& headerDataSP) :
|
||||
addr_t file_offset,
|
||||
addr_t file_size,
|
||||
DataBufferSP& file_data_sp) :
|
||||
ModuleChild (module),
|
||||
m_file (), // This file could be different from the original module's file
|
||||
m_type (eTypeInvalid),
|
||||
m_strata (eStrataInvalid),
|
||||
m_offset (offset),
|
||||
m_length (length),
|
||||
m_data (headerDataSP, endian::InlHostByteOrder(), 4),
|
||||
m_offset (file_offset),
|
||||
m_length (file_size),
|
||||
m_data (),
|
||||
m_unwind_table (*this)
|
||||
{
|
||||
if (file_spec_ptr)
|
||||
m_file = *file_spec_ptr;
|
||||
if (file_data_sp)
|
||||
m_data.SetData (file_data_sp, file_offset, file_size);
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
|
||||
if (log)
|
||||
{
|
||||
|
@ -277,4 +284,18 @@ ObjectFile::GetSP ()
|
|||
return ObjectFileSP (this);
|
||||
}
|
||||
|
||||
size_t
|
||||
ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
|
||||
{
|
||||
// The entire file has already been mmap'ed into m_data, so just copy from there
|
||||
// as the back mmap buffer will be shared with shared pointers.
|
||||
return data.SetData (m_data, offset, length);
|
||||
}
|
||||
|
||||
size_t
|
||||
ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
|
||||
{
|
||||
// The entire file has already been mmap'ed into m_data, so just copy from there
|
||||
return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue