llvm.org GIT mirror llvm / fd7aa38
At Jim Grosbach's request detemplate Object/MachO.h. We are still able to handle mixed endian objects by swapping one struct at a time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179778 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 7 years ago
11 changed file(s) with 2120 addition(s) and 1836 deletion(s). Raw diff Collapse all Expand all
9999 }
100100
101101 bool isLittleEndian() const {
102 return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B);
102 return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
103 TypeID == ID_MachO32B || TypeID == ID_MachO64B);
103104 }
104105 };
105106
66 //
77 //===----------------------------------------------------------------------===//
88 //
9 // This file declares the MachOObjectFile class, which binds the MachOObject
10 // class to the generic ObjectFile wrapper.
9 // This file declares the MachOObjectFile class, which implement the ObjectFile
10 // interface for MachO files.
1111 //
1212 //===----------------------------------------------------------------------===//
1313
1616
1717 #include "llvm/ADT/ArrayRef.h"
1818 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/Triple.h"
2019 #include "llvm/Object/MachOFormat.h"
2120 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Format.h"
2521 #include "llvm/Support/MachO.h"
2622 #include "llvm/Support/raw_ostream.h"
2723
2824 namespace llvm {
2925 namespace object {
3026
31 using support::endianness;
32
33 template
34 struct MachOType {
35 static const endianness TargetEndianness = E;
36 static const bool Is64Bits = B;
37 };
38
39 template
40 struct MachOInt24Impl;
41
42 template<>
43 struct MachOInt24Impl {
44 uint8_t bytes[3];
45 operator uint32_t() const {
46 return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
47 }
48 };
49
50 template<>
51 struct MachOInt24Impl {
52 uint8_t bytes[3];
53 operator uint32_t() const {
54 return (bytes[0] << 24) | (bytes[1] << 16) | bytes[2];
55 }
56 };
57
58 template
59 struct MachODataTypeTypedefHelperCommon {
60 typedef support::detail::packed_endian_specific_integral
61 MachOInt16;
62 typedef support::detail::packed_endian_specific_integral
63 MachOInt32;
64 typedef support::detail::packed_endian_specific_integral
65 MachOInt64;
66 typedef MachOInt24Impl MachOInt24;
67 };
68
69 #define LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \
70 typedef typename MachODataTypeTypedefHelperCommon::MachOInt16 MachOInt16; \
71 typedef typename MachODataTypeTypedefHelperCommon::MachOInt32 MachOInt32; \
72 typedef typename MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; \
73 typedef typename MachODataTypeTypedefHelperCommon::MachOInt24 MachOInt24;
74
75 #define LLVM_MACHOB_IMPORT_TYPES(E) \
76 typedef MachODataTypeTypedefHelperCommon::MachOInt16 MachOInt16; \
77 typedef MachODataTypeTypedefHelperCommon::MachOInt32 MachOInt32; \
78 typedef MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; \
79 typedef MachODataTypeTypedefHelperCommon::MachOInt24 MachOInt24;
80
81 template
82 struct MachODataTypeTypedefHelper;
83
84 template
85 struct MachODataTypeTypedefHelper > {
86 typedef MachODataTypeTypedefHelperCommon Base;
87 typedef typename Base::MachOInt32 MachOIntPtr;
88 };
89
90 template
91 struct MachODataTypeTypedefHelper > {
92 typedef MachODataTypeTypedefHelperCommon Base;
93 typedef typename Base::MachOInt64 MachOIntPtr;
94 };
95
96 #define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B) \
97 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \
98 typedef typename \
99 MachODataTypeTypedefHelper >::MachOIntPtr MachOIntPtr;
100
101 namespace MachOFormat {
102 struct SectionBase {
103 char Name[16];
104 char SegmentName[16];
27 class MachOObjectFile : public ObjectFile {
28 public:
29 struct LoadCommandInfo {
30 const char *Ptr; // Where in memory the load command is.
31 macho::LoadCommand C; // The command itself.
10532 };
10633
107 template
108 struct Section;
34 MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits,
35 error_code &ec);
10936
110 template
111 struct Section > {
112 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
113 char Name[16];
114 char SegmentName[16];
115 MachOInt32 Address;
116 MachOInt32 Size;
117 MachOInt32 Offset;
118 MachOInt32 Align;
119 MachOInt32 RelocationTableOffset;
120 MachOInt32 NumRelocationTableEntries;
121 MachOInt32 Flags;
122 MachOInt32 Reserved1;
123 MachOInt32 Reserved2;
124 };
37 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
38 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
39 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
40 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
41 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
42 virtual error_code getSymbolType(DataRefImpl Symb,
43 SymbolRef::Type &Res) const;
44 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
45 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
46 virtual error_code getSymbolSection(DataRefImpl Symb,
47 section_iterator &Res) const;
48 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
12549
126 template
127 struct Section > {
128 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
129 char Name[16];
130 char SegmentName[16];
131 MachOInt64 Address;
132 MachOInt64 Size;
133 MachOInt32 Offset;
134 MachOInt32 Align;
135 MachOInt32 RelocationTableOffset;
136 MachOInt32 NumRelocationTableEntries;
137 MachOInt32 Flags;
138 MachOInt32 Reserved1;
139 MachOInt32 Reserved2;
140 MachOInt32 Reserved3;
141 };
142
143 struct MachOInt24 {
144 uint8_t bytes[3];
145 operator uint32_t() const {
146 return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
147 }
148 };
149
150 template
151 struct RelocationEntry;
152
153 template<>
154 struct RelocationEntry {
155 LLVM_MACHOB_IMPORT_TYPES(support::little)
156 MachOInt32 Address;
157 MachOInt24 SymbolNum;
158 unsigned PCRel : 1;
159 unsigned Length : 2;
160 unsigned External : 1;
161 unsigned Type : 4;
162 };
163
164 template<>
165 struct RelocationEntry {
166 LLVM_MACHOB_IMPORT_TYPES(support::little)
167 MachOInt32 Address;
168 MachOInt24 SymbolNum;
169 unsigned Type : 4;
170 unsigned External : 1;
171 unsigned Length : 2;
172 unsigned PCRel : 1;
173 };
174
175 template<>
176 struct RelocationEntry {
177 LLVM_MACHOB_IMPORT_TYPES(support::big)
178 MachOInt32 Address;
179 MachOInt24 SymbolNum;
180 unsigned Type : 4;
181 unsigned External : 1;
182 unsigned Length : 2;
183 unsigned PCRel : 1;
184 };
185
186 template<>
187 struct RelocationEntry {
188 LLVM_MACHOB_IMPORT_TYPES(support::big)
189 MachOInt32 Address;
190 MachOInt24 SymbolNum;
191 unsigned PCRel : 1;
192 unsigned Length : 2;
193 unsigned External : 1;
194 unsigned Type : 4;
195 };
196
197 template
198 struct ScatteredRelocationEntry;
199
200 template<>
201 struct ScatteredRelocationEntry {
202 LLVM_MACHOB_IMPORT_TYPES(support::little)
203 MachOInt24 Address;
204 unsigned Type : 4;
205 unsigned Length : 2;
206 unsigned PCRel : 1;
207 unsigned Scattered : 1;
208 MachOInt32 Value;
209 };
210
211 template<>
212 struct ScatteredRelocationEntry {
213 LLVM_MACHOB_IMPORT_TYPES(support::little)
214 MachOInt24 Address;
215 unsigned Scattered : 1;
216 unsigned PCRel : 1;
217 unsigned Length : 2;
218 unsigned Type : 4;
219 MachOInt32 Value;
220 };
221
222 template<>
223 struct ScatteredRelocationEntry {
224 LLVM_MACHOB_IMPORT_TYPES(support::big)
225 unsigned Type : 4;
226 unsigned Length : 2;
227 unsigned PCRel : 1;
228 unsigned Scattered : 1;
229 MachOInt24 Address;
230 MachOInt32 Value;
231 };
232
233 template<>
234 struct ScatteredRelocationEntry {
235 LLVM_MACHOB_IMPORT_TYPES(support::big)
236 unsigned Scattered : 1;
237 unsigned PCRel : 1;
238 unsigned Length : 2;
239 unsigned Type : 4;
240 MachOInt24 Address;
241 MachOInt32 Value;
242 };
243
244 template
245 struct SymbolTableEntryBase {
246 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
247 MachOInt32 StringIndex;
248 uint8_t Type;
249 uint8_t SectionIndex;
250 MachOInt16 Flags;
251 };
252
253 template
254 struct SymbolTableEntry;
255
256 template
257 struct SymbolTableEntry > {
258 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
259 MachOInt32 StringIndex;
260 uint8_t Type;
261 uint8_t SectionIndex;
262 MachOInt16 Flags;
263 MachOIntPtr Value;
264 };
265
266 template
267 struct LoadCommand {
268 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
269 MachOInt32 Type;
270 MachOInt32 Size;
271 };
272
273 template
274 struct SymtabLoadCommand {
275 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
276 MachOInt32 Type;
277 MachOInt32 Size;
278 MachOInt32 SymbolTableOffset;
279 MachOInt32 NumSymbolTableEntries;
280 MachOInt32 StringTableOffset;
281 MachOInt32 StringTableSize;
282 };
283
284 template
285 struct SegmentLoadCommand;
286
287 template
288 struct SegmentLoadCommand > {
289 LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
290 MachOInt32 Type;
291 MachOInt32 Size;
292 char Name[16];
293 MachOIntPtr VMAddress;
294 MachOIntPtr VMSize;
295 MachOIntPtr FileOffset;
296 MachOIntPtr FileSize;
297 MachOInt32 MaxVMProtection;
298 MachOInt32 InitialVMProtection;
299 MachOInt32 NumSections;
300 MachOInt32 Flags;
301 };
302
303 template
304 struct LinkeditDataLoadCommand {
305 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
306 MachOInt32 Type;
307 MachOInt32 Size;
308 MachOInt32 DataOffset;
309 MachOInt32 DataSize;
310 };
311
312 template
313 struct Header {
314 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
315 MachOInt32 Magic;
316 MachOInt32 CPUType;
317 MachOInt32 CPUSubtype;
318 MachOInt32 FileType;
319 MachOInt32 NumLoadCommands;
320 MachOInt32 SizeOfLoadCommands;
321 MachOInt32 Flags;
322 };
323 }
324
325 class MachOObjectFileBase : public ObjectFile {
326 public:
327 typedef MachOFormat::SectionBase SectionBase;
328
329 MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits,
330 error_code &ec);
331
332 virtual symbol_iterator begin_dynamic_symbols() const;
333 virtual symbol_iterator end_dynamic_symbols() const;
334 virtual library_iterator begin_libraries_needed() const;
335 virtual library_iterator end_libraries_needed() const;
336
337 virtual uint8_t getBytesInAddress() const;
338 virtual StringRef getLoadName() const;
339
340 bool is64Bit() const;
341 void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const;
342 unsigned getHeaderSize() const;
343 StringRef getData(size_t Offset, size_t Size) const;
344
345 static inline bool classof(const Binary *v) {
346 return v->isMachO();
347 }
348
349 protected:
350 StringRef parseSegmentOrSectionName(const char *P) const;
351
352 virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
50 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
51 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
52 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
53 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
54 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
55 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
56 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
35357 virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
35458 virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
35559 virtual error_code isSectionRequiredForExecution(DataRefImpl Sec,
35660 bool &Res) const;
35761 virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const;
62 virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
35863 virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const;
64 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
65 bool &Result) const;
35966 virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
67 virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
36068
36169 virtual error_code getRelocationNext(DataRefImpl Rel,
36270 RelocationRef &Res) const;
71 virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
72 virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
73 virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
74 virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
75 virtual error_code getRelocationTypeName(DataRefImpl Rel,
76 SmallVectorImpl &Result) const;
77 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
78 int64_t &Res) const;
79 virtual error_code getRelocationValueString(DataRefImpl Rel,
80 SmallVectorImpl &Result) const;
81 virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
36382
36483 virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const;
36584 virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const;
366 virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
367 int64_t &Res) const;
36885
369 std::size_t getSectionIndex(DataRefImpl Sec) const;
86 virtual symbol_iterator begin_symbols() const;
87 virtual symbol_iterator end_symbols() const;
37088
371 typedef SmallVector SectionList;
372 SectionList Sections;
373 };
89 virtual symbol_iterator begin_dynamic_symbols() const;
90 virtual symbol_iterator end_dynamic_symbols() const;
37491
375 template
376 class MachOObjectFileMiddle : public MachOObjectFileBase {
377 public:
92 virtual section_iterator begin_sections() const;
93 virtual section_iterator end_sections() const;
37894
379 typedef MachOFormat::SymbolTableEntryBase
380 SymbolTableEntryBase;
381 typedef MachOFormat::LinkeditDataLoadCommand
382 LinkeditDataLoadCommand;
383 typedef MachOFormat::Header Header;
384 typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand;
385 typedef MachOFormat::RelocationEntry RelocationEntry;
386 typedef MachOFormat::ScatteredRelocationEntry
387 ScatteredRelocationEntry;
388 typedef MachOFormat::LoadCommand LoadCommand;
95 virtual library_iterator begin_libraries_needed() const;
96 virtual library_iterator end_libraries_needed() const;
38997
390 MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
98 virtual uint8_t getBytesInAddress() const;
39199
392 const Header *getHeader() const;
393 const LoadCommand *getLoadCommandInfo(unsigned Index) const;
394 const RelocationEntry *getRelocation(DataRefImpl Rel) const;
395 bool isRelocationScattered(const RelocationEntry *RE) const;
396 bool isRelocationPCRel(const RelocationEntry *RE) const;
397 unsigned getRelocationLength(const RelocationEntry *RE) const;
398 unsigned getRelocationTypeImpl(const RelocationEntry *RE) const;
100 virtual StringRef getFileFormatName() const;
101 virtual unsigned getArch() const;
399102
400 void moveToNextSymbol(DataRefImpl &DRI) const;
401 void printRelocationTargetName(const RelocationEntry *RE,
402 raw_string_ostream &fmt) const;
403 const SectionBase *getSectionBase(DataRefImpl DRI) const;
404 const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const;
405 unsigned getCPUType() const;
103 virtual StringRef getLoadName() const;
406104
407105 // In a MachO file, sections have a segment name. This is used in the .o
408106 // files. They have a single segment, but this field specifies which segment
414112 ArrayRef getSectionRawName(DataRefImpl Sec) const;
415113 ArrayRef getSectionRawFinalSegmentName(DataRefImpl Sec) const;
416114
417 virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
418 virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
419 virtual error_code getSymbolType(DataRefImpl Symb,
420 SymbolRef::Type &Res) const;
421 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
422 virtual error_code getSymbolSection(DataRefImpl Symb,
423 section_iterator &Res) const;
424 virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
425 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
426 virtual symbol_iterator begin_symbols() const;
427 virtual unsigned getArch() const;
428 virtual StringRef getFileFormatName() const;
429 virtual symbol_iterator end_symbols() const;
430 virtual section_iterator end_sections() const;
115 // MachO specific Info about relocations.
116 bool isRelocationScattered(const macho::RelocationEntry &RE) const;
117 unsigned getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const;
118 bool getPlainRelocationExternal(const macho::RelocationEntry &RE) const;
119 bool getScatteredRelocationScattered(const macho::RelocationEntry &RE) const;
120 uint32_t getScatteredRelocationValue(const macho::RelocationEntry &RE) const;
121 unsigned getAnyRelocationAddress(const macho::RelocationEntry &RE) const;
122 unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const;
123 unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const;
124 unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const;
431125
432 static bool classof(const Binary *v);
126 // Walk load commands.
127 LoadCommandInfo getFirstLoadCommandInfo() const;
128 LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const;
129
130 // MachO specific structures.
131 macho::Section getSection(DataRefImpl DRI) const;
132 macho::Section64 getSection64(DataRefImpl DRI) const;
133 macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const;
134 macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const;
135 macho::LinkeditDataLoadCommand
136 getLinkeditDataLoadCommand(const LoadCommandInfo &L) const;
137 macho::RelocationEntry getRelocation(DataRefImpl Rel) const;
138 macho::Header getHeader() const;
139 macho::SymtabLoadCommand getSymtabLoadCommand() const;
140
141 bool is64Bit() const;
142 void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const;
143
144 static bool classof(const Binary *v) {
145 return v->isMachO();
146 }
433147
434148 private:
435 // Helper to advance a section or symbol iterator multiple increments at a
436 // time.
437 template
438 static error_code advance(T &it, size_t Val);
439
440 template
441 static void advanceTo(T &it, size_t Val);
149 typedef SmallVector SectionList;
150 SectionList Sections;
151 const char *SymtabLoadCmd;
442152 };
443
444 template
445 struct MachOObjectFileHelperCommon;
446
447 template
448 struct MachOObjectFileHelperCommon > {
449 typedef
450 MachOFormat::SegmentLoadCommand >
451 SegmentLoadCommand;
452 typedef MachOFormat::SymbolTableEntry >
453 SymbolTableEntry;
454 typedef MachOFormat::Section > Section;
455 };
456
457 template
458 struct MachOObjectFileHelper;
459
460 template
461 struct MachOObjectFileHelper > :
462 public MachOObjectFileHelperCommon > {
463 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment;
464 };
465
466 template
467 struct MachOObjectFileHelper > :
468 public MachOObjectFileHelperCommon > {
469 static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64;
470 };
471
472 template
473 class MachOObjectFile : public MachOObjectFileMiddle {
474 public:
475 static const endianness TargetEndianness = MachOT::TargetEndianness;
476 static const bool Is64Bits = MachOT::Is64Bits;
477
478 typedef MachOObjectFileMiddle Base;
479 typedef typename Base::RelocationEntry RelocationEntry;
480 typedef typename Base::SectionBase SectionBase;
481 typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase;
482 typedef typename Base::LoadCommand LoadCommand;
483
484 typedef MachOObjectFileHelper Helper;
485 static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType;
486 typedef typename Helper::SegmentLoadCommand SegmentLoadCommand;
487 typedef typename Helper::SymbolTableEntry SymbolTableEntry;
488 typedef typename Helper::Section Section;
489
490 MachOObjectFile(MemoryBuffer *Object, error_code &ec);
491 static bool classof(const Binary *v);
492
493 const Section *getSection(DataRefImpl DRI) const;
494 const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
495 const RelocationEntry *getRelocation(DataRefImpl Rel) const;
496
497 virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
498 virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
499 virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
500 virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
501 virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
502 virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
503 virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
504 virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
505 virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
506 virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
507 virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
508 virtual error_code getRelocationTypeName(DataRefImpl Rel,
509 SmallVectorImpl &Result) const;
510 virtual error_code getRelocationValueString(DataRefImpl Rel,
511 SmallVectorImpl &Result) const;
512 virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
513 virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
514 virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
515 bool &Result) const;
516 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
517 virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
518 virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
519 virtual section_iterator begin_sections() const;
520 void moveToNextSection(DataRefImpl &DRI) const;
521 };
522
523 typedef MachOObjectFileMiddle MachOObjectFileLE;
524 typedef MachOObjectFileMiddle MachOObjectFileBE;
525
526 typedef MachOObjectFile >
527 MachOObjectFileLE32;
528 typedef MachOObjectFile >
529 MachOObjectFileBE32;
530 typedef MachOObjectFile >
531 MachOObjectFileLE64;
532 typedef MachOObjectFile >
533 MachOObjectFileBE64;
534
535 template
536 MachOObjectFileMiddle::MachOObjectFileMiddle(MemoryBuffer *O,
537 bool Is64Bits,
538 error_code &ec) :
539 MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) {
540 }
541
542 template
543 const typename MachOObjectFileMiddle::SymbolTableEntryBase *
544 MachOObjectFileMiddle::getSymbolTableEntryBase(DataRefImpl DRI) const {
545 const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
546 const SymtabLoadCommand *S = reinterpret_cast(L);
547
548 unsigned Index = DRI.d.b;
549
550 unsigned SymbolTableEntrySize = is64Bit() ?
551 sizeof(MachOObjectFileLE64::SymbolTableEntry) :
552 sizeof(MachOObjectFileLE32::SymbolTableEntry);
553
554 uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize;
555 StringRef Data = getData(Offset, SymbolTableEntrySize);
556 return reinterpret_cast(Data.data());
557 }
558
559 template
560 const typename MachOObjectFileMiddle::Header *
561 MachOObjectFileMiddle::getHeader() const {
562 StringRef Data = getData(0, sizeof(Header));
563 return reinterpret_cast(Data.data());
564 }
565
566 template
567 const typename MachOObjectFileMiddle::LoadCommand *
568 MachOObjectFileMiddle::getLoadCommandInfo(unsigned Index) const {
569 assert(Index < getHeader()->NumLoadCommands);
570 uint64_t Offset;
571 uint64_t NewOffset = getHeaderSize();
572 const LoadCommand *Load;
573 unsigned I = 0;
574 do {
575 Offset = NewOffset;
576 StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand));
577 Load = reinterpret_cast(Data.data());
578 NewOffset = Offset + Load->Size;
579 ++I;
580 } while (I != Index + 1);
581
582 return reinterpret_cast(Load);
583 }
584
585 template
586 const typename MachOObjectFileMiddle::RelocationEntry *
587 MachOObjectFileMiddle::getRelocation(DataRefImpl Rel) const {
588 if (const MachOObjectFile > *O =
589 dyn_cast > >(this))
590 return O->getRelocation(Rel);
591
592 const MachOObjectFile > *O =
593 cast > >(this);
594 return O->getRelocation(Rel);
595 }
596
597 template
598 bool
599 MachOObjectFileMiddle::isRelocationScattered(const RelocationEntry *RE)
600 const {
601 if (this->getCPUType() == llvm::MachO::CPUTypeX86_64)
602 return false;
603 return RE->Address & macho::RF_Scattered;
604 }
605
606 template
607 bool
608 MachOObjectFileMiddle::isRelocationPCRel(const RelocationEntry *RE) const {
609 typedef MachOObjectFileMiddle ObjType;
610 if (isRelocationScattered(RE)) {
611 const typename MachOObjectFileMiddle::ScatteredRelocationEntry *SRE =
612 reinterpret_cast(RE);
613 return SRE->PCRel;
614 }
615 return RE->PCRel;
616 }
617
618 template
619 unsigned
620 MachOObjectFileMiddle::getRelocationLength(const RelocationEntry *RE) const {
621 typedef MachOObjectFileMiddle ObjType;
622 if (isRelocationScattered(RE)) {
623 const typename ObjType::ScatteredRelocationEntry *SRE =
624 reinterpret_cast(RE);
625 return SRE->Length;
626 }
627 return RE->Length;
628 }
629
630 template
631 unsigned
632 MachOObjectFileMiddle::getRelocationTypeImpl(const RelocationEntry *RE)
633 const {
634 typedef MachOObjectFileMiddle ObjType;
635 if (isRelocationScattered(RE)) {
636 const typename ObjType::ScatteredRelocationEntry *SRE =
637 reinterpret_cast(RE);
638 return SRE->Type;
639 }
640 return RE->Type;
641 }
642
643 // Helper to advance a section or symbol iterator multiple increments at a time.
644 template
645 template
646 error_code MachOObjectFileMiddle::advance(T &it, size_t Val) {
647 error_code ec;
648 while (Val--) {
649 it.increment(ec);
650 }
651 return ec;
652 }
653
654 template
655 template
656 void MachOObjectFileMiddle::advanceTo(T &it, size_t Val) {
657 if (error_code ec = advance(it, Val))
658 report_fatal_error(ec.message());
659 }
660
661 template
662 void
663 MachOObjectFileMiddle::printRelocationTargetName(const RelocationEntry *RE,
664 raw_string_ostream &fmt) const {
665 bool IsScattered = isRelocationScattered(RE);
666
667 // Target of a scattered relocation is an address. In the interest of
668 // generating pretty output, scan through the symbol table looking for a
669 // symbol that aligns with that address. If we find one, print it.
670 // Otherwise, we just print the hex address of the target.
671 if (IsScattered) {
672 uint32_t Val = RE->SymbolNum;
673
674 error_code ec;
675 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
676 SI.increment(ec)) {
677 if (ec) report_fatal_error(ec.message());
678
679 uint64_t Addr;
680 StringRef Name;
681
682 if ((ec = SI->getAddress(Addr)))
683 report_fatal_error(ec.message());
684 if (Addr != Val) continue;
685 if ((ec = SI->getName(Name)))
686 report_fatal_error(ec.message());
687 fmt << Name;
688 return;
689 }
690
691 // If we couldn't find a symbol that this relocation refers to, try
692 // to find a section beginning instead.
693 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
694 SI.increment(ec)) {
695 if (ec) report_fatal_error(ec.message());
696
697 uint64_t Addr;
698 StringRef Name;
699
700 if ((ec = SI->getAddress(Addr)))
701 report_fatal_error(ec.message());
702 if (Addr != Val) continue;
703 if ((ec = SI->getName(Name)))
704 report_fatal_error(ec.message());
705 fmt << Name;
706 return;
707 }
708
709 fmt << format("0x%x", Val);
710 return;
711 }
712
713 StringRef S;
714 bool isExtern = RE->External;
715 uint64_t Val = RE->Address;
716
717 if (isExtern) {
718 symbol_iterator SI = begin_symbols();
719 advanceTo(SI, Val);
720 SI->getName(S);
721 } else {
722 section_iterator SI = begin_sections();
723 advanceTo(SI, Val);
724 SI->getName(S);
725 }
726
727 fmt << S;
728 }
729
730 template
731 const typename MachOObjectFileMiddle::SectionBase *
732 MachOObjectFileMiddle::getSectionBase(DataRefImpl DRI) const {
733 uintptr_t CommandAddr =
734 reinterpret_cast(getLoadCommandInfo(DRI.d.a));
735
736 bool Is64 = is64Bit();
737 unsigned SegmentLoadSize =
738 Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) :
739 sizeof(MachOObjectFileLE32::SegmentLoadCommand);
740 unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) :
741 sizeof(MachOObjectFileLE32::Section);
742
743 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
744 return reinterpret_cast(SectionAddr);
745 }
746
747 template
748 unsigned MachOObjectFileMiddle::getCPUType() const {
749 return getHeader()->CPUType;
750 }
751
752 template
753 void MachOObjectFileMiddle::moveToNextSymbol(DataRefImpl &DRI) const {
754 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
755 while (DRI.d.a < LoadCommandCount) {
756 const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
757 if (L->Type == macho::LCT_Symtab) {
758 const SymtabLoadCommand *S =
759 reinterpret_cast(L);
760 if (DRI.d.b < S->NumSymbolTableEntries)
761 return;
762 }
763
764 DRI.d.a++;
765 DRI.d.b = 0;
766 }
767 }
768
769 template
770 StringRef
771 MachOObjectFileMiddle::getSectionFinalSegmentName(DataRefImpl Sec) const {
772 ArrayRef Raw = getSectionRawFinalSegmentName(Sec);
773 return parseSegmentOrSectionName(Raw.data());
774 }
775
776 template
777 ArrayRef
778 MachOObjectFileMiddle::getSectionRawName(DataRefImpl Sec) const {
779 const SectionBase *Base = getSectionBase(Sec);
780 return ArrayRef(Base->Name);
781 }
782
783 template
784 ArrayRef
785 MachOObjectFileMiddle::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
786 const SectionBase *Base = getSectionBase(Sec);
787 return ArrayRef(Base->SegmentName);
788 }
789
790 template
791 error_code MachOObjectFileMiddle::getSymbolFlags(DataRefImpl DRI,
792 uint32_t &Result) const {
793 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
794
795 uint8_t MachOType = Entry->Type;
796 uint16_t MachOFlags = Entry->Flags;
797
798 // TODO: Correctly set SF_ThreadLocal
799 Result = SymbolRef::SF_None;
800
801 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
802 Result |= SymbolRef::SF_Undefined;
803
804 if (MachOFlags & macho::STF_StabsEntryMask)
805 Result |= SymbolRef::SF_FormatSpecific;
806
807 if (MachOType & MachO::NlistMaskExternal) {
808 Result |= SymbolRef::SF_Global;
809 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
810 Result |= SymbolRef::SF_Common;
811 }
812
813 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
814 Result |= SymbolRef::SF_Weak;
815
816 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
817 Result |= SymbolRef::SF_Absolute;
818
819 return object_error::success;
820 }
821
822 template
823 error_code MachOObjectFileMiddle::getSymbolType(DataRefImpl Symb,
824 SymbolRef::Type &Res) const {
825 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
826 uint8_t n_type = Entry->Type;
827
828 Res = SymbolRef::ST_Other;
829
830 // If this is a STAB debugging symbol, we can do nothing more.
831 if (n_type & MachO::NlistMaskStab) {
832 Res = SymbolRef::ST_Debug;
833 return object_error::success;
834 }
835
836 switch (n_type & MachO::NlistMaskType) {
837 case MachO::NListTypeUndefined :
838 Res = SymbolRef::ST_Unknown;
839 break;
840 case MachO::NListTypeSection :
841 Res = SymbolRef::ST_Function;
842 break;
843 }
844 return object_error::success;
845 }
846
847 template
848 error_code MachOObjectFileMiddle::getSymbolName(DataRefImpl Symb,
849 StringRef &Res) const {
850 const LoadCommand *L = getLoadCommandInfo(Symb.d.a);
851 const SymtabLoadCommand *S = reinterpret_cast(L);
852 StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize);
853 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
854 const char *Start = &StringTable.data()[Entry->StringIndex];
855 Res = StringRef(Start);
856 return object_error::success;
857 }
858
859 template
860 error_code
861 MachOObjectFileMiddle::getSymbolSection(DataRefImpl Symb,
862 section_iterator &Res) const {
863 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
864 uint8_t index = Entry->SectionIndex;
865
866 if (index == 0)
867 Res = end_sections();
868 else
869 Res = section_iterator(SectionRef(Sections[index-1], this));
870
871 return object_error::success;
872 }
873
874
875 template
876 error_code MachOObjectFileMiddle::getSymbolNMTypeChar(DataRefImpl Symb,
877 char &Res) const {
878 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
879 uint8_t Type = Entry->Type;
880 uint16_t Flags = Entry->Flags;
881
882 char Char;
883 switch (Type & macho::STF_TypeMask) {
884 case macho::STT_Undefined:
885 Char = 'u';
886 break;
887 case macho::STT_Absolute:
888 case macho::STT_Section:
889 Char = 's';
890 break;
891 default:
892 Char = '?';
893 break;
894 }
895
896 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
897 Char = toupper(static_cast(Char));
898 Res = Char;
899 return object_error::success;
900 }
901
902 template
903 error_code
904 MachOObjectFileMiddle::getSectionName(DataRefImpl Sec,
905 StringRef &Result) const {
906 ArrayRef Raw = getSectionRawName(Sec);
907 Result = parseSegmentOrSectionName(Raw.data());
908 return object_error::success;
909 }
910
911 template
912 error_code MachOObjectFileMiddle::getSymbolNext(DataRefImpl Symb,
913 SymbolRef &Res) const {
914 Symb.d.b++;
915 moveToNextSymbol(Symb);
916 Res = SymbolRef(Symb, this);
917 return object_error::success;
918 }
919
920 template
921 symbol_iterator MachOObjectFileMiddle::begin_symbols() const {
922 // DRI.d.a = segment number; DRI.d.b = symbol index.
923 DataRefImpl DRI;
924 moveToNextSymbol(DRI);
925 return symbol_iterator(SymbolRef(DRI, this));
926 }
927
928 template
929 unsigned MachOObjectFileMiddle::getArch() const {
930 switch (getCPUType()) {
931 case llvm::MachO::CPUTypeI386:
932 return Triple::x86;
933 case llvm::MachO::CPUTypeX86_64:
934 return Triple::x86_64;
935 case llvm::MachO::CPUTypeARM:
936 return Triple::arm;
937 case llvm::MachO::CPUTypePowerPC:
938 return Triple::ppc;
939 case llvm::MachO::CPUTypePowerPC64:
940 return Triple::ppc64;
941 default:
942 return Triple::UnknownArch;
943 }
944 }
945
946 template
947 StringRef MachOObjectFileMiddle::getFileFormatName() const {
948 unsigned CPUType = getCPUType();
949 if (!is64Bit()) {
950 switch (CPUType) {
951 case llvm::MachO::CPUTypeI386:
952 return "Mach-O 32-bit i386";
953 case llvm::MachO::CPUTypeARM:
954 return "Mach-O arm";
955 case llvm::MachO::CPUTypePowerPC:
956 return "Mach-O 32-bit ppc";
957 default:
958 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
959 "64-bit object file when we're not 64-bit?");
960 return "Mach-O 32-bit unknown";
961 }
962 }
963
964 // Make sure the cpu type has the correct mask.
965 assert((CPUType & llvm::MachO::CPUArchABI64)
966 == llvm::MachO::CPUArchABI64 &&
967 "32-bit object file when we're 64-bit?");
968
969 switch (CPUType) {
970 case llvm::MachO::CPUTypeX86_64:
971 return "Mach-O 64-bit x86-64";
972 case llvm::MachO::CPUTypePowerPC64:
973 return "Mach-O 64-bit ppc64";
974 default:
975 return "Mach-O 64-bit unknown";
976 }
977 }
978
979 template
980 symbol_iterator MachOObjectFileMiddle::end_symbols() const {
981 DataRefImpl DRI;
982 DRI.d.a = getHeader()->NumLoadCommands;
983 return symbol_iterator(SymbolRef(DRI, this));
984 }
985
986 template
987 section_iterator MachOObjectFileMiddle::end_sections() const {
988 DataRefImpl DRI;
989 DRI.d.a = getHeader()->NumLoadCommands;
990 return section_iterator(SectionRef(DRI, this));
991 }
992
993 template
994 bool MachOObjectFileMiddle::classof(const Binary *v) {
995 return isa > >(v) ||
996 isa > >(v);
997 }
998
999 template
1000 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
1001 error_code &ec) :
1002 MachOObjectFileMiddle(Object, Is64Bits, ec) {
1003 DataRefImpl DRI;
1004 moveToNextSection(DRI);
1005 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1006 while (DRI.d.a < LoadCommandCount) {
1007 this->Sections.push_back(DRI);
1008 DRI.d.b++;
1009 moveToNextSection(DRI);
1010 }
1011 }
1012
1013 template
1014 bool MachOObjectFile::classof(const Binary *v) {
1015 return v->getType() ==
1016 Base::getMachOType(TargetEndianness == support::little, Is64Bits);
1017 }
1018
1019 template
1020 const typename MachOObjectFile::Section *
1021 MachOObjectFile::getSection(DataRefImpl DRI) const {
1022 const SectionBase *Addr = this->getSectionBase(DRI);
1023 return reinterpret_cast(Addr);
1024 }
1025
1026 template
1027 const typename MachOObjectFile::SymbolTableEntry *
1028 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1029 const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI);
1030 return reinterpret_cast(Base);
1031 }
1032
1033 template
1034 const typename MachOObjectFile::RelocationEntry *
1035 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1036 const Section *Sect = getSection(this->Sections[Rel.d.b]);
1037 uint32_t RelOffset = Sect->RelocationTableOffset;
1038 uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry);
1039 StringRef Data = this->getData(Offset, sizeof(RelocationEntry));
1040 return reinterpret_cast(Data.data());
1041 }
1042
1043 template
1044 error_code
1045 MachOObjectFile::getSectionAddress(DataRefImpl Sec,
1046 uint64_t &Res) const {
1047 const Section *Sect = getSection(Sec);
1048 Res = Sect->Address;
1049 return object_error::success;
1050 }
1051
1052 template
1053 error_code
1054 MachOObjectFile::getSectionSize(DataRefImpl Sec,
1055 uint64_t &Res) const {
1056 const Section *Sect = getSection(Sec);
1057 Res = Sect->Size;
1058 return object_error::success;
1059 }
1060
1061 template
1062 error_code
1063 MachOObjectFile::getSectionContents(DataRefImpl Sec,
1064 StringRef &Res) const {
1065 const Section *Sect = getSection(Sec);
1066 Res = this->getData(Sect->Offset, Sect->Size);
1067 return object_error::success;
1068 }
1069
1070 template
1071 error_code
1072 MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
1073 uint64_t &Res) const {
1074 const Section *Sect = getSection(Sec);
1075 Res = uint64_t(1) << Sect->Align;
1076 return object_error::success;
1077 }
1078
1079 template
1080 error_code
1081 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
1082 const Section *Sect = getSection(Sec);
1083 Res = Sect->Flags & macho::SF_PureInstructions;
1084 return object_error::success;
1085 }
1086
1087 template
1088 error_code
1089 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
1090 const Section *Sect = getSection(Sec);
1091 unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
1092 Res = SectionType == MachO::SectionTypeZeroFill ||
1093 SectionType == MachO::SectionTypeZeroFillLarge;
1094 return object_error::success;
1095 }
1096
1097 template
1098 relocation_iterator
1099 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
1100 const Section *Sect = getSection(Sec);
1101 uint32_t LastReloc = Sect->NumRelocationTableEntries;
1102 DataRefImpl Ret;
1103 Ret.d.a = LastReloc;
1104 Ret.d.b = this->getSectionIndex(Sec);
1105 return relocation_iterator(RelocationRef(Ret, this));
1106 }
1107
1108 template
1109 error_code
1110 MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
1111 uint64_t &Res) const {
1112 const Section *Sect = getSection(this->Sections[Rel.d.b]);
1113 uint64_t SectAddress = Sect->Address;
1114 const RelocationEntry *RE = getRelocation(Rel);
1115
1116 uint64_t RelAddr;
1117 if (this->isRelocationScattered(RE))
1118 RelAddr = RE->Address & 0xFFFFFF;
1119 else
1120 RelAddr = RE->Address;
1121
1122 Res = SectAddress + RelAddr;
1123 return object_error::success;
1124 }
1125
1126 template
1127 error_code
1128 MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
1129 uint64_t &Res) const {
1130 const RelocationEntry *RE = getRelocation(Rel);
1131 if (this->isRelocationScattered(RE))
1132 Res = RE->Address & 0xFFFFFF;
1133 else
1134 Res = RE->Address;
1135 return object_error::success;
1136 }
1137
1138 template
1139 error_code
1140 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
1141 SymbolRef &Res) const {
1142 const RelocationEntry *RE = getRelocation(Rel);
1143 uint32_t SymbolIdx = RE->SymbolNum;
1144 bool isExtern = RE->External;
1145
1146 DataRefImpl Sym;
1147 this->moveToNextSymbol(Sym);
1148 if (isExtern) {
1149 for (unsigned i = 0; i < SymbolIdx; i++) {
1150 Sym.d.b++;
1151 this->moveToNextSymbol(Sym);
1152 assert(Sym.d.a < this->getHeader()->NumLoadCommands &&
1153 "Relocation symbol index out of range!");
1154 }
1155 }
1156 Res = SymbolRef(Sym, this);
1157 return object_error::success;
1158 }
1159
1160 template
1161 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
1162 uint64_t &Res) const {
1163 const RelocationEntry *RE = getRelocation(Rel);
1164 Res = this->getRelocationTypeImpl(RE);
1165 return object_error::success;
1166 }
1167
1168 template
1169 error_code
1170 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
1171 SmallVectorImpl &Result) const {
1172 // TODO: Support scattered relocations.
1173 StringRef res;
1174 const RelocationEntry *RE = getRelocation(Rel);
1175
1176 unsigned Arch = this->getArch();
1177
1178 unsigned r_type = this->getRelocationTypeImpl(RE);
1179
1180 switch (Arch) {
1181 case Triple::x86: {
1182 static const char *const Table[] = {
1183 "GENERIC_RELOC_VANILLA",
1184 "GENERIC_RELOC_PAIR",
1185 "GENERIC_RELOC_SECTDIFF",
1186 "GENERIC_RELOC_PB_LA_PTR",
1187 "GENERIC_RELOC_LOCAL_SECTDIFF",
1188 "GENERIC_RELOC_TLV" };
1189
1190 if (r_type > 6)
1191 res = "Unknown";
1192 else
1193 res = Table[r_type];
1194 break;
1195 }
1196 case Triple::x86_64: {
1197 static const char *const Table[] = {
1198 "X86_64_RELOC_UNSIGNED",
1199 "X86_64_RELOC_SIGNED",
1200 "X86_64_RELOC_BRANCH",
1201 "X86_64_RELOC_GOT_LOAD",
1202 "X86_64_RELOC_GOT",
1203 "X86_64_RELOC_SUBTRACTOR",
1204 "X86_64_RELOC_SIGNED_1",
1205 "X86_64_RELOC_SIGNED_2",
1206 "X86_64_RELOC_SIGNED_4",
1207 "X86_64_RELOC_TLV" };
1208
1209 if (r_type > 9)
1210 res = "Unknown";
1211 else
1212 res = Table[r_type];
1213 break;
1214 }
1215 case Triple::arm: {
1216 static const char *const Table[] = {
1217 "ARM_RELOC_VANILLA",
1218 "ARM_RELOC_PAIR",
1219 "ARM_RELOC_SECTDIFF",
1220 "ARM_RELOC_LOCAL_SECTDIFF",
1221 "ARM_RELOC_PB_LA_PTR",
1222 "ARM_RELOC_BR24",
1223 "ARM_THUMB_RELOC_BR22",
1224 "ARM_THUMB_32BIT_BRANCH",
1225 "ARM_RELOC_HALF",
1226 "ARM_RELOC_HALF_SECTDIFF" };
1227
1228 if (r_type > 9)
1229 res = "Unknown";
1230 else
1231 res = Table[r_type];
1232 break;
1233 }
1234 case Triple::ppc: {
1235 static const char *const Table[] = {
1236 "PPC_RELOC_VANILLA",
1237 "PPC_RELOC_PAIR",
1238 "PPC_RELOC_BR14",
1239 "PPC_RELOC_BR24",
1240 "PPC_RELOC_HI16",
1241 "PPC_RELOC_LO16",
1242 "PPC_RELOC_HA16",
1243 "PPC_RELOC_LO14",
1244 "PPC_RELOC_SECTDIFF",
1245 "PPC_RELOC_PB_LA_PTR",
1246 "PPC_RELOC_HI16_SECTDIFF",
1247 "PPC_RELOC_LO16_SECTDIFF",
1248 "PPC_RELOC_HA16_SECTDIFF",
1249 "PPC_RELOC_JBSR",
1250 "PPC_RELOC_LO14_SECTDIFF",
1251 "PPC_RELOC_LOCAL_SECTDIFF" };
1252
1253 res = Table[r_type];
1254 break;
1255 }
1256 case Triple::UnknownArch:
1257 res = "Unknown";
1258 break;
1259 }
1260 Result.append(res.begin(), res.end());
1261 return object_error::success;
1262 }
1263
1264 template
1265 error_code
1266 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
1267 SmallVectorImpl &Result) const {
1268 const RelocationEntry *RE = getRelocation(Rel);
1269
1270 unsigned Arch = this->getArch();
1271 bool IsScattered = this->isRelocationScattered(RE);
1272
1273 std::string fmtbuf;
1274 raw_string_ostream fmt(fmtbuf);
1275
1276 unsigned Type = this->getRelocationTypeImpl(RE);
1277 bool IsPCRel = this->isRelocationPCRel(RE);
1278
1279 // Determine any addends that should be displayed with the relocation.
1280 // These require decoding the relocation type, which is triple-specific.
1281
1282 // X86_64 has entirely custom relocation types.
1283 if (Arch == Triple::x86_64) {
1284 bool isPCRel = RE->PCRel;
1285
1286 switch (Type) {
1287 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
1288 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
1289 this->printRelocationTargetName(RE, fmt);
1290 fmt << "@GOT";
1291 if (isPCRel) fmt << "PCREL";
1292 break;
1293 }
1294 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1295 DataRefImpl RelNext = Rel;
1296 RelNext.d.a++;
1297 const RelocationEntry *RENext = getRelocation(RelNext);
1298
1299 // X86_64_SUBTRACTOR must be followed by a relocation of type
1300 // X86_64_RELOC_UNSIGNED.
1301 // NOTE: Scattered relocations don't exist on x86_64.
1302 unsigned RType = RENext->Type;
1303 if (RType != 0)
1304 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1305 "X86_64_RELOC_SUBTRACTOR.");
1306
1307 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1308 // X86_64_SUBTRACTOR contains to the subtrahend.
1309 this->printRelocationTargetName(RENext, fmt);
1310 fmt << "-";
1311 this->printRelocationTargetName(RE, fmt);
1312 break;
1313 }
1314 case macho::RIT_X86_64_TLV:
1315 this->printRelocationTargetName(RE, fmt);
1316 fmt << "@TLV";
1317 if (isPCRel) fmt << "P";
1318 break;
1319 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1320 this->printRelocationTargetName(RE, fmt);
1321 fmt << "-1";
1322 break;
1323 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1324 this->printRelocationTargetName(RE, fmt);
1325 fmt << "-2";
1326 break;
1327 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1328 this->printRelocationTargetName(RE, fmt);
1329 fmt << "-4";
1330 break;
1331 default:
1332 this->printRelocationTargetName(RE, fmt);
1333 break;
1334 }
1335 // X86 and ARM share some relocation types in common.
1336 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1337 // Generic relocation types...
1338 switch (Type) {
1339 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1340 return object_error::success;
1341 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1342 DataRefImpl RelNext = Rel;
1343 RelNext.d.a++;
1344 const RelocationEntry *RENext = getRelocation(RelNext);
1345
1346 // X86 sect diff's must be followed by a relocation of type
1347 // GENERIC_RELOC_PAIR.
1348 bool isNextScattered = (Arch != Triple::x86_64) &&
1349 (RENext->Address & macho::RF_Scattered);
1350 unsigned RType;
1351 if (isNextScattered)
1352 RType = (RENext->Address >> 24) & 0xF;
1353 else
1354 RType = RENext->Type;
1355 if (RType != 1)
1356 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1357 "GENERIC_RELOC_SECTDIFF.");
1358
1359 this->printRelocationTargetName(RE, fmt);
1360 fmt << "-";
1361 this->printRelocationTargetName(RENext, fmt);
1362 break;
1363 }
1364 }
1365
1366 if (Arch == Triple::x86) {
1367 // All X86 relocations that need special printing were already
1368 // handled in the generic code.
1369 switch (Type) {
1370 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1371 DataRefImpl RelNext = Rel;
1372 RelNext.d.a++;
1373 const RelocationEntry *RENext = getRelocation(RelNext);
1374
1375 // X86 sect diff's must be followed by a relocation of type
1376 // GENERIC_RELOC_PAIR.
1377 bool isNextScattered = (Arch != Triple::x86_64) &&
1378 (RENext->Address & macho::RF_Scattered);
1379 unsigned RType;
1380 if (isNextScattered)
1381 RType = (RENext->Address >> 24) & 0xF;
1382 else
1383 RType = RENext->Type;
1384 if (RType != 1)
1385 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1386 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1387
1388 this->printRelocationTargetName(RE, fmt);
1389 fmt << "-";
1390 this->printRelocationTargetName(RENext, fmt);
1391 break;
1392 }
1393 case macho::RIT_Generic_TLV: {
1394 this->printRelocationTargetName(RE, fmt);
1395 fmt << "@TLV";
1396 if (IsPCRel) fmt << "P";
1397 break;
1398 }
1399 default:
1400 this->printRelocationTargetName(RE, fmt);
1401 }
1402 } else { // ARM-specific relocations
1403 switch (Type) {
1404 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1405 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1406 // Half relocations steal a bit from the length field to encode
1407 // whether this is an upper16 or a lower16 relocation.
1408 bool isUpper;
1409 if (IsScattered)
1410 isUpper = (RE->Address >> 28) & 1;
1411 else
1412 isUpper = (RE->Length >> 1) & 1;
1413
1414 if (isUpper)
1415 fmt << ":upper16:(";
1416 else
1417 fmt << ":lower16:(";
1418 this->printRelocationTargetName(RE, fmt);
1419
1420 DataRefImpl RelNext = Rel;
1421 RelNext.d.a++;
1422 const RelocationEntry *RENext = getRelocation(RelNext);
1423
1424 // ARM half relocs must be followed by a relocation of type
1425 // ARM_RELOC_PAIR.
1426 bool isNextScattered = (Arch != Triple::x86_64) &&
1427 (RENext->Address & macho::RF_Scattered);
1428 unsigned RType;
1429 if (isNextScattered)
1430 RType = (RENext->Address >> 24) & 0xF;
1431 else
1432 RType = RENext->Type;
1433
1434 if (RType != 1)
1435 report_fatal_error("Expected ARM_RELOC_PAIR after "
1436 "GENERIC_RELOC_HALF");
1437
1438 // NOTE: The half of the target virtual address is stashed in the
1439 // address field of the secondary relocation, but we can't reverse
1440 // engineer the constant offset from it without decoding the movw/movt
1441 // instruction to find the other half in its immediate field.
1442
1443 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1444 // symbol/section pointer of the follow-on relocation.
1445 if (Type == macho::RIT_ARM_HalfDifference) {
1446 fmt << "-";
1447 this->printRelocationTargetName(RENext, fmt);
1448 }
1449
1450 fmt << ")";
1451 break;
1452 }
1453 default: {
1454 this->printRelocationTargetName(RE, fmt);
1455 }
1456 }
1457 }
1458 } else
1459 this->printRelocationTargetName(RE, fmt);
1460
1461 fmt.flush();
1462 Result.append(fmtbuf.begin(), fmtbuf.end());
1463 return object_error::success;
1464 }
1465
1466 template
1467 error_code
1468 MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1469 bool &Result) const {
1470 const RelocationEntry *RE = getRelocation(Rel);
1471 unsigned Arch = this->getArch();
1472 unsigned Type = this->getRelocationTypeImpl(RE);
1473
1474 Result = false;
1475
1476 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1477 // is always hidden.
1478 if (Arch == Triple::x86 || Arch == Triple::arm) {
1479 if (Type == macho::RIT_Pair) Result = true;
1480 } else if (Arch == Triple::x86_64) {
1481 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1482 // an X864_64_RELOC_SUBTRACTOR.
1483 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1484 DataRefImpl RelPrev = Rel;
1485 RelPrev.d.a--;
1486 const RelocationEntry *REPrev = this->getRelocation(RelPrev);
1487
1488 unsigned PrevType = REPrev->Type;
1489
1490 if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1491 }
1492 }
1493
1494 return object_error::success;
1495 }
1496
1497 template
1498 error_code
1499 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
1500 uint64_t &Res) const {
1501 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1502 Res = Entry->Value;
1503 if (Entry->SectionIndex) {
1504 const Section *Sec =
1505 this->getSection(this->Sections[Entry->SectionIndex-1]);
1506 Res += Sec->Offset - Sec->Address;
1507 }
1508
1509 return object_error::success;
1510 }
1511
1512 template
1513 error_code
1514 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
1515 DataRefImpl Symb,
1516 bool &Result) const {
1517 SymbolRef::Type ST;
1518 this->getSymbolType(Symb, ST);
1519 if (ST == SymbolRef::ST_Unknown) {
1520 Result = false;
1521 return object_error::success;
1522 }
1523
1524 uint64_t SectBegin, SectEnd;
1525 getSectionAddress(Sec, SectBegin);
1526 getSectionSize(Sec, SectEnd);
1527 SectEnd += SectBegin;
1528
1529 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1530 uint64_t SymAddr= Entry->Value;
1531 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
1532
1533 return object_error::success;
1534 }
1535
1536 template
1537 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
1538 uint64_t &Res) const {
1539 const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1540 Res = Entry->Value;
1541 return object_error::success;
1542 }
1543
1544 template
1545 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
1546 uint64_t &Result) const {
1547 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1548 uint64_t BeginOffset;
1549 uint64_t EndOffset = 0;
1550 uint8_t SectionIndex;
1551
1552 const SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
1553 BeginOffset = Entry->Value;
1554 SectionIndex = Entry->SectionIndex;
1555 if (!SectionIndex) {
1556 uint32_t flags = SymbolRef::SF_None;
1557 this->getSymbolFlags(DRI, flags);
1558 if (flags & SymbolRef::SF_Common)
1559 Result = Entry->Value;
1560 else
1561 Result = UnknownAddressOrSize;
1562 return object_error::success;
1563 }
1564 // Unfortunately symbols are unsorted so we need to touch all
1565 // symbols from load command
1566 DRI.d.b = 0;
1567 uint32_t Command = DRI.d.a;
1568 while (Command == DRI.d.a) {
1569 this->moveToNextSymbol(DRI);
1570 if (DRI.d.a < LoadCommandCount) {
1571 Entry = getSymbolTableEntry(DRI);
1572 if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
1573 if (!EndOffset || Entry->Value < EndOffset)
1574 EndOffset = Entry->Value;
1575 }
1576 DRI.d.b++;
1577 }
1578 if (!EndOffset) {
1579 uint64_t Size;
1580 this->getSectionSize(this->Sections[SectionIndex-1], Size);
1581 this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset);
1582 EndOffset += Size;
1583 }
1584 Result = EndOffset - BeginOffset;
1585 return object_error::success;
1586 }
1587
1588 template
1589 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
1590 SectionRef &Res) const {
1591 Sec.d.b++;
1592 moveToNextSection(Sec);
1593 Res = SectionRef(Sec, this);
1594 return object_error::success;
1595 }
1596
1597 template
1598 section_iterator MachOObjectFile::begin_sections() const {
1599 DataRefImpl DRI;
1600 moveToNextSection(DRI);
1601 return section_iterator(SectionRef(DRI, this));
1602 }
1603
1604 template
1605 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
1606 uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1607 while (DRI.d.a < LoadCommandCount) {
1608 const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a);
1609 if (Command->Type == SegmentLoadType) {
1610 const SegmentLoadCommand *SegmentLoadCmd =
1611 reinterpret_cast(Command);
1612 if (DRI.d.b < SegmentLoadCmd->NumSections)
1613 return;
1614 }
1615
1616 DRI.d.a++;
1617 DRI.d.b = 0;
1618 }
1619 }
1620153
1621154 }
1622155 }
1414 #include "llvm/Object/MachO.h"
1515 #include "llvm/ADT/Triple.h"
1616 #include "llvm/Object/MachOFormat.h"
17 #include "llvm/Support/Casting.h"
1817 #include "llvm/Support/DataExtractor.h"
1918 #include "llvm/Support/Format.h"
19 #include "llvm/Support/Host.h"
2020 #include "llvm/Support/MemoryBuffer.h"
2121 #include
2222 #include
2828 namespace llvm {
2929 namespace object {
3030
31 MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object,
32 bool IsLittleEndian, bool Is64bits,
33 error_code &ec)
34 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
35 }
36
37 bool MachOObjectFileBase::is64Bit() const {
38 return isa(this) || isa(this);
39 }
40
41 void MachOObjectFileBase::ReadULEB128s(uint64_t Index,
42 SmallVectorImpl &Out) const {
31 struct SymbolTableEntryBase {
32 uint32_t StringIndex;
33 uint8_t Type;
34 uint8_t SectionIndex;
35 uint16_t Flags;
36 };
37
38 struct SectionBase {
39 char Name[16];
40 char SegmentName[16];
41 };
42
43 template
44 static void SwapValue(T &Value) {
45 Value = sys::SwapByteOrder(Value);
46 }
47
48 template
49 static void SwapStruct(T &Value);
50
51 template<>
52 void SwapStruct(macho::RelocationEntry &H) {
53 SwapValue(H.Word0);
54 SwapValue(H.Word1);
55 }
56
57 template<>
58 void SwapStruct(macho::LoadCommand &L) {
59 SwapValue(L.Type);
60 SwapValue(L.Size);
61 }
62
63 template<>
64 void SwapStruct(SymbolTableEntryBase &S) {
65 SwapValue(S.StringIndex);
66 SwapValue(S.Flags);
67 }
68
69 template<>
70 void SwapStruct(macho::Section &S) {
71 SwapValue(S.Address);
72 SwapValue(S.Size);
73 SwapValue(S.Offset);
74 SwapValue(S.Align);
75 SwapValue(S.RelocationTableOffset);
76 SwapValue(S.NumRelocationTableEntries);
77 SwapValue(S.Flags);
78 SwapValue(S.Reserved1);
79 SwapValue(S.Reserved2);
80 }
81
82 template<>
83 void SwapStruct(macho::Section64 &S) {
84 SwapValue(S.Address);
85 SwapValue(S.Size);
86 SwapValue(S.Offset);
87 SwapValue(S.Align);
88 SwapValue(S.RelocationTableOffset);
89 SwapValue(S.NumRelocationTableEntries);
90 SwapValue(S.Flags);
91 SwapValue(S.Reserved1);
92 SwapValue(S.Reserved2);
93 SwapValue(S.Reserved3);
94 }
95
96 template<>
97 void SwapStruct(macho::SymbolTableEntry &S) {
98 SwapValue(S.StringIndex);
99 SwapValue(S.Flags);
100 SwapValue(S.Value);
101 }
102
103 template<>
104 void SwapStruct(macho::Symbol64TableEntry &S) {
105 SwapValue(S.StringIndex);
106 SwapValue(S.Flags);
107 SwapValue(S.Value);
108 }
109
110 template<>
111 void SwapStruct(macho::Header &H) {
112 SwapValue(H.Magic);
113 SwapValue(H.CPUType);
114 SwapValue(H.CPUSubtype);
115 SwapValue(H.FileType);
116 SwapValue(H.NumLoadCommands);
117 SwapValue(H.SizeOfLoadCommands);
118 SwapValue(H.Flags);
119 }
120
121 template<>
122 void SwapStruct(macho::SymtabLoadCommand &C) {
123 SwapValue(C.Type);
124 SwapValue(C.Size);
125 SwapValue(C.SymbolTableOffset);
126 SwapValue(C.NumSymbolTableEntries);
127 SwapValue(C.StringTableOffset);
128 SwapValue(C.StringTableSize);
129 }
130
131 template<>
132 void SwapStruct(macho::LinkeditDataLoadCommand &C) {
133 SwapValue(C.Type);
134 SwapValue(C.Size);
135 SwapValue(C.DataOffset);
136 SwapValue(C.DataSize);
137 }
138
139 template<>
140 void SwapStruct(macho::SegmentLoadCommand &C) {
141 SwapValue(C.Type);
142 SwapValue(C.Size);
143 SwapValue(C.VMAddress);
144 SwapValue(C.VMSize);
145 SwapValue(C.FileOffset);
146 SwapValue(C.FileSize);
147 SwapValue(C.MaxVMProtection);
148 SwapValue(C.InitialVMProtection);
149 SwapValue(C.NumSections);
150 SwapValue(C.Flags);
151 }
152
153 template<>
154 void SwapStruct(macho::Segment64LoadCommand &C) {
155 SwapValue(C.Type);
156 SwapValue(C.Size);
157 SwapValue(C.VMAddress);
158 SwapValue(C.VMSize);
159 SwapValue(C.FileOffset);
160 SwapValue(C.FileSize);
161 SwapValue(C.MaxVMProtection);
162 SwapValue(C.InitialVMProtection);
163 SwapValue(C.NumSections);
164 SwapValue(C.Flags);
165 }
166
167 static bool isSwappedEndian(const MachOObjectFile *O) {
168 return O->isLittleEndian() != sys::IsLittleEndianHost;
169 }
170
171 static macho::SegmentLoadCommand
172 getSegmentLoadCommand(const MachOObjectFile *O,
173 const MachOObjectFile::LoadCommandInfo &L) {
174 macho::SegmentLoadCommand Cmd;
175 memcpy(&Cmd, L.Ptr, sizeof(macho::SegmentLoadCommand));
176 if (isSwappedEndian(O))
177 SwapStruct(Cmd);
178 return Cmd;
179 }
180
181 static macho::Segment64LoadCommand
182 getSegment64LoadCommand(const MachOObjectFile *O,
183 const MachOObjectFile::LoadCommandInfo &L) {
184 macho::Segment64LoadCommand Cmd;
185 memcpy(&Cmd, L.Ptr, sizeof(macho::Segment64LoadCommand));
186 if (isSwappedEndian(O))
187 SwapStruct(Cmd);
188 return Cmd;
189 }
190
191 static uint32_t
192 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
193 const MachOObjectFile::LoadCommandInfo &L) {
194 if (O->is64Bit()) {
195 macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
196 return S.NumSections;
197 }
198 macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
199 return S.NumSections;
200 }
201
202 static const SectionBase *
203 getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
204 unsigned Sec) {
205 uintptr_t CommandAddr = reinterpret_cast(L.Ptr);
206
207 bool Is64 = O->is64Bit();
208 unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
209 sizeof(macho::SegmentLoadCommand);
210 unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
211 sizeof(macho::Section);
212
213 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
214 return reinterpret_cast(SectionAddr);
215 }
216
217 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
218 return O->getData().substr(Offset, 1).data();
219 }
220
221 static const char *getSymbolTableEntryPtr(const MachOObjectFile *O,
222 DataRefImpl DRI) {
223 macho::SymtabLoadCommand S = O->getSymtabLoadCommand();
224
225 unsigned Index = DRI.d.b;
226
227 unsigned SymbolTableEntrySize = O->is64Bit() ?
228 sizeof(macho::Symbol64TableEntry) :
229 sizeof(macho::SymbolTableEntry);
230
231 uint64_t Offset = S.SymbolTableOffset + Index * SymbolTableEntrySize;
232 return getPtr(O, Offset);
233 }
234
235 static SymbolTableEntryBase
236 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
237 const char *P = getSymbolTableEntryPtr(O, DRI);
238 SymbolTableEntryBase Ret;
239 memcpy(&Ret, P, sizeof(SymbolTableEntryBase));
240 if (isSwappedEndian(O))
241 SwapStruct(Ret);
242
243 return Ret;
244 }
245
246 static StringRef parseSegmentOrSectionName(const char *P) {
247 if (P[15] == 0)
248 // Null terminated.
249 return P;
250 // Not null terminated, so this is a 16 char string.
251 return StringRef(P, 16);
252 }
253
254 // Helper to advance a section or symbol iterator multiple increments at a time.
255 template
256 static error_code advance(T &it, size_t Val) {
257 error_code ec;
258 while (Val--) {
259 it.increment(ec);
260 }
261 return ec;
262 }
263
264 template
265 static void advanceTo(T &it, size_t Val) {
266 if (error_code ec = advance(it, Val))
267 report_fatal_error(ec.message());
268 }
269
270 static unsigned getCPUType(const MachOObjectFile *O) {
271 return O->getHeader().CPUType;
272 }
273
274 static void printRelocationTargetName(const MachOObjectFile *O,
275 const macho::RelocationEntry &RE,
276 raw_string_ostream &fmt) {
277 bool IsScattered = O->isRelocationScattered(RE);
278
279 // Target of a scattered relocation is an address. In the interest of
280 // generating pretty output, scan through the symbol table looking for a
281 // symbol that aligns with that address. If we find one, print it.
282 // Otherwise, we just print the hex address of the target.
283 if (IsScattered) {
284 uint32_t Val = O->getPlainRelocationSymbolNum(RE);
285
286 error_code ec;
287 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
288 SI != SE; SI.increment(ec)) {
289 if (ec) report_fatal_error(ec.message());
290
291 uint64_t Addr;
292 StringRef Name;
293
294 if ((ec = SI->getAddress(Addr)))
295 report_fatal_error(ec.message());
296 if (Addr != Val) continue;
297 if ((ec = SI->getName(Name)))
298 report_fatal_error(ec.message());
299 fmt << Name;
300 return;
301 }
302
303 // If we couldn't find a symbol that this relocation refers to, try
304 // to find a section beginning instead.
305 for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
306 SI != SE; SI.increment(ec)) {
307 if (ec) report_fatal_error(ec.message());
308
309 uint64_t Addr;
310 StringRef Name;
311
312 if ((ec = SI->getAddress(Addr)))
313 report_fatal_error(ec.message());
314 if (Addr != Val) continue;
315 if ((ec = SI->getName(Name)))
316 report_fatal_error(ec.message());
317 fmt << Name;
318 return;
319 }
320
321 fmt << format("0x%x", Val);
322 return;
323 }
324
325 StringRef S;
326 bool isExtern = O->getPlainRelocationExternal(RE);
327 uint64_t Val = O->getAnyRelocationAddress(RE);
328
329 if (isExtern) {
330 symbol_iterator SI = O->begin_symbols();
331 advanceTo(SI, Val);
332 SI->getName(S);
333 } else {
334 section_iterator SI = O->begin_sections();
335 advanceTo(SI, Val);
336 SI->getName(S);
337 }
338
339 fmt << S;
340 }
341
342 static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
343 return RE.Word0;
344 }
345
346 static unsigned
347 getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
348 return RE.Word0 & 0xffffff;
349 }
350
351 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
352 const macho::RelocationEntry &RE) {
353 if (O->isLittleEndian())
354 return (RE.Word1 >> 24) & 1;
355 return (RE.Word1 >> 7) & 1;
356 }
357
358 static bool
359 getScatteredRelocationPCRel(const MachOObjectFile *O,
360 const macho::RelocationEntry &RE) {
361 return (RE.Word0 >> 30) & 1;
362 }
363
364 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
365 const macho::RelocationEntry &RE) {
366 if (O->isLittleEndian())
367 return (RE.Word1 >> 25) & 3;
368 return (RE.Word1 >> 5) & 3;
369 }
370
371 static unsigned
372 getScatteredRelocationLength(const macho::RelocationEntry &RE) {
373 return (RE.Word0 >> 28) & 3;
374 }
375
376 static unsigned getPlainRelocationType(const MachOObjectFile *O,
377 const macho::RelocationEntry &RE) {
378 if (O->isLittleEndian())
379 return RE.Word1 >> 28;
380 return RE.Word1 & 0xf;
381 }
382
383 static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
384 return (RE.Word0 >> 24) & 0xf;
385 }
386
387 static uint32_t getSectionFlags(const MachOObjectFile *O,
388 DataRefImpl Sec) {
389 if (O->is64Bit()) {
390 macho::Section64 Sect = O->getSection64(Sec);
391 return Sect.Flags;
392 }
393 macho::Section Sect = O->getSection(Sec);
394 return Sect.Flags;
395 }
396
397 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
398 bool IsLittleEndian, bool Is64bits,
399 error_code &ec)
400 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
401 SymtabLoadCmd(NULL) {
402 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
403 macho::LoadCommandType SegmentLoadType = is64Bit() ?
404 macho::LCT_Segment64 : macho::LCT_Segment;
405
406 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
407 for (unsigned I = 0; I < LoadCommandCount; ++I) {
408 if (Load.C.Type == macho::LCT_Symtab) {
409 assert(!SymtabLoadCmd && "Multiple symbol tables");
410 SymtabLoadCmd = Load.Ptr;
411 }
412
413 if (Load.C.Type == SegmentLoadType) {
414 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
415 for (unsigned J = 0; J < NumSections; ++J) {
416 const SectionBase *Sec = getSectionBase(this, Load, J);
417 Sections.push_back(reinterpret_cast(Sec));
418 }
419 }
420 Load = getNextLoadCommandInfo(Load);
421 }
422 }
423
424 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
425 SymbolRef &Res) const {
426 Symb.d.b++;
427 Res = SymbolRef(Symb, this);
428 return object_error::success;
429 }
430
431 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
432 StringRef &Res) const {
433 macho::SymtabLoadCommand S = getSymtabLoadCommand();
434 const char *StringTable = getPtr(this, S.StringTableOffset);
435 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
436 const char *Start = &StringTable[Entry.StringIndex];
437 Res = StringRef(Start);
438 return object_error::success;
439 }
440
441 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
442 uint64_t &Res) const {
443 if (is64Bit()) {
444 macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
445 Res = Entry.Value;
446 } else {
447 macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
448 Res = Entry.Value;
449 }
450 return object_error::success;
451 }
452
453 error_code
454 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
455 uint64_t &Res) const {
456 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
457 getSymbolAddress(Symb, Res);
458 if (Entry.SectionIndex) {
459 uint64_t Delta;
460 DataRefImpl SecRel;
461 SecRel.d.a = Entry.SectionIndex-1;
462 if (is64Bit()) {
463 macho::Section64 Sec = getSection64(SecRel);
464 Delta = Sec.Offset - Sec.Address;
465 } else {
466 macho::Section Sec = getSection(SecRel);
467 Delta = Sec.Offset - Sec.Address;
468 }
469
470 Res += Delta;
471 }
472
473 return object_error::success;
474 }
475
476 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
477 uint64_t &Result) const {
478 uint64_t BeginOffset;
479 uint64_t EndOffset = 0;
480 uint8_t SectionIndex;
481
482 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
483 uint64_t Value;
484 getSymbolAddress(DRI, Value);
485
486 BeginOffset = Value;
487
488 SectionIndex = Entry.SectionIndex;
489 if (!SectionIndex) {
490 uint32_t flags = SymbolRef::SF_None;
491 this->getSymbolFlags(DRI, flags);
492 if (flags & SymbolRef::SF_Common)
493 Result = Value;
494 else
495 Result = UnknownAddressOrSize;
496 return object_error::success;
497 }
498 // Unfortunately symbols are unsorted so we need to touch all
499 // symbols from load command
500 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
501 DRI.d.b = 0;
502 while (DRI.d.b <= Symtab.NumSymbolTableEntries) {
503 Entry = getSymbolTableEntryBase(this, DRI);
504 getSymbolAddress(DRI, Value);
505 if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
506 if (!EndOffset || Value < EndOffset)
507 EndOffset = Value;
508 DRI.d.b++;
509 }
510 if (!EndOffset) {
511 uint64_t Size;
512 DataRefImpl Sec;
513 Sec.d.a = SectionIndex-1;
514 getSectionSize(Sec, Size);
515 getSectionAddress(Sec, EndOffset);
516 EndOffset += Size;
517 }
518 Result = EndOffset - BeginOffset;
519 return object_error::success;
520 }
521
522 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
523 SymbolRef::Type &Res) const {
524 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
525 uint8_t n_type = Entry.Type;
526
527 Res = SymbolRef::ST_Other;
528
529 // If this is a STAB debugging symbol, we can do nothing more.
530 if (n_type & MachO::NlistMaskStab) {
531 Res = SymbolRef::ST_Debug;
532 return object_error::success;
533 }
534
535 switch (n_type & MachO::NlistMaskType) {
536 case MachO::NListTypeUndefined :
537 Res = SymbolRef::ST_Unknown;
538 break;
539 case MachO::NListTypeSection :
540 Res = SymbolRef::ST_Function;
541 break;
542 }
543 return object_error::success;
544 }
545
546 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
547 char &Res) const {
548 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
549 uint8_t Type = Entry.Type;
550 uint16_t Flags = Entry.Flags;
551
552 char Char;
553 switch (Type & macho::STF_TypeMask) {
554 case macho::STT_Undefined:
555 Char = 'u';
556 break;
557 case macho::STT_Absolute:
558 case macho::STT_Section:
559 Char = 's';
560 break;
561 default:
562 Char = '?';
563 break;
564 }
565
566 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
567 Char = toupper(static_cast(Char));
568 Res = Char;
569 return object_error::success;
570 }
571
572 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
573 uint32_t &Result) const {
574 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
575
576 uint8_t MachOType = Entry.Type;
577 uint16_t MachOFlags = Entry.Flags;
578
579 // TODO: Correctly set SF_ThreadLocal
580 Result = SymbolRef::SF_None;
581
582 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
583 Result |= SymbolRef::SF_Undefined;
584
585 if (MachOFlags & macho::STF_StabsEntryMask)
586 Result |= SymbolRef::SF_FormatSpecific;
587
588 if (MachOType & MachO::NlistMaskExternal) {
589 Result |= SymbolRef::SF_Global;
590 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
591 Result |= SymbolRef::SF_Common;
592 }
593
594 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
595 Result |= SymbolRef::SF_Weak;
596
597 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
598 Result |= SymbolRef::SF_Absolute;
599
600 return object_error::success;
601 }
602
603 error_code
604 MachOObjectFile::getSymbolSection(DataRefImpl Symb,
605 section_iterator &Res) const {
606 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
607 uint8_t index = Entry.SectionIndex;
608
609 if (index == 0) {
610 Res = end_sections();
611 } else {
612 DataRefImpl DRI;
613 DRI.d.a = index - 1;
614 Res = section_iterator(SectionRef(DRI, this));
615 }
616
617 return object_error::success;
618 }
619
620 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
621 uint64_t &Val) const {
622 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
623 }
624
625 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
626 SectionRef &Res) const {
627 Sec.d.a++;
628 Res = SectionRef(Sec, this);
629 return object_error::success;
630 }
631
632 error_code
633 MachOObjectFile::getSectionName(DataRefImpl Sec,
634 StringRef &Result) const {
635 ArrayRef Raw = getSectionRawName(Sec);
636 Result = parseSegmentOrSectionName(Raw.data());
637 return object_error::success;
638 }
639
640 error_code
641 MachOObjectFile::getSectionAddress(DataRefImpl Sec,
642 uint64_t &Res) const {
643 if (is64Bit()) {
644 macho::Section64 Sect = getSection64(Sec);
645 Res = Sect.Address;
646 } else {
647 macho::Section Sect = getSection(Sec);
648 Res = Sect.Address;
649 }
650 return object_error::success;
651 }
652
653 error_code
654 MachOObjectFile::getSectionSize(DataRefImpl Sec,
655 uint64_t &Res) const {
656 if (is64Bit()) {
657 macho::Section64 Sect = getSection64(Sec);
658 Res = Sect.Size;
659 } else {
660 macho::Section Sect = getSection(Sec);
661 Res = Sect.Size;
662 }
663
664 return object_error::success;
665 }
666
667 error_code
668 MachOObjectFile::getSectionContents(DataRefImpl Sec,
669 StringRef &Res) const {
670 uint32_t Offset;
671 uint64_t Size;
672
673 if (is64Bit()) {
674 macho::Section64 Sect = getSection64(Sec);
675 Offset = Sect.Offset;
676 Size = Sect.Size;
677 } else {
678 macho::Section Sect =getSection(Sec);
679 Offset = Sect.Offset;
680 Size = Sect.Size;
681 }
682
683 Res = this->getData().substr(Offset, Size);
684 return object_error::success;
685 }
686
687 error_code
688 MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
689 uint64_t &Res) const {
690 uint32_t Align;
691 if (is64Bit()) {
692 macho::Section64 Sect = getSection64(Sec);
693 Align = Sect.Align;
694 } else {
695 macho::Section Sect = getSection(Sec);
696 Align = Sect.Align;
697 }
698
699 Res = uint64_t(1) << Align;
700 return object_error::success;
701 }
702
703 error_code
704 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
705 uint32_t Flags = getSectionFlags(this, Sec);
706 Res = Flags & macho::SF_PureInstructions;
707 return object_error::success;
708 }
709
710 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
711 bool &Result) const {
712 // FIXME: Unimplemented.
713 Result = false;
714 return object_error::success;
715 }
716
717 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
718 bool &Result) const {
719 // FIXME: Unimplemented.
720 Result = false;
721 return object_error::success;
722 }
723
724 error_code
725 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
726 bool &Result) const {
727 // FIXME: Unimplemented.
728 Result = true;
729 return object_error::success;
730 }
731
732 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
733 bool &Result) const {
734 // FIXME: Unimplemented.
735 Result = false;
736 return object_error::success;
737 }
738
739 error_code
740 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
741 uint32_t Flags = getSectionFlags(this, Sec);
742 unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
743 Res = SectionType == MachO::SectionTypeZeroFill ||
744 SectionType == MachO::SectionTypeZeroFillLarge;
745 return object_error::success;
746 }
747
748 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
749 bool &Result) const {
750 // Consider using the code from isSectionText to look for __const sections.
751 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
752 // to use section attributes to distinguish code from data.
753
754 // FIXME: Unimplemented.
755 Result = false;
756 return object_error::success;
757 }
758
759 error_code
760 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
761 DataRefImpl Symb,
762 bool &Result) const {
763 SymbolRef::Type ST;
764 this->getSymbolType(Symb, ST);
765 if (ST == SymbolRef::ST_Unknown) {
766 Result = false;
767 return object_error::success;
768 }
769
770 uint64_t SectBegin, SectEnd;
771 getSectionAddress(Sec, SectBegin);
772 getSectionSize(Sec, SectEnd);
773 SectEnd += SectBegin;
774
775 uint64_t SymAddr;
776 getSymbolAddress(Symb, SymAddr);
777 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
778
779 return object_error::success;
780 }
781
782 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
783 DataRefImpl ret;
784 ret.d.b = Sec.d.a;
785 return relocation_iterator(RelocationRef(ret, this));
786 }
787
788 relocation_iterator
789 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
790 uint32_t LastReloc;
791 if (is64Bit()) {
792 macho::Section64 Sect = getSection64(Sec);
793 LastReloc = Sect.NumRelocationTableEntries;
794 } else {
795 macho::Section Sect = getSection(Sec);
796 LastReloc = Sect.NumRelocationTableEntries;
797 }
798
799 DataRefImpl Ret;
800 Ret.d.a = LastReloc;
801 Ret.d.b = Sec.d.a;
802 return relocation_iterator(RelocationRef(Ret, this));
803 }
804
805 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
806 RelocationRef &Res) const {
807 ++Rel.d.a;
808 Res = RelocationRef(Rel, this);
809 return object_error::success;
810 }
811
812 error_code
813 MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
814 uint64_t &Res) const {
815 uint64_t SectAddress;
816 DataRefImpl Sec;
817 Sec.d.a = Rel.d.b;
818 if (is64Bit()) {
819 macho::Section64 Sect = getSection64(Sec);
820 SectAddress = Sect.Address;
821 } else {
822 macho::Section Sect = getSection(Sec);
823 SectAddress = Sect.Address;
824 }
825
826 macho::RelocationEntry RE = getRelocation(Rel);
827 uint64_t RelAddr = getAnyRelocationAddress(RE);
828 Res = SectAddress + RelAddr;
829 return object_error::success;
830 }
831
832 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
833 uint64_t &Res) const {
834 macho::RelocationEntry RE = getRelocation(Rel);
835 Res = getAnyRelocationAddress(RE);
836 return object_error::success;
837 }
838
839 error_code
840 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
841 SymbolRef &Res) const {
842 macho::RelocationEntry RE = getRelocation(Rel);
843 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
844 bool isExtern = getPlainRelocationExternal(RE);
845
846 DataRefImpl Sym;
847 if (isExtern) {
848 Sym.d.b = SymbolIdx;
849 }
850 Res = SymbolRef(Sym, this);
851 return object_error::success;
852 }
853
854 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
855 uint64_t &Res) const {
856 macho::RelocationEntry RE = getRelocation(Rel);
857 Res = getAnyRelocationType(RE);
858 return object_error::success;
859 }
860
861 error_code
862 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
863 SmallVectorImpl &Result) const {
864 StringRef res;
865 uint64_t RType;
866 getRelocationType(Rel, RType);
867
868 unsigned Arch = this->getArch();
869
870 switch (Arch) {
871 case Triple::x86: {
872 static const char *const Table[] = {
873 "GENERIC_RELOC_VANILLA",
874 "GENERIC_RELOC_PAIR",
875 "GENERIC_RELOC_SECTDIFF",
876 "GENERIC_RELOC_PB_LA_PTR",
877 "GENERIC_RELOC_LOCAL_SECTDIFF",
878 "GENERIC_RELOC_TLV" };
879
880 if (RType > 6)
881 res = "Unknown";
882 else
883 res = Table[RType];
884 break;
885 }
886 case Triple::x86_64: {
887 static const char *const Table[] = {
888 "X86_64_RELOC_UNSIGNED",
889 "X86_64_RELOC_SIGNED",
890 "X86_64_RELOC_BRANCH",
891 "X86_64_RELOC_GOT_LOAD",
892 "X86_64_RELOC_GOT",
893 "X86_64_RELOC_SUBTRACTOR",
894 "X86_64_RELOC_SIGNED_1",
895 "X86_64_RELOC_SIGNED_2",
896 "X86_64_RELOC_SIGNED_4",
897 "X86_64_RELOC_TLV" };
898
899 if (RType > 9)
900 res = "Unknown";
901 else
902 res = Table[RType];
903 break;
904 }
905 case Triple::arm: {
906 static const char *const Table[] = {
907 "ARM_RELOC_VANILLA",
908 "ARM_RELOC_PAIR",
909 "ARM_RELOC_SECTDIFF",
910 "ARM_RELOC_LOCAL_SECTDIFF",
911 "ARM_RELOC_PB_LA_PTR",
912 "ARM_RELOC_BR24",
913 "ARM_THUMB_RELOC_BR22",
914 "ARM_THUMB_32BIT_BRANCH",
915 "ARM_RELOC_HALF",
916 "ARM_RELOC_HALF_SECTDIFF" };
917
918 if (RType > 9)
919 res = "Unknown";
920 else
921 res = Table[RType];
922 break;
923 }
924 case Triple::ppc: {
925 static const char *const Table[] = {
926 "PPC_RELOC_VANILLA",
927 "PPC_RELOC_PAIR",
928 "PPC_RELOC_BR14",
929 "PPC_RELOC_BR24",
930 "PPC_RELOC_HI16",
931 "PPC_RELOC_LO16",
932 "PPC_RELOC_HA16",
933 "PPC_RELOC_LO14",
934 "PPC_RELOC_SECTDIFF",
935 "PPC_RELOC_PB_LA_PTR",
936 "PPC_RELOC_HI16_SECTDIFF",
937 "PPC_RELOC_LO16_SECTDIFF",
938 "PPC_RELOC_HA16_SECTDIFF",
939 "PPC_RELOC_JBSR",
940 "PPC_RELOC_LO14_SECTDIFF",
941 "PPC_RELOC_LOCAL_SECTDIFF" };
942
943 res = Table[RType];
944 break;
945 }
946 case Triple::UnknownArch:
947 res = "Unknown";
948 break;
949 }
950 Result.append(res.begin(), res.end());
951 return object_error::success;
952 }
953
954 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
955 int64_t &Res) const {
956 Res = 0;
957 return object_error::success;
958 }
959
960 error_code
961 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
962 SmallVectorImpl &Result) const {
963 macho::RelocationEntry RE = getRelocation(Rel);
964
965 unsigned Arch = this->getArch();
966
967 std::string fmtbuf;
968 raw_string_ostream fmt(fmtbuf);
969 unsigned Type = this->getAnyRelocationType(RE);
970 bool IsPCRel = this->getAnyRelocationPCRel(RE);
971
972 // Determine any addends that should be displayed with the relocation.
973 // These require decoding the relocation type, which is triple-specific.
974
975 // X86_64 has entirely custom relocation types.
976 if (Arch == Triple::x86_64) {
977 bool isPCRel = getAnyRelocationPCRel(RE);
978
979 switch (Type) {
980 case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
981 case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT
982 printRelocationTargetName(this, RE, fmt);
983 fmt << "@GOT";
984 if (isPCRel) fmt << "PCREL";
985 break;
986 }
987 case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
988 DataRefImpl RelNext = Rel;
989 RelNext.d.a++;
990 macho::RelocationEntry RENext = getRelocation(RelNext);
991
992 // X86_64_SUBTRACTOR must be followed by a relocation of type
993 // X86_64_RELOC_UNSIGNED.
994 // NOTE: Scattered relocations don't exist on x86_64.
995 unsigned RType = getAnyRelocationType(RENext);
996 if (RType != 0)
997 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
998 "X86_64_RELOC_SUBTRACTOR.");
999
1000 // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1001 // X86_64_SUBTRACTOR contains to the subtrahend.
1002 printRelocationTargetName(this, RENext, fmt);
1003 fmt << "-";
1004 printRelocationTargetName(this, RE, fmt);
1005 break;
1006 }
1007 case macho::RIT_X86_64_TLV:
1008 printRelocationTargetName(this, RE, fmt);
1009 fmt << "@TLV";
1010 if (isPCRel) fmt << "P";
1011 break;
1012 case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1013 printRelocationTargetName(this, RE, fmt);
1014 fmt << "-1";
1015 break;
1016 case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1017 printRelocationTargetName(this, RE, fmt);
1018 fmt << "-2";
1019 break;
1020 case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1021 printRelocationTargetName(this, RE, fmt);
1022 fmt << "-4";
1023 break;
1024 default:
1025 printRelocationTargetName(this, RE, fmt);
1026 break;
1027 }
1028 // X86 and ARM share some relocation types in common.
1029 } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1030 // Generic relocation types...
1031 switch (Type) {
1032 case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1033 return object_error::success;
1034 case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1035 DataRefImpl RelNext = Rel;
1036 RelNext.d.a++;
1037 macho::RelocationEntry RENext = getRelocation(RelNext);
1038
1039 // X86 sect diff's must be followed by a relocation of type
1040 // GENERIC_RELOC_PAIR.
1041 unsigned RType = getAnyRelocationType(RENext);
1042
1043 if (RType != 1)
1044 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1045 "GENERIC_RELOC_SECTDIFF.");
1046
1047 printRelocationTargetName(this, RE, fmt);
1048 fmt << "-";
1049 printRelocationTargetName(this, RENext, fmt);
1050 break;
1051 }
1052 }
1053
1054 if (Arch == Triple::x86) {
1055 // All X86 relocations that need special printing were already
1056 // handled in the generic code.
1057 switch (Type) {
1058 case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1059 DataRefImpl RelNext = Rel;
1060 RelNext.d.a++;
1061 macho::RelocationEntry RENext = getRelocation(RelNext);
1062
1063 // X86 sect diff's must be followed by a relocation of type
1064 // GENERIC_RELOC_PAIR.
1065 unsigned RType = getAnyRelocationType(RENext);
1066 if (RType != 1)
1067 report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1068 "GENERIC_RELOC_LOCAL_SECTDIFF.");
1069
1070 printRelocationTargetName(this, RE, fmt);
1071 fmt << "-";
1072 printRelocationTargetName(this, RENext, fmt);
1073 break;
1074 }
1075 case macho::RIT_Generic_TLV: {
1076 printRelocationTargetName(this, RE, fmt);
1077 fmt << "@TLV";
1078 if (IsPCRel) fmt << "P";
1079 break;
1080 }
1081 default:
1082 printRelocationTargetName(this, RE, fmt);
1083 }
1084 } else { // ARM-specific relocations
1085 switch (Type) {
1086 case macho::RIT_ARM_Half: // ARM_RELOC_HALF
1087 case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1088 // Half relocations steal a bit from the length field to encode
1089 // whether this is an upper16 or a lower16 relocation.
1090 bool isUpper = getAnyRelocationLength(RE) >> 1;
1091
1092 if (isUpper)
1093 fmt << ":upper16:(";
1094 else
1095 fmt << ":lower16:(";
1096 printRelocationTargetName(this, RE, fmt);
1097
1098 DataRefImpl RelNext = Rel;
1099 RelNext.d.a++;
1100 macho::RelocationEntry RENext = getRelocation(RelNext);
1101
1102 // ARM half relocs must be followed by a relocation of type
1103 // ARM_RELOC_PAIR.
1104 unsigned RType = getAnyRelocationType(RENext);
1105 if (RType != 1)
1106 report_fatal_error("Expected ARM_RELOC_PAIR after "
1107 "GENERIC_RELOC_HALF");
1108
1109 // NOTE: The half of the target virtual address is stashed in the
1110 // address field of the secondary relocation, but we can't reverse
1111 // engineer the constant offset from it without decoding the movw/movt
1112 // instruction to find the other half in its immediate field.
1113
1114 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1115 // symbol/section pointer of the follow-on relocation.
1116 if (Type == macho::RIT_ARM_HalfDifference) {
1117 fmt << "-";
1118 printRelocationTargetName(this, RENext, fmt);
1119 }
1120
1121 fmt << ")";
1122 break;
1123 }
1124 default: {
1125 printRelocationTargetName(this, RE, fmt);
1126 }
1127 }
1128 }
1129 } else
1130 printRelocationTargetName(this, RE, fmt);
1131
1132 fmt.flush();
1133 Result.append(fmtbuf.begin(), fmtbuf.end());
1134 return object_error::success;
1135 }
1136
1137 error_code
1138 MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
1139 bool &Result) const {
1140 unsigned Arch = getArch();
1141 uint64_t Type;
1142 getRelocationType(Rel, Type);
1143
1144 Result = false;
1145
1146 // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1147 // is always hidden.
1148 if (Arch == Triple::x86 || Arch == Triple::arm) {
1149 if (Type == macho::RIT_Pair) Result = true;
1150 } else if (Arch == Triple::x86_64) {
1151 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1152 // an X864_64_RELOC_SUBTRACTOR.
1153 if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1154 DataRefImpl RelPrev = Rel;
1155 RelPrev.d.a--;
1156 uint64_t PrevType;
1157 getRelocationType(RelPrev, PrevType);
1158 if (PrevType == macho::RIT_X86_64_Subtractor)
1159 Result = true;
1160 }
1161 }
1162
1163 return object_error::success;
1164 }
1165
1166 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
1167 LibraryRef &Res) const {
1168 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1169 }
1170
1171 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
1172 StringRef &Res) const {
1173 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1174 }
1175
1176 symbol_iterator MachOObjectFile::begin_symbols() const {
1177 // DRI.d.a = segment number; DRI.d.b = symbol index.
1178 DataRefImpl DRI;
1179 return symbol_iterator(SymbolRef(DRI, this));
1180 }
1181
1182 symbol_iterator MachOObjectFile::end_symbols() const {
1183 DataRefImpl DRI;
1184 if (SymtabLoadCmd) {
1185 macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
1186 DRI.d.b = Symtab.NumSymbolTableEntries;
1187 }
1188 return symbol_iterator(SymbolRef(DRI, this));
1189 }
1190
1191 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
1192 // TODO: implement
1193 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1194 }
1195
1196 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
1197 // TODO: implement
1198 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
1199 }
1200
1201 section_iterator MachOObjectFile::begin_sections() const {
1202 DataRefImpl DRI;
1203 return section_iterator(SectionRef(DRI, this));
1204 }
1205
1206 section_iterator MachOObjectFile::end_sections() const {
1207 DataRefImpl DRI;
1208 DRI.d.a = Sections.size();
1209 return section_iterator(SectionRef(DRI, this));
1210 }
1211
1212 library_iterator MachOObjectFile::begin_libraries_needed() const {
1213 // TODO: implement
1214 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1215 }
1216
1217 library_iterator MachOObjectFile::end_libraries_needed() const {
1218 // TODO: implement
1219 report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
1220 }
1221
1222 uint8_t MachOObjectFile::getBytesInAddress() const {
1223 return is64Bit() ? 8 : 4;
1224 }
1225
1226 StringRef MachOObjectFile::getFileFormatName() const {
1227 unsigned CPUType = getCPUType(this);
1228 if (!is64Bit()) {
1229 switch (CPUType) {
1230 case llvm::MachO::CPUTypeI386:
1231 return "Mach-O 32-bit i386";
1232 case llvm::MachO::CPUTypeARM:
1233 return "Mach-O arm";
1234 case llvm::MachO::CPUTypePowerPC:
1235 return "Mach-O 32-bit ppc";
1236 default:
1237 assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
1238 "64-bit object file when we're not 64-bit?");
1239 return "Mach-O 32-bit unknown";
1240 }
1241 }
1242
1243 // Make sure the cpu type has the correct mask.
1244 assert((CPUType & llvm::MachO::CPUArchABI64)
1245 == llvm::MachO::CPUArchABI64 &&
1246 "32-bit object file when we're 64-bit?");
1247
1248 switch (CPUType) {
1249 case llvm::MachO::CPUTypeX86_64:
1250 return "Mach-O 64-bit x86-64";
1251 case llvm::MachO::CPUTypePowerPC64:
1252 return "Mach-O 64-bit ppc64";
1253 default:
1254 return "Mach-O 64-bit unknown";
1255 }
1256 }
1257
1258 unsigned MachOObjectFile::getArch() const {
1259 switch (getCPUType(this)) {
1260 case llvm::MachO::CPUTypeI386:
1261 return Triple::x86;
1262 case llvm::MachO::CPUTypeX86_64:
1263 return Triple::x86_64;
1264 case llvm::MachO::CPUTypeARM:
1265 return Triple::arm;
1266 case llvm::MachO::CPUTypePowerPC:
1267 return Triple::ppc;
1268 case llvm::MachO::CPUTypePowerPC64:
1269 return Triple::ppc64;
1270 default:
1271 return Triple::UnknownArch;
1272 }
1273 }
1274
1275 StringRef MachOObjectFile::getLoadName() const {
1276 // TODO: Implement
1277 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
1278 }
1279
1280 StringRef
1281 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
1282 ArrayRef Raw = getSectionRawFinalSegmentName(Sec);
1283 return parseSegmentOrSectionName(Raw.data());
1284 }
1285
1286 ArrayRef
1287 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
1288 const SectionBase *Base =
1289 reinterpret_cast(Sections[Sec.d.a]);
1290 return ArrayRef(Base->Name);
1291 }
1292
1293 ArrayRef
1294 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
1295 const SectionBase *Base =
1296 reinterpret_cast(Sections[Sec.d.a]);
1297 return ArrayRef(Base->SegmentName);
1298 }
1299
1300 bool
1301 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
1302 const {
1303 if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
1304 return false;
1305 return getPlainRelocationAddress(RE) & macho::RF_Scattered;
1306 }
1307
1308 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
1309 if (isLittleEndian())
1310 return RE.Word1 & 0xffffff;
1311 return RE.Word1 >> 8;
1312 }
1313
1314 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
1315 if (isLittleEndian())
1316 return (RE.Word1 >> 27) & 1;
1317 return (RE.Word1 >> 4) & 1;
1318 }
1319
1320 bool
1321 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
1322 return RE.Word0 >> 31;
1323 }
1324
1325 uint32_t
1326 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
1327 return RE.Word1;
1328 }
1329
1330 unsigned
1331 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
1332 if (isRelocationScattered(RE))
1333 return getScatteredRelocationAddress(RE);
1334 return getPlainRelocationAddress(RE);
1335 }
1336
1337 unsigned
1338 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
1339 if (isRelocationScattered(RE))
1340 return getScatteredRelocationPCRel(this, RE);
1341 return getPlainRelocationPCRel(this, RE);
1342 }
1343
1344 unsigned
1345 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
1346 if (isRelocationScattered(RE))
1347 return getScatteredRelocationLength(RE);
1348 return getPlainRelocationLength(this, RE);
1349 }
1350
1351 unsigned
1352 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
1353 if (isRelocationScattered(RE))
1354 return getScatteredRelocationType(RE);
1355 return getPlainRelocationType(this, RE);
1356 }
1357
1358 MachOObjectFile::LoadCommandInfo
1359 MachOObjectFile::getFirstLoadCommandInfo() const {
1360 MachOObjectFile::LoadCommandInfo Load;
1361
1362 unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
1363 Load.Ptr = getPtr(this, HeaderSize);
1364 memcpy(&Load.C, Load.Ptr, sizeof(macho::LoadCommand));
1365 if (isSwappedEndian(this))
1366 SwapStruct(Load.C);
1367 return Load;
1368 }
1369
1370 MachOObjectFile::LoadCommandInfo
1371 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
1372 MachOObjectFile::LoadCommandInfo Next;
1373 Next.Ptr = L.Ptr + L.C.Size;
1374 memcpy(&Next.C, Next.Ptr, sizeof(macho::LoadCommand));
1375 if (isSwappedEndian(this))
1376 SwapStruct(Next.C);
1377 return Next;
1378 }
1379
1380 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
1381 const SectionBase *Addr =
1382 reinterpret_cast(Sections[DRI.d.a]);
1383 macho::Section Ret;
1384 memcpy(&Ret, Addr, sizeof(macho::Section));
1385 if (isSwappedEndian(this))
1386 SwapStruct(Ret);
1387 return Ret;
1388 }
1389
1390 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
1391 const SectionBase *Addr =
1392 reinterpret_cast(Sections[DRI.d.a]);
1393 macho::Section64 Ret;
1394 memcpy(&Ret, Addr, sizeof(macho::Section64));
1395 if (isSwappedEndian(this))
1396 SwapStruct(Ret);
1397 return Ret;
1398 }
1399
1400 macho::SymbolTableEntry
1401 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
1402 const char *P = getSymbolTableEntryPtr(this, DRI);
1403 macho::SymbolTableEntry Ret;
1404 memcpy(&Ret, P, sizeof(macho::SymbolTableEntry));
1405 if (isSwappedEndian(this))
1406 SwapStruct(Ret);
1407 return Ret;
1408 }
1409
1410 macho::Symbol64TableEntry
1411 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
1412 const char *P = getSymbolTableEntryPtr(this, DRI);
1413 macho::Symbol64TableEntry Ret;
1414 memcpy(&Ret, P, sizeof(macho::Symbol64TableEntry));
1415 if (isSwappedEndian(this))
1416 SwapStruct(Ret);
1417 return Ret;
1418 }
1419
1420 macho::LinkeditDataLoadCommand
1421 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
1422 macho::LinkeditDataLoadCommand Cmd;
1423 memcpy(&Cmd, L.Ptr, sizeof(macho::LinkeditDataLoadCommand));
1424 if (isSwappedEndian(this))
1425 SwapStruct(Cmd);
1426 return Cmd;
1427 }
1428
1429 macho::RelocationEntry
1430 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
1431 uint32_t RelOffset;
1432 DataRefImpl Sec;
1433 Sec.d.a = Rel.d.b;
1434 if (is64Bit()) {
1435 macho::Section64 Sect = getSection64(Sec);
1436 RelOffset = Sect.RelocationTableOffset;
1437 } else {
1438 macho::Section Sect = getSection(Sec);
1439 RelOffset = Sect.RelocationTableOffset;
1440 }
1441
1442 uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry);
1443
1444 macho::RelocationEntry Ret;
1445 memcpy(&Ret, getPtr(this, Offset), sizeof(macho::RelocationEntry));
1446 if (isSwappedEndian(this))
1447 SwapStruct(Ret);
1448
1449 return Ret;
1450 }
1451
1452 macho::Header MachOObjectFile::getHeader() const {
1453 macho::Header H;
1454 memcpy(&H, getPtr(this, 0), sizeof(macho::Header));
1455 if (isSwappedEndian(this))
1456 SwapStruct(H);
1457 return H;
1458 }
1459
1460 macho::SymtabLoadCommand
1461 MachOObjectFile::getSymtabLoadCommand() const {
1462 macho::SymtabLoadCommand Cmd;
1463 memcpy(&Cmd, SymtabLoadCmd, sizeof(macho::SymtabLoadCommand));
1464 if (isSwappedEndian(this))
1465 SwapStruct(Cmd);
1466 return Cmd;
1467 }
1468
1469 bool MachOObjectFile::is64Bit() const {
1470 return getType() == getMachOType(false, true) ||
1471 getType() == getMachOType(true, true);
1472 }
1473
1474 void MachOObjectFile::ReadULEB128s(uint64_t Index,
1475 SmallVectorImpl &Out) const {
431476 DataExtractor extractor(ObjectFile::getData(), true, 0);
441477
451478 uint32_t offset = Index;
501483 }
511484 }
521485
53 unsigned MachOObjectFileBase::getHeaderSize() const {
54 return is64Bit() ? macho::Header64Size : macho::Header32Size;
55 }
56
57 StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
58 return ObjectFile::getData().substr(Offset, Size);
59 }
60
611486 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
621487 StringRef Magic = Buffer->getBuffer().slice(0, 4);
631488 error_code ec;
641489 ObjectFile *Ret;
651490 if (Magic == "\xFE\xED\xFA\xCE")
66 Ret = new MachOObjectFileBE32(Buffer, ec);
1491 Ret = new MachOObjectFile(Buffer, false, false, ec);
671492 else if (Magic == "\xCE\xFA\xED\xFE")
68 Ret = new MachOObjectFileLE32(Buffer, ec);
1493 Ret = new MachOObjectFile(Buffer, true, false, ec);
691494 else if (Magic == "\xFE\xED\xFA\xCF")
70 Ret = new MachOObjectFileBE64(Buffer, ec);
1495 Ret = new MachOObjectFile(Buffer, false, true, ec);
711496 else if (Magic == "\xCF\xFA\xED\xFE")
72 Ret = new MachOObjectFileLE64(Buffer, ec);
1497 Ret = new MachOObjectFile(Buffer, true, true, ec);
731498 else
741499 return NULL;
751500
781503 return Ret;
791504 }
801505
81 /*===-- Symbols -----------------------------------------------------------===*/
82
83 error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb,
84 uint64_t &Val) const {
85 report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase");
86 }
87
88 symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
89 // TODO: implement
90 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
91 }
92
93 symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
94 // TODO: implement
95 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
96 }
97
98 library_iterator MachOObjectFileBase::begin_libraries_needed() const {
99 // TODO: implement
100 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
101 }
102
103 library_iterator MachOObjectFileBase::end_libraries_needed() const {
104 // TODO: implement
105 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
106 }
107
108 StringRef MachOObjectFileBase::getLoadName() const {
109 // TODO: Implement
110 report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
111 }
112
113 /*===-- Sections ----------------------------------------------------------===*/
114
115 std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
116 SectionList::const_iterator loc =
117 std::find(Sections.begin(), Sections.end(), Sec);
118 assert(loc != Sections.end() && "Sec is not a valid section!");
119 return std::distance(Sections.begin(), loc);
120 }
121
122 StringRef MachOObjectFileBase::parseSegmentOrSectionName(const char *P) const {
123 if (P[15] == 0)
124 // Null terminated.
125 return P;
126 // Not null terminated, so this is a 16 char string.
127 return StringRef(P, 16);
128 }
129
130 error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
131 bool &Result) const {
132 // FIXME: Unimplemented.
133 Result = false;
134 return object_error::success;
135 }
136
137 error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
138 bool &Result) const {
139 // FIXME: Unimplemented.
140 Result = false;
141 return object_error::success;
142 }
143
144 error_code
145 MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
146 bool &Result) const {
147 // FIXME: Unimplemented.
148 Result = true;
149 return object_error::success;
150 }
151
152 error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
153 bool &Result) const {
154 // FIXME: Unimplemented.
155 Result = false;
156 return object_error::success;
157 }
158
159 error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec,
160 bool &Result) const {
161 // Consider using the code from isSectionText to look for __const sections.
162 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
163 // to use section attributes to distinguish code from data.
164
165 // FIXME: Unimplemented.
166 Result = false;
167 return object_error::success;
168 }
169
170 relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
171 DataRefImpl ret;
172 ret.d.b = getSectionIndex(Sec);
173 return relocation_iterator(RelocationRef(ret, this));
174 }
175
176
177 /*===-- Relocations -------------------------------------------------------===*/
178
179 error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
180 RelocationRef &Res) const {
181 ++Rel.d.a;
182 Res = RelocationRef(Rel, this);
183 return object_error::success;
184 }
185
186 error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData,
187 LibraryRef &Res) const {
188 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
189 }
190
191 error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData,
192 StringRef &Res) const {
193 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
194 }
195
196 error_code MachOObjectFileBase::getRelocationAdditionalInfo(DataRefImpl Rel,
197 int64_t &Res) const {
198 Res = 0;
199 return object_error::success;
200 }
201
202
203 /*===-- Miscellaneous -----------------------------------------------------===*/
204
205 uint8_t MachOObjectFileBase::getBytesInAddress() const {
206 return is64Bit() ? 8 : 4;
207 }
208
2091506 } // end namespace object
2101507 } // end namespace llvm
99 RUN: | FileCheck %s -check-prefix MACHO-PPC
1010 RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-ppc64 \
1111 RUN: | FileCheck %s -check-prefix MACHO-PPC64
12 RUN: llvm-readobj -r -expand-relocs %p/Inputs/trivial.obj.macho-arm \
13 RUN: | FileCheck %s -check-prefix MACHO-ARM
1214
1315 COFF: Relocations [
1416 COFF-NEXT: Section (1) .text {
8183 MACHO-PPC64-NEXT: 0x0 0 3 1 0 dyld_stub_binding_helper
8284 MACHO-PPC64-NEXT: }
8385 MACHO-PPC64-NEXT: ]
86
87
88 MACHO-ARM: Relocations [
89 MACHO-ARM-NEXT: Section __text {
90 MACHO-ARM-NEXT: Relocation {
91 MACHO-ARM-NEXT: Offset: 0x38
92 MACHO-ARM-NEXT: PCRel: 0
93 MACHO-ARM-NEXT: Length: 2
94 MACHO-ARM-NEXT: Extern: N/A
95 MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2)
96 MACHO-ARM-NEXT: Symbol: _b
97 MACHO-ARM-NEXT: Scattered: 1
98 MACHO-ARM-NEXT: }
99 MACHO-ARM-NEXT: Relocation {
100 MACHO-ARM-NEXT: Offset: 0x0
101 MACHO-ARM-NEXT: PCRel: 0
102 MACHO-ARM-NEXT: Length: 2
103 MACHO-ARM-NEXT: Extern: N/A
104 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
105 MACHO-ARM-NEXT: Symbol: _b
106 MACHO-ARM-NEXT: Scattered: 1
107 MACHO-ARM-NEXT: }
108 MACHO-ARM-NEXT: Relocation {
109 MACHO-ARM-NEXT: Offset: 0x20
110 MACHO-ARM-NEXT: PCRel: 1
111 MACHO-ARM-NEXT: Length: 2
112 MACHO-ARM-NEXT: Extern: 1
113 MACHO-ARM-NEXT: Type: ARM_RELOC_BR24 (5)
114 MACHO-ARM-NEXT: Symbol: _g
115 MACHO-ARM-NEXT: Scattered: 0
116 MACHO-ARM-NEXT: }
117 MACHO-ARM-NEXT: Relocation {
118 MACHO-ARM-NEXT: Offset: 0x1C
119 MACHO-ARM-NEXT: PCRel: 0
120 MACHO-ARM-NEXT: Length: 1
121 MACHO-ARM-NEXT: Extern: 1
122 MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8)
123 MACHO-ARM-NEXT: Symbol: _g
124 MACHO-ARM-NEXT: Scattered: 0
125 MACHO-ARM-NEXT: }
126 MACHO-ARM-NEXT: Relocation {
127 MACHO-ARM-NEXT: Offset: 0x0
128 MACHO-ARM-NEXT: PCRel: 0
129 MACHO-ARM-NEXT: Length: 1
130 MACHO-ARM-NEXT: Extern: 0
131 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
132 MACHO-ARM-NEXT: Symbol: _b
133 MACHO-ARM-NEXT: Scattered: 0
134 MACHO-ARM-NEXT: }
135 MACHO-ARM-NEXT: Relocation {
136 MACHO-ARM-NEXT: Offset: 0x18
137 MACHO-ARM-NEXT: PCRel: 0
138 MACHO-ARM-NEXT: Length: 0
139 MACHO-ARM-NEXT: Extern: 1
140 MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8)
141 MACHO-ARM-NEXT: Symbol: _g
142 MACHO-ARM-NEXT: Scattered: 0
143 MACHO-ARM-NEXT: }
144 MACHO-ARM-NEXT: Relocation {
145 MACHO-ARM-NEXT: Offset: 0x0
146 MACHO-ARM-NEXT: PCRel: 0
147 MACHO-ARM-NEXT: Length: 0
148 MACHO-ARM-NEXT: Extern: 0
149 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
150 MACHO-ARM-NEXT: Symbol: _b
151 MACHO-ARM-NEXT: Scattered: 0
152 MACHO-ARM-NEXT: }
153 MACHO-ARM-NEXT: Relocation {
154 MACHO-ARM-NEXT: Offset: 0xC
155 MACHO-ARM-NEXT: PCRel: 0
156 MACHO-ARM-NEXT: Length: 2
157 MACHO-ARM-NEXT: Extern: N/A
158 MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2)
159 MACHO-ARM-NEXT: Symbol: _b
160 MACHO-ARM-NEXT: Scattered: 1
161 MACHO-ARM-NEXT: }
162 MACHO-ARM-NEXT: Relocation {
163 MACHO-ARM-NEXT: Offset: 0x0
164 MACHO-ARM-NEXT: PCRel: 0
165 MACHO-ARM-NEXT: Length: 2
166 MACHO-ARM-NEXT: Extern: N/A
167 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
168 MACHO-ARM-NEXT: Symbol: _b
169 MACHO-ARM-NEXT: Scattered: 1
170 MACHO-ARM-NEXT: }
171 MACHO-ARM-NEXT: }
172 MACHO-ARM-NEXT: ]
99 RUN: | FileCheck %s -check-prefix MACHO-PPC
1010 RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-ppc64 \
1111 RUN: | FileCheck %s -check-prefix MACHO-PPC64
12 RUN: llvm-readobj -expand-relocs -s -st -sr -sd %p/Inputs/trivial.obj.macho-arm \
13 RUN: | FileCheck %s -check-prefix MACHO-ARM
1214
1315 COFF: Sections [
1416 COFF-NEXT: Section {
561563 MACHO-PPC64-NEXT: )
562564 MACHO-PPC64-NEXT: }
563565 MACHO-PPC64-NEXT: ]
566
567 MACHO-ARM: Sections [
568 MACHO-ARM-NEXT: Section {
569 MACHO-ARM-NEXT: Index: 0
570 MACHO-ARM-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
571 MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
572 MACHO-ARM-NEXT: Address: 0x0
573 MACHO-ARM-NEXT: Size: 0x3C
574 MACHO-ARM-NEXT: Offset: 664
575 MACHO-ARM-NEXT: Alignment: 2
576 MACHO-ARM-NEXT: RelocationOffset: 0x2E0
577 MACHO-ARM-NEXT: RelocationCount: 9
578 MACHO-ARM-NEXT: Type: 0x0
579 MACHO-ARM-NEXT: Attributes [ (0x800004)
580 MACHO-ARM-NEXT: PureInstructions (0x800000)
581 MACHO-ARM-NEXT: SomeInstructions (0x4)
582 MACHO-ARM-NEXT: ]
583 MACHO-ARM-NEXT: Reserved1: 0x0
584 MACHO-ARM-NEXT: Reserved2: 0x0
585 MACHO-ARM-NEXT: Relocations [
586 MACHO-ARM-NEXT: Relocation {
587 MACHO-ARM-NEXT: Offset: 0x38
588 MACHO-ARM-NEXT: PCRel: 0
589 MACHO-ARM-NEXT: Length: 2
590 MACHO-ARM-NEXT: Extern: N/A
591 MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2)
592 MACHO-ARM-NEXT: Symbol: _b
593 MACHO-ARM-NEXT: Scattered: 1
594 MACHO-ARM-NEXT: }
595 MACHO-ARM-NEXT: Relocation {
596 MACHO-ARM-NEXT: Offset: 0x0
597 MACHO-ARM-NEXT: PCRel: 0
598 MACHO-ARM-NEXT: Length: 2
599 MACHO-ARM-NEXT: Extern: N/A
600 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
601 MACHO-ARM-NEXT: Symbol: _b
602 MACHO-ARM-NEXT: Scattered: 1
603 MACHO-ARM-NEXT: }
604 MACHO-ARM-NEXT: Relocation {
605 MACHO-ARM-NEXT: Offset: 0x20
606 MACHO-ARM-NEXT: PCRel: 1
607 MACHO-ARM-NEXT: Length: 2
608 MACHO-ARM-NEXT: Extern: 1
609 MACHO-ARM-NEXT: Type: ARM_RELOC_BR24 (5)
610 MACHO-ARM-NEXT: Symbol: _g
611 MACHO-ARM-NEXT: Scattered: 0
612 MACHO-ARM-NEXT: }
613 MACHO-ARM-NEXT: Relocation {
614 MACHO-ARM-NEXT: Offset: 0x1C
615 MACHO-ARM-NEXT: PCRel: 0
616 MACHO-ARM-NEXT: Length: 1
617 MACHO-ARM-NEXT: Extern: 1
618 MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8)
619 MACHO-ARM-NEXT: Symbol: _g
620 MACHO-ARM-NEXT: Scattered: 0
621 MACHO-ARM-NEXT: }
622 MACHO-ARM-NEXT: Relocation {
623 MACHO-ARM-NEXT: Offset: 0x0
624 MACHO-ARM-NEXT: PCRel: 0
625 MACHO-ARM-NEXT: Length: 1
626 MACHO-ARM-NEXT: Extern: 0
627 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
628 MACHO-ARM-NEXT: Symbol: _b
629 MACHO-ARM-NEXT: Scattered: 0
630 MACHO-ARM-NEXT: }
631 MACHO-ARM-NEXT: Relocation {
632 MACHO-ARM-NEXT: Offset: 0x18
633 MACHO-ARM-NEXT: PCRel: 0
634 MACHO-ARM-NEXT: Length: 0
635 MACHO-ARM-NEXT: Extern: 1
636 MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8)
637 MACHO-ARM-NEXT: Symbol: _g
638 MACHO-ARM-NEXT: Scattered: 0
639 MACHO-ARM-NEXT: }
640 MACHO-ARM-NEXT: Relocation {
641 MACHO-ARM-NEXT: Offset: 0x0
642 MACHO-ARM-NEXT: PCRel: 0
643 MACHO-ARM-NEXT: Length: 0
644 MACHO-ARM-NEXT: Extern: 0
645 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
646 MACHO-ARM-NEXT: Symbol: _b
647 MACHO-ARM-NEXT: Scattered: 0
648 MACHO-ARM-NEXT: }
649 MACHO-ARM-NEXT: Relocation {
650 MACHO-ARM-NEXT: Offset: 0xC
651 MACHO-ARM-NEXT: PCRel: 0
652 MACHO-ARM-NEXT: Length: 2
653 MACHO-ARM-NEXT: Extern: N/A
654 MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2)
655 MACHO-ARM-NEXT: Symbol: _b
656 MACHO-ARM-NEXT: Scattered: 1
657 MACHO-ARM-NEXT: }
658 MACHO-ARM-NEXT: Relocation {
659 MACHO-ARM-NEXT: Offset: 0x0
660 MACHO-ARM-NEXT: PCRel: 0
661 MACHO-ARM-NEXT: Length: 2
662 MACHO-ARM-NEXT: Extern: N/A
663 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1)
664 MACHO-ARM-NEXT: Symbol: _b
665 MACHO-ARM-NEXT: Scattered: 1
666 MACHO-ARM-NEXT: }
667 MACHO-ARM-NEXT: ]
668 MACHO-ARM-NEXT: Symbols [
669 MACHO-ARM-NEXT: Symbol {
670 MACHO-ARM-NEXT: Name: _f (4)
671 MACHO-ARM-NEXT: Type: 0xF
672 MACHO-ARM-NEXT: Section: __text (0x1)
673 MACHO-ARM-NEXT: RefType: UndefinedNonLazy (0x0)
674 MACHO-ARM-NEXT: Flags [ (0x0)
675 MACHO-ARM-NEXT: ]
676 MACHO-ARM-NEXT: Value: 0x10
677 MACHO-ARM-NEXT: }
678 MACHO-ARM-NEXT: Symbol {
679 MACHO-ARM-NEXT: Name: _h (1)
680 MACHO-ARM-NEXT: Type: 0xF
681 MACHO-ARM-NEXT: Section: __text (0x1)
682 MACHO-ARM-NEXT: RefType: UndefinedNonLazy (0x0)
683 MACHO-ARM-NEXT: Flags [ (0x0)
684 MACHO-ARM-NEXT: ]
685 MACHO-ARM-NEXT: Value: 0x0
686 MACHO-ARM-NEXT: }
687 MACHO-ARM-NEXT: ]
688 MACHO-ARM-NEXT: SectionData (
689 MACHO-ARM-NEXT: 0000: 04009FE5 00009FE7 1EFF2FE1 38000000 |........../.8...|
690 MACHO-ARM-NEXT: 0010: 80402DE9 0D70A0E1 000000E3 000040E3 |.@-..p........@.|
691 MACHO-ARM-NEXT: 0020: F6FFFFEB 0C009FE5 00009FE7 000090E5 |................|
692 MACHO-ARM-NEXT: 0030: 8040BDE8 1EFF2FE1 10000000 |.@..../.....|
693 MACHO-ARM-NEXT: )
694 MACHO-ARM-NEXT: }
695 MACHO-ARM-NEXT: Section {
696 MACHO-ARM-NEXT: Index: 1
697 MACHO-ARM-NEXT: Name: __textcoal_nt (5F 5F 74 65 78 74 63 6F 61 6C 5F 6E 74 00 00 00)
698 MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
699 MACHO-ARM-NEXT: Address: 0x3C
700 MACHO-ARM-NEXT: Size: 0x0
701 MACHO-ARM-NEXT: Offset: 724
702 MACHO-ARM-NEXT: Alignment: 0
703 MACHO-ARM-NEXT: RelocationOffset: 0x0
704 MACHO-ARM-NEXT: RelocationCount: 0
705 MACHO-ARM-NEXT: Type: 0xB
706 MACHO-ARM-NEXT: Attributes [ (0x800000)
707 MACHO-ARM-NEXT: PureInstructions (0x800000)
708 MACHO-ARM-NEXT: ]
709 MACHO-ARM-NEXT: Reserved1: 0x0
710 MACHO-ARM-NEXT: Reserved2: 0x0
711 MACHO-ARM-NEXT: Relocations [
712 MACHO-ARM-NEXT: ]
713 MACHO-ARM-NEXT: Symbols [
714 MACHO-ARM-NEXT: ]
715 MACHO-ARM-NEXT: SectionData (
716 MACHO-ARM-NEXT: )
717 MACHO-ARM-NEXT: }
718 MACHO-ARM-NEXT: Section {
719 MACHO-ARM-NEXT: Index: 2
720