blob: 015e498a7ccd8bcebbe12b584e3f4c0476eb3424 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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