blob: 37d6c21833f29f1dae2bc5bd4f2a1bdfb5a3b1da [file] [log] [blame]
Eric Christopher6256b032011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Andersonf7c93a32011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000016#include "llvm/ADT/Triple.h"
Eric Christopher6256b032011-04-22 03:19:48 +000017#include "llvm/Object/MachOFormat.h"
Rafael Espindola8764c892013-04-07 20:01:29 +000018#include "llvm/Support/DataExtractor.h"
Owen Anderson1832f4d2011-10-26 20:42:54 +000019#include "llvm/Support/Format.h"
Rafael Espindolafd7aa382013-04-18 18:08:55 +000020#include "llvm/Support/Host.h"
Jakub Staszak0856d3d2013-08-21 01:20:11 +000021#include "llvm/Support/MachO.h"
Eric Christopher6256b032011-04-22 03:19:48 +000022#include "llvm/Support/MemoryBuffer.h"
Jakub Staszak0856d3d2013-08-21 01:20:11 +000023#include "llvm/Support/raw_ostream.h"
Eric Christopher6256b032011-04-22 03:19:48 +000024#include <cctype>
25#include <cstring>
26#include <limits>
27
28using namespace llvm;
29using namespace object;
30
31namespace llvm {
Owen Andersonf7c93a32011-10-11 17:32:27 +000032namespace object {
Eric Christopher6256b032011-04-22 03:19:48 +000033
Rafael Espindolafd7aa382013-04-18 18:08:55 +000034struct SymbolTableEntryBase {
35 uint32_t StringIndex;
36 uint8_t Type;
37 uint8_t SectionIndex;
38 uint16_t Flags;
39};
40
41struct SectionBase {
42 char Name[16];
43 char SegmentName[16];
44};
45
46template<typename T>
47static void SwapValue(T &Value) {
48 Value = sys::SwapByteOrder(Value);
Benjamin Kramer0fcab072011-09-08 20:52:17 +000049}
50
Rafael Espindolafd7aa382013-04-18 18:08:55 +000051template<typename T>
52static void SwapStruct(T &Value);
53
54template<>
55void SwapStruct(macho::RelocationEntry &H) {
56 SwapValue(H.Word0);
57 SwapValue(H.Word1);
Rafael Espindola3eff3182013-04-07 16:07:35 +000058}
59
Rafael Espindolafd7aa382013-04-18 18:08:55 +000060template<>
61void SwapStruct(macho::LoadCommand &L) {
62 SwapValue(L.Type);
63 SwapValue(L.Size);
64}
Rafael Espindola8764c892013-04-07 20:01:29 +000065
Rafael Espindolafd7aa382013-04-18 18:08:55 +000066template<>
67void SwapStruct(SymbolTableEntryBase &S) {
68 SwapValue(S.StringIndex);
69 SwapValue(S.Flags);
70}
71
72template<>
73void SwapStruct(macho::Section &S) {
74 SwapValue(S.Address);
75 SwapValue(S.Size);
76 SwapValue(S.Offset);
77 SwapValue(S.Align);
78 SwapValue(S.RelocationTableOffset);
79 SwapValue(S.NumRelocationTableEntries);
80 SwapValue(S.Flags);
81 SwapValue(S.Reserved1);
82 SwapValue(S.Reserved2);
83}
84
85template<>
86void SwapStruct(macho::Section64 &S) {
87 SwapValue(S.Address);
88 SwapValue(S.Size);
89 SwapValue(S.Offset);
90 SwapValue(S.Align);
91 SwapValue(S.RelocationTableOffset);
92 SwapValue(S.NumRelocationTableEntries);
93 SwapValue(S.Flags);
94 SwapValue(S.Reserved1);
95 SwapValue(S.Reserved2);
96 SwapValue(S.Reserved3);
97}
98
99template<>
100void SwapStruct(macho::SymbolTableEntry &S) {
101 SwapValue(S.StringIndex);
102 SwapValue(S.Flags);
103 SwapValue(S.Value);
104}
105
106template<>
107void SwapStruct(macho::Symbol64TableEntry &S) {
108 SwapValue(S.StringIndex);
109 SwapValue(S.Flags);
110 SwapValue(S.Value);
111}
112
113template<>
114void SwapStruct(macho::Header &H) {
115 SwapValue(H.Magic);
116 SwapValue(H.CPUType);
117 SwapValue(H.CPUSubtype);
118 SwapValue(H.FileType);
119 SwapValue(H.NumLoadCommands);
120 SwapValue(H.SizeOfLoadCommands);
121 SwapValue(H.Flags);
122}
123
124template<>
Rafael Espindola2173e182013-04-26 20:07:33 +0000125void SwapStruct(macho::Header64Ext &E) {
126 SwapValue(E.Reserved);
127}
128
129template<>
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000130void SwapStruct(macho::SymtabLoadCommand &C) {
131 SwapValue(C.Type);
132 SwapValue(C.Size);
133 SwapValue(C.SymbolTableOffset);
134 SwapValue(C.NumSymbolTableEntries);
135 SwapValue(C.StringTableOffset);
136 SwapValue(C.StringTableSize);
137}
138
139template<>
Rafael Espindola2173e182013-04-26 20:07:33 +0000140void SwapStruct(macho::DysymtabLoadCommand &C) {
141 SwapValue(C.Type);
142 SwapValue(C.Size);
143 SwapValue(C.LocalSymbolsIndex);
144 SwapValue(C.NumLocalSymbols);
145 SwapValue(C.ExternalSymbolsIndex);
146 SwapValue(C.NumExternalSymbols);
147 SwapValue(C.UndefinedSymbolsIndex);
148 SwapValue(C.NumUndefinedSymbols);
149 SwapValue(C.TOCOffset);
150 SwapValue(C.NumTOCEntries);
151 SwapValue(C.ModuleTableOffset);
152 SwapValue(C.NumModuleTableEntries);
153 SwapValue(C.ReferenceSymbolTableOffset);
154 SwapValue(C.NumReferencedSymbolTableEntries);
155 SwapValue(C.IndirectSymbolTableOffset);
156 SwapValue(C.NumIndirectSymbolTableEntries);
157 SwapValue(C.ExternalRelocationTableOffset);
158 SwapValue(C.NumExternalRelocationTableEntries);
159 SwapValue(C.LocalRelocationTableOffset);
160 SwapValue(C.NumLocalRelocationTableEntries);
161}
162
163template<>
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000164void SwapStruct(macho::LinkeditDataLoadCommand &C) {
165 SwapValue(C.Type);
166 SwapValue(C.Size);
167 SwapValue(C.DataOffset);
168 SwapValue(C.DataSize);
169}
170
171template<>
172void SwapStruct(macho::SegmentLoadCommand &C) {
173 SwapValue(C.Type);
174 SwapValue(C.Size);
175 SwapValue(C.VMAddress);
176 SwapValue(C.VMSize);
177 SwapValue(C.FileOffset);
178 SwapValue(C.FileSize);
179 SwapValue(C.MaxVMProtection);
180 SwapValue(C.InitialVMProtection);
181 SwapValue(C.NumSections);
182 SwapValue(C.Flags);
183}
184
185template<>
186void SwapStruct(macho::Segment64LoadCommand &C) {
187 SwapValue(C.Type);
188 SwapValue(C.Size);
189 SwapValue(C.VMAddress);
190 SwapValue(C.VMSize);
191 SwapValue(C.FileOffset);
192 SwapValue(C.FileSize);
193 SwapValue(C.MaxVMProtection);
194 SwapValue(C.InitialVMProtection);
195 SwapValue(C.NumSections);
196 SwapValue(C.Flags);
197}
198
Rafael Espindola2173e182013-04-26 20:07:33 +0000199template<>
200void SwapStruct(macho::IndirectSymbolTableEntry &C) {
201 SwapValue(C.Index);
202}
203
204template<>
205void SwapStruct(macho::LinkerOptionsLoadCommand &C) {
206 SwapValue(C.Type);
207 SwapValue(C.Size);
208 SwapValue(C.Count);
209}
210
211template<>
212void SwapStruct(macho::DataInCodeTableEntry &C) {
213 SwapValue(C.Offset);
214 SwapValue(C.Length);
215 SwapValue(C.Kind);
216}
217
Rafael Espindola143d2232013-04-19 13:45:05 +0000218template<typename T>
219T getStruct(const MachOObjectFile *O, const char *P) {
220 T Cmd;
221 memcpy(&Cmd, P, sizeof(T));
222 if (O->isLittleEndian() != sys::IsLittleEndianHost)
223 SwapStruct(Cmd);
224 return Cmd;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000225}
226
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000227static uint32_t
228getSegmentLoadCommandNumSections(const MachOObjectFile *O,
229 const MachOObjectFile::LoadCommandInfo &L) {
230 if (O->is64Bit()) {
Rafael Espindola2173e182013-04-26 20:07:33 +0000231 macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000232 return S.NumSections;
Rafael Espindola8764c892013-04-07 20:01:29 +0000233 }
Rafael Espindola2173e182013-04-26 20:07:33 +0000234 macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000235 return S.NumSections;
Rafael Espindola3eff3182013-04-07 16:07:35 +0000236}
237
Rafael Espindola2173e182013-04-26 20:07:33 +0000238static const char *
239getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
240 unsigned Sec) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000241 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
242
243 bool Is64 = O->is64Bit();
244 unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
245 sizeof(macho::SegmentLoadCommand);
246 unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
247 sizeof(macho::Section);
248
249 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
Rafael Espindola2173e182013-04-26 20:07:33 +0000250 return reinterpret_cast<const char*>(SectionAddr);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000251}
252
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000253static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
254 return O->getData().substr(Offset, 1).data();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000255}
256
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000257static SymbolTableEntryBase
258getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola802fe932013-04-24 19:47:55 +0000259 const char *P = reinterpret_cast<const char *>(DRI.p);
Rafael Espindola143d2232013-04-19 13:45:05 +0000260 return getStruct<SymbolTableEntryBase>(O, P);
Eric Christopher6256b032011-04-22 03:19:48 +0000261}
262
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000263static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolacef81b32012-12-21 03:47:03 +0000264 if (P[15] == 0)
265 // Null terminated.
266 return P;
267 // Not null terminated, so this is a 16 char string.
268 return StringRef(P, 16);
269}
270
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000271// Helper to advance a section or symbol iterator multiple increments at a time.
272template<class T>
273static error_code advance(T &it, size_t Val) {
274 error_code ec;
275 while (Val--) {
276 it.increment(ec);
277 }
278 return ec;
279}
280
281template<class T>
282static void advanceTo(T &it, size_t Val) {
283 if (error_code ec = advance(it, Val))
284 report_fatal_error(ec.message());
285}
286
287static unsigned getCPUType(const MachOObjectFile *O) {
288 return O->getHeader().CPUType;
289}
290
291static void printRelocationTargetName(const MachOObjectFile *O,
292 const macho::RelocationEntry &RE,
293 raw_string_ostream &fmt) {
294 bool IsScattered = O->isRelocationScattered(RE);
295
296 // Target of a scattered relocation is an address. In the interest of
297 // generating pretty output, scan through the symbol table looking for a
298 // symbol that aligns with that address. If we find one, print it.
299 // Otherwise, we just print the hex address of the target.
300 if (IsScattered) {
301 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
302
303 error_code ec;
304 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
305 SI != SE; SI.increment(ec)) {
306 if (ec) report_fatal_error(ec.message());
307
308 uint64_t Addr;
309 StringRef Name;
310
311 if ((ec = SI->getAddress(Addr)))
312 report_fatal_error(ec.message());
313 if (Addr != Val) continue;
314 if ((ec = SI->getName(Name)))
315 report_fatal_error(ec.message());
316 fmt << Name;
317 return;
318 }
319
320 // If we couldn't find a symbol that this relocation refers to, try
321 // to find a section beginning instead.
322 for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
323 SI != SE; SI.increment(ec)) {
324 if (ec) report_fatal_error(ec.message());
325
326 uint64_t Addr;
327 StringRef Name;
328
329 if ((ec = SI->getAddress(Addr)))
330 report_fatal_error(ec.message());
331 if (Addr != Val) continue;
332 if ((ec = SI->getName(Name)))
333 report_fatal_error(ec.message());
334 fmt << Name;
335 return;
336 }
337
338 fmt << format("0x%x", Val);
339 return;
340 }
341
342 StringRef S;
343 bool isExtern = O->getPlainRelocationExternal(RE);
Ahmed Bougachaebb9f172013-05-14 22:41:29 +0000344 uint64_t Val = O->getPlainRelocationSymbolNum(RE);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000345
346 if (isExtern) {
347 symbol_iterator SI = O->begin_symbols();
348 advanceTo(SI, Val);
349 SI->getName(S);
350 } else {
351 section_iterator SI = O->begin_sections();
Ahmed Bougachaebb9f172013-05-14 22:41:29 +0000352 // Adjust for the fact that sections are 1-indexed.
353 advanceTo(SI, Val - 1);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000354 SI->getName(S);
355 }
356
357 fmt << S;
358}
359
360static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
361 return RE.Word0;
362}
363
364static unsigned
365getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
366 return RE.Word0 & 0xffffff;
367}
368
369static bool getPlainRelocationPCRel(const MachOObjectFile *O,
370 const macho::RelocationEntry &RE) {
371 if (O->isLittleEndian())
372 return (RE.Word1 >> 24) & 1;
373 return (RE.Word1 >> 7) & 1;
374}
375
376static bool
377getScatteredRelocationPCRel(const MachOObjectFile *O,
378 const macho::RelocationEntry &RE) {
379 return (RE.Word0 >> 30) & 1;
380}
381
382static unsigned getPlainRelocationLength(const MachOObjectFile *O,
383 const macho::RelocationEntry &RE) {
384 if (O->isLittleEndian())
385 return (RE.Word1 >> 25) & 3;
386 return (RE.Word1 >> 5) & 3;
387}
388
389static unsigned
390getScatteredRelocationLength(const macho::RelocationEntry &RE) {
391 return (RE.Word0 >> 28) & 3;
392}
393
394static unsigned getPlainRelocationType(const MachOObjectFile *O,
395 const macho::RelocationEntry &RE) {
396 if (O->isLittleEndian())
397 return RE.Word1 >> 28;
398 return RE.Word1 & 0xf;
399}
400
401static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
402 return (RE.Word0 >> 24) & 0xf;
403}
404
405static uint32_t getSectionFlags(const MachOObjectFile *O,
406 DataRefImpl Sec) {
407 if (O->is64Bit()) {
408 macho::Section64 Sect = O->getSection64(Sec);
409 return Sect.Flags;
410 }
411 macho::Section Sect = O->getSection(Sec);
412 return Sect.Flags;
413}
414
415MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
416 bool IsLittleEndian, bool Is64bits,
417 error_code &ec)
418 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
Kevin Enderby54154f32013-06-06 17:20:50 +0000419 SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000420 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
421 macho::LoadCommandType SegmentLoadType = is64Bit() ?
422 macho::LCT_Segment64 : macho::LCT_Segment;
423
424 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindoladb5f9272013-04-19 11:36:47 +0000425 for (unsigned I = 0; ; ++I) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000426 if (Load.C.Type == macho::LCT_Symtab) {
427 assert(!SymtabLoadCmd && "Multiple symbol tables");
428 SymtabLoadCmd = Load.Ptr;
Rafael Espindola2173e182013-04-26 20:07:33 +0000429 } else if (Load.C.Type == macho::LCT_Dysymtab) {
430 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
431 DysymtabLoadCmd = Load.Ptr;
Kevin Enderby54154f32013-06-06 17:20:50 +0000432 } else if (Load.C.Type == macho::LCT_DataInCode) {
433 assert(!DataInCodeLoadCmd && "Multiple data in code tables");
434 DataInCodeLoadCmd = Load.Ptr;
Rafael Espindola2173e182013-04-26 20:07:33 +0000435 } else if (Load.C.Type == SegmentLoadType) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000436 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
437 for (unsigned J = 0; J < NumSections; ++J) {
Rafael Espindola2173e182013-04-26 20:07:33 +0000438 const char *Sec = getSectionPtr(this, Load, J);
439 Sections.push_back(Sec);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000440 }
441 }
Rafael Espindoladb5f9272013-04-19 11:36:47 +0000442
443 if (I == LoadCommandCount - 1)
444 break;
445 else
446 Load = getNextLoadCommandInfo(Load);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000447 }
448}
449
450error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
451 SymbolRef &Res) const {
Rafael Espindola802fe932013-04-24 19:47:55 +0000452 unsigned SymbolTableEntrySize = is64Bit() ?
453 sizeof(macho::Symbol64TableEntry) :
454 sizeof(macho::SymbolTableEntry);
455 Symb.p += SymbolTableEntrySize;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000456 Res = SymbolRef(Symb, this);
457 return object_error::success;
458}
459
460error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
461 StringRef &Res) const {
Rafael Espindola2173e182013-04-26 20:07:33 +0000462 StringRef StringTable = getStringTableData();
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000463 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
Rafael Espindola2173e182013-04-26 20:07:33 +0000464 const char *Start = &StringTable.data()[Entry.StringIndex];
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000465 Res = StringRef(Start);
466 return object_error::success;
467}
468
469error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
470 uint64_t &Res) const {
471 if (is64Bit()) {
472 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
473 Res = Entry.Value;
474 } else {
475 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
476 Res = Entry.Value;
477 }
478 return object_error::success;
479}
480
481error_code
482MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
483 uint64_t &Res) const {
484 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
485 getSymbolAddress(Symb, Res);
486 if (Entry.SectionIndex) {
487 uint64_t Delta;
488 DataRefImpl SecRel;
489 SecRel.d.a = Entry.SectionIndex-1;
490 if (is64Bit()) {
491 macho::Section64 Sec = getSection64(SecRel);
492 Delta = Sec.Offset - Sec.Address;
493 } else {
494 macho::Section Sec = getSection(SecRel);
495 Delta = Sec.Offset - Sec.Address;
496 }
497
498 Res += Delta;
499 }
500
501 return object_error::success;
502}
503
Rafael Espindola59a0e792013-04-29 22:24:22 +0000504error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
505 uint32_t &Result) const {
506 uint32_t flags;
507 this->getSymbolFlags(DRI, flags);
508 if (flags & SymbolRef::SF_Common) {
509 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
510 Result = 1 << MachO::GET_COMM_ALIGN(Entry.Flags);
511 } else {
512 Result = 0;
513 }
514 return object_error::success;
515}
516
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000517error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
518 uint64_t &Result) const {
519 uint64_t BeginOffset;
520 uint64_t EndOffset = 0;
521 uint8_t SectionIndex;
522
523 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
524 uint64_t Value;
525 getSymbolAddress(DRI, Value);
526
527 BeginOffset = Value;
528
529 SectionIndex = Entry.SectionIndex;
530 if (!SectionIndex) {
531 uint32_t flags = SymbolRef::SF_None;
532 this->getSymbolFlags(DRI, flags);
533 if (flags & SymbolRef::SF_Common)
534 Result = Value;
535 else
536 Result = UnknownAddressOrSize;
537 return object_error::success;
538 }
539 // Unfortunately symbols are unsorted so we need to touch all
540 // symbols from load command
Rafael Espindola802fe932013-04-24 19:47:55 +0000541 error_code ec;
542 for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E;
543 I.increment(ec)) {
544 DataRefImpl DRI = I->getRawDataRefImpl();
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000545 Entry = getSymbolTableEntryBase(this, DRI);
546 getSymbolAddress(DRI, Value);
547 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
548 if (!EndOffset || Value < EndOffset)
549 EndOffset = Value;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000550 }
551 if (!EndOffset) {
552 uint64_t Size;
553 DataRefImpl Sec;
554 Sec.d.a = SectionIndex-1;
555 getSectionSize(Sec, Size);
556 getSectionAddress(Sec, EndOffset);
557 EndOffset += Size;
558 }
559 Result = EndOffset - BeginOffset;
560 return object_error::success;
561}
562
563error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
564 SymbolRef::Type &Res) const {
565 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
566 uint8_t n_type = Entry.Type;
567
568 Res = SymbolRef::ST_Other;
569
570 // If this is a STAB debugging symbol, we can do nothing more.
Charles Davisbf778d02013-08-27 05:00:13 +0000571 if (n_type & MachO::N_STAB) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000572 Res = SymbolRef::ST_Debug;
573 return object_error::success;
574 }
575
Charles Davisbf778d02013-08-27 05:00:13 +0000576 switch (n_type & MachO::N_TYPE) {
577 case MachO::N_UNDF :
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000578 Res = SymbolRef::ST_Unknown;
579 break;
Charles Davisbf778d02013-08-27 05:00:13 +0000580 case MachO::N_SECT :
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000581 Res = SymbolRef::ST_Function;
582 break;
583 }
584 return object_error::success;
585}
586
587error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
588 char &Res) const {
589 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
590 uint8_t Type = Entry.Type;
591 uint16_t Flags = Entry.Flags;
592
593 char Char;
594 switch (Type & macho::STF_TypeMask) {
595 case macho::STT_Undefined:
596 Char = 'u';
597 break;
598 case macho::STT_Absolute:
599 case macho::STT_Section:
600 Char = 's';
601 break;
602 default:
603 Char = '?';
604 break;
605 }
606
607 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
608 Char = toupper(static_cast<unsigned char>(Char));
609 Res = Char;
610 return object_error::success;
611}
612
613error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
614 uint32_t &Result) const {
615 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
616
617 uint8_t MachOType = Entry.Type;
618 uint16_t MachOFlags = Entry.Flags;
619
620 // TODO: Correctly set SF_ThreadLocal
621 Result = SymbolRef::SF_None;
622
Charles Davisbf778d02013-08-27 05:00:13 +0000623 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000624 Result |= SymbolRef::SF_Undefined;
625
626 if (MachOFlags & macho::STF_StabsEntryMask)
627 Result |= SymbolRef::SF_FormatSpecific;
628
Charles Davisbf778d02013-08-27 05:00:13 +0000629 if (MachOType & MachO::N_EXT) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000630 Result |= SymbolRef::SF_Global;
Charles Davisbf778d02013-08-27 05:00:13 +0000631 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
Rafael Espindola59a0e792013-04-29 22:24:22 +0000632 uint64_t Value;
633 getSymbolAddress(DRI, Value);
634 if (Value)
635 Result |= SymbolRef::SF_Common;
636 }
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000637 }
638
Charles Davisbf778d02013-08-27 05:00:13 +0000639 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000640 Result |= SymbolRef::SF_Weak;
641
Charles Davisbf778d02013-08-27 05:00:13 +0000642 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000643 Result |= SymbolRef::SF_Absolute;
644
645 return object_error::success;
646}
647
648error_code
649MachOObjectFile::getSymbolSection(DataRefImpl Symb,
650 section_iterator &Res) const {
651 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
652 uint8_t index = Entry.SectionIndex;
653
654 if (index == 0) {
655 Res = end_sections();
656 } else {
657 DataRefImpl DRI;
658 DRI.d.a = index - 1;
659 Res = section_iterator(SectionRef(DRI, this));
660 }
661
662 return object_error::success;
663}
664
665error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000666 uint64_t &Val) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000667 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
668}
669
670error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
671 SectionRef &Res) const {
672 Sec.d.a++;
673 Res = SectionRef(Sec, this);
674 return object_error::success;
675}
676
677error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000678MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000679 ArrayRef<char> Raw = getSectionRawName(Sec);
680 Result = parseSegmentOrSectionName(Raw.data());
681 return object_error::success;
682}
683
684error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000685MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000686 if (is64Bit()) {
687 macho::Section64 Sect = getSection64(Sec);
688 Res = Sect.Address;
689 } else {
690 macho::Section Sect = getSection(Sec);
691 Res = Sect.Address;
692 }
693 return object_error::success;
694}
695
696error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000697MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000698 if (is64Bit()) {
699 macho::Section64 Sect = getSection64(Sec);
700 Res = Sect.Size;
701 } else {
702 macho::Section Sect = getSection(Sec);
703 Res = Sect.Size;
704 }
705
706 return object_error::success;
707}
708
709error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000710MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000711 uint32_t Offset;
712 uint64_t Size;
713
714 if (is64Bit()) {
715 macho::Section64 Sect = getSection64(Sec);
716 Offset = Sect.Offset;
717 Size = Sect.Size;
718 } else {
719 macho::Section Sect =getSection(Sec);
720 Offset = Sect.Offset;
721 Size = Sect.Size;
722 }
723
724 Res = this->getData().substr(Offset, Size);
725 return object_error::success;
726}
727
728error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000729MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000730 uint32_t Align;
731 if (is64Bit()) {
732 macho::Section64 Sect = getSection64(Sec);
733 Align = Sect.Align;
734 } else {
735 macho::Section Sect = getSection(Sec);
736 Align = Sect.Align;
737 }
738
739 Res = uint64_t(1) << Align;
740 return object_error::success;
741}
742
743error_code
744MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
745 uint32_t Flags = getSectionFlags(this, Sec);
746 Res = Flags & macho::SF_PureInstructions;
747 return object_error::success;
748}
749
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000750error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const {
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000751 // FIXME: Unimplemented.
752 Result = false;
753 return object_error::success;
754}
755
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000756error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000757 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000758 Result = false;
759 return object_error::success;
760}
761
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000762error_code
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000763MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000764 bool &Result) const {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000765 // FIXME: Unimplemented.
766 Result = true;
Preston Gurdc68dda82012-04-12 20:13:57 +0000767 return object_error::success;
768}
769
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000770error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000771 bool &Result) const {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000772 // FIXME: Unimplemented.
773 Result = false;
774 return object_error::success;
775}
776
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000777error_code
778MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
779 uint32_t Flags = getSectionFlags(this, Sec);
Charles Davisbf778d02013-08-27 05:00:13 +0000780 unsigned SectionType = Flags & MachO::SECTION_TYPE;
781 Res = SectionType == MachO::S_ZEROFILL ||
782 SectionType == MachO::S_GB_ZEROFILL;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000783 return object_error::success;
784}
785
786error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000787 bool &Result) const {
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000788 // Consider using the code from isSectionText to look for __const sections.
789 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
790 // to use section attributes to distinguish code from data.
791
792 // FIXME: Unimplemented.
793 Result = false;
794 return object_error::success;
795}
796
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000797error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000798MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000799 bool &Result) const {
800 SymbolRef::Type ST;
801 this->getSymbolType(Symb, ST);
802 if (ST == SymbolRef::ST_Unknown) {
803 Result = false;
804 return object_error::success;
805 }
806
807 uint64_t SectBegin, SectEnd;
808 getSectionAddress(Sec, SectBegin);
809 getSectionSize(Sec, SectEnd);
810 SectEnd += SectBegin;
811
812 uint64_t SymAddr;
813 getSymbolAddress(Symb, SymAddr);
814 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
815
816 return object_error::success;
817}
818
819relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
Rafael Espindolae5330f72013-04-25 12:45:46 +0000820 uint32_t Offset;
821 if (is64Bit()) {
822 macho::Section64 Sect = getSection64(Sec);
823 Offset = Sect.RelocationTableOffset;
824 } else {
825 macho::Section Sect = getSection(Sec);
826 Offset = Sect.RelocationTableOffset;
827 }
828
829 DataRefImpl Ret;
830 Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
831 return relocation_iterator(RelocationRef(Ret, this));
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000832}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000833
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000834relocation_iterator
835MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
Rafael Espindolae5330f72013-04-25 12:45:46 +0000836 uint32_t Offset;
837 uint32_t Num;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000838 if (is64Bit()) {
839 macho::Section64 Sect = getSection64(Sec);
Rafael Espindolae5330f72013-04-25 12:45:46 +0000840 Offset = Sect.RelocationTableOffset;
841 Num = Sect.NumRelocationTableEntries;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000842 } else {
843 macho::Section Sect = getSection(Sec);
Rafael Espindolae5330f72013-04-25 12:45:46 +0000844 Offset = Sect.RelocationTableOffset;
845 Num = Sect.NumRelocationTableEntries;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000846 }
Eric Christopher6256b032011-04-22 03:19:48 +0000847
Rafael Espindolae5330f72013-04-25 12:45:46 +0000848 const macho::RelocationEntry *P =
849 reinterpret_cast<const macho::RelocationEntry*>(getPtr(this, Offset));
850
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000851 DataRefImpl Ret;
Rafael Espindolae5330f72013-04-25 12:45:46 +0000852 Ret.p = reinterpret_cast<uintptr_t>(P + Num);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000853 return relocation_iterator(RelocationRef(Ret, this));
854}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000855
Rafael Espindolae5330f72013-04-25 12:45:46 +0000856error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
857 RelocationRef &Res) const {
858 const macho::RelocationEntry *P =
859 reinterpret_cast<const macho::RelocationEntry *>(Rel.p);
860 Rel.p = reinterpret_cast<uintptr_t>(P + 1);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000861 Res = RelocationRef(Rel, this);
862 return object_error::success;
863}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000864
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000865error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000866MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
Rafael Espindola956ca722013-04-25 12:28:45 +0000867 report_fatal_error("getRelocationAddress not implemented in MachOObjectFile");
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000868}
869
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000870error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000871 uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000872 macho::RelocationEntry RE = getRelocation(Rel);
873 Res = getAnyRelocationAddress(RE);
874 return object_error::success;
David Meyer5c2b4ea2012-03-01 01:36:50 +0000875}
876
Rafael Espindola6c1202c2013-06-05 01:33:53 +0000877symbol_iterator
878MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000879 macho::RelocationEntry RE = getRelocation(Rel);
880 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
881 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola6c1202c2013-06-05 01:33:53 +0000882 if (!isExtern)
883 return end_symbols();
Rafael Espindola802fe932013-04-24 19:47:55 +0000884
885 macho::SymtabLoadCommand S = getSymtabLoadCommand();
886 unsigned SymbolTableEntrySize = is64Bit() ?
887 sizeof(macho::Symbol64TableEntry) :
888 sizeof(macho::SymbolTableEntry);
889 uint64_t Offset = S.SymbolTableOffset + SymbolIdx * SymbolTableEntrySize;
890 DataRefImpl Sym;
891 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindola6c1202c2013-06-05 01:33:53 +0000892 return symbol_iterator(SymbolRef(Sym, this));
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000893}
894
895error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000896 uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000897 macho::RelocationEntry RE = getRelocation(Rel);
898 Res = getAnyRelocationType(RE);
899 return object_error::success;
900}
901
902error_code
903MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
904 SmallVectorImpl<char> &Result) const {
905 StringRef res;
906 uint64_t RType;
907 getRelocationType(Rel, RType);
908
909 unsigned Arch = this->getArch();
910
911 switch (Arch) {
912 case Triple::x86: {
913 static const char *const Table[] = {
914 "GENERIC_RELOC_VANILLA",
915 "GENERIC_RELOC_PAIR",
916 "GENERIC_RELOC_SECTDIFF",
917 "GENERIC_RELOC_PB_LA_PTR",
918 "GENERIC_RELOC_LOCAL_SECTDIFF",
919 "GENERIC_RELOC_TLV" };
920
921 if (RType > 6)
922 res = "Unknown";
923 else
924 res = Table[RType];
925 break;
926 }
927 case Triple::x86_64: {
928 static const char *const Table[] = {
929 "X86_64_RELOC_UNSIGNED",
930 "X86_64_RELOC_SIGNED",
931 "X86_64_RELOC_BRANCH",
932 "X86_64_RELOC_GOT_LOAD",
933 "X86_64_RELOC_GOT",
934 "X86_64_RELOC_SUBTRACTOR",
935 "X86_64_RELOC_SIGNED_1",
936 "X86_64_RELOC_SIGNED_2",
937 "X86_64_RELOC_SIGNED_4",
938 "X86_64_RELOC_TLV" };
939
940 if (RType > 9)
941 res = "Unknown";
942 else
943 res = Table[RType];
944 break;
945 }
946 case Triple::arm: {
947 static const char *const Table[] = {
948 "ARM_RELOC_VANILLA",
949 "ARM_RELOC_PAIR",
950 "ARM_RELOC_SECTDIFF",
951 "ARM_RELOC_LOCAL_SECTDIFF",
952 "ARM_RELOC_PB_LA_PTR",
953 "ARM_RELOC_BR24",
954 "ARM_THUMB_RELOC_BR22",
955 "ARM_THUMB_32BIT_BRANCH",
956 "ARM_RELOC_HALF",
957 "ARM_RELOC_HALF_SECTDIFF" };
958
959 if (RType > 9)
960 res = "Unknown";
961 else
962 res = Table[RType];
963 break;
964 }
965 case Triple::ppc: {
966 static const char *const Table[] = {
967 "PPC_RELOC_VANILLA",
968 "PPC_RELOC_PAIR",
969 "PPC_RELOC_BR14",
970 "PPC_RELOC_BR24",
971 "PPC_RELOC_HI16",
972 "PPC_RELOC_LO16",
973 "PPC_RELOC_HA16",
974 "PPC_RELOC_LO14",
975 "PPC_RELOC_SECTDIFF",
976 "PPC_RELOC_PB_LA_PTR",
977 "PPC_RELOC_HI16_SECTDIFF",
978 "PPC_RELOC_LO16_SECTDIFF",
979 "PPC_RELOC_HA16_SECTDIFF",
980 "PPC_RELOC_JBSR",
981 "PPC_RELOC_LO14_SECTDIFF",
982 "PPC_RELOC_LOCAL_SECTDIFF" };
983
984 res = Table[RType];
985 break;
986 }
987 case Triple::UnknownArch:
988 res = "Unknown";
989 break;
990 }
991 Result.append(res.begin(), res.end());
992 return object_error::success;
993}
994
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000995error_code
996MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000997 SmallVectorImpl<char> &Result) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000998 macho::RelocationEntry RE = getRelocation(Rel);
David Meyer5c2b4ea2012-03-01 01:36:50 +0000999
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001000 unsigned Arch = this->getArch();
Eric Christopher6256b032011-04-22 03:19:48 +00001001
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001002 std::string fmtbuf;
1003 raw_string_ostream fmt(fmtbuf);
1004 unsigned Type = this->getAnyRelocationType(RE);
1005 bool IsPCRel = this->getAnyRelocationPCRel(RE);
1006
1007 // Determine any addends that should be displayed with the relocation.
1008 // These require decoding the relocation type, which is triple-specific.
1009
1010 // X86_64 has entirely custom relocation types.
1011 if (Arch == Triple::x86_64) {
1012 bool isPCRel = getAnyRelocationPCRel(RE);
1013
1014 switch (Type) {
1015 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1016 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1017 printRelocationTargetName(this, RE, fmt);
1018 fmt << "@GOT";
1019 if (isPCRel) fmt << "PCREL";
1020 break;
1021 }
1022 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1023 DataRefImpl RelNext = Rel;
1024 RelNext.d.a++;
1025 macho::RelocationEntry RENext = getRelocation(RelNext);
1026
1027 // X86_64_SUBTRACTOR must be followed by a relocation of type
1028 // X86_64_RELOC_UNSIGNED.
1029 // NOTE: Scattered relocations don't exist on x86_64.
1030 unsigned RType = getAnyRelocationType(RENext);
1031 if (RType != 0)
1032 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1033 "X86_64_RELOC_SUBTRACTOR.");
1034
1035 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1036 // X86_64_SUBTRACTOR contains to the subtrahend.
1037 printRelocationTargetName(this, RENext, fmt);
1038 fmt << "-";
1039 printRelocationTargetName(this, RE, fmt);
1040 break;
1041 }
1042 case macho::RIT_X86_64_TLV:
1043 printRelocationTargetName(this, RE, fmt);
1044 fmt << "@TLV";
1045 if (isPCRel) fmt << "P";
1046 break;
1047 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1048 printRelocationTargetName(this, RE, fmt);
1049 fmt << "-1";
1050 break;
1051 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1052 printRelocationTargetName(this, RE, fmt);
1053 fmt << "-2";
1054 break;
1055 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1056 printRelocationTargetName(this, RE, fmt);
1057 fmt << "-4";
1058 break;
1059 default:
1060 printRelocationTargetName(this, RE, fmt);
1061 break;
1062 }
1063 // X86 and ARM share some relocation types in common.
David Fangd4f9d052013-08-08 20:14:40 +00001064 } else if (Arch == Triple::x86 || Arch == Triple::arm ||
1065 Arch == Triple::ppc) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001066 // Generic relocation types...
1067 switch (Type) {
1068 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1069 return object_error::success;
1070 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1071 DataRefImpl RelNext = Rel;
1072 RelNext.d.a++;
1073 macho::RelocationEntry RENext = getRelocation(RelNext);
1074
1075 // X86 sect diff's must be followed by a relocation of type
1076 // GENERIC_RELOC_PAIR.
1077 unsigned RType = getAnyRelocationType(RENext);
1078
1079 if (RType != 1)
1080 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1081 "GENERIC_RELOC_SECTDIFF.");
1082
1083 printRelocationTargetName(this, RE, fmt);
1084 fmt << "-";
1085 printRelocationTargetName(this, RENext, fmt);
1086 break;
1087 }
1088 }
1089
David Fangd4f9d052013-08-08 20:14:40 +00001090 if (Arch == Triple::x86 || Arch == Triple::ppc) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001091 // All X86 relocations that need special printing were already
1092 // handled in the generic code.
1093 switch (Type) {
1094 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1095 DataRefImpl RelNext = Rel;
1096 RelNext.d.a++;
1097 macho::RelocationEntry RENext = getRelocation(RelNext);
1098
1099 // X86 sect diff's must be followed by a relocation of type
1100 // GENERIC_RELOC_PAIR.
1101 unsigned RType = getAnyRelocationType(RENext);
1102 if (RType != 1)
1103 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1104 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1105
1106 printRelocationTargetName(this, RE, fmt);
1107 fmt << "-";
1108 printRelocationTargetName(this, RENext, fmt);
1109 break;
1110 }
1111 case macho::RIT_Generic_TLV: {
1112 printRelocationTargetName(this, RE, fmt);
1113 fmt << "@TLV";
1114 if (IsPCRel) fmt << "P";
1115 break;
1116 }
1117 default:
1118 printRelocationTargetName(this, RE, fmt);
1119 }
1120 } else { // ARM-specific relocations
1121 switch (Type) {
1122 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1123 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1124 // Half relocations steal a bit from the length field to encode
1125 // whether this is an upper16 or a lower16 relocation.
1126 bool isUpper = getAnyRelocationLength(RE) >> 1;
1127
1128 if (isUpper)
1129 fmt << ":upper16:(";
1130 else
1131 fmt << ":lower16:(";
1132 printRelocationTargetName(this, RE, fmt);
1133
1134 DataRefImpl RelNext = Rel;
1135 RelNext.d.a++;
1136 macho::RelocationEntry RENext = getRelocation(RelNext);
1137
1138 // ARM half relocs must be followed by a relocation of type
1139 // ARM_RELOC_PAIR.
1140 unsigned RType = getAnyRelocationType(RENext);
1141 if (RType != 1)
1142 report_fatal_error("Expected ARM_RELOC_PAIR after "
1143 "GENERIC_RELOC_HALF");
1144
1145 // NOTE: The half of the target virtual address is stashed in the
1146 // address field of the secondary relocation, but we can't reverse
1147 // engineer the constant offset from it without decoding the movw/movt
1148 // instruction to find the other half in its immediate field.
1149
1150 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1151 // symbol/section pointer of the follow-on relocation.
1152 if (Type == macho::RIT_ARM_HalfDifference) {
1153 fmt << "-";
1154 printRelocationTargetName(this, RENext, fmt);
1155 }
1156
1157 fmt << ")";
1158 break;
1159 }
1160 default: {
1161 printRelocationTargetName(this, RE, fmt);
1162 }
1163 }
1164 }
1165 } else
1166 printRelocationTargetName(this, RE, fmt);
1167
1168 fmt.flush();
1169 Result.append(fmtbuf.begin(), fmtbuf.end());
1170 return object_error::success;
1171}
1172
1173error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +00001174MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001175 unsigned Arch = getArch();
1176 uint64_t Type;
1177 getRelocationType(Rel, Type);
1178
1179 Result = false;
1180
1181 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1182 // is always hidden.
David Fangd4f9d052013-08-08 20:14:40 +00001183 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001184 if (Type == macho::RIT_Pair) Result = true;
1185 } else if (Arch == Triple::x86_64) {
1186 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
Eric Christopherbd8f8a32013-07-22 22:25:09 +00001187 // an X86_64_RELOC_SUBTRACTOR.
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001188 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1189 DataRefImpl RelPrev = Rel;
1190 RelPrev.d.a--;
1191 uint64_t PrevType;
1192 getRelocationType(RelPrev, PrevType);
1193 if (PrevType == macho::RIT_X86_64_Subtractor)
1194 Result = true;
1195 }
1196 }
1197
1198 return object_error::success;
1199}
1200
1201error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +00001202 LibraryRef &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001203 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1204}
1205
1206error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +00001207 StringRef &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001208 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1209}
1210
1211symbol_iterator MachOObjectFile::begin_symbols() const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001212 DataRefImpl DRI;
Rafael Espindola802fe932013-04-24 19:47:55 +00001213 if (!SymtabLoadCmd)
1214 return symbol_iterator(SymbolRef(DRI, this));
1215
1216 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1217 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.SymbolTableOffset));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001218 return symbol_iterator(SymbolRef(DRI, this));
1219}
1220
1221symbol_iterator MachOObjectFile::end_symbols() const {
1222 DataRefImpl DRI;
Rafael Espindola802fe932013-04-24 19:47:55 +00001223 if (!SymtabLoadCmd)
1224 return symbol_iterator(SymbolRef(DRI, this));
1225
1226 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1227 unsigned SymbolTableEntrySize = is64Bit() ?
1228 sizeof(macho::Symbol64TableEntry) :
1229 sizeof(macho::SymbolTableEntry);
1230 unsigned Offset = Symtab.SymbolTableOffset +
1231 Symtab.NumSymbolTableEntries * SymbolTableEntrySize;
1232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001233 return symbol_iterator(SymbolRef(DRI, this));
1234}
1235
1236symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1237 // TODO: implement
1238 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1239}
1240
1241symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1242 // TODO: implement
1243 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1244}
1245
1246section_iterator MachOObjectFile::begin_sections() const {
1247 DataRefImpl DRI;
1248 return section_iterator(SectionRef(DRI, this));
1249}
1250
1251section_iterator MachOObjectFile::end_sections() const {
1252 DataRefImpl DRI;
1253 DRI.d.a = Sections.size();
1254 return section_iterator(SectionRef(DRI, this));
1255}
1256
1257library_iterator MachOObjectFile::begin_libraries_needed() const {
1258 // TODO: implement
1259 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1260}
1261
1262library_iterator MachOObjectFile::end_libraries_needed() const {
1263 // TODO: implement
1264 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1265}
1266
1267uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001268 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001269}
1270
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001271StringRef MachOObjectFile::getFileFormatName() const {
1272 unsigned CPUType = getCPUType(this);
1273 if (!is64Bit()) {
1274 switch (CPUType) {
Charles Davisbf778d02013-08-27 05:00:13 +00001275 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001276 return "Mach-O 32-bit i386";
Charles Davisbf778d02013-08-27 05:00:13 +00001277 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001278 return "Mach-O arm";
Charles Davisbf778d02013-08-27 05:00:13 +00001279 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001280 return "Mach-O 32-bit ppc";
1281 default:
Charles Davisbf778d02013-08-27 05:00:13 +00001282 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 &&
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001283 "64-bit object file when we're not 64-bit?");
1284 return "Mach-O 32-bit unknown";
1285 }
1286 }
1287
1288 // Make sure the cpu type has the correct mask.
Charles Davisbf778d02013-08-27 05:00:13 +00001289 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64)
1290 == llvm::MachO::CPU_ARCH_ABI64 &&
Eric Christopher60d65912013-07-22 22:25:07 +00001291 "32-bit object file when we're 64-bit?");
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001292
1293 switch (CPUType) {
Charles Davisbf778d02013-08-27 05:00:13 +00001294 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001295 return "Mach-O 64-bit x86-64";
Charles Davisbf778d02013-08-27 05:00:13 +00001296 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001297 return "Mach-O 64-bit ppc64";
1298 default:
1299 return "Mach-O 64-bit unknown";
1300 }
1301}
1302
Alexey Samsonov9c22f872013-06-18 15:03:28 +00001303Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
1304 switch (CPUType) {
Charles Davisbf778d02013-08-27 05:00:13 +00001305 case llvm::MachO::CPU_TYPE_I386:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001306 return Triple::x86;
Charles Davisbf778d02013-08-27 05:00:13 +00001307 case llvm::MachO::CPU_TYPE_X86_64:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001308 return Triple::x86_64;
Charles Davisbf778d02013-08-27 05:00:13 +00001309 case llvm::MachO::CPU_TYPE_ARM:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001310 return Triple::arm;
Charles Davisbf778d02013-08-27 05:00:13 +00001311 case llvm::MachO::CPU_TYPE_POWERPC:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001312 return Triple::ppc;
Charles Davisbf778d02013-08-27 05:00:13 +00001313 case llvm::MachO::CPU_TYPE_POWERPC64:
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001314 return Triple::ppc64;
1315 default:
1316 return Triple::UnknownArch;
1317 }
1318}
1319
Alexey Samsonov9c22f872013-06-18 15:03:28 +00001320unsigned MachOObjectFile::getArch() const {
1321 return getArch(getCPUType(this));
1322}
1323
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001324StringRef MachOObjectFile::getLoadName() const {
1325 // TODO: Implement
1326 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1327}
1328
Rafael Espindola2173e182013-04-26 20:07:33 +00001329relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const {
1330 DataRefImpl DRI;
1331 DRI.d.a = Index;
1332 return getSectionRelBegin(DRI);
1333}
1334
1335relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const {
1336 DataRefImpl DRI;
1337 DRI.d.a = Index;
1338 return getSectionRelEnd(DRI);
1339}
1340
Kevin Enderby54154f32013-06-06 17:20:50 +00001341dice_iterator MachOObjectFile::begin_dices() const {
1342 DataRefImpl DRI;
1343 if (!DataInCodeLoadCmd)
1344 return dice_iterator(DiceRef(DRI, this));
1345
1346 macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand();
1347 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.DataOffset));
1348 return dice_iterator(DiceRef(DRI, this));
1349}
1350
1351dice_iterator MachOObjectFile::end_dices() const {
1352 DataRefImpl DRI;
1353 if (!DataInCodeLoadCmd)
1354 return dice_iterator(DiceRef(DRI, this));
1355
1356 macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand();
1357 unsigned Offset = DicLC.DataOffset + DicLC.DataSize;
1358 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
1359 return dice_iterator(DiceRef(DRI, this));
1360}
1361
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001362StringRef
1363MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1364 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1365 return parseSegmentOrSectionName(Raw.data());
1366}
1367
1368ArrayRef<char>
1369MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1370 const SectionBase *Base =
1371 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1372 return ArrayRef<char>(Base->Name);
1373}
1374
1375ArrayRef<char>
1376MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1377 const SectionBase *Base =
1378 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1379 return ArrayRef<char>(Base->SegmentName);
1380}
1381
1382bool
1383MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1384 const {
Charles Davisbf778d02013-08-27 05:00:13 +00001385 if (getCPUType(this) == llvm::MachO::CPU_TYPE_X86_64)
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001386 return false;
1387 return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1388}
1389
Eric Christopher60d65912013-07-22 22:25:07 +00001390unsigned MachOObjectFile::getPlainRelocationSymbolNum(
1391 const macho::RelocationEntry &RE) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001392 if (isLittleEndian())
1393 return RE.Word1 & 0xffffff;
1394 return RE.Word1 >> 8;
1395}
1396
Eric Christopher60d65912013-07-22 22:25:07 +00001397bool MachOObjectFile::getPlainRelocationExternal(
1398 const macho::RelocationEntry &RE) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001399 if (isLittleEndian())
1400 return (RE.Word1 >> 27) & 1;
1401 return (RE.Word1 >> 4) & 1;
1402}
1403
Eric Christopher60d65912013-07-22 22:25:07 +00001404bool MachOObjectFile::getScatteredRelocationScattered(
1405 const macho::RelocationEntry &RE) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001406 return RE.Word0 >> 31;
1407}
1408
Eric Christopher60d65912013-07-22 22:25:07 +00001409uint32_t MachOObjectFile::getScatteredRelocationValue(
1410 const macho::RelocationEntry &RE) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001411 return RE.Word1;
1412}
1413
Eric Christopher60d65912013-07-22 22:25:07 +00001414unsigned MachOObjectFile::getAnyRelocationAddress(
1415 const macho::RelocationEntry &RE) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001416 if (isRelocationScattered(RE))
1417 return getScatteredRelocationAddress(RE);
1418 return getPlainRelocationAddress(RE);
1419}
1420
1421unsigned
1422MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1423 if (isRelocationScattered(RE))
1424 return getScatteredRelocationPCRel(this, RE);
1425 return getPlainRelocationPCRel(this, RE);
1426}
1427
Eric Christopher60d65912013-07-22 22:25:07 +00001428unsigned MachOObjectFile::getAnyRelocationLength(
1429 const macho::RelocationEntry &RE) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001430 if (isRelocationScattered(RE))
1431 return getScatteredRelocationLength(RE);
1432 return getPlainRelocationLength(this, RE);
1433}
1434
1435unsigned
1436MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1437 if (isRelocationScattered(RE))
1438 return getScatteredRelocationType(RE);
1439 return getPlainRelocationType(this, RE);
1440}
1441
Rafael Espindolae87dadc2013-04-30 15:40:54 +00001442SectionRef
1443MachOObjectFile::getRelocationSection(const macho::RelocationEntry &RE) const {
1444 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
1445 return *end_sections();
1446 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
1447 DataRefImpl DRI;
1448 DRI.d.a = SecNum;
1449 return SectionRef(DRI, this);
1450}
1451
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001452MachOObjectFile::LoadCommandInfo
1453MachOObjectFile::getFirstLoadCommandInfo() const {
1454 MachOObjectFile::LoadCommandInfo Load;
1455
1456 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1457 Load.Ptr = getPtr(this, HeaderSize);
Rafael Espindola143d2232013-04-19 13:45:05 +00001458 Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001459 return Load;
1460}
1461
1462MachOObjectFile::LoadCommandInfo
1463MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1464 MachOObjectFile::LoadCommandInfo Next;
1465 Next.Ptr = L.Ptr + L.C.Size;
Rafael Espindola143d2232013-04-19 13:45:05 +00001466 Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001467 return Next;
1468}
1469
1470macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001471 return getStruct<macho::Section>(this, Sections[DRI.d.a]);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001472}
1473
1474macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001475 return getStruct<macho::Section64>(this, Sections[DRI.d.a]);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001476}
1477
Rafael Espindola2173e182013-04-26 20:07:33 +00001478macho::Section MachOObjectFile::getSection(const LoadCommandInfo &L,
1479 unsigned Index) const {
1480 const char *Sec = getSectionPtr(this, L, Index);
1481 return getStruct<macho::Section>(this, Sec);
1482}
1483
1484macho::Section64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1485 unsigned Index) const {
1486 const char *Sec = getSectionPtr(this, L, Index);
1487 return getStruct<macho::Section64>(this, Sec);
1488}
1489
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001490macho::SymbolTableEntry
1491MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola802fe932013-04-24 19:47:55 +00001492 const char *P = reinterpret_cast<const char *>(DRI.p);
Rafael Espindola143d2232013-04-19 13:45:05 +00001493 return getStruct<macho::SymbolTableEntry>(this, P);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001494}
1495
1496macho::Symbol64TableEntry
1497MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola802fe932013-04-24 19:47:55 +00001498 const char *P = reinterpret_cast<const char *>(DRI.p);
Rafael Espindola143d2232013-04-19 13:45:05 +00001499 return getStruct<macho::Symbol64TableEntry>(this, P);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001500}
1501
Eric Christopher60d65912013-07-22 22:25:07 +00001502macho::LinkeditDataLoadCommand MachOObjectFile::getLinkeditDataLoadCommand(
1503 const MachOObjectFile::LoadCommandInfo &L) const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001504 return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001505}
1506
Rafael Espindola2173e182013-04-26 20:07:33 +00001507macho::SegmentLoadCommand
1508MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1509 return getStruct<macho::SegmentLoadCommand>(this, L.Ptr);
1510}
1511
1512macho::Segment64LoadCommand
1513MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1514 return getStruct<macho::Segment64LoadCommand>(this, L.Ptr);
1515}
1516
1517macho::LinkerOptionsLoadCommand
1518MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1519 return getStruct<macho::LinkerOptionsLoadCommand>(this, L.Ptr);
1520}
1521
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001522macho::RelocationEntry
1523MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindolae5330f72013-04-25 12:45:46 +00001524 const char *P = reinterpret_cast<const char *>(Rel.p);
1525 return getStruct<macho::RelocationEntry>(this, P);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001526}
1527
Kevin Enderby54154f32013-06-06 17:20:50 +00001528macho::DataInCodeTableEntry
1529MachOObjectFile::getDice(DataRefImpl Rel) const {
1530 const char *P = reinterpret_cast<const char *>(Rel.p);
1531 return getStruct<macho::DataInCodeTableEntry>(this, P);
1532}
1533
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001534macho::Header MachOObjectFile::getHeader() const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001535 return getStruct<macho::Header>(this, getPtr(this, 0));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001536}
1537
Rafael Espindola2173e182013-04-26 20:07:33 +00001538macho::Header64Ext MachOObjectFile::getHeader64Ext() const {
1539 return
1540 getStruct<macho::Header64Ext>(this, getPtr(this, sizeof(macho::Header)));
1541}
1542
1543macho::IndirectSymbolTableEntry MachOObjectFile::getIndirectSymbolTableEntry(
1544 const macho::DysymtabLoadCommand &DLC,
1545 unsigned Index) const {
1546 uint64_t Offset = DLC.IndirectSymbolTableOffset +
1547 Index * sizeof(macho::IndirectSymbolTableEntry);
1548 return getStruct<macho::IndirectSymbolTableEntry>(this, getPtr(this, Offset));
1549}
1550
1551macho::DataInCodeTableEntry
1552MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1553 unsigned Index) const {
1554 uint64_t Offset = DataOffset + Index * sizeof(macho::DataInCodeTableEntry);
1555 return getStruct<macho::DataInCodeTableEntry>(this, getPtr(this, Offset));
1556}
1557
1558macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001559 return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001560}
1561
Rafael Espindola2173e182013-04-26 20:07:33 +00001562macho::DysymtabLoadCommand MachOObjectFile::getDysymtabLoadCommand() const {
1563 return getStruct<macho::DysymtabLoadCommand>(this, DysymtabLoadCmd);
1564}
1565
Kevin Enderby54154f32013-06-06 17:20:50 +00001566macho::LinkeditDataLoadCommand
1567MachOObjectFile::getDataInCodeLoadCommand() const {
1568 if (DataInCodeLoadCmd)
1569 return getStruct<macho::LinkeditDataLoadCommand>(this, DataInCodeLoadCmd);
1570
1571 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
1572 macho::LinkeditDataLoadCommand Cmd;
1573 Cmd.Type = macho::LCT_DataInCode;
1574 Cmd.Size = macho::LinkeditLoadCommandSize;
1575 Cmd.DataOffset = 0;
1576 Cmd.DataSize = 0;
1577 return Cmd;
1578}
1579
Rafael Espindola2173e182013-04-26 20:07:33 +00001580StringRef MachOObjectFile::getStringTableData() const {
1581 macho::SymtabLoadCommand S = getSymtabLoadCommand();
1582 return getData().substr(S.StringTableOffset, S.StringTableSize);
1583}
1584
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001585bool MachOObjectFile::is64Bit() const {
1586 return getType() == getMachOType(false, true) ||
1587 getType() == getMachOType(true, true);
1588}
1589
1590void MachOObjectFile::ReadULEB128s(uint64_t Index,
1591 SmallVectorImpl<uint64_t> &Out) const {
1592 DataExtractor extractor(ObjectFile::getData(), true, 0);
1593
1594 uint32_t offset = Index;
1595 uint64_t data = 0;
1596 while (uint64_t delta = extractor.getULEB128(&offset)) {
1597 data += delta;
1598 Out.push_back(data);
1599 }
1600}
1601
1602ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1603 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1604 error_code ec;
Benjamin Kramer782fdce2013-08-03 22:16:37 +00001605 OwningPtr<ObjectFile> Ret;
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001606 if (Magic == "\xFE\xED\xFA\xCE")
Benjamin Kramer782fdce2013-08-03 22:16:37 +00001607 Ret.reset(new MachOObjectFile(Buffer, false, false, ec));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001608 else if (Magic == "\xCE\xFA\xED\xFE")
Benjamin Kramer782fdce2013-08-03 22:16:37 +00001609 Ret.reset(new MachOObjectFile(Buffer, true, false, ec));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001610 else if (Magic == "\xFE\xED\xFA\xCF")
Benjamin Kramer782fdce2013-08-03 22:16:37 +00001611 Ret.reset(new MachOObjectFile(Buffer, false, true, ec));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001612 else if (Magic == "\xCF\xFA\xED\xFE")
Benjamin Kramer782fdce2013-08-03 22:16:37 +00001613 Ret.reset(new MachOObjectFile(Buffer, true, true, ec));
1614 else {
1615 delete Buffer;
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001616 return NULL;
Benjamin Kramer782fdce2013-08-03 22:16:37 +00001617 }
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001618
1619 if (ec)
1620 return NULL;
Benjamin Kramer782fdce2013-08-03 22:16:37 +00001621 return Ret.take();
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001622}
1623
Owen Andersonf7c93a32011-10-11 17:32:27 +00001624} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001625} // end namespace llvm