blob: 9a28736e3e687f2e3af4f29c71ecfecd5e2a8fbd [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"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include "lldb/Core/ArchSpec.h"
Greg Clayton5ce9c562013-02-06 17:22:03 +000012#include "lldb/Core/DataBuffer.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000013#include "lldb/Core/Module.h"
14#include "lldb/Core/PluginManager.h"
Greg Clayton5ce9c562013-02-06 17:22:03 +000015#include "lldb/Core/Stream.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Symbol/ObjectFile.h"
Caroline Ticedaccaa92010-09-20 20:44:43 +000017#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018
19using namespace lldb;
20using namespace lldb_private;
Greg Claytone1a916a2010-07-21 22:12:05 +000021using namespace llvm::MachO;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
23void
24ObjectContainerUniversalMachO::Initialize()
25{
26 PluginManager::RegisterPlugin (GetPluginNameStatic(),
27 GetPluginDescriptionStatic(),
28 CreateInstance);
29}
30
31void
32ObjectContainerUniversalMachO::Terminate()
33{
34 PluginManager::UnregisterPlugin (CreateInstance);
35}
36
37
38const char *
39ObjectContainerUniversalMachO::GetPluginNameStatic()
40{
41 return "object-container.mach-o";
42}
43
44const char *
45ObjectContainerUniversalMachO::GetPluginDescriptionStatic()
46{
47 return "Universal mach-o object container reader.";
48}
49
50
51ObjectContainer *
52ObjectContainerUniversalMachO::CreateInstance
53(
Greg Claytone72dfb32012-02-24 01:59:29 +000054 const lldb::ModuleSP &module_sp,
Greg Clayton44435ed2012-01-12 05:25:17 +000055 DataBufferSP& data_sp,
Greg Clayton5ce9c562013-02-06 17:22:03 +000056 lldb::offset_t data_offset,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057 const FileSpec *file,
Greg Clayton5ce9c562013-02-06 17:22:03 +000058 lldb::offset_t file_offset,
59 lldb::offset_t length
Chris Lattner30fdc8d2010-06-08 16:52:24 +000060)
61{
Greg Clayton5ce9c562013-02-06 17:22:03 +000062 // We get data when we aren't trying to look for cached container information,
63 // so only try and look for an architecture slice if we get data
64 if (data_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065 {
Greg Clayton5ce9c562013-02-06 17:22:03 +000066 DataExtractor data;
67 data.SetData (data_sp, data_offset, length);
68 if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069 {
Greg Clayton7b0992d2013-04-18 22:45:39 +000070 std::unique_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module_sp, data_sp, data_offset, file, file_offset, length));
Greg Clayton5ce9c562013-02-06 17:22:03 +000071 if (container_ap->ParseHeader())
72 {
73 return container_ap.release();
74 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075 }
76 }
77 return NULL;
78}
79
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080bool
Greg Clayton44435ed2012-01-12 05:25:17 +000081ObjectContainerUniversalMachO::MagicBytesMatch (const DataExtractor &data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082{
Greg Claytonc7bece562013-01-25 18:06:21 +000083 lldb::offset_t offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084 uint32_t magic = data.GetU32(&offset);
Greg Claytone1a916a2010-07-21 22:12:05 +000085 return magic == UniversalMagic || magic == UniversalMagicSwapped;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000086}
87
88ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
89(
Greg Claytone72dfb32012-02-24 01:59:29 +000090 const lldb::ModuleSP &module_sp,
Greg Clayton5ce9c562013-02-06 17:22:03 +000091 DataBufferSP& data_sp,
92 lldb::offset_t data_offset,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000093 const FileSpec *file,
Greg Clayton5ce9c562013-02-06 17:22:03 +000094 lldb::offset_t file_offset,
95 lldb::offset_t length
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096) :
Greg Clayton5ce9c562013-02-06 17:22:03 +000097 ObjectContainer (module_sp, file, file_offset, length, data_sp, data_offset),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098 m_header(),
99 m_fat_archs()
100{
101 memset(&m_header, 0, sizeof(m_header));
102}
103
104
105ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO()
106{
107}
108
109bool
110ObjectContainerUniversalMachO::ParseHeader ()
111{
Greg Clayton5ce9c562013-02-06 17:22:03 +0000112 bool success = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 // Store the file offset for this universal file as we could have a universal .o file
114 // in a BSD archive, or be contained in another kind of object.
Greg Claytonc7bece562013-01-25 18:06:21 +0000115 lldb::offset_t offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 // Universal mach-o files always have their headers in big endian.
117 m_data.SetByteOrder (eByteOrderBig);
118 m_header.magic = m_data.GetU32(&offset);
119
Greg Claytone1a916a2010-07-21 22:12:05 +0000120 if (m_header.magic == UniversalMagic)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121 {
122 m_data.SetAddressByteSize(4);
123
124 m_header.nfat_arch = m_data.GetU32(&offset);
125
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126 // Now we should have enough data for all of the fat headers, so lets index
Greg Clayton710dd5a2011-01-08 20:28:42 +0000127 // them so we know how many architectures that this universal binary contains.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128 uint32_t arch_idx = 0;
129 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
130 {
Greg Claytone1a916a2010-07-21 22:12:05 +0000131 if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000132 {
Greg Claytone1a916a2010-07-21 22:12:05 +0000133 fat_arch arch;
134 if (m_data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000135 {
136 m_fat_archs.push_back(arch);
137 }
138 }
139 }
Greg Clayton5ce9c562013-02-06 17:22:03 +0000140 success = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141 }
142 else
143 {
144 memset(&m_header, 0, sizeof(m_header));
145 }
146
Greg Clayton5ce9c562013-02-06 17:22:03 +0000147 // We no longer need any data, we parsed all we needed to parse
148 // and cached it in m_header and m_fat_archs
149 m_data.Clear();
150 return success;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151}
152
153void
154ObjectContainerUniversalMachO::Dump (Stream *s) const
155{
Jason Molendafd54b362011-09-20 21:44:10 +0000156 s->Printf("%p: ", this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157 s->Indent();
158 const size_t num_archs = GetNumArchitectures();
159 const size_t num_objects = GetNumObjects();
Jason Molendafd54b362011-09-20 21:44:10 +0000160 s->Printf("ObjectContainerUniversalMachO, num_archs = %lu, num_objects = %lu", num_archs, num_objects);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161 uint32_t i;
162 ArchSpec arch;
163 s->IndentMore();
164 for (i=0; i<num_archs; i++)
165 {
166 s->Indent();
167 GetArchitectureAtIndex(i, arch);
Jason Molendafd54b362011-09-20 21:44:10 +0000168 s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 }
170 for (i=0; i<num_objects; i++)
171 {
172 s->Indent();
Jason Molendafd54b362011-09-20 21:44:10 +0000173 s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex (i));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174 }
175 s->IndentLess();
176 s->EOL();
177}
178
179size_t
180ObjectContainerUniversalMachO::GetNumArchitectures () const
181{
182 return m_header.nfat_arch;
183}
184
185bool
186ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const
187{
188 if (idx < m_header.nfat_arch)
189 {
Greg Claytone0d378b2011-03-24 21:19:54 +0000190 arch.SetArchitecture (eArchTypeMachO, m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 return true;
192 }
193 return false;
194}
195
Greg Clayton762f7132011-09-18 18:59:15 +0000196ObjectFileSP
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
198{
199 uint32_t arch_idx = 0;
Jim Ingham5aee1622010-08-09 23:31:02 +0000200 ArchSpec arch;
201 // If the module hasn't specified an architecture yet, set it to the default
202 // architecture:
Greg Claytone72dfb32012-02-24 01:59:29 +0000203 ModuleSP module_sp (GetModule());
204 if (module_sp)
Jim Ingham5aee1622010-08-09 23:31:02 +0000205 {
Greg Claytone72dfb32012-02-24 01:59:29 +0000206 if (!module_sp->GetArchitecture().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000207 {
Greg Claytone72dfb32012-02-24 01:59:29 +0000208 arch = Target::GetDefaultArchitecture ();
209 if (!arch.IsValid())
Greg Clayton70512312012-05-08 01:45:38 +0000210 arch.SetTriple (LLDB_ARCH_DEFAULT);
Greg Claytone72dfb32012-02-24 01:59:29 +0000211 }
212 else
213 arch = module_sp->GetArchitecture();
214
215 ArchSpec curr_arch;
Jason Molendaba813dc2012-11-04 03:20:05 +0000216 // First, try to find an exact match for the Arch of the Target.
Greg Claytone72dfb32012-02-24 01:59:29 +0000217 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
218 {
Greg Clayton5ce9c562013-02-06 17:22:03 +0000219 if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsExactMatch(curr_arch))
220 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000221 }
Jason Molendaba813dc2012-11-04 03:20:05 +0000222
223 // Failing an exact match, try to find a compatible Arch of the Target.
Greg Clayton5ce9c562013-02-06 17:22:03 +0000224 if (arch_idx >= m_header.nfat_arch)
Jason Molendaba813dc2012-11-04 03:20:05 +0000225 {
Greg Clayton5ce9c562013-02-06 17:22:03 +0000226 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
Jason Molendaba813dc2012-11-04 03:20:05 +0000227 {
Greg Clayton5ce9c562013-02-06 17:22:03 +0000228 if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsCompatibleMatch(curr_arch))
229 break;
Jason Molendaba813dc2012-11-04 03:20:05 +0000230 }
231 }
232
Greg Clayton5ce9c562013-02-06 17:22:03 +0000233 if (arch_idx < m_header.nfat_arch)
234 {
235 DataBufferSP data_sp;
236 lldb::offset_t data_offset = 0;
237 return ObjectFile::FindPlugin (module_sp,
238 file,
239 m_offset + m_fat_archs[arch_idx].offset,
240 m_fat_archs[arch_idx].size,
241 data_sp,
242 data_offset);
243 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 }
Greg Clayton762f7132011-09-18 18:59:15 +0000245 return ObjectFileSP();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246}
247
248
249//------------------------------------------------------------------
250// PluginInterface protocol
251//------------------------------------------------------------------
252const char *
253ObjectContainerUniversalMachO::GetPluginName()
254{
255 return "ObjectContainerUniversalMachO";
256}
257
258const char *
259ObjectContainerUniversalMachO::GetShortPluginName()
260{
261 return GetPluginNameStatic();
262}
263
264uint32_t
265ObjectContainerUniversalMachO::GetPluginVersion()
266{
267 return 1;
268}
269
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000270