Files
clang-p2996/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
Greg Clayton 44435ed07a 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
2012-01-12 05:25:17 +00:00

243 lines
6.2 KiB
C++

//===-- ObjectContainerUniversalMachO.cpp -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ObjectContainerUniversalMachO.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;
void
ObjectContainerUniversalMachO::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
}
void
ObjectContainerUniversalMachO::Terminate()
{
PluginManager::UnregisterPlugin (CreateInstance);
}
const char *
ObjectContainerUniversalMachO::GetPluginNameStatic()
{
return "object-container.mach-o";
}
const char *
ObjectContainerUniversalMachO::GetPluginDescriptionStatic()
{
return "Universal mach-o object container reader.";
}
ObjectContainer *
ObjectContainerUniversalMachO::CreateInstance
(
Module* module,
DataBufferSP& data_sp,
const FileSpec *file,
addr_t offset,
addr_t length
)
{
DataExtractor data;
data.SetData (data_sp, offset, length);
if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
{
std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, data_sp, file, offset, length));
if (container_ap->ParseHeader())
{
return container_ap.release();
}
}
return NULL;
}
bool
ObjectContainerUniversalMachO::MagicBytesMatch (const DataExtractor &data)
{
uint32_t offset = 0;
uint32_t magic = data.GetU32(&offset);
return magic == UniversalMagic || magic == UniversalMagicSwapped;
}
ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
(
Module* module,
DataBufferSP& dataSP,
const FileSpec *file,
addr_t offset,
addr_t length
) :
ObjectContainer (module, file, offset, length, dataSP),
m_header(),
m_fat_archs()
{
memset(&m_header, 0, sizeof(m_header));
}
ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO()
{
}
bool
ObjectContainerUniversalMachO::ParseHeader ()
{
// Store the file offset for this universal file as we could have a universal .o file
// in a BSD archive, or be contained in another kind of object.
uint32_t offset = 0;
// Universal mach-o files always have their headers in big endian.
m_data.SetByteOrder (eByteOrderBig);
m_header.magic = m_data.GetU32(&offset);
if (m_header.magic == UniversalMagic)
{
m_data.SetAddressByteSize(4);
m_header.nfat_arch = m_data.GetU32(&offset);
// 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;
for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
{
if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
{
fat_arch arch;
if (m_data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
{
m_fat_archs.push_back(arch);
}
}
}
return true;
}
else
{
memset(&m_header, 0, sizeof(m_header));
}
return false;
}
void
ObjectContainerUniversalMachO::Dump (Stream *s) const
{
s->Printf("%p: ", this);
s->Indent();
const size_t num_archs = GetNumArchitectures();
const size_t num_objects = GetNumObjects();
s->Printf("ObjectContainerUniversalMachO, num_archs = %lu, num_objects = %lu", num_archs, num_objects);
uint32_t i;
ArchSpec arch;
s->IndentMore();
for (i=0; i<num_archs; i++)
{
s->Indent();
GetArchitectureAtIndex(i, arch);
s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
}
for (i=0; i<num_objects; i++)
{
s->Indent();
s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex (i));
}
s->IndentLess();
s->EOL();
}
size_t
ObjectContainerUniversalMachO::GetNumArchitectures () const
{
return m_header.nfat_arch;
}
bool
ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const
{
if (idx < m_header.nfat_arch)
{
arch.SetArchitecture (eArchTypeMachO, m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
return true;
}
return false;
}
ObjectFileSP
ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
{
uint32_t arch_idx = 0;
ArchSpec arch;
// If the module hasn't specified an architecture yet, set it to the default
// architecture:
if (!m_module->GetArchitecture().IsValid())
{
arch = Target::GetDefaultArchitecture ();
if (!arch.IsValid())
arch.SetTriple (LLDB_ARCH_DEFAULT, NULL);
}
else
arch = m_module->GetArchitecture();
ArchSpec curr_arch;
for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
{
if (GetArchitectureAtIndex (arch_idx, curr_arch))
{
if (arch == curr_arch)
{
return ObjectFile::FindPlugin (m_module,
file,
m_offset + m_fat_archs[arch_idx].offset,
m_fat_archs[arch_idx].size,
m_data.GetSharedDataBuffer());
}
}
}
return ObjectFileSP();
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
const char *
ObjectContainerUniversalMachO::GetPluginName()
{
return "ObjectContainerUniversalMachO";
}
const char *
ObjectContainerUniversalMachO::GetShortPluginName()
{
return GetPluginNameStatic();
}
uint32_t
ObjectContainerUniversalMachO::GetPluginVersion()
{
return 1;
}