blob: 8c4359f32b07544e6b6a07ef98557b65c0c76b96 [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"
Caroline Ticedaccaa92010-09-20 20:44:43 +000016#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017
18using namespace lldb;
19using namespace lldb_private;
Greg Claytone1a916a2010-07-21 22:12:05 +000020using namespace llvm::MachO;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
22void
23ObjectContainerUniversalMachO::Initialize()
24{
25 PluginManager::RegisterPlugin (GetPluginNameStatic(),
26 GetPluginDescriptionStatic(),
27 CreateInstance);
28}
29
30void
31ObjectContainerUniversalMachO::Terminate()
32{
33 PluginManager::UnregisterPlugin (CreateInstance);
34}
35
36
37const char *
38ObjectContainerUniversalMachO::GetPluginNameStatic()
39{
40 return "object-container.mach-o";
41}
42
43const char *
44ObjectContainerUniversalMachO::GetPluginDescriptionStatic()
45{
46 return "Universal mach-o object container reader.";
47}
48
49
50ObjectContainer *
51ObjectContainerUniversalMachO::CreateInstance
52(
53 Module* module,
54 DataBufferSP& dataSP,
55 const FileSpec *file,
56 addr_t offset,
57 addr_t length
58)
59{
60 if (ObjectContainerUniversalMachO::MagicBytesMatch(dataSP))
61 {
62 std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, dataSP, file, offset, length));
63 if (container_ap->ParseHeader())
64 {
65 return container_ap.release();
66 }
67 }
68 return NULL;
69}
70
71
72
73bool
74ObjectContainerUniversalMachO::MagicBytesMatch (DataBufferSP& dataSP)
75{
Greg Clayton7fb56d02011-02-01 01:31:41 +000076 DataExtractor data(dataSP, lldb::endian::InlHostByteOrder(), 4);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077 uint32_t offset = 0;
78 uint32_t magic = data.GetU32(&offset);
Greg Claytone1a916a2010-07-21 22:12:05 +000079 return magic == UniversalMagic || magic == UniversalMagicSwapped;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080}
81
82ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
83(
84 Module* module,
85 DataBufferSP& dataSP,
86 const FileSpec *file,
87 addr_t offset,
88 addr_t length
89) :
90 ObjectContainer (module, file, offset, length, dataSP),
91 m_header(),
92 m_fat_archs()
93{
94 memset(&m_header, 0, sizeof(m_header));
95}
96
97
98ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO()
99{
100}
101
102bool
103ObjectContainerUniversalMachO::ParseHeader ()
104{
105 // Store the file offset for this universal file as we could have a universal .o file
106 // in a BSD archive, or be contained in another kind of object.
107 uint32_t offset = 0;
108 // Universal mach-o files always have their headers in big endian.
109 m_data.SetByteOrder (eByteOrderBig);
110 m_header.magic = m_data.GetU32(&offset);
111
Greg Claytone1a916a2010-07-21 22:12:05 +0000112 if (m_header.magic == UniversalMagic)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 {
114 m_data.SetAddressByteSize(4);
115
116 m_header.nfat_arch = m_data.GetU32(&offset);
117
Greg Claytone1a916a2010-07-21 22:12:05 +0000118 const size_t nfat_arch_size = sizeof(fat_arch) * m_header.nfat_arch;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119 // See if the current data we have is enough for all of the fat headers?
120 if (!m_data.ValidOffsetForDataOfSize(offset, nfat_arch_size))
121 {
122 // The fat headers are larger than the number of bytes we have been
123 // given when this class was constructed. We will read the exact number
124 // of bytes that we need.
Greg Claytone1a916a2010-07-21 22:12:05 +0000125 DataBufferSP data_sp(m_file.ReadFileContents(m_offset, nfat_arch_size + sizeof(fat_header)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126 m_data.SetData (data_sp);
127 }
128
129 // Now we should have enough data for all of the fat headers, so lets index
Greg Clayton710dd5a2011-01-08 20:28:42 +0000130 // them so we know how many architectures that this universal binary contains.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000131 uint32_t arch_idx = 0;
132 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
133 {
Greg Claytone1a916a2010-07-21 22:12:05 +0000134 if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000135 {
Greg Claytone1a916a2010-07-21 22:12:05 +0000136 fat_arch arch;
137 if (m_data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 {
139 m_fat_archs.push_back(arch);
140 }
141 }
142 }
143 // Now that we have indexed the universal headers, we no longer need any cached data.
144 m_data.Clear();
145
146 return true;
147 }
148 else
149 {
150 memset(&m_header, 0, sizeof(m_header));
151 }
152
153 return false;
154}
155
156void
157ObjectContainerUniversalMachO::Dump (Stream *s) const
158{
Jason Molendafd54b362011-09-20 21:44:10 +0000159 s->Printf("%p: ", this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 s->Indent();
161 const size_t num_archs = GetNumArchitectures();
162 const size_t num_objects = GetNumObjects();
Jason Molendafd54b362011-09-20 21:44:10 +0000163 s->Printf("ObjectContainerUniversalMachO, num_archs = %lu, num_objects = %lu", num_archs, num_objects);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164 uint32_t i;
165 ArchSpec arch;
166 s->IndentMore();
167 for (i=0; i<num_archs; i++)
168 {
169 s->Indent();
170 GetArchitectureAtIndex(i, arch);
Jason Molendafd54b362011-09-20 21:44:10 +0000171 s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000172 }
173 for (i=0; i<num_objects; i++)
174 {
175 s->Indent();
Jason Molendafd54b362011-09-20 21:44:10 +0000176 s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex (i));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000177 }
178 s->IndentLess();
179 s->EOL();
180}
181
182size_t
183ObjectContainerUniversalMachO::GetNumArchitectures () const
184{
185 return m_header.nfat_arch;
186}
187
188bool
189ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const
190{
191 if (idx < m_header.nfat_arch)
192 {
Greg Claytone0d378b2011-03-24 21:19:54 +0000193 arch.SetArchitecture (eArchTypeMachO, m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 return true;
195 }
196 return false;
197}
198
Greg Clayton762f7132011-09-18 18:59:15 +0000199ObjectFileSP
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
201{
202 uint32_t arch_idx = 0;
Jim Ingham5aee1622010-08-09 23:31:02 +0000203 ArchSpec arch;
204 // If the module hasn't specified an architecture yet, set it to the default
205 // architecture:
206 if (!m_module->GetArchitecture().IsValid())
207 {
Caroline Ticedaccaa92010-09-20 20:44:43 +0000208 arch = Target::GetDefaultArchitecture ();
Jim Ingham5aee1622010-08-09 23:31:02 +0000209 if (!arch.IsValid())
Greg Claytoneb0103f2011-04-07 22:46:35 +0000210 arch.SetTriple (LLDB_ARCH_DEFAULT, NULL);
Jim Ingham5aee1622010-08-09 23:31:02 +0000211 }
212 else
213 arch = m_module->GetArchitecture();
214
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000215 ArchSpec curr_arch;
216 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
217 {
218 if (GetArchitectureAtIndex (arch_idx, curr_arch))
219 {
220 if (arch == curr_arch)
221 {
Greg Clayton762f7132011-09-18 18:59:15 +0000222 return ObjectFile::FindPlugin (m_module,
223 file,
224 m_offset + m_fat_archs[arch_idx].offset,
225 m_fat_archs[arch_idx].size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226 }
227 }
228 }
Greg Clayton762f7132011-09-18 18:59:15 +0000229 return ObjectFileSP();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230}
231
232
233//------------------------------------------------------------------
234// PluginInterface protocol
235//------------------------------------------------------------------
236const char *
237ObjectContainerUniversalMachO::GetPluginName()
238{
239 return "ObjectContainerUniversalMachO";
240}
241
242const char *
243ObjectContainerUniversalMachO::GetShortPluginName()
244{
245 return GetPluginNameStatic();
246}
247
248uint32_t
249ObjectContainerUniversalMachO::GetPluginVersion()
250{
251 return 1;
252}
253
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000254