summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ObjectContainer/Universal-Mach-O
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ObjectContainer/Universal-Mach-O')
-rw-r--r--lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp259
-rw-r--r--lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h103
2 files changed, 362 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
new file mode 100644
index 00000000000..015e498a7cc
--- /dev/null
+++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
@@ -0,0 +1,259 @@
+//===-- 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"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+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& dataSP,
+ const FileSpec *file,
+ addr_t offset,
+ addr_t length
+)
+{
+ if (ObjectContainerUniversalMachO::MagicBytesMatch(dataSP))
+ {
+ std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, dataSP, file, offset, length));
+ if (container_ap->ParseHeader())
+ {
+ return container_ap.release();
+ }
+ }
+ return NULL;
+}
+
+
+
+bool
+ObjectContainerUniversalMachO::MagicBytesMatch (DataBufferSP& dataSP)
+{
+ DataExtractor data(dataSP, eByteOrderHost, 4);
+ uint32_t offset = 0;
+ uint32_t magic = data.GetU32(&offset);
+ return magic == FAT_MAGIC || magic == FAT_CIGAM;
+}
+
+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 == FAT_MAGIC)
+ {
+ m_data.SetAddressByteSize(4);
+
+ m_header.nfat_arch = m_data.GetU32(&offset);
+
+ const size_t nfat_arch_size = sizeof(fat_arch_t) * 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_t)));
+ 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 univeral 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_t)))
+ {
+ fat_arch_t arch;
+ if (m_data.GetU32(&offset, &arch, sizeof(fat_arch_t)/sizeof(uint32_t)))
+ {
+ m_fat_archs.push_back(arch);
+ }
+ }
+ }
+ // Now that we have indexed the universal headers, we no longer need any cached data.
+ m_data.Clear();
+
+ return true;
+ }
+ else
+ {
+ memset(&m_header, 0, sizeof(m_header));
+ }
+
+ return false;
+}
+
+void
+ObjectContainerUniversalMachO::Dump (Stream *s) const
+{
+ s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
+ s->Indent();
+ const size_t num_archs = GetNumArchitectures();
+ const size_t num_objects = GetNumObjects();
+ s->Printf("ObjectContainerUniversalMachO, num_archs = %u, num_objects = %u", 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", arch.AsCString());
+ }
+ for (i=0; i<num_objects; i++)
+ {
+ s->Indent();
+ s->Printf("object[%u] = %s\n", 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.SetArch(m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
+ return true;
+ }
+ return false;
+}
+
+ObjectFile *
+ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
+{
+ uint32_t arch_idx = 0;
+ const ArchSpec 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);
+ }
+ }
+ }
+ return NULL;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ObjectContainerUniversalMachO::GetPluginName()
+{
+ return "ObjectContainerUniversalMachO";
+}
+
+const char *
+ObjectContainerUniversalMachO::GetShortPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectContainerUniversalMachO::GetPluginVersion()
+{
+ return 1;
+}
+
+void
+ObjectContainerUniversalMachO::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+ObjectContainerUniversalMachO::ExecutePluginCommand (Args &command, Stream *strm)
+{
+ Error error;
+ error.SetErrorString("No plug-in command are currently supported.");
+ return error;
+}
+
+Log *
+ObjectContainerUniversalMachO::EnablePluginLogging (Stream *strm, Args &command)
+{
+ return NULL;
+}
+
+
+
diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
new file mode 100644
index 00000000000..8a7f975bc67
--- /dev/null
+++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
@@ -0,0 +1,103 @@
+//===-- ObjectContainerUniversalMachO.h -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ObjectContainerUniversalMachO_h_
+#define liblldb_ObjectContainerUniversalMachO_h_
+
+#include <mach-o/fat.h>
+
+#include "lldb/Symbol/ObjectContainer.h"
+#include "lldb/Core/FileSpec.h"
+
+class ObjectContainerUniversalMachO :
+ public lldb_private::ObjectContainer
+{
+public:
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static const char *
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ static lldb_private::ObjectContainer *
+ CreateInstance (lldb_private::Module* module,
+ lldb::DataBufferSP& dataSP,
+ const lldb_private::FileSpec *file,
+ lldb::addr_t offset,
+ lldb::addr_t length);
+
+ static bool
+ MagicBytesMatch (lldb::DataBufferSP& dataSP);
+
+ //------------------------------------------------------------------
+ // Member Functions
+ //------------------------------------------------------------------
+ ObjectContainerUniversalMachO (lldb_private::Module* module,
+ lldb::DataBufferSP& dataSP,
+ const lldb_private::FileSpec *file,
+ lldb::addr_t offset,
+ lldb::addr_t length);
+
+ virtual
+ ~ObjectContainerUniversalMachO();
+
+ virtual bool
+ ParseHeader ();
+
+ virtual void
+ Dump (lldb_private::Stream *s) const;
+
+ virtual size_t
+ GetNumArchitectures () const;
+
+ virtual bool
+ GetArchitectureAtIndex (uint32_t cpu_idx, lldb_private::ArchSpec& arch) const;
+
+ virtual lldb_private::ObjectFile *
+ GetObjectFile (const lldb_private::FileSpec *file);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual void
+ GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Error
+ ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Log *
+ EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
+
+
+protected:
+ typedef struct fat_header fat_header_t;
+ typedef struct fat_arch fat_arch_t;
+ fat_header_t m_header;
+ std::vector<fat_arch_t> m_fat_archs;
+};
+
+#endif // liblldb_ObjectContainerUniversalMachO_h_
OpenPOWER on IntegriCloud