blob: d26eb2ce6112a6b7cfa61facceb988c8c23cd72a [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
168static bool isSwappedEndian(const MachOObjectFile *O) {
169 return O->isLittleEndian() != sys::IsLittleEndianHost;
170}
171
172static macho::SegmentLoadCommand
173getSegmentLoadCommand(const MachOObjectFile *O,
174 const MachOObjectFile::LoadCommandInfo &L) {
175 macho::SegmentLoadCommand Cmd;
176 memcpy(&Cmd, L.Ptr, sizeof(macho::SegmentLoadCommand));
177 if (isSwappedEndian(O))
178 SwapStruct(Cmd);
179 return Cmd;
180}
181
182static macho::Segment64LoadCommand
183getSegment64LoadCommand(const MachOObjectFile *O,
184 const MachOObjectFile::LoadCommandInfo &L) {
185 macho::Segment64LoadCommand Cmd;
186 memcpy(&Cmd, L.Ptr, sizeof(macho::Segment64LoadCommand));
187 if (isSwappedEndian(O))
188 SwapStruct(Cmd);
189 return Cmd;
190}
191
192static uint32_t
193getSegmentLoadCommandNumSections(const MachOObjectFile *O,
194 const MachOObjectFile::LoadCommandInfo &L) {
195 if (O->is64Bit()) {
196 macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
197 return S.NumSections;
Rafael Espindola8764c892013-04-07 20:01:29 +0000198 }
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000199 macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
200 return S.NumSections;
Rafael Espindola3eff3182013-04-07 16:07:35 +0000201}
202
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000203static const SectionBase *
204getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
205 unsigned Sec) {
206 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
207
208 bool Is64 = O->is64Bit();
209 unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
210 sizeof(macho::SegmentLoadCommand);
211 unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
212 sizeof(macho::Section);
213
214 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
215 return reinterpret_cast<const SectionBase*>(SectionAddr);
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000216}
217
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000218static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
219 return O->getData().substr(Offset, 1).data();
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000220}
221
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000222static const char *getSymbolTableEntryPtr(const MachOObjectFile *O,
223 DataRefImpl DRI) {
224 macho::SymtabLoadCommand S = O->getSymtabLoadCommand();
Rafael Espindolada2a2372013-04-13 01:45:40 +0000225
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000226 unsigned Index = DRI.d.b;
227
228 unsigned SymbolTableEntrySize = O->is64Bit() ?
229 sizeof(macho::Symbol64TableEntry) :
230 sizeof(macho::SymbolTableEntry);
231
232 uint64_t Offset = S.SymbolTableOffset + Index * SymbolTableEntrySize;
233 return getPtr(O, Offset);
234}
235
236static SymbolTableEntryBase
237getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
238 const char *P = getSymbolTableEntryPtr(O, DRI);
239 SymbolTableEntryBase Ret;
240 memcpy(&Ret, P, sizeof(SymbolTableEntryBase));
241 if (isSwappedEndian(O))
242 SwapStruct(Ret);
243
Rafael Espindola6f1f3392013-04-07 16:58:48 +0000244 return Ret;
Eric Christopher6256b032011-04-22 03:19:48 +0000245}
246
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000247static StringRef parseSegmentOrSectionName(const char *P) {
Rafael Espindolacef81b32012-12-21 03:47:03 +0000248 if (P[15] == 0)
249 // Null terminated.
250 return P;
251 // Not null terminated, so this is a 16 char string.
252 return StringRef(P, 16);
253}
254
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000255// Helper to advance a section or symbol iterator multiple increments at a time.
256template<class T>
257static error_code advance(T &it, size_t Val) {
258 error_code ec;
259 while (Val--) {
260 it.increment(ec);
261 }
262 return ec;
263}
264
265template<class T>
266static void advanceTo(T &it, size_t Val) {
267 if (error_code ec = advance(it, Val))
268 report_fatal_error(ec.message());
269}
270
271static unsigned getCPUType(const MachOObjectFile *O) {
272 return O->getHeader().CPUType;
273}
274
275static void printRelocationTargetName(const MachOObjectFile *O,
276 const macho::RelocationEntry &RE,
277 raw_string_ostream &fmt) {
278 bool IsScattered = O->isRelocationScattered(RE);
279
280 // Target of a scattered relocation is an address. In the interest of
281 // generating pretty output, scan through the symbol table looking for a
282 // symbol that aligns with that address. If we find one, print it.
283 // Otherwise, we just print the hex address of the target.
284 if (IsScattered) {
285 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
286
287 error_code ec;
288 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
289 SI != SE; SI.increment(ec)) {
290 if (ec) report_fatal_error(ec.message());
291
292 uint64_t Addr;
293 StringRef Name;
294
295 if ((ec = SI->getAddress(Addr)))
296 report_fatal_error(ec.message());
297 if (Addr != Val) continue;
298 if ((ec = SI->getName(Name)))
299 report_fatal_error(ec.message());
300 fmt << Name;
301 return;
302 }
303
304 // If we couldn't find a symbol that this relocation refers to, try
305 // to find a section beginning instead.
306 for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
307 SI != SE; SI.increment(ec)) {
308 if (ec) report_fatal_error(ec.message());
309
310 uint64_t Addr;
311 StringRef Name;
312
313 if ((ec = SI->getAddress(Addr)))
314 report_fatal_error(ec.message());
315 if (Addr != Val) continue;
316 if ((ec = SI->getName(Name)))
317 report_fatal_error(ec.message());
318 fmt << Name;
319 return;
320 }
321
322 fmt << format("0x%x", Val);
323 return;
324 }
325
326 StringRef S;
327 bool isExtern = O->getPlainRelocationExternal(RE);
328 uint64_t Val = O->getAnyRelocationAddress(RE);
329
330 if (isExtern) {
331 symbol_iterator SI = O->begin_symbols();
332 advanceTo(SI, Val);
333 SI->getName(S);
334 } else {
335 section_iterator SI = O->begin_sections();
336 advanceTo(SI, Val);
337 SI->getName(S);
338 }
339
340 fmt << S;
341}
342
343static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
344 return RE.Word0;
345}
346
347static unsigned
348getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
349 return RE.Word0 & 0xffffff;
350}
351
352static bool getPlainRelocationPCRel(const MachOObjectFile *O,
353 const macho::RelocationEntry &RE) {
354 if (O->isLittleEndian())
355 return (RE.Word1 >> 24) & 1;
356 return (RE.Word1 >> 7) & 1;
357}
358
359static bool
360getScatteredRelocationPCRel(const MachOObjectFile *O,
361 const macho::RelocationEntry &RE) {
362 return (RE.Word0 >> 30) & 1;
363}
364
365static unsigned getPlainRelocationLength(const MachOObjectFile *O,
366 const macho::RelocationEntry &RE) {
367 if (O->isLittleEndian())
368 return (RE.Word1 >> 25) & 3;
369 return (RE.Word1 >> 5) & 3;
370}
371
372static unsigned
373getScatteredRelocationLength(const macho::RelocationEntry &RE) {
374 return (RE.Word0 >> 28) & 3;
375}
376
377static unsigned getPlainRelocationType(const MachOObjectFile *O,
378 const macho::RelocationEntry &RE) {
379 if (O->isLittleEndian())
380 return RE.Word1 >> 28;
381 return RE.Word1 & 0xf;
382}
383
384static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
385 return (RE.Word0 >> 24) & 0xf;
386}
387
388static uint32_t getSectionFlags(const MachOObjectFile *O,
389 DataRefImpl Sec) {
390 if (O->is64Bit()) {
391 macho::Section64 Sect = O->getSection64(Sec);
392 return Sect.Flags;
393 }
394 macho::Section Sect = O->getSection(Sec);
395 return Sect.Flags;
396}
397
398MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
399 bool IsLittleEndian, bool Is64bits,
400 error_code &ec)
401 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
402 SymtabLoadCmd(NULL) {
403 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
404 macho::LoadCommandType SegmentLoadType = is64Bit() ?
405 macho::LCT_Segment64 : macho::LCT_Segment;
406
407 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
Rafael Espindoladb5f9272013-04-19 11:36:47 +0000408 for (unsigned I = 0; ; ++I) {
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000409 if (Load.C.Type == macho::LCT_Symtab) {
410 assert(!SymtabLoadCmd && "Multiple symbol tables");
411 SymtabLoadCmd = Load.Ptr;
412 }
413
414 if (Load.C.Type == SegmentLoadType) {
415 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
416 for (unsigned J = 0; J < NumSections; ++J) {
417 const SectionBase *Sec = getSectionBase(this, Load, J);
418 Sections.push_back(reinterpret_cast<const char*>(Sec));
419 }
420 }
Rafael Espindoladb5f9272013-04-19 11:36:47 +0000421
422 if (I == LoadCommandCount - 1)
423 break;
424 else
425 Load = getNextLoadCommandInfo(Load);
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000426 }
427}
428
429error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
430 SymbolRef &Res) const {
431 Symb.d.b++;
432 Res = SymbolRef(Symb, this);
433 return object_error::success;
434}
435
436error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
437 StringRef &Res) const {
438 macho::SymtabLoadCommand S = getSymtabLoadCommand();
439 const char *StringTable = getPtr(this, S.StringTableOffset);
440 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
441 const char *Start = &StringTable[Entry.StringIndex];
442 Res = StringRef(Start);
443 return object_error::success;
444}
445
446error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
447 uint64_t &Res) const {
448 if (is64Bit()) {
449 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
450 Res = Entry.Value;
451 } else {
452 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
453 Res = Entry.Value;
454 }
455 return object_error::success;
456}
457
458error_code
459MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
460 uint64_t &Res) const {
461 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
462 getSymbolAddress(Symb, Res);
463 if (Entry.SectionIndex) {
464 uint64_t Delta;
465 DataRefImpl SecRel;
466 SecRel.d.a = Entry.SectionIndex-1;
467 if (is64Bit()) {
468 macho::Section64 Sec = getSection64(SecRel);
469 Delta = Sec.Offset - Sec.Address;
470 } else {
471 macho::Section Sec = getSection(SecRel);
472 Delta = Sec.Offset - Sec.Address;
473 }
474
475 Res += Delta;
476 }
477
478 return object_error::success;
479}
480
481error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
482 uint64_t &Result) const {
483 uint64_t BeginOffset;
484 uint64_t EndOffset = 0;
485 uint8_t SectionIndex;
486
487 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
488 uint64_t Value;
489 getSymbolAddress(DRI, Value);
490
491 BeginOffset = Value;
492
493 SectionIndex = Entry.SectionIndex;
494 if (!SectionIndex) {
495 uint32_t flags = SymbolRef::SF_None;
496 this->getSymbolFlags(DRI, flags);
497 if (flags & SymbolRef::SF_Common)
498 Result = Value;
499 else
500 Result = UnknownAddressOrSize;
501 return object_error::success;
502 }
503 // Unfortunately symbols are unsorted so we need to touch all
504 // symbols from load command
505 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
506 DRI.d.b = 0;
507 while (DRI.d.b <= Symtab.NumSymbolTableEntries) {
508 Entry = getSymbolTableEntryBase(this, DRI);
509 getSymbolAddress(DRI, Value);
510 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
511 if (!EndOffset || Value < EndOffset)
512 EndOffset = Value;
513 DRI.d.b++;
514 }
515 if (!EndOffset) {
516 uint64_t Size;
517 DataRefImpl Sec;
518 Sec.d.a = SectionIndex-1;
519 getSectionSize(Sec, Size);
520 getSectionAddress(Sec, EndOffset);
521 EndOffset += Size;
522 }
523 Result = EndOffset - BeginOffset;
524 return object_error::success;
525}
526
527error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
528 SymbolRef::Type &Res) const {
529 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
530 uint8_t n_type = Entry.Type;
531
532 Res = SymbolRef::ST_Other;
533
534 // If this is a STAB debugging symbol, we can do nothing more.
535 if (n_type & MachO::NlistMaskStab) {
536 Res = SymbolRef::ST_Debug;
537 return object_error::success;
538 }
539
540 switch (n_type & MachO::NlistMaskType) {
541 case MachO::NListTypeUndefined :
542 Res = SymbolRef::ST_Unknown;
543 break;
544 case MachO::NListTypeSection :
545 Res = SymbolRef::ST_Function;
546 break;
547 }
548 return object_error::success;
549}
550
551error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
552 char &Res) const {
553 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
554 uint8_t Type = Entry.Type;
555 uint16_t Flags = Entry.Flags;
556
557 char Char;
558 switch (Type & macho::STF_TypeMask) {
559 case macho::STT_Undefined:
560 Char = 'u';
561 break;
562 case macho::STT_Absolute:
563 case macho::STT_Section:
564 Char = 's';
565 break;
566 default:
567 Char = '?';
568 break;
569 }
570
571 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
572 Char = toupper(static_cast<unsigned char>(Char));
573 Res = Char;
574 return object_error::success;
575}
576
577error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
578 uint32_t &Result) const {
579 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
580
581 uint8_t MachOType = Entry.Type;
582 uint16_t MachOFlags = Entry.Flags;
583
584 // TODO: Correctly set SF_ThreadLocal
585 Result = SymbolRef::SF_None;
586
587 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
588 Result |= SymbolRef::SF_Undefined;
589
590 if (MachOFlags & macho::STF_StabsEntryMask)
591 Result |= SymbolRef::SF_FormatSpecific;
592
593 if (MachOType & MachO::NlistMaskExternal) {
594 Result |= SymbolRef::SF_Global;
595 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
596 Result |= SymbolRef::SF_Common;
597 }
598
599 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
600 Result |= SymbolRef::SF_Weak;
601
602 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
603 Result |= SymbolRef::SF_Absolute;
604
605 return object_error::success;
606}
607
608error_code
609MachOObjectFile::getSymbolSection(DataRefImpl Symb,
610 section_iterator &Res) const {
611 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
612 uint8_t index = Entry.SectionIndex;
613
614 if (index == 0) {
615 Res = end_sections();
616 } else {
617 DataRefImpl DRI;
618 DRI.d.a = index - 1;
619 Res = section_iterator(SectionRef(DRI, this));
620 }
621
622 return object_error::success;
623}
624
625error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
626 uint64_t &Val) const {
627 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
628}
629
630error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
631 SectionRef &Res) const {
632 Sec.d.a++;
633 Res = SectionRef(Sec, this);
634 return object_error::success;
635}
636
637error_code
638MachOObjectFile::getSectionName(DataRefImpl Sec,
639 StringRef &Result) const {
640 ArrayRef<char> Raw = getSectionRawName(Sec);
641 Result = parseSegmentOrSectionName(Raw.data());
642 return object_error::success;
643}
644
645error_code
646MachOObjectFile::getSectionAddress(DataRefImpl Sec,
647 uint64_t &Res) const {
648 if (is64Bit()) {
649 macho::Section64 Sect = getSection64(Sec);
650 Res = Sect.Address;
651 } else {
652 macho::Section Sect = getSection(Sec);
653 Res = Sect.Address;
654 }
655 return object_error::success;
656}
657
658error_code
659MachOObjectFile::getSectionSize(DataRefImpl Sec,
660 uint64_t &Res) const {
661 if (is64Bit()) {
662 macho::Section64 Sect = getSection64(Sec);
663 Res = Sect.Size;
664 } else {
665 macho::Section Sect = getSection(Sec);
666 Res = Sect.Size;
667 }
668
669 return object_error::success;
670}
671
672error_code
673MachOObjectFile::getSectionContents(DataRefImpl Sec,
674 StringRef &Res) const {
675 uint32_t Offset;
676 uint64_t Size;
677
678 if (is64Bit()) {
679 macho::Section64 Sect = getSection64(Sec);
680 Offset = Sect.Offset;
681 Size = Sect.Size;
682 } else {
683 macho::Section Sect =getSection(Sec);
684 Offset = Sect.Offset;
685 Size = Sect.Size;
686 }
687
688 Res = this->getData().substr(Offset, Size);
689 return object_error::success;
690}
691
692error_code
693MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
694 uint64_t &Res) const {
695 uint32_t Align;
696 if (is64Bit()) {
697 macho::Section64 Sect = getSection64(Sec);
698 Align = Sect.Align;
699 } else {
700 macho::Section Sect = getSection(Sec);
701 Align = Sect.Align;
702 }
703
704 Res = uint64_t(1) << Align;
705 return object_error::success;
706}
707
708error_code
709MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
710 uint32_t Flags = getSectionFlags(this, Sec);
711 Res = Flags & macho::SF_PureInstructions;
712 return object_error::success;
713}
714
715error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000716 bool &Result) const {
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000717 // FIXME: Unimplemented.
718 Result = false;
719 return object_error::success;
720}
721
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000722error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000723 bool &Result) const {
724 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000725 Result = false;
726 return object_error::success;
727}
728
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000729error_code
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000730MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000731 bool &Result) const {
732 // FIXME: Unimplemented.
733 Result = true;
Preston Gurdc68dda82012-04-12 20:13:57 +0000734 return object_error::success;
735}
736
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000737error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000738 bool &Result) const {
739 // FIXME: Unimplemented.
740 Result = false;
741 return object_error::success;
742}
743
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000744error_code
745MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
746 uint32_t Flags = getSectionFlags(this, Sec);
747 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
748 Res = SectionType == MachO::SectionTypeZeroFill ||
749 SectionType == MachO::SectionTypeZeroFillLarge;
750 return object_error::success;
751}
752
753error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000754 bool &Result) const {
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000755 // Consider using the code from isSectionText to look for __const sections.
756 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
757 // to use section attributes to distinguish code from data.
758
759 // FIXME: Unimplemented.
760 Result = false;
761 return object_error::success;
762}
763
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000764error_code
765MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
766 DataRefImpl Symb,
767 bool &Result) const {
768 SymbolRef::Type ST;
769 this->getSymbolType(Symb, ST);
770 if (ST == SymbolRef::ST_Unknown) {
771 Result = false;
772 return object_error::success;
773 }
774
775 uint64_t SectBegin, SectEnd;
776 getSectionAddress(Sec, SectBegin);
777 getSectionSize(Sec, SectEnd);
778 SectEnd += SectBegin;
779
780 uint64_t SymAddr;
781 getSymbolAddress(Symb, SymAddr);
782 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
783
784 return object_error::success;
785}
786
787relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000788 DataRefImpl ret;
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000789 ret.d.b = Sec.d.a;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000790 return relocation_iterator(RelocationRef(ret, this));
791}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000792
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000793relocation_iterator
794MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
795 uint32_t LastReloc;
796 if (is64Bit()) {
797 macho::Section64 Sect = getSection64(Sec);
798 LastReloc = Sect.NumRelocationTableEntries;
799 } else {
800 macho::Section Sect = getSection(Sec);
801 LastReloc = Sect.NumRelocationTableEntries;
802 }
Eric Christopher6256b032011-04-22 03:19:48 +0000803
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000804 DataRefImpl Ret;
805 Ret.d.a = LastReloc;
806 Ret.d.b = Sec.d.a;
807 return relocation_iterator(RelocationRef(Ret, this));
808}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000809
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000810error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000811 RelocationRef &Res) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000812 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000813 Res = RelocationRef(Rel, this);
814 return object_error::success;
815}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000816
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000817error_code
818MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
819 uint64_t &Res) const {
820 uint64_t SectAddress;
821 DataRefImpl Sec;
822 Sec.d.a = Rel.d.b;
823 if (is64Bit()) {
824 macho::Section64 Sect = getSection64(Sec);
825 SectAddress = Sect.Address;
826 } else {
827 macho::Section Sect = getSection(Sec);
828 SectAddress = Sect.Address;
829 }
830
831 macho::RelocationEntry RE = getRelocation(Rel);
832 uint64_t RelAddr = getAnyRelocationAddress(RE);
833 Res = SectAddress + RelAddr;
834 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000835}
836
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000837error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
838 uint64_t &Res) const {
839 macho::RelocationEntry RE = getRelocation(Rel);
840 Res = getAnyRelocationAddress(RE);
841 return object_error::success;
David Meyer5c2b4ea2012-03-01 01:36:50 +0000842}
843
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000844error_code
845MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
846 SymbolRef &Res) const {
847 macho::RelocationEntry RE = getRelocation(Rel);
848 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
849 bool isExtern = getPlainRelocationExternal(RE);
850
851 DataRefImpl Sym;
852 if (isExtern) {
853 Sym.d.b = SymbolIdx;
854 }
855 Res = SymbolRef(Sym, this);
856 return object_error::success;
857}
858
859error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
860 uint64_t &Res) const {
861 macho::RelocationEntry RE = getRelocation(Rel);
862 Res = getAnyRelocationType(RE);
863 return object_error::success;
864}
865
866error_code
867MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
868 SmallVectorImpl<char> &Result) const {
869 StringRef res;
870 uint64_t RType;
871 getRelocationType(Rel, RType);
872
873 unsigned Arch = this->getArch();
874
875 switch (Arch) {
876 case Triple::x86: {
877 static const char *const Table[] = {
878 "GENERIC_RELOC_VANILLA",
879 "GENERIC_RELOC_PAIR",
880 "GENERIC_RELOC_SECTDIFF",
881 "GENERIC_RELOC_PB_LA_PTR",
882 "GENERIC_RELOC_LOCAL_SECTDIFF",
883 "GENERIC_RELOC_TLV" };
884
885 if (RType > 6)
886 res = "Unknown";
887 else
888 res = Table[RType];
889 break;
890 }
891 case Triple::x86_64: {
892 static const char *const Table[] = {
893 "X86_64_RELOC_UNSIGNED",
894 "X86_64_RELOC_SIGNED",
895 "X86_64_RELOC_BRANCH",
896 "X86_64_RELOC_GOT_LOAD",
897 "X86_64_RELOC_GOT",
898 "X86_64_RELOC_SUBTRACTOR",
899 "X86_64_RELOC_SIGNED_1",
900 "X86_64_RELOC_SIGNED_2",
901 "X86_64_RELOC_SIGNED_4",
902 "X86_64_RELOC_TLV" };
903
904 if (RType > 9)
905 res = "Unknown";
906 else
907 res = Table[RType];
908 break;
909 }
910 case Triple::arm: {
911 static const char *const Table[] = {
912 "ARM_RELOC_VANILLA",
913 "ARM_RELOC_PAIR",
914 "ARM_RELOC_SECTDIFF",
915 "ARM_RELOC_LOCAL_SECTDIFF",
916 "ARM_RELOC_PB_LA_PTR",
917 "ARM_RELOC_BR24",
918 "ARM_THUMB_RELOC_BR22",
919 "ARM_THUMB_32BIT_BRANCH",
920 "ARM_RELOC_HALF",
921 "ARM_RELOC_HALF_SECTDIFF" };
922
923 if (RType > 9)
924 res = "Unknown";
925 else
926 res = Table[RType];
927 break;
928 }
929 case Triple::ppc: {
930 static const char *const Table[] = {
931 "PPC_RELOC_VANILLA",
932 "PPC_RELOC_PAIR",
933 "PPC_RELOC_BR14",
934 "PPC_RELOC_BR24",
935 "PPC_RELOC_HI16",
936 "PPC_RELOC_LO16",
937 "PPC_RELOC_HA16",
938 "PPC_RELOC_LO14",
939 "PPC_RELOC_SECTDIFF",
940 "PPC_RELOC_PB_LA_PTR",
941 "PPC_RELOC_HI16_SECTDIFF",
942 "PPC_RELOC_LO16_SECTDIFF",
943 "PPC_RELOC_HA16_SECTDIFF",
944 "PPC_RELOC_JBSR",
945 "PPC_RELOC_LO14_SECTDIFF",
946 "PPC_RELOC_LOCAL_SECTDIFF" };
947
948 res = Table[RType];
949 break;
950 }
951 case Triple::UnknownArch:
952 res = "Unknown";
953 break;
954 }
955 Result.append(res.begin(), res.end());
956 return object_error::success;
957}
958
959error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
960 int64_t &Res) const {
Rafael Espindola8bf80062013-04-11 02:21:31 +0000961 Res = 0;
962 return object_error::success;
963}
964
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000965error_code
966MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
967 SmallVectorImpl<char> &Result) const {
968 macho::RelocationEntry RE = getRelocation(Rel);
David Meyer5c2b4ea2012-03-01 01:36:50 +0000969
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000970 unsigned Arch = this->getArch();
Eric Christopher6256b032011-04-22 03:19:48 +0000971
Rafael Espindolafd7aa382013-04-18 18:08:55 +0000972 std::string fmtbuf;
973 raw_string_ostream fmt(fmtbuf);
974 unsigned Type = this->getAnyRelocationType(RE);
975 bool IsPCRel = this->getAnyRelocationPCRel(RE);
976
977 // Determine any addends that should be displayed with the relocation.
978 // These require decoding the relocation type, which is triple-specific.
979
980 // X86_64 has entirely custom relocation types.
981 if (Arch == Triple::x86_64) {
982 bool isPCRel = getAnyRelocationPCRel(RE);
983
984 switch (Type) {
985 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
986 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
987 printRelocationTargetName(this, RE, fmt);
988 fmt << "@GOT";
989 if (isPCRel) fmt << "PCREL";
990 break;
991 }
992 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
993 DataRefImpl RelNext = Rel;
994 RelNext.d.a++;
995 macho::RelocationEntry RENext = getRelocation(RelNext);
996
997 // X86_64_SUBTRACTOR must be followed by a relocation of type
998 // X86_64_RELOC_UNSIGNED.
999 // NOTE: Scattered relocations don't exist on x86_64.
1000 unsigned RType = getAnyRelocationType(RENext);
1001 if (RType != 0)
1002 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1003 "X86_64_RELOC_SUBTRACTOR.");
1004
1005 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1006 // X86_64_SUBTRACTOR contains to the subtrahend.
1007 printRelocationTargetName(this, RENext, fmt);
1008 fmt << "-";
1009 printRelocationTargetName(this, RE, fmt);
1010 break;
1011 }
1012 case macho::RIT_X86_64_TLV:
1013 printRelocationTargetName(this, RE, fmt);
1014 fmt << "@TLV";
1015 if (isPCRel) fmt << "P";
1016 break;
1017 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1018 printRelocationTargetName(this, RE, fmt);
1019 fmt << "-1";
1020 break;
1021 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1022 printRelocationTargetName(this, RE, fmt);
1023 fmt << "-2";
1024 break;
1025 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1026 printRelocationTargetName(this, RE, fmt);
1027 fmt << "-4";
1028 break;
1029 default:
1030 printRelocationTargetName(this, RE, fmt);
1031 break;
1032 }
1033 // X86 and ARM share some relocation types in common.
1034 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1035 // Generic relocation types...
1036 switch (Type) {
1037 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1038 return object_error::success;
1039 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1040 DataRefImpl RelNext = Rel;
1041 RelNext.d.a++;
1042 macho::RelocationEntry RENext = getRelocation(RelNext);
1043
1044 // X86 sect diff's must be followed by a relocation of type
1045 // GENERIC_RELOC_PAIR.
1046 unsigned RType = getAnyRelocationType(RENext);
1047
1048 if (RType != 1)
1049 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1050 "GENERIC_RELOC_SECTDIFF.");
1051
1052 printRelocationTargetName(this, RE, fmt);
1053 fmt << "-";
1054 printRelocationTargetName(this, RENext, fmt);
1055 break;
1056 }
1057 }
1058
1059 if (Arch == Triple::x86) {
1060 // All X86 relocations that need special printing were already
1061 // handled in the generic code.
1062 switch (Type) {
1063 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1064 DataRefImpl RelNext = Rel;
1065 RelNext.d.a++;
1066 macho::RelocationEntry RENext = getRelocation(RelNext);
1067
1068 // X86 sect diff's must be followed by a relocation of type
1069 // GENERIC_RELOC_PAIR.
1070 unsigned RType = getAnyRelocationType(RENext);
1071 if (RType != 1)
1072 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1073 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1074
1075 printRelocationTargetName(this, RE, fmt);
1076 fmt << "-";
1077 printRelocationTargetName(this, RENext, fmt);
1078 break;
1079 }
1080 case macho::RIT_Generic_TLV: {
1081 printRelocationTargetName(this, RE, fmt);
1082 fmt << "@TLV";
1083 if (IsPCRel) fmt << "P";
1084 break;
1085 }
1086 default:
1087 printRelocationTargetName(this, RE, fmt);
1088 }
1089 } else { // ARM-specific relocations
1090 switch (Type) {
1091 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1092 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1093 // Half relocations steal a bit from the length field to encode
1094 // whether this is an upper16 or a lower16 relocation.
1095 bool isUpper = getAnyRelocationLength(RE) >> 1;
1096
1097 if (isUpper)
1098 fmt << ":upper16:(";
1099 else
1100 fmt << ":lower16:(";
1101 printRelocationTargetName(this, RE, fmt);
1102
1103 DataRefImpl RelNext = Rel;
1104 RelNext.d.a++;
1105 macho::RelocationEntry RENext = getRelocation(RelNext);
1106
1107 // ARM half relocs must be followed by a relocation of type
1108 // ARM_RELOC_PAIR.
1109 unsigned RType = getAnyRelocationType(RENext);
1110 if (RType != 1)
1111 report_fatal_error("Expected ARM_RELOC_PAIR after "
1112 "GENERIC_RELOC_HALF");
1113
1114 // NOTE: The half of the target virtual address is stashed in the
1115 // address field of the secondary relocation, but we can't reverse
1116 // engineer the constant offset from it without decoding the movw/movt
1117 // instruction to find the other half in its immediate field.
1118
1119 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1120 // symbol/section pointer of the follow-on relocation.
1121 if (Type == macho::RIT_ARM_HalfDifference) {
1122 fmt << "-";
1123 printRelocationTargetName(this, RENext, fmt);
1124 }
1125
1126 fmt << ")";
1127 break;
1128 }
1129 default: {
1130 printRelocationTargetName(this, RE, fmt);
1131 }
1132 }
1133 }
1134 } else
1135 printRelocationTargetName(this, RE, fmt);
1136
1137 fmt.flush();
1138 Result.append(fmtbuf.begin(), fmtbuf.end());
1139 return object_error::success;
1140}
1141
1142error_code
1143MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1144 bool &Result) const {
1145 unsigned Arch = getArch();
1146 uint64_t Type;
1147 getRelocationType(Rel, Type);
1148
1149 Result = false;
1150
1151 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1152 // is always hidden.
1153 if (Arch == Triple::x86 || Arch == Triple::arm) {
1154 if (Type == macho::RIT_Pair) Result = true;
1155 } else if (Arch == Triple::x86_64) {
1156 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1157 // an X864_64_RELOC_SUBTRACTOR.
1158 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1159 DataRefImpl RelPrev = Rel;
1160 RelPrev.d.a--;
1161 uint64_t PrevType;
1162 getRelocationType(RelPrev, PrevType);
1163 if (PrevType == macho::RIT_X86_64_Subtractor)
1164 Result = true;
1165 }
1166 }
1167
1168 return object_error::success;
1169}
1170
1171error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1172 LibraryRef &Res) const {
1173 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1174}
1175
1176error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1177 StringRef &Res) const {
1178 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1179}
1180
1181symbol_iterator MachOObjectFile::begin_symbols() const {
1182 // DRI.d.a = segment number; DRI.d.b = symbol index.
1183 DataRefImpl DRI;
1184 return symbol_iterator(SymbolRef(DRI, this));
1185}
1186
1187symbol_iterator MachOObjectFile::end_symbols() const {
1188 DataRefImpl DRI;
1189 if (SymtabLoadCmd) {
1190 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1191 DRI.d.b = Symtab.NumSymbolTableEntries;
1192 }
1193 return symbol_iterator(SymbolRef(DRI, this));
1194}
1195
1196symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1197 // TODO: implement
1198 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1199}
1200
1201symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1202 // TODO: implement
1203 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1204}
1205
1206section_iterator MachOObjectFile::begin_sections() const {
1207 DataRefImpl DRI;
1208 return section_iterator(SectionRef(DRI, this));
1209}
1210
1211section_iterator MachOObjectFile::end_sections() const {
1212 DataRefImpl DRI;
1213 DRI.d.a = Sections.size();
1214 return section_iterator(SectionRef(DRI, this));
1215}
1216
1217library_iterator MachOObjectFile::begin_libraries_needed() const {
1218 // TODO: implement
1219 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1220}
1221
1222library_iterator MachOObjectFile::end_libraries_needed() const {
1223 // TODO: implement
1224 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1225}
1226
1227uint8_t MachOObjectFile::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +00001228 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +00001229}
1230
Rafael Espindolafd7aa382013-04-18 18:08:55 +00001231StringRef MachOObjectFile::getFileFormatName() const {
1232 unsigned CPUType = getCPUType(this);
1233 if (!is64Bit()) {
1234 switch (CPUType) {
1235 case llvm::MachO::CPUTypeI386:
1236 return "Mach-O 32-bit i386";
1237 case llvm::MachO::CPUTypeARM:
1238 return "Mach-O arm";
1239 case llvm::MachO::CPUTypePowerPC:
1240 return "Mach-O 32-bit ppc";
1241 default:
1242 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1243 "64-bit object file when we're not 64-bit?");
1244 return "Mach-O 32-bit unknown";
1245 }
1246 }
1247
1248 // Make sure the cpu type has the correct mask.
1249 assert((CPUType & llvm::MachO::CPUArchABI64)
1250 == llvm::MachO::CPUArchABI64 &&
1251 "32-bit object file when we're 64-bit?");
1252
1253 switch (CPUType) {
1254 case llvm::MachO::CPUTypeX86_64:
1255 return "Mach-O 64-bit x86-64";
1256 case llvm::MachO::CPUTypePowerPC64:
1257 return "Mach-O 64-bit ppc64";
1258 default:
1259 return "Mach-O 64-bit unknown";
1260 }
1261}
1262
1263unsigned MachOObjectFile::getArch() const {
1264 switch (getCPUType(this)) {
1265 case llvm::MachO::CPUTypeI386:
1266 return Triple::x86;
1267 case llvm::MachO::CPUTypeX86_64:
1268 return Triple::x86_64;
1269 case llvm::MachO::CPUTypeARM:
1270 return Triple::arm;
1271 case llvm::MachO::CPUTypePowerPC:
1272 return Triple::ppc;
1273 case llvm::MachO::CPUTypePowerPC64:
1274 return Triple::ppc64;
1275 default:
1276 return Triple::UnknownArch;
1277 }
1278}
1279
1280StringRef MachOObjectFile::getLoadName() const {
1281 // TODO: Implement
1282 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1283}
1284
1285StringRef
1286MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1287 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
1288 return parseSegmentOrSectionName(Raw.data());
1289}
1290
1291ArrayRef<char>
1292MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1293 const SectionBase *Base =
1294 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1295 return ArrayRef<char>(Base->Name);
1296}
1297
1298ArrayRef<char>
1299MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1300 const SectionBase *Base =
1301 reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
1302 return ArrayRef<char>(Base->SegmentName);
1303}
1304
1305bool
1306MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1307 const {
1308 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
1309 return false;
1310 return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1311}
1312
1313unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
1314 if (isLittleEndian())
1315 return RE.Word1 & 0xffffff;
1316 return RE.Word1 >> 8;
1317}
1318
1319bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
1320 if (isLittleEndian())
1321 return (RE.Word1 >> 27) & 1;
1322 return (RE.Word1 >> 4) & 1;
1323}
1324
1325bool
1326MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
1327 return RE.Word0 >> 31;
1328}
1329
1330uint32_t
1331MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
1332 return RE.Word1;
1333}
1334
1335unsigned
1336MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
1337 if (isRelocationScattered(RE))
1338 return getScatteredRelocationAddress(RE);
1339 return getPlainRelocationAddress(RE);
1340}
1341
1342unsigned
1343MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1344 if (isRelocationScattered(RE))
1345 return getScatteredRelocationPCRel(this, RE);
1346 return getPlainRelocationPCRel(this, RE);
1347}
1348
1349unsigned
1350MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
1351 if (isRelocationScattered(RE))
1352 return getScatteredRelocationLength(RE);
1353 return getPlainRelocationLength(this, RE);
1354}
1355
1356unsigned
1357MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1358 if (isRelocationScattered(RE))
1359 return getScatteredRelocationType(RE);
1360 return getPlainRelocationType(this, RE);
1361}
1362
1363MachOObjectFile::LoadCommandInfo
1364MachOObjectFile::getFirstLoadCommandInfo() const {
1365 MachOObjectFile::LoadCommandInfo Load;
1366
1367 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1368 Load.Ptr = getPtr(this, HeaderSize);
1369 memcpy(&Load.C, Load.Ptr, sizeof(macho::LoadCommand));
1370 if (isSwappedEndian(this))
1371 SwapStruct(Load.C);
1372 return Load;
1373}
1374
1375MachOObjectFile::LoadCommandInfo
1376MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1377 MachOObjectFile::LoadCommandInfo Next;
1378 Next.Ptr = L.Ptr + L.C.Size;
1379 memcpy(&Next.C, Next.Ptr, sizeof(macho::LoadCommand));
1380 if (isSwappedEndian(this))
1381 SwapStruct(Next.C);
1382 return Next;
1383}
1384
1385macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
1386 const SectionBase *Addr =
1387 reinterpret_cast<const SectionBase*>(Sections[DRI.d.a]);
1388 macho::Section Ret;
1389 memcpy(&Ret, Addr, sizeof(macho::Section));
1390 if (isSwappedEndian(this))
1391 SwapStruct(Ret);
1392 return Ret;
1393}
1394
1395macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1396 const SectionBase *Addr =
1397 reinterpret_cast<const SectionBase*>(Sections[DRI.d.a]);
1398 macho::Section64 Ret;
1399 memcpy(&Ret, Addr, sizeof(macho::Section64));
1400 if (isSwappedEndian(this))
1401 SwapStruct(Ret);
1402 return Ret;
1403}
1404
1405macho::SymbolTableEntry
1406MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1407 const char *P = getSymbolTableEntryPtr(this, DRI);
1408 macho::SymbolTableEntry Ret;
1409 memcpy(&Ret, P, sizeof(macho::SymbolTableEntry));
1410 if (isSwappedEndian(this))
1411 SwapStruct(Ret);
1412 return Ret;
1413}
1414
1415macho::Symbol64TableEntry
1416MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1417 const char *P = getSymbolTableEntryPtr(this, DRI);
1418 macho::Symbol64TableEntry Ret;
1419 memcpy(&Ret, P, sizeof(macho::Symbol64TableEntry));
1420 if (isSwappedEndian(this))
1421 SwapStruct(Ret);
1422 return Ret;
1423}
1424
1425macho::LinkeditDataLoadCommand
1426MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
1427 macho::LinkeditDataLoadCommand Cmd;
1428 memcpy(&Cmd, L.Ptr, sizeof(macho::LinkeditDataLoadCommand));
1429 if (isSwappedEndian(this))
1430 SwapStruct(Cmd);
1431 return Cmd;
1432}
1433
1434macho::RelocationEntry
1435MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1436 uint32_t RelOffset;
1437 DataRefImpl Sec;
1438 Sec.d.a = Rel.d.b;
1439 if (is64Bit()) {
1440 macho::Section64 Sect = getSection64(Sec);
1441 RelOffset = Sect.RelocationTableOffset;
1442 } else {
1443 macho::Section Sect = getSection(Sec);
1444 RelOffset = Sect.RelocationTableOffset;
1445 }
1446
1447 uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry);
1448
1449 macho::RelocationEntry Ret;
1450 memcpy(&Ret, getPtr(this, Offset), sizeof(macho::RelocationEntry));
1451 if (isSwappedEndian(this))
1452 SwapStruct(Ret);
1453
1454 return Ret;
1455}
1456
1457macho::Header MachOObjectFile::getHeader() const {
1458 macho::Header H;
1459 memcpy(&H, getPtr(this, 0), sizeof(macho::Header));
1460 if (isSwappedEndian(this))
1461 SwapStruct(H);
1462 return H;
1463}
1464
1465macho::SymtabLoadCommand
1466MachOObjectFile::getSymtabLoadCommand() const {
1467 macho::SymtabLoadCommand Cmd;
1468 memcpy(&Cmd, SymtabLoadCmd, sizeof(macho::SymtabLoadCommand));
1469 if (isSwappedEndian(this))
1470 SwapStruct(Cmd);
1471 return Cmd;
1472}
1473
1474bool MachOObjectFile::is64Bit() const {
1475 return getType() == getMachOType(false, true) ||
1476 getType() == getMachOType(true, true);
1477}
1478
1479void MachOObjectFile::ReadULEB128s(uint64_t Index,
1480 SmallVectorImpl<uint64_t> &Out) const {
1481 DataExtractor extractor(ObjectFile::getData(), true, 0);
1482
1483 uint32_t offset = Index;
1484 uint64_t data = 0;
1485 while (uint64_t delta = extractor.getULEB128(&offset)) {
1486 data += delta;
1487 Out.push_back(data);
1488 }
1489}
1490
1491ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1492 StringRef Magic = Buffer->getBuffer().slice(0, 4);
1493 error_code ec;
1494 ObjectFile *Ret;
1495 if (Magic == "\xFE\xED\xFA\xCE")
1496 Ret = new MachOObjectFile(Buffer, false, false, ec);
1497 else if (Magic == "\xCE\xFA\xED\xFE")
1498 Ret = new MachOObjectFile(Buffer, true, false, ec);
1499 else if (Magic == "\xFE\xED\xFA\xCF")
1500 Ret = new MachOObjectFile(Buffer, false, true, ec);
1501 else if (Magic == "\xCF\xFA\xED\xFE")
1502 Ret = new MachOObjectFile(Buffer, true, true, ec);
1503 else
1504 return NULL;
1505
1506 if (ec)
1507 return NULL;
1508 return Ret;
1509}
1510
Owen Andersonf7c93a32011-10-11 17:32:27 +00001511} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +00001512} // end namespace llvm