LibCallSimplifier: optimize speed for short-lived instances
[oota-llvm.git] / lib / Object / MachOObject.cpp
1 //===- MachOObject.cpp - Mach-O Object File Wrapper -----------------------===//
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 "llvm/Object/MachOObject.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/DataExtractor.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Host.h"
16 #include "llvm/Support/MemoryBuffer.h"
17 #include "llvm/Support/SwapByteOrder.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 using namespace llvm;
21 using namespace llvm::object;
22
23 /* Translation Utilities */
24
25 template<typename T>
26 static void SwapValue(T &Value) {
27   Value = sys::SwapByteOrder(Value);
28 }
29
30 template<typename T>
31 static void SwapStruct(T &Value);
32
33 template<typename T>
34 static void ReadInMemoryStruct(const MachOObject &MOO,
35                                StringRef Buffer, uint64_t Base,
36                                InMemoryStruct<T> &Res) {
37   typedef T struct_type;
38   uint64_t Size = sizeof(struct_type);
39
40   // Check that the buffer contains the expected data.
41   if (Base + Size >  Buffer.size()) {
42     Res = 0;
43     return;
44   }
45
46   // Check whether we can return a direct pointer.
47   struct_type *Ptr = reinterpret_cast<struct_type *>(
48                        const_cast<char *>(Buffer.data() + Base));
49   if (!MOO.isSwappedEndian()) {
50     Res = Ptr;
51     return;
52   }
53
54   // Otherwise, copy the struct and translate the values.
55   Res = *Ptr;
56   SwapStruct(*Res);
57 }
58
59 /* *** */
60
61 MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_,
62                          bool Is64Bit_)
63   : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_),
64     IsSwappedEndian(IsLittleEndian != sys::isLittleEndianHost()),
65     HasStringTable(false), LoadCommands(0), NumLoadedCommands(0) {
66   // Load the common header.
67   memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header));
68   if (IsSwappedEndian) {
69     SwapValue(Header.Magic);
70     SwapValue(Header.CPUType);
71     SwapValue(Header.CPUSubtype);
72     SwapValue(Header.FileType);
73     SwapValue(Header.NumLoadCommands);
74     SwapValue(Header.SizeOfLoadCommands);
75     SwapValue(Header.Flags);
76   }
77
78   if (is64Bit()) {
79     memcpy(&Header64Ext, Buffer->getBuffer().data() + sizeof(Header),
80            sizeof(Header64Ext));
81     if (IsSwappedEndian) {
82       SwapValue(Header64Ext.Reserved);
83     }
84   }
85
86   // Create the load command array if sane.
87   if (getHeader().NumLoadCommands < (1 << 20))
88     LoadCommands = new LoadCommandInfo[getHeader().NumLoadCommands];
89 }
90
91 MachOObject::~MachOObject() {
92   delete [] LoadCommands;
93 }
94
95 MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer,
96                                          std::string *ErrorStr) {
97   // First, check the magic value and initialize the basic object info.
98   bool IsLittleEndian = false, Is64Bit = false;
99   StringRef Magic = Buffer->getBuffer().slice(0, 4);
100   if (Magic == "\xFE\xED\xFA\xCE") {
101   }  else if (Magic == "\xCE\xFA\xED\xFE") {
102     IsLittleEndian = true;
103   } else if (Magic == "\xFE\xED\xFA\xCF") {
104     Is64Bit = true;
105   } else if (Magic == "\xCF\xFA\xED\xFE") {
106     IsLittleEndian = true;
107     Is64Bit = true;
108   } else {
109     if (ErrorStr) *ErrorStr = "not a Mach object file (invalid magic)";
110     return 0;
111   }
112
113   // Ensure that the at least the full header is present.
114   unsigned HeaderSize = Is64Bit ? macho::Header64Size : macho::Header32Size;
115   if (Buffer->getBufferSize() < HeaderSize) {
116     if (ErrorStr) *ErrorStr = "not a Mach object file (invalid header)";
117     return 0;
118   }
119
120   OwningPtr<MachOObject> Object(new MachOObject(Buffer, IsLittleEndian,
121                                                 Is64Bit));
122
123   // Check for bogus number of load commands.
124   if (Object->getHeader().NumLoadCommands >= (1 << 20)) {
125     if (ErrorStr) *ErrorStr = "not a Mach object file (unreasonable header)";
126     return 0;
127   }
128
129   if (ErrorStr) *ErrorStr = "";
130   return Object.take();
131 }
132
133 StringRef MachOObject::getData(size_t Offset, size_t Size) const {
134   return Buffer->getBuffer().substr(Offset,Size);
135 }
136
137 void MachOObject::RegisterStringTable(macho::SymtabLoadCommand &SLC) {
138   HasStringTable = true;
139   StringTable = Buffer->getBuffer().substr(SLC.StringTableOffset,
140                                            SLC.StringTableSize);
141 }
142
143 const MachOObject::LoadCommandInfo &
144 MachOObject::getLoadCommandInfo(unsigned Index) const {
145   assert(Index < getHeader().NumLoadCommands && "Invalid index!");
146
147   // Load the command, if necessary.
148   if (Index >= NumLoadedCommands) {
149     uint64_t Offset;
150     if (Index == 0) {
151       Offset = getHeaderSize();
152     } else {
153       const LoadCommandInfo &Prev = getLoadCommandInfo(Index - 1);
154       Offset = Prev.Offset + Prev.Command.Size;
155     }
156
157     LoadCommandInfo &Info = LoadCommands[Index];
158     memcpy(&Info.Command, Buffer->getBuffer().data() + Offset,
159            sizeof(macho::LoadCommand));
160     if (IsSwappedEndian) {
161       SwapValue(Info.Command.Type);
162       SwapValue(Info.Command.Size);
163     }
164     Info.Offset = Offset;
165     NumLoadedCommands = Index + 1;
166   }
167
168   return LoadCommands[Index];
169 }
170
171 template<>
172 void SwapStruct(macho::SegmentLoadCommand &Value) {
173   SwapValue(Value.Type);
174   SwapValue(Value.Size);
175   SwapValue(Value.VMAddress);
176   SwapValue(Value.VMSize);
177   SwapValue(Value.FileOffset);
178   SwapValue(Value.FileSize);
179   SwapValue(Value.MaxVMProtection);
180   SwapValue(Value.InitialVMProtection);
181   SwapValue(Value.NumSections);
182   SwapValue(Value.Flags);
183 }
184 void MachOObject::ReadSegmentLoadCommand(const LoadCommandInfo &LCI,
185                          InMemoryStruct<macho::SegmentLoadCommand> &Res) const {
186   ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
187 }
188
189 template<>
190 void SwapStruct(macho::Segment64LoadCommand &Value) {
191   SwapValue(Value.Type);
192   SwapValue(Value.Size);
193   SwapValue(Value.VMAddress);
194   SwapValue(Value.VMSize);
195   SwapValue(Value.FileOffset);
196   SwapValue(Value.FileSize);
197   SwapValue(Value.MaxVMProtection);
198   SwapValue(Value.InitialVMProtection);
199   SwapValue(Value.NumSections);
200   SwapValue(Value.Flags);
201 }
202 void MachOObject::ReadSegment64LoadCommand(const LoadCommandInfo &LCI,
203                        InMemoryStruct<macho::Segment64LoadCommand> &Res) const {
204   ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
205 }
206
207 template<>
208 void SwapStruct(macho::SymtabLoadCommand &Value) {
209   SwapValue(Value.Type);
210   SwapValue(Value.Size);
211   SwapValue(Value.SymbolTableOffset);
212   SwapValue(Value.NumSymbolTableEntries);
213   SwapValue(Value.StringTableOffset);
214   SwapValue(Value.StringTableSize);
215 }
216 void MachOObject::ReadSymtabLoadCommand(const LoadCommandInfo &LCI,
217                           InMemoryStruct<macho::SymtabLoadCommand> &Res) const {
218   ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
219 }
220
221 template<>
222 void SwapStruct(macho::DysymtabLoadCommand &Value) {
223   SwapValue(Value.Type);
224   SwapValue(Value.Size);
225   SwapValue(Value.LocalSymbolsIndex);
226   SwapValue(Value.NumLocalSymbols);
227   SwapValue(Value.ExternalSymbolsIndex);
228   SwapValue(Value.NumExternalSymbols);
229   SwapValue(Value.UndefinedSymbolsIndex);
230   SwapValue(Value.NumUndefinedSymbols);
231   SwapValue(Value.TOCOffset);
232   SwapValue(Value.NumTOCEntries);
233   SwapValue(Value.ModuleTableOffset);
234   SwapValue(Value.NumModuleTableEntries);
235   SwapValue(Value.ReferenceSymbolTableOffset);
236   SwapValue(Value.NumReferencedSymbolTableEntries);
237   SwapValue(Value.IndirectSymbolTableOffset);
238   SwapValue(Value.NumIndirectSymbolTableEntries);
239   SwapValue(Value.ExternalRelocationTableOffset);
240   SwapValue(Value.NumExternalRelocationTableEntries);
241   SwapValue(Value.LocalRelocationTableOffset);
242   SwapValue(Value.NumLocalRelocationTableEntries);
243 }
244 void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI,
245                         InMemoryStruct<macho::DysymtabLoadCommand> &Res) const {
246   ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
247 }
248
249 template<>
250 void SwapStruct(macho::LinkeditDataLoadCommand &Value) {
251   SwapValue(Value.Type);
252   SwapValue(Value.Size);
253   SwapValue(Value.DataOffset);
254   SwapValue(Value.DataSize);
255 }
256 void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI,
257                     InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const {
258   ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
259 }
260
261 template<>
262 void SwapStruct(macho::LinkerOptionsLoadCommand &Value) {
263   SwapValue(Value.Type);
264   SwapValue(Value.Size);
265   SwapValue(Value.Count);
266 }
267 void MachOObject::ReadLinkerOptionsLoadCommand(const LoadCommandInfo &LCI,
268                    InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const {
269   ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
270 }
271
272 template<>
273 void SwapStruct(macho::IndirectSymbolTableEntry &Value) {
274   SwapValue(Value.Index);
275 }
276 void
277 MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC,
278                                           unsigned Index,
279                    InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const {
280   uint64_t Offset = (DLC.IndirectSymbolTableOffset +
281                      Index * sizeof(macho::IndirectSymbolTableEntry));
282   ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
283 }
284
285
286 template<>
287 void SwapStruct(macho::Section &Value) {
288   SwapValue(Value.Address);
289   SwapValue(Value.Size);
290   SwapValue(Value.Offset);
291   SwapValue(Value.Align);
292   SwapValue(Value.RelocationTableOffset);
293   SwapValue(Value.NumRelocationTableEntries);
294   SwapValue(Value.Flags);
295   SwapValue(Value.Reserved1);
296   SwapValue(Value.Reserved2);
297 }
298 void MachOObject::ReadSection(const LoadCommandInfo &LCI,
299                               unsigned Index,
300                               InMemoryStruct<macho::Section> &Res) const {
301   assert(LCI.Command.Type == macho::LCT_Segment &&
302          "Unexpected load command info!");
303   uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) +
304                      Index * sizeof(macho::Section));
305   ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
306 }
307
308 template<>
309 void SwapStruct(macho::Section64 &Value) {
310   SwapValue(Value.Address);
311   SwapValue(Value.Size);
312   SwapValue(Value.Offset);
313   SwapValue(Value.Align);
314   SwapValue(Value.RelocationTableOffset);
315   SwapValue(Value.NumRelocationTableEntries);
316   SwapValue(Value.Flags);
317   SwapValue(Value.Reserved1);
318   SwapValue(Value.Reserved2);
319   SwapValue(Value.Reserved3);
320 }
321 void MachOObject::ReadSection64(const LoadCommandInfo &LCI,
322                                 unsigned Index,
323                                 InMemoryStruct<macho::Section64> &Res) const {
324   assert(LCI.Command.Type == macho::LCT_Segment64 &&
325          "Unexpected load command info!");
326   uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) +
327                      Index * sizeof(macho::Section64));
328   ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
329 }
330
331 template<>
332 void SwapStruct(macho::RelocationEntry &Value) {
333   SwapValue(Value.Word0);
334   SwapValue(Value.Word1);
335 }
336 void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset,
337                                       unsigned Index,
338                             InMemoryStruct<macho::RelocationEntry> &Res) const {
339   uint64_t Offset = (RelocationTableOffset +
340                      Index * sizeof(macho::RelocationEntry));
341   ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
342 }
343
344 template<>
345 void SwapStruct(macho::SymbolTableEntry &Value) {
346   SwapValue(Value.StringIndex);
347   SwapValue(Value.Flags);
348   SwapValue(Value.Value);
349 }
350 void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset,
351                                        unsigned Index,
352                            InMemoryStruct<macho::SymbolTableEntry> &Res) const {
353   uint64_t Offset = (SymbolTableOffset +
354                      Index * sizeof(macho::SymbolTableEntry));
355   ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
356 }
357
358 template<>
359 void SwapStruct(macho::Symbol64TableEntry &Value) {
360   SwapValue(Value.StringIndex);
361   SwapValue(Value.Flags);
362   SwapValue(Value.Value);
363 }
364 void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset,
365                                        unsigned Index,
366                          InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
367   uint64_t Offset = (SymbolTableOffset +
368                      Index * sizeof(macho::Symbol64TableEntry));
369   ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
370 }
371
372 template<>
373 void SwapStruct(macho::DataInCodeTableEntry &Value) {
374   SwapValue(Value.Offset);
375   SwapValue(Value.Length);
376   SwapValue(Value.Kind);
377 }
378 void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset,
379                                            unsigned Index,
380                        InMemoryStruct<macho::DataInCodeTableEntry> &Res) const {
381   uint64_t Offset = (TableOffset +
382                      Index * sizeof(macho::DataInCodeTableEntry));
383   ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
384 }
385
386 void MachOObject::ReadULEB128s(uint64_t Index,
387                                SmallVectorImpl<uint64_t> &Out) const {
388   DataExtractor extractor(Buffer->getBuffer(), true, 0);
389
390   uint32_t offset = Index;
391   uint64_t data = 0;
392   while (uint64_t delta = extractor.getULEB128(&offset)) {
393     data += delta;
394     Out.push_back(data);
395   }
396 }
397
398 /* ** */
399 // Object Dumping Facilities
400 void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; }
401 void MachOObject::dumpHeader() const { printHeader(dbgs()); dbgs() << '\n'; }
402
403 void MachOObject::printHeader(raw_ostream &O) const {
404   O << "('cputype', " << Header.CPUType << ")\n";
405   O << "('cpusubtype', " << Header.CPUSubtype << ")\n";
406   O << "('filetype', " << Header.FileType << ")\n";
407   O << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
408   O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
409   O << "('flag', " << Header.Flags << ")\n";
410
411   // Print extended header if 64-bit.
412   if (is64Bit())
413     O << "('reserved', " << Header64Ext.Reserved << ")\n";
414 }
415
416 void MachOObject::print(raw_ostream &O) const {
417   O << "Header:\n";
418   printHeader(O);
419   O << "Load Commands:\n";
420
421   O << "Buffer:\n";
422 }