blob: 51cd5b9a95d746d9a25e1da66e7226ab111da5f5 [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"
Eric Christopher6256b032011-04-22 03:19:48 +000021#include "llvm/Support/MemoryBuffer.h"
Eric Christopher6256b032011-04-22 03:19:48 +000022#include <cctype>
23#include <cstring>
24#include <limits>
25
26using namespace llvm;
27using namespace object;
28
29namespace llvm {
Owen Andersonf7c93a32011-10-11 17:32:27 +000030namespace object {
Eric Christopher6256b032011-04-22 03:19:48 +000031
Rafael Espindolafd7aa382013-04-18 18:08:55 +000032struct SymbolTableEntryBase {
33 uint32_t StringIndex;
34 uint8_t Type;
35 uint8_t SectionIndex;
36 uint16_t Flags;
37};
38
39struct SectionBase {
40 char Name[16];
41 char SegmentName[16];
42};
43
44template<typename T>
45static void SwapValue(T &Value) {
46 Value = sys::SwapByteOrder(Value);
Benjamin Kramer0fcab072011-09-08 20:52:17 +000047}
48
Rafael Espindolafd7aa382013-04-18 18:08:55 +000049template<typename T>
50static void SwapStruct(T &Value);
51
52template<>
53void SwapStruct(macho::RelocationEntry &H) {
54 SwapValue(H.Word0);
55 SwapValue(H.Word1);
Rafael Espindola3eff3182013-04-07 16:07:35 +000056}
57
Rafael Espindolafd7aa382013-04-18 18:08:55 +000058template<>
59void SwapStruct(macho::LoadCommand &L) {
60 SwapValue(L.Type);
61 SwapValue(L.Size);
62}
Rafael Espindola8764c892013-04-07 20:01:29 +000063
Rafael Espindolafd7aa382013-04-18 18:08:55 +000064template<>
65void SwapStruct(SymbolTableEntryBase &S) {
66 SwapValue(S.StringIndex);
67 SwapValue(S.Flags);
68}
69
70template<>
71void SwapStruct(macho::Section &S) {
72 SwapValue(S.Address);
73 SwapValue(S.Size);
74 SwapValue(S.Offset);
75 SwapValue(S.Align);
76 SwapValue(S.RelocationTableOffset);
77 SwapValue(S.NumRelocationTableEntries);
78 SwapValue(S.Flags);
79 SwapValue(S.Reserved1);
80 SwapValue(S.Reserved2);
81}
82
83template<>
84void SwapStruct(macho::Section64 &S) {
85 SwapValue(S.Address);
86 SwapValue(S.Size);
87 SwapValue(S.Offset);
88 SwapValue(S.Align);
89 SwapValue(S.RelocationTableOffset);
90 SwapValue(S.NumRelocationTableEntries);
91 SwapValue(S.Flags);
92 SwapValue(S.Reserved1);
93 SwapValue(S.Reserved2);
94 SwapValue(S.Reserved3);
95}
96
97template<>
98void SwapStruct(macho::SymbolTableEntry &S) {
99 SwapValue(S.StringIndex);
100 SwapValue(S.Flags);
101 SwapValue(S.Value);
102}
103
104template<>
105void SwapStruct(macho::Symbol64TableEntry &S) {
106 SwapValue(S.StringIndex);
107 SwapValue(S.Flags);
108 SwapValue(S.Value);
109}
110
111template<>
112void SwapStruct(macho::Header &H) {
113 SwapValue(H.Magic);
114 SwapValue(H.CPUType);
115 SwapValue(H.CPUSubtype);
116 SwapValue(H.FileType);
117 SwapValue(H.NumLoadCommands);
118 SwapValue(H.SizeOfLoadCommands);
119 SwapValue(H.Flags);
120}
121
122template<>
123void SwapStruct(macho::SymtabLoadCommand &C) {
124 SwapValue(C.Type);
125 SwapValue(C.Size);
126 SwapValue(C.SymbolTableOffset);
127 SwapValue(C.NumSymbolTableEntries);
128 SwapValue(C.StringTableOffset);
129 SwapValue(C.StringTableSize);
130}
131
132template<>
133void SwapStruct(macho::LinkeditDataLoadCommand &C) {
134 SwapValue(C.Type);
135 SwapValue(C.Size);
136 SwapValue(C.DataOffset);
137 SwapValue(C.DataSize);
138}
139
140template<>
141void SwapStruct(macho::SegmentLoadCommand &C) {
142 SwapValue(C.Type);
143 SwapValue(C.Size);
144 SwapValue(C.VMAddress);
145 SwapValue(C.VMSize);
146 SwapValue(C.FileOffset);
147 SwapValue(C.FileSize);
148 SwapValue(C.MaxVMProtection);
149 SwapValue(C.InitialVMProtection);
150 SwapValue(C.NumSections);
151 SwapValue(C.Flags);
152}
153
154template<>
155void SwapStruct(macho::Segment64LoadCommand &C) {
156 SwapValue(C.Type);
157 SwapValue(C.Size);
158 SwapValue(C.VMAddress);
159 SwapValue(C.VMSize);
160 SwapValue(C.FileOffset);
161 SwapValue(C.FileSize);
162 SwapValue(C.MaxVMProtection);
163 SwapValue(C.InitialVMProtection);
164 SwapValue(C.NumSections);
165 SwapValue(C.Flags);
166}
167
Rafael Espindola143d2232013-04-19 13:45:05 +0000168template<typename T>
169T getStruct(const MachOObjectFile *O, const char *P) {
170 T Cmd;
171 memcpy(&Cmd, P, sizeof(T));
172 if (O->isLittleEndian() != sys::IsLittleEndianHost)
173 SwapStruct(Cmd);
174 return Cmd;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000175}
176
177static macho::SegmentLoadCommand
178getSegmentLoadCommand(const MachOObjectFile *O,
179 const MachOObjectFile::LoadCommandInfo &L) {
Rafael Espindola143d2232013-04-19 13:45:05 +0000180 return getStruct<macho::SegmentLoadCommand>(O, L.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000181}
182
183static macho::Segment64LoadCommand
184getSegment64LoadCommand(const MachOObjectFile *O,
185 const MachOObjectFile::LoadCommandInfo &L) {
Rafael Espindola143d2232013-04-19 13:45:05 +0000186 return getStruct<macho::Segment64LoadCommand>(O, L.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000187}
188
189static uint32_t
190getSegmentLoadCommandNumSections(const MachOObjectFile *O,
191 const MachOObjectFile::LoadCommandInfo &L) {
192 if (O->is64Bit()) {
193 macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
194 return S.NumSections;
Rafael Espindola8764c892013-04-07 20:01:29 +0000195 }
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000196 macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
197 return S.NumSections;
Rafael Espindola3eff3182013-04-07 16:07:35 +0000198}
199
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000200static const SectionBase *
201getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
202 unsigned Sec) {
203 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
204
205 bool Is64 = O->is64Bit();
206 unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
207 sizeof(macho::SegmentLoadCommand);
208 unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
209 sizeof(macho::Section);
210
211 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
212 return reinterpret_cast<const SectionBase*>(SectionAddr);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000213}
214
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000215static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
216 return O->getData().substr(Offset, 1).data();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000217}
218
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000219static SymbolTableEntryBase
220getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
Rafael Espindola802fe932013-04-24 19:47:55 +0000221 const char *P = reinterpret_cast<const char *>(DRI.p);
Rafael Espindola143d2232013-04-19 13:45:05 +0000222 return getStruct<SymbolTableEntryBase>(O, P);
Eric Christopher6256b032011-04-22 03:19:48 +0000223}
224
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000225static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolacef81b32012-12-21 03:47:03 +0000226 if (P[15] == 0)
227 // Null terminated.
228 return P;
229 // Not null terminated, so this is a 16 char string.
230 return StringRef(P, 16);
231}
232
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000233// Helper to advance a section or symbol iterator multiple increments at a time.
234template<class T>
235static error_code advance(T &it, size_t Val) {
236 error_code ec;
237 while (Val--) {
238 it.increment(ec);
239 }
240 return ec;
241}
242
243template<class T>
244static void advanceTo(T &it, size_t Val) {
245 if (error_code ec = advance(it, Val))
246 report_fatal_error(ec.message());
247}
248
249static unsigned getCPUType(const MachOObjectFile *O) {
250 return O->getHeader().CPUType;
251}
252
253static void printRelocationTargetName(const MachOObjectFile *O,
254 const macho::RelocationEntry &RE,
255 raw_string_ostream &fmt) {
256 bool IsScattered = O->isRelocationScattered(RE);
257
258 // Target of a scattered relocation is an address. In the interest of
259 // generating pretty output, scan through the symbol table looking for a
260 // symbol that aligns with that address. If we find one, print it.
261 // Otherwise, we just print the hex address of the target.
262 if (IsScattered) {
263 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
264
265 error_code ec;
266 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
267 SI != SE; SI.increment(ec)) {
268 if (ec) report_fatal_error(ec.message());
269
270 uint64_t Addr;
271 StringRef Name;
272
273 if ((ec = SI->getAddress(Addr)))
274 report_fatal_error(ec.message());
275 if (Addr != Val) continue;
276 if ((ec = SI->getName(Name)))
277 report_fatal_error(ec.message());
278 fmt << Name;
279 return;
280 }
281
282 // If we couldn't find a symbol that this relocation refers to, try
283 // to find a section beginning instead.
284 for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
285 SI != SE; SI.increment(ec)) {
286 if (ec) report_fatal_error(ec.message());
287
288 uint64_t Addr;
289 StringRef Name;
290
291 if ((ec = SI->getAddress(Addr)))
292 report_fatal_error(ec.message());
293 if (Addr != Val) continue;
294 if ((ec = SI->getName(Name)))
295 report_fatal_error(ec.message());
296 fmt << Name;
297 return;
298 }
299
300 fmt << format("0x%x", Val);
301 return;
302 }
303
304 StringRef S;
305 bool isExtern = O->getPlainRelocationExternal(RE);
306 uint64_t Val = O->getAnyRelocationAddress(RE);
307
308 if (isExtern) {
309 symbol_iterator SI = O->begin_symbols();
310 advanceTo(SI, Val);
311 SI->getName(S);
312 } else {
313 section_iterator SI = O->begin_sections();
314 advanceTo(SI, Val);
315 SI->getName(S);
316 }
317
318 fmt << S;
319}
320
321static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
322 return RE.Word0;
323}
324
325static unsigned
326getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
327 return RE.Word0 & 0xffffff;
328}
329
330static bool getPlainRelocationPCRel(const MachOObjectFile *O,
331 const macho::RelocationEntry &RE) {
332 if (O->isLittleEndian())
333 return (RE.Word1 >> 24) & 1;
334 return (RE.Word1 >> 7) & 1;
335}
336
337static bool
338getScatteredRelocationPCRel(const MachOObjectFile *O,
339 const macho::RelocationEntry &RE) {
340 return (RE.Word0 >> 30) & 1;
341}
342
343static unsigned getPlainRelocationLength(const MachOObjectFile *O,
344 const macho::RelocationEntry &RE) {
345 if (O->isLittleEndian())
346 return (RE.Word1 >> 25) & 3;
347 return (RE.Word1 >> 5) & 3;
348}
349
350static unsigned
351getScatteredRelocationLength(const macho::RelocationEntry &RE) {
352 return (RE.Word0 >> 28) & 3;
353}
354
355static unsigned getPlainRelocationType(const MachOObjectFile *O,
356 const macho::RelocationEntry &RE) {
357 if (O->isLittleEndian())
358 return RE.Word1 >> 28;
359 return RE.Word1 & 0xf;
360}
361
362static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
363 return (RE.Word0 >> 24) & 0xf;
364}
365
366static uint32_t getSectionFlags(const MachOObjectFile *O,
367 DataRefImpl Sec) {
368 if (O->is64Bit()) {
369 macho::Section64 Sect = O->getSection64(Sec);
370 return Sect.Flags;
371 }
372 macho::Section Sect = O->getSection(Sec);
373 return Sect.Flags;
374}
375
376MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
377 bool IsLittleEndian, bool Is64bits,
378 error_code &ec)
379 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
380 SymtabLoadCmd(NULL) {
381 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
382 macho::LoadCommandType SegmentLoadType = is64Bit() ?
383 macho::LCT_Segment64 : macho::LCT_Segment;
384
385 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindoladb5f9272013-04-19 11:36:47 +0000386 for (unsigned I = 0; ; ++I) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000387 if (Load.C.Type == macho::LCT_Symtab) {
388 assert(!SymtabLoadCmd && "Multiple symbol tables");
389 SymtabLoadCmd = Load.Ptr;
390 }
391
392 if (Load.C.Type == SegmentLoadType) {
393 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
394 for (unsigned J = 0; J < NumSections; ++J) {
395 const SectionBase *Sec = getSectionBase(this, Load, J);
396 Sections.push_back(reinterpret_cast<const char*>(Sec));
397 }
398 }
Rafael Espindoladb5f9272013-04-19 11:36:47 +0000399
400 if (I == LoadCommandCount - 1)
401 break;
402 else
403 Load = getNextLoadCommandInfo(Load);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000404 }
405}
406
407error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
408 SymbolRef &Res) const {
Rafael Espindola802fe932013-04-24 19:47:55 +0000409 unsigned SymbolTableEntrySize = is64Bit() ?
410 sizeof(macho::Symbol64TableEntry) :
411 sizeof(macho::SymbolTableEntry);
412 Symb.p += SymbolTableEntrySize;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000413 Res = SymbolRef(Symb, this);
414 return object_error::success;
415}
416
417error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
418 StringRef &Res) const {
419 macho::SymtabLoadCommand S = getSymtabLoadCommand();
420 const char *StringTable = getPtr(this, S.StringTableOffset);
421 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
422 const char *Start = &StringTable[Entry.StringIndex];
423 Res = StringRef(Start);
424 return object_error::success;
425}
426
427error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
428 uint64_t &Res) const {
429 if (is64Bit()) {
430 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
431 Res = Entry.Value;
432 } else {
433 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
434 Res = Entry.Value;
435 }
436 return object_error::success;
437}
438
439error_code
440MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
441 uint64_t &Res) const {
442 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
443 getSymbolAddress(Symb, Res);
444 if (Entry.SectionIndex) {
445 uint64_t Delta;
446 DataRefImpl SecRel;
447 SecRel.d.a = Entry.SectionIndex-1;
448 if (is64Bit()) {
449 macho::Section64 Sec = getSection64(SecRel);
450 Delta = Sec.Offset - Sec.Address;
451 } else {
452 macho::Section Sec = getSection(SecRel);
453 Delta = Sec.Offset - Sec.Address;
454 }
455
456 Res += Delta;
457 }
458
459 return object_error::success;
460}
461
462error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
463 uint64_t &Result) const {
464 uint64_t BeginOffset;
465 uint64_t EndOffset = 0;
466 uint8_t SectionIndex;
467
468 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
469 uint64_t Value;
470 getSymbolAddress(DRI, Value);
471
472 BeginOffset = Value;
473
474 SectionIndex = Entry.SectionIndex;
475 if (!SectionIndex) {
476 uint32_t flags = SymbolRef::SF_None;
477 this->getSymbolFlags(DRI, flags);
478 if (flags & SymbolRef::SF_Common)
479 Result = Value;
480 else
481 Result = UnknownAddressOrSize;
482 return object_error::success;
483 }
484 // Unfortunately symbols are unsorted so we need to touch all
485 // symbols from load command
Rafael Espindola802fe932013-04-24 19:47:55 +0000486 error_code ec;
487 for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E;
488 I.increment(ec)) {
489 DataRefImpl DRI = I->getRawDataRefImpl();
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000490 Entry = getSymbolTableEntryBase(this, DRI);
491 getSymbolAddress(DRI, Value);
492 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
493 if (!EndOffset || Value < EndOffset)
494 EndOffset = Value;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000495 }
496 if (!EndOffset) {
497 uint64_t Size;
498 DataRefImpl Sec;
499 Sec.d.a = SectionIndex-1;
500 getSectionSize(Sec, Size);
501 getSectionAddress(Sec, EndOffset);
502 EndOffset += Size;
503 }
504 Result = EndOffset - BeginOffset;
505 return object_error::success;
506}
507
508error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
509 SymbolRef::Type &Res) const {
510 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
511 uint8_t n_type = Entry.Type;
512
513 Res = SymbolRef::ST_Other;
514
515 // If this is a STAB debugging symbol, we can do nothing more.
516 if (n_type & MachO::NlistMaskStab) {
517 Res = SymbolRef::ST_Debug;
518 return object_error::success;
519 }
520
521 switch (n_type & MachO::NlistMaskType) {
522 case MachO::NListTypeUndefined :
523 Res = SymbolRef::ST_Unknown;
524 break;
525 case MachO::NListTypeSection :
526 Res = SymbolRef::ST_Function;
527 break;
528 }
529 return object_error::success;
530}
531
532error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
533 char &Res) const {
534 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
535 uint8_t Type = Entry.Type;
536 uint16_t Flags = Entry.Flags;
537
538 char Char;
539 switch (Type & macho::STF_TypeMask) {
540 case macho::STT_Undefined:
541 Char = 'u';
542 break;
543 case macho::STT_Absolute:
544 case macho::STT_Section:
545 Char = 's';
546 break;
547 default:
548 Char = '?';
549 break;
550 }
551
552 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
553 Char = toupper(static_cast<unsigned char>(Char));
554 Res = Char;
555 return object_error::success;
556}
557
558error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
559 uint32_t &Result) const {
560 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
561
562 uint8_t MachOType = Entry.Type;
563 uint16_t MachOFlags = Entry.Flags;
564
565 // TODO: Correctly set SF_ThreadLocal
566 Result = SymbolRef::SF_None;
567
568 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
569 Result |= SymbolRef::SF_Undefined;
570
571 if (MachOFlags & macho::STF_StabsEntryMask)
572 Result |= SymbolRef::SF_FormatSpecific;
573
574 if (MachOType & MachO::NlistMaskExternal) {
575 Result |= SymbolRef::SF_Global;
576 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
577 Result |= SymbolRef::SF_Common;
578 }
579
580 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
581 Result |= SymbolRef::SF_Weak;
582
583 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
584 Result |= SymbolRef::SF_Absolute;
585
586 return object_error::success;
587}
588
589error_code
590MachOObjectFile::getSymbolSection(DataRefImpl Symb,
591 section_iterator &Res) const {
592 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
593 uint8_t index = Entry.SectionIndex;
594
595 if (index == 0) {
596 Res = end_sections();
597 } else {
598 DataRefImpl DRI;
599 DRI.d.a = index - 1;
600 Res = section_iterator(SectionRef(DRI, this));
601 }
602
603 return object_error::success;
604}
605
606error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000607 uint64_t &Val) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000608 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
609}
610
611error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
612 SectionRef &Res) const {
613 Sec.d.a++;
614 Res = SectionRef(Sec, this);
615 return object_error::success;
616}
617
618error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000619MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000620 ArrayRef<char> Raw = getSectionRawName(Sec);
621 Result = parseSegmentOrSectionName(Raw.data());
622 return object_error::success;
623}
624
625error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000626MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000627 if (is64Bit()) {
628 macho::Section64 Sect = getSection64(Sec);
629 Res = Sect.Address;
630 } else {
631 macho::Section Sect = getSection(Sec);
632 Res = Sect.Address;
633 }
634 return object_error::success;
635}
636
637error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000638MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000639 if (is64Bit()) {
640 macho::Section64 Sect = getSection64(Sec);
641 Res = Sect.Size;
642 } else {
643 macho::Section Sect = getSection(Sec);
644 Res = Sect.Size;
645 }
646
647 return object_error::success;
648}
649
650error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000651MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000652 uint32_t Offset;
653 uint64_t Size;
654
655 if (is64Bit()) {
656 macho::Section64 Sect = getSection64(Sec);
657 Offset = Sect.Offset;
658 Size = Sect.Size;
659 } else {
660 macho::Section Sect =getSection(Sec);
661 Offset = Sect.Offset;
662 Size = Sect.Size;
663 }
664
665 Res = this->getData().substr(Offset, Size);
666 return object_error::success;
667}
668
669error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000670MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000671 uint32_t Align;
672 if (is64Bit()) {
673 macho::Section64 Sect = getSection64(Sec);
674 Align = Sect.Align;
675 } else {
676 macho::Section Sect = getSection(Sec);
677 Align = Sect.Align;
678 }
679
680 Res = uint64_t(1) << Align;
681 return object_error::success;
682}
683
684error_code
685MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
686 uint32_t Flags = getSectionFlags(this, Sec);
687 Res = Flags & macho::SF_PureInstructions;
688 return object_error::success;
689}
690
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000691error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const {
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000692 // FIXME: Unimplemented.
693 Result = false;
694 return object_error::success;
695}
696
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000697error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000698 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000699 Result = false;
700 return object_error::success;
701}
702
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000703error_code
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000704MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000705 bool &Result) const {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000706 // FIXME: Unimplemented.
707 Result = true;
Preston Gurdc68dda82012-04-12 20:13:57 +0000708 return object_error::success;
709}
710
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000711error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000712 bool &Result) const {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000713 // FIXME: Unimplemented.
714 Result = false;
715 return object_error::success;
716}
717
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000718error_code
719MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
720 uint32_t Flags = getSectionFlags(this, Sec);
721 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
722 Res = SectionType == MachO::SectionTypeZeroFill ||
723 SectionType == MachO::SectionTypeZeroFillLarge;
724 return object_error::success;
725}
726
727error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000728 bool &Result) const {
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000729 // Consider using the code from isSectionText to look for __const sections.
730 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
731 // to use section attributes to distinguish code from data.
732
733 // FIXME: Unimplemented.
734 Result = false;
735 return object_error::success;
736}
737
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000738error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000739MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000740 bool &Result) const {
741 SymbolRef::Type ST;
742 this->getSymbolType(Symb, ST);
743 if (ST == SymbolRef::ST_Unknown) {
744 Result = false;
745 return object_error::success;
746 }
747
748 uint64_t SectBegin, SectEnd;
749 getSectionAddress(Sec, SectBegin);
750 getSectionSize(Sec, SectEnd);
751 SectEnd += SectBegin;
752
753 uint64_t SymAddr;
754 getSymbolAddress(Symb, SymAddr);
755 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
756
757 return object_error::success;
758}
759
760relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
Rafael Espindola51cc8282013-04-24 16:10:49 +0000761 DataRefImpl ret;
762 ret.d.b = Sec.d.a;
763 return relocation_iterator(RelocationRef(ret, this));
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000764}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000765
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000766relocation_iterator
767MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
Rafael Espindola51cc8282013-04-24 16:10:49 +0000768 uint32_t LastReloc;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000769 if (is64Bit()) {
770 macho::Section64 Sect = getSection64(Sec);
Rafael Espindola51cc8282013-04-24 16:10:49 +0000771 LastReloc = Sect.NumRelocationTableEntries;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000772 } else {
773 macho::Section Sect = getSection(Sec);
Rafael Espindola51cc8282013-04-24 16:10:49 +0000774 LastReloc = Sect.NumRelocationTableEntries;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000775 }
Eric Christopher6256b032011-04-22 03:19:48 +0000776
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000777 DataRefImpl Ret;
Rafael Espindola51cc8282013-04-24 16:10:49 +0000778 Ret.d.a = LastReloc;
779 Ret.d.b = Sec.d.a;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000780 return relocation_iterator(RelocationRef(Ret, this));
781}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000782
Rafael Espindola51cc8282013-04-24 16:10:49 +0000783 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
784 RelocationRef &Res) const {
785 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000786 Res = RelocationRef(Rel, this);
787 return object_error::success;
788}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000789
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000790error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000791MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000792 uint64_t SectAddress;
793 DataRefImpl Sec;
794 Sec.d.a = Rel.d.b;
795 if (is64Bit()) {
796 macho::Section64 Sect = getSection64(Sec);
797 SectAddress = Sect.Address;
798 } else {
799 macho::Section Sect = getSection(Sec);
800 SectAddress = Sect.Address;
801 }
802
803 macho::RelocationEntry RE = getRelocation(Rel);
804 uint64_t RelAddr = getAnyRelocationAddress(RE);
805 Res = SectAddress + RelAddr;
806 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000807}
808
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000809error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000810 uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000811 macho::RelocationEntry RE = getRelocation(Rel);
812 Res = getAnyRelocationAddress(RE);
813 return object_error::success;
David Meyer5c2b4ea2012-03-01 01:36:50 +0000814}
815
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000816error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000817MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000818 macho::RelocationEntry RE = getRelocation(Rel);
819 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
820 bool isExtern = getPlainRelocationExternal(RE);
Rafael Espindola802fe932013-04-24 19:47:55 +0000821 if (!isExtern) {
822 Res = *end_symbols();
823 return object_error::success;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000824 }
Rafael Espindola802fe932013-04-24 19:47:55 +0000825
826 macho::SymtabLoadCommand S = getSymtabLoadCommand();
827 unsigned SymbolTableEntrySize = is64Bit() ?
828 sizeof(macho::Symbol64TableEntry) :
829 sizeof(macho::SymbolTableEntry);
830 uint64_t Offset = S.SymbolTableOffset + SymbolIdx * SymbolTableEntrySize;
831 DataRefImpl Sym;
832 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000833 Res = SymbolRef(Sym, this);
834 return object_error::success;
835}
836
837error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000838 uint64_t &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000839 macho::RelocationEntry RE = getRelocation(Rel);
840 Res = getAnyRelocationType(RE);
841 return object_error::success;
842}
843
844error_code
845MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
846 SmallVectorImpl<char> &Result) const {
847 StringRef res;
848 uint64_t RType;
849 getRelocationType(Rel, RType);
850
851 unsigned Arch = this->getArch();
852
853 switch (Arch) {
854 case Triple::x86: {
855 static const char *const Table[] = {
856 "GENERIC_RELOC_VANILLA",
857 "GENERIC_RELOC_PAIR",
858 "GENERIC_RELOC_SECTDIFF",
859 "GENERIC_RELOC_PB_LA_PTR",
860 "GENERIC_RELOC_LOCAL_SECTDIFF",
861 "GENERIC_RELOC_TLV" };
862
863 if (RType > 6)
864 res = "Unknown";
865 else
866 res = Table[RType];
867 break;
868 }
869 case Triple::x86_64: {
870 static const char *const Table[] = {
871 "X86_64_RELOC_UNSIGNED",
872 "X86_64_RELOC_SIGNED",
873 "X86_64_RELOC_BRANCH",
874 "X86_64_RELOC_GOT_LOAD",
875 "X86_64_RELOC_GOT",
876 "X86_64_RELOC_SUBTRACTOR",
877 "X86_64_RELOC_SIGNED_1",
878 "X86_64_RELOC_SIGNED_2",
879 "X86_64_RELOC_SIGNED_4",
880 "X86_64_RELOC_TLV" };
881
882 if (RType > 9)
883 res = "Unknown";
884 else
885 res = Table[RType];
886 break;
887 }
888 case Triple::arm: {
889 static const char *const Table[] = {
890 "ARM_RELOC_VANILLA",
891 "ARM_RELOC_PAIR",
892 "ARM_RELOC_SECTDIFF",
893 "ARM_RELOC_LOCAL_SECTDIFF",
894 "ARM_RELOC_PB_LA_PTR",
895 "ARM_RELOC_BR24",
896 "ARM_THUMB_RELOC_BR22",
897 "ARM_THUMB_32BIT_BRANCH",
898 "ARM_RELOC_HALF",
899 "ARM_RELOC_HALF_SECTDIFF" };
900
901 if (RType > 9)
902 res = "Unknown";
903 else
904 res = Table[RType];
905 break;
906 }
907 case Triple::ppc: {
908 static const char *const Table[] = {
909 "PPC_RELOC_VANILLA",
910 "PPC_RELOC_PAIR",
911 "PPC_RELOC_BR14",
912 "PPC_RELOC_BR24",
913 "PPC_RELOC_HI16",
914 "PPC_RELOC_LO16",
915 "PPC_RELOC_HA16",
916 "PPC_RELOC_LO14",
917 "PPC_RELOC_SECTDIFF",
918 "PPC_RELOC_PB_LA_PTR",
919 "PPC_RELOC_HI16_SECTDIFF",
920 "PPC_RELOC_LO16_SECTDIFF",
921 "PPC_RELOC_HA16_SECTDIFF",
922 "PPC_RELOC_JBSR",
923 "PPC_RELOC_LO14_SECTDIFF",
924 "PPC_RELOC_LOCAL_SECTDIFF" };
925
926 res = Table[RType];
927 break;
928 }
929 case Triple::UnknownArch:
930 res = "Unknown";
931 break;
932 }
933 Result.append(res.begin(), res.end());
934 return object_error::success;
935}
936
937error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
938 int64_t &Res) const {
Rafael Espindola8bf80062013-04-11 02:21:31 +0000939 Res = 0;
940 return object_error::success;
941}
942
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000943error_code
944MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +0000945 SmallVectorImpl<char> &Result) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000946 macho::RelocationEntry RE = getRelocation(Rel);
David Meyer5c2b4ea2012-03-01 01:36:50 +0000947
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000948 unsigned Arch = this->getArch();
Eric Christopher6256b032011-04-22 03:19:48 +0000949
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000950 std::string fmtbuf;
951 raw_string_ostream fmt(fmtbuf);
952 unsigned Type = this->getAnyRelocationType(RE);
953 bool IsPCRel = this->getAnyRelocationPCRel(RE);
954
955 // Determine any addends that should be displayed with the relocation.
956 // These require decoding the relocation type, which is triple-specific.
957
958 // X86_64 has entirely custom relocation types.
959 if (Arch == Triple::x86_64) {
960 bool isPCRel = getAnyRelocationPCRel(RE);
961
962 switch (Type) {
963 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
964 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
965 printRelocationTargetName(this, RE, fmt);
966 fmt << "@GOT";
967 if (isPCRel) fmt << "PCREL";
968 break;
969 }
970 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
971 DataRefImpl RelNext = Rel;
972 RelNext.d.a++;
973 macho::RelocationEntry RENext = getRelocation(RelNext);
974
975 // X86_64_SUBTRACTOR must be followed by a relocation of type
976 // X86_64_RELOC_UNSIGNED.
977 // NOTE: Scattered relocations don't exist on x86_64.
978 unsigned RType = getAnyRelocationType(RENext);
979 if (RType != 0)
980 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
981 "X86_64_RELOC_SUBTRACTOR.");
982
983 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
984 // X86_64_SUBTRACTOR contains to the subtrahend.
985 printRelocationTargetName(this, RENext, fmt);
986 fmt << "-";
987 printRelocationTargetName(this, RE, fmt);
988 break;
989 }
990 case macho::RIT_X86_64_TLV:
991 printRelocationTargetName(this, RE, fmt);
992 fmt << "@TLV";
993 if (isPCRel) fmt << "P";
994 break;
995 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
996 printRelocationTargetName(this, RE, fmt);
997 fmt << "-1";
998 break;
999 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1000 printRelocationTargetName(this, RE, fmt);
1001 fmt << "-2";
1002 break;
1003 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1004 printRelocationTargetName(this, RE, fmt);
1005 fmt << "-4";
1006 break;
1007 default:
1008 printRelocationTargetName(this, RE, fmt);
1009 break;
1010 }
1011 // X86 and ARM share some relocation types in common.
1012 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1013 // Generic relocation types...
1014 switch (Type) {
1015 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1016 return object_error::success;
1017 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1018 DataRefImpl RelNext = Rel;
1019 RelNext.d.a++;
1020 macho::RelocationEntry RENext = getRelocation(RelNext);
1021
1022 // X86 sect diff's must be followed by a relocation of type
1023 // GENERIC_RELOC_PAIR.
1024 unsigned RType = getAnyRelocationType(RENext);
1025
1026 if (RType != 1)
1027 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1028 "GENERIC_RELOC_SECTDIFF.");
1029
1030 printRelocationTargetName(this, RE, fmt);
1031 fmt << "-";
1032 printRelocationTargetName(this, RENext, fmt);
1033 break;
1034 }
1035 }
1036
1037 if (Arch == Triple::x86) {
1038 // All X86 relocations that need special printing were already
1039 // handled in the generic code.
1040 switch (Type) {
1041 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1042 DataRefImpl RelNext = Rel;
1043 RelNext.d.a++;
1044 macho::RelocationEntry RENext = getRelocation(RelNext);
1045
1046 // X86 sect diff's must be followed by a relocation of type
1047 // GENERIC_RELOC_PAIR.
1048 unsigned RType = getAnyRelocationType(RENext);
1049 if (RType != 1)
1050 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1051 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1052
1053 printRelocationTargetName(this, RE, fmt);
1054 fmt << "-";
1055 printRelocationTargetName(this, RENext, fmt);
1056 break;
1057 }
1058 case macho::RIT_Generic_TLV: {
1059 printRelocationTargetName(this, RE, fmt);
1060 fmt << "@TLV";
1061 if (IsPCRel) fmt << "P";
1062 break;
1063 }
1064 default:
1065 printRelocationTargetName(this, RE, fmt);
1066 }
1067 } else { // ARM-specific relocations
1068 switch (Type) {
1069 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1070 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1071 // Half relocations steal a bit from the length field to encode
1072 // whether this is an upper16 or a lower16 relocation.
1073 bool isUpper = getAnyRelocationLength(RE) >> 1;
1074
1075 if (isUpper)
1076 fmt << ":upper16:(";
1077 else
1078 fmt << ":lower16:(";
1079 printRelocationTargetName(this, RE, fmt);
1080
1081 DataRefImpl RelNext = Rel;
1082 RelNext.d.a++;
1083 macho::RelocationEntry RENext = getRelocation(RelNext);
1084
1085 // ARM half relocs must be followed by a relocation of type
1086 // ARM_RELOC_PAIR.
1087 unsigned RType = getAnyRelocationType(RENext);
1088 if (RType != 1)
1089 report_fatal_error("Expected ARM_RELOC_PAIR after "
1090 "GENERIC_RELOC_HALF");
1091
1092 // NOTE: The half of the target virtual address is stashed in the
1093 // address field of the secondary relocation, but we can't reverse
1094 // engineer the constant offset from it without decoding the movw/movt
1095 // instruction to find the other half in its immediate field.
1096
1097 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1098 // symbol/section pointer of the follow-on relocation.
1099 if (Type == macho::RIT_ARM_HalfDifference) {
1100 fmt << "-";
1101 printRelocationTargetName(this, RENext, fmt);
1102 }
1103
1104 fmt << ")";
1105 break;
1106 }
1107 default: {
1108 printRelocationTargetName(this, RE, fmt);
1109 }
1110 }
1111 }
1112 } else
1113 printRelocationTargetName(this, RE, fmt);
1114
1115 fmt.flush();
1116 Result.append(fmtbuf.begin(), fmtbuf.end());
1117 return object_error::success;
1118}
1119
1120error_code
Rafael Espindolaf69a81f2013-04-24 15:14:22 +00001121MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001122 unsigned Arch = getArch();
1123 uint64_t Type;
1124 getRelocationType(Rel, Type);
1125
1126 Result = false;
1127
1128 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1129 // is always hidden.
1130 if (Arch == Triple::x86 || Arch == Triple::arm) {
1131 if (Type == macho::RIT_Pair) Result = true;
1132 } else if (Arch == Triple::x86_64) {
1133 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1134 // an X864_64_RELOC_SUBTRACTOR.
1135 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1136 DataRefImpl RelPrev = Rel;
1137 RelPrev.d.a--;
1138 uint64_t PrevType;
1139 getRelocationType(RelPrev, PrevType);
1140 if (PrevType == macho::RIT_X86_64_Subtractor)
1141 Result = true;
1142 }
1143 }
1144
1145 return object_error::success;
1146}
1147
1148error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +00001149 LibraryRef &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001150 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1151}
1152
1153error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
Rafael Espindolaf69a81f2013-04-24 15:14:22 +00001154 StringRef &Res) const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001155 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1156}
1157
1158symbol_iterator MachOObjectFile::begin_symbols() const {
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001159 DataRefImpl DRI;
Rafael Espindola802fe932013-04-24 19:47:55 +00001160 if (!SymtabLoadCmd)
1161 return symbol_iterator(SymbolRef(DRI, this));
1162
1163 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1164 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.SymbolTableOffset));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001165 return symbol_iterator(SymbolRef(DRI, this));
1166}
1167
1168symbol_iterator MachOObjectFile::end_symbols() const {
1169 DataRefImpl DRI;
Rafael Espindola802fe932013-04-24 19:47:55 +00001170 if (!SymtabLoadCmd)
1171 return symbol_iterator(SymbolRef(DRI, this));
1172
1173 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1174 unsigned SymbolTableEntrySize = is64Bit() ?
1175 sizeof(macho::Symbol64TableEntry) :
1176 sizeof(macho::SymbolTableEntry);
1177 unsigned Offset = Symtab.SymbolTableOffset +
1178 Symtab.NumSymbolTableEntries * SymbolTableEntrySize;
1179 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001180 return symbol_iterator(SymbolRef(DRI, this));
1181}
1182
1183symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1184 // TODO: implement
1185 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1186}
1187
1188symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1189 // TODO: implement
1190 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1191}
1192
1193section_iterator MachOObjectFile::begin_sections() const {
1194 DataRefImpl DRI;
1195 return section_iterator(SectionRef(DRI, this));
1196}
1197
1198section_iterator MachOObjectFile::end_sections() const {
1199 DataRefImpl DRI;
1200 DRI.d.a = Sections.size();
1201 return section_iterator(SectionRef(DRI, this));
1202}
1203
1204library_iterator MachOObjectFile::begin_libraries_needed() const {
1205 // TODO: implement
1206 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1207}
1208
1209library_iterator MachOObjectFile::end_libraries_needed() const {
1210 // TODO: implement
1211 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1212}
1213
1214uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001215 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001216}
1217
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001218StringRef MachOObjectFile::getFileFormatName() const {
1219 unsigned CPUType = getCPUType(this);
1220 if (!is64Bit()) {
1221 switch (CPUType) {
1222 case llvm::MachO::CPUTypeI386:
1223 return "Mach-O 32-bit i386";
1224 case llvm::MachO::CPUTypeARM:
1225 return "Mach-O arm";
1226 case llvm::MachO::CPUTypePowerPC:
1227 return "Mach-O 32-bit ppc";
1228 default:
1229 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1230 "64-bit object file when we're not 64-bit?");
1231 return "Mach-O 32-bit unknown";
1232 }
1233 }
1234
1235 // Make sure the cpu type has the correct mask.
1236 assert((CPUType & llvm::MachO::CPUArchABI64)
1237 == llvm::MachO::CPUArchABI64 &&
1238 "32-bit object file when we're 64-bit?");
1239
1240 switch (CPUType) {
1241 case llvm::MachO::CPUTypeX86_64:
1242 return "Mach-O 64-bit x86-64";
1243 case llvm::MachO::CPUTypePowerPC64:
1244 return "Mach-O 64-bit ppc64";
1245 default:
1246 return "Mach-O 64-bit unknown";
1247 }
1248}
1249
1250unsigned MachOObjectFile::getArch() const {
1251 switch (getCPUType(this)) {
1252 case llvm::MachO::CPUTypeI386:
1253 return Triple::x86;
1254 case llvm::MachO::CPUTypeX86_64:
1255 return Triple::x86_64;
1256 case llvm::MachO::CPUTypeARM:
1257 return Triple::arm;
1258 case llvm::MachO::CPUTypePowerPC:
1259 return Triple::ppc;
1260 case llvm::MachO::CPUTypePowerPC64:
1261 return Triple::ppc64;
1262 default:
1263 return Triple::UnknownArch;
1264 }
1265}
1266
1267StringRef MachOObjectFile::getLoadName() const {
1268 // TODO: Implement
1269 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1270}
1271
1272StringRef
1273MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1274 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1275 return parseSegmentOrSectionName(Raw.data());
1276}
1277
1278ArrayRef<char>
1279MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1280 const SectionBase *Base =
1281 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1282 return ArrayRef<char>(Base->Name);
1283}
1284
1285ArrayRef<char>
1286MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1287 const SectionBase *Base =
1288 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1289 return ArrayRef<char>(Base->SegmentName);
1290}
1291
1292bool
1293MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1294 const {
1295 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
1296 return false;
1297 return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1298}
1299
1300unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
1301 if (isLittleEndian())
1302 return RE.Word1 & 0xffffff;
1303 return RE.Word1 >> 8;
1304}
1305
1306bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
1307 if (isLittleEndian())
1308 return (RE.Word1 >> 27) & 1;
1309 return (RE.Word1 >> 4) & 1;
1310}
1311
1312bool
1313MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
1314 return RE.Word0 >> 31;
1315}
1316
1317uint32_t
1318MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
1319 return RE.Word1;
1320}
1321
1322unsigned
1323MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
1324 if (isRelocationScattered(RE))
1325 return getScatteredRelocationAddress(RE);
1326 return getPlainRelocationAddress(RE);
1327}
1328
1329unsigned
1330MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1331 if (isRelocationScattered(RE))
1332 return getScatteredRelocationPCRel(this, RE);
1333 return getPlainRelocationPCRel(this, RE);
1334}
1335
1336unsigned
1337MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
1338 if (isRelocationScattered(RE))
1339 return getScatteredRelocationLength(RE);
1340 return getPlainRelocationLength(this, RE);
1341}
1342
1343unsigned
1344MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1345 if (isRelocationScattered(RE))
1346 return getScatteredRelocationType(RE);
1347 return getPlainRelocationType(this, RE);
1348}
1349
1350MachOObjectFile::LoadCommandInfo
1351MachOObjectFile::getFirstLoadCommandInfo() const {
1352 MachOObjectFile::LoadCommandInfo Load;
1353
1354 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1355 Load.Ptr = getPtr(this, HeaderSize);
Rafael Espindola143d2232013-04-19 13:45:05 +00001356 Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001357 return Load;
1358}
1359
1360MachOObjectFile::LoadCommandInfo
1361MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1362 MachOObjectFile::LoadCommandInfo Next;
1363 Next.Ptr = L.Ptr + L.C.Size;
Rafael Espindola143d2232013-04-19 13:45:05 +00001364 Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001365 return Next;
1366}
1367
1368macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001369 return getStruct<macho::Section>(this, Sections[DRI.d.a]);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001370}
1371
1372macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001373 return getStruct<macho::Section64>(this, Sections[DRI.d.a]);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001374}
1375
1376macho::SymbolTableEntry
1377MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
Rafael Espindola802fe932013-04-24 19:47:55 +00001378 const char *P = reinterpret_cast<const char *>(DRI.p);
Rafael Espindola143d2232013-04-19 13:45:05 +00001379 return getStruct<macho::SymbolTableEntry>(this, P);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001380}
1381
1382macho::Symbol64TableEntry
1383MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
Rafael Espindola802fe932013-04-24 19:47:55 +00001384 const char *P = reinterpret_cast<const char *>(DRI.p);
Rafael Espindola143d2232013-04-19 13:45:05 +00001385 return getStruct<macho::Symbol64TableEntry>(this, P);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001386}
1387
1388macho::LinkeditDataLoadCommand
1389MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001390 return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001391}
1392
1393macho::RelocationEntry
1394MachOObjectFile::getRelocation(DataRefImpl Rel) const {
Rafael Espindola51cc8282013-04-24 16:10:49 +00001395 uint32_t RelOffset;
1396 DataRefImpl Sec;
1397 Sec.d.a = Rel.d.b;
1398 if (is64Bit()) {
1399 macho::Section64 Sect = getSection64(Sec);
1400 RelOffset = Sect.RelocationTableOffset;
1401 } else {
1402 macho::Section Sect = getSection(Sec);
1403 RelOffset = Sect.RelocationTableOffset;
1404 }
1405
1406 uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry);
1407 return getStruct<macho::RelocationEntry>(this, getPtr(this, Offset));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001408}
1409
1410macho::Header MachOObjectFile::getHeader() const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001411 return getStruct<macho::Header>(this, getPtr(this, 0));
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001412}
1413
1414macho::SymtabLoadCommand
1415MachOObjectFile::getSymtabLoadCommand() const {
Rafael Espindola143d2232013-04-19 13:45:05 +00001416 return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd);
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001417}
1418
1419bool MachOObjectFile::is64Bit() const {
1420 return getType() == getMachOType(false, true) ||
1421 getType() == getMachOType(true, true);
1422}
1423
1424void MachOObjectFile::ReadULEB128s(uint64_t Index,
1425 SmallVectorImpl<uint64_t> &Out) const {
1426 DataExtractor extractor(ObjectFile::getData(), true, 0);
1427
1428 uint32_t offset = Index;
1429 uint64_t data = 0;
1430 while (uint64_t delta = extractor.getULEB128(&offset)) {
1431 data += delta;
1432 Out.push_back(data);
1433 }
1434}
1435
1436ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1437 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1438 error_code ec;
1439 ObjectFile *Ret;
1440 if (Magic == "\xFE\xED\xFA\xCE")
1441 Ret = new MachOObjectFile(Buffer, false, false, ec);
1442 else if (Magic == "\xCE\xFA\xED\xFE")
1443 Ret = new MachOObjectFile(Buffer, true, false, ec);
1444 else if (Magic == "\xFE\xED\xFA\xCF")
1445 Ret = new MachOObjectFile(Buffer, false, true, ec);
1446 else if (Magic == "\xCF\xFA\xED\xFE")
1447 Ret = new MachOObjectFile(Buffer, true, true, ec);
1448 else
1449 return NULL;
1450
1451 if (ec)
1452 return NULL;
1453 return Ret;
1454}
1455
Owen Andersonf7c93a32011-10-11 17:32:27 +00001456} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001457} // end namespace llvm