ObjectContainerUniversalMachO.cpp revision 24943d2ee8bfaa7cf5893e4709143924157a5c1e
1//===-- ObjectContainerUniversalMachO.cpp -----------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ObjectContainerUniversalMachO.h"
11#include "lldb/Core/Stream.h"
12#include "lldb/Core/ArchSpec.h"
13#include "lldb/Core/Module.h"
14#include "lldb/Core/PluginManager.h"
15#include "lldb/Symbol/ObjectFile.h"
16
17using namespace lldb;
18using namespace lldb_private;
19
20
21void
22ObjectContainerUniversalMachO::Initialize()
23{
24    PluginManager::RegisterPlugin (GetPluginNameStatic(),
25                                   GetPluginDescriptionStatic(),
26                                   CreateInstance);
27}
28
29void
30ObjectContainerUniversalMachO::Terminate()
31{
32    PluginManager::UnregisterPlugin (CreateInstance);
33}
34
35
36const char *
37ObjectContainerUniversalMachO::GetPluginNameStatic()
38{
39    return "object-container.mach-o";
40}
41
42const char *
43ObjectContainerUniversalMachO::GetPluginDescriptionStatic()
44{
45    return "Universal mach-o object container reader.";
46}
47
48
49ObjectContainer *
50ObjectContainerUniversalMachO::CreateInstance
51(
52    Module* module,
53    DataBufferSP& dataSP,
54    const FileSpec *file,
55    addr_t offset,
56    addr_t length
57)
58{
59    if (ObjectContainerUniversalMachO::MagicBytesMatch(dataSP))
60    {
61        std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, dataSP, file, offset, length));
62        if (container_ap->ParseHeader())
63        {
64            return container_ap.release();
65        }
66    }
67    return NULL;
68}
69
70
71
72bool
73ObjectContainerUniversalMachO::MagicBytesMatch (DataBufferSP& dataSP)
74{
75    DataExtractor data(dataSP, eByteOrderHost, 4);
76    uint32_t offset = 0;
77    uint32_t magic = data.GetU32(&offset);
78    return magic == FAT_MAGIC || magic == FAT_CIGAM;
79}
80
81ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
82(
83    Module* module,
84    DataBufferSP& dataSP,
85    const FileSpec *file,
86    addr_t offset,
87    addr_t length
88) :
89    ObjectContainer (module, file, offset, length, dataSP),
90    m_header(),
91    m_fat_archs()
92{
93    memset(&m_header, 0, sizeof(m_header));
94}
95
96
97ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO()
98{
99}
100
101bool
102ObjectContainerUniversalMachO::ParseHeader ()
103{
104    // Store the file offset for this universal file as we could have a universal .o file
105    // in a BSD archive, or be contained in another kind of object.
106    uint32_t offset = 0;
107    // Universal mach-o files always have their headers in big endian.
108    m_data.SetByteOrder (eByteOrderBig);
109    m_header.magic = m_data.GetU32(&offset);
110
111    if (m_header.magic == FAT_MAGIC)
112    {
113        m_data.SetAddressByteSize(4);
114
115        m_header.nfat_arch = m_data.GetU32(&offset);
116
117        const size_t nfat_arch_size = sizeof(fat_arch_t) * m_header.nfat_arch;
118        // See if the current data we have is enough for all of the fat headers?
119        if (!m_data.ValidOffsetForDataOfSize(offset, nfat_arch_size))
120        {
121            // The fat headers are larger than the number of bytes we have been
122            // given when this class was constructed. We will read the exact number
123            // of bytes that we need.
124            DataBufferSP data_sp(m_file.ReadFileContents(m_offset, nfat_arch_size + sizeof(fat_header_t)));
125            m_data.SetData (data_sp);
126        }
127
128        // Now we should have enough data for all of the fat headers, so lets index
129        // them so we know how many architectures that this univeral binary contains.
130        uint32_t arch_idx = 0;
131        for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
132        {
133            if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch_t)))
134            {
135                fat_arch_t arch;
136                if (m_data.GetU32(&offset, &arch, sizeof(fat_arch_t)/sizeof(uint32_t)))
137                {
138                    m_fat_archs.push_back(arch);
139                }
140            }
141        }
142        // Now that we have indexed the universal headers, we no longer need any cached data.
143        m_data.Clear();
144
145        return true;
146    }
147    else
148    {
149        memset(&m_header, 0, sizeof(m_header));
150    }
151
152    return false;
153}
154
155void
156ObjectContainerUniversalMachO::Dump (Stream *s) const
157{
158    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
159    s->Indent();
160    const size_t num_archs = GetNumArchitectures();
161    const size_t num_objects = GetNumObjects();
162    s->Printf("ObjectContainerUniversalMachO, num_archs = %u, num_objects = %u", num_archs, num_objects);
163    uint32_t i;
164    ArchSpec arch;
165    s->IndentMore();
166    for (i=0; i<num_archs; i++)
167    {
168        s->Indent();
169        GetArchitectureAtIndex(i, arch);
170        s->Printf("arch[%u] = %s\n", arch.AsCString());
171    }
172    for (i=0; i<num_objects; i++)
173    {
174        s->Indent();
175        s->Printf("object[%u] = %s\n", GetObjectNameAtIndex (i));
176    }
177    s->IndentLess();
178    s->EOL();
179}
180
181size_t
182ObjectContainerUniversalMachO::GetNumArchitectures () const
183{
184    return m_header.nfat_arch;
185}
186
187bool
188ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const
189{
190    if (idx < m_header.nfat_arch)
191    {
192        arch.SetArch(m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
193        return true;
194    }
195    return false;
196}
197
198ObjectFile *
199ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
200{
201    uint32_t arch_idx = 0;
202    const ArchSpec arch = m_module->GetArchitecture();
203    ArchSpec curr_arch;
204    for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
205    {
206        if (GetArchitectureAtIndex (arch_idx, curr_arch))
207        {
208            if (arch == curr_arch)
209            {
210                return ObjectFile::FindPlugin (m_module, file, m_offset + m_fat_archs[arch_idx].offset, m_fat_archs[arch_idx].size);
211            }
212        }
213    }
214    return NULL;
215}
216
217
218//------------------------------------------------------------------
219// PluginInterface protocol
220//------------------------------------------------------------------
221const char *
222ObjectContainerUniversalMachO::GetPluginName()
223{
224    return "ObjectContainerUniversalMachO";
225}
226
227const char *
228ObjectContainerUniversalMachO::GetShortPluginName()
229{
230    return GetPluginNameStatic();
231}
232
233uint32_t
234ObjectContainerUniversalMachO::GetPluginVersion()
235{
236    return 1;
237}
238
239void
240ObjectContainerUniversalMachO::GetPluginCommandHelp (const char *command, Stream *strm)
241{
242}
243
244Error
245ObjectContainerUniversalMachO::ExecutePluginCommand (Args &command, Stream *strm)
246{
247    Error error;
248    error.SetErrorString("No plug-in command are currently supported.");
249    return error;
250}
251
252Log *
253ObjectContainerUniversalMachO::EnablePluginLogging (Stream *strm, Args &command)
254{
255    return NULL;
256}
257
258
259
260