blob: 4a003249191e29d07f6c830847ba928fa81b64f6 [file] [log] [blame]
Eric Christopher6256b032011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ADT/Triple.h"
16#include "llvm/Object/MachOFormat.h"
17#include "llvm/Object/MachOObject.h"
18#include "llvm/Object/ObjectFile.h"
19#include "llvm/Support/MemoryBuffer.h"
20
21#include <cctype>
22#include <cstring>
23#include <limits>
24
25using namespace llvm;
26using namespace object;
27
28namespace llvm {
29
30typedef MachOObject::LoadCommandInfo LoadCommandInfo;
31
32class MachOObjectFile : public ObjectFile {
33public:
34 MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO)
35 : ObjectFile(Object),
36 MachOObj(MOO),
37 RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {}
38
39 virtual symbol_iterator begin_symbols() const;
40 virtual symbol_iterator end_symbols() const;
41 virtual section_iterator begin_sections() const;
42 virtual section_iterator end_sections() const;
43
44 virtual uint8_t getBytesInAddress() const;
45 virtual StringRef getFileFormatName() const;
46 virtual unsigned getArch() const;
47
48protected:
49 virtual SymbolRef getSymbolNext(DataRefImpl Symb) const;
50 virtual StringRef getSymbolName(DataRefImpl Symb) const;
51 virtual uint64_t getSymbolAddress(DataRefImpl Symb) const;
52 virtual uint64_t getSymbolSize(DataRefImpl Symb) const;
53 virtual char getSymbolNMTypeChar(DataRefImpl Symb) const;
54 virtual bool isSymbolInternal(DataRefImpl Symb) const;
55
56 virtual SectionRef getSectionNext(DataRefImpl Sec) const;
57 virtual StringRef getSectionName(DataRefImpl Sec) const;
58 virtual uint64_t getSectionAddress(DataRefImpl Sec) const;
59 virtual uint64_t getSectionSize(DataRefImpl Sec) const;
60 virtual StringRef getSectionContents(DataRefImpl Sec) const;
61 virtual bool isSectionText(DataRefImpl Sec) const;
62
63private:
64 MachOObject *MachOObj;
65 mutable uint32_t RegisteredStringTable;
66
67 void moveToNextSection(DataRefImpl &DRI) const;
68 void getSymbolTableEntry(DataRefImpl DRI,
69 InMemoryStruct<macho::SymbolTableEntry> &Res) const;
70 void moveToNextSymbol(DataRefImpl &DRI) const;
71 void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
72};
73
74ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
75 std::string Err;
76 MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
77 if (!MachOObj)
78 return NULL;
79 return new MachOObjectFile(Buffer, MachOObj);
80}
81
82/*===-- Symbols -----------------------------------------------------------===*/
83
84void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
85 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
86 while (DRI.d.a < LoadCommandCount) {
87 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
88 if (LCI.Command.Type == macho::LCT_Symtab) {
89 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
90 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
91 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
92 return;
93 }
94
95 DRI.d.a++;
96 DRI.d.b = 0;
97 }
98}
99
100void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
101 InMemoryStruct<macho::SymbolTableEntry> &Res) const {
102 InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
103 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
104 MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
105
106 if (RegisteredStringTable != DRI.d.a) {
107 MachOObj->RegisterStringTable(*SymtabLoadCmd);
108 RegisteredStringTable = DRI.d.a;
109 }
110
111 MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
112 Res);
113}
114
115
116SymbolRef MachOObjectFile::getSymbolNext(DataRefImpl DRI) const {
117 DRI.d.b++;
118 moveToNextSymbol(DRI);
119 return SymbolRef(DRI, this);
120}
121
122StringRef MachOObjectFile::getSymbolName(DataRefImpl DRI) const {
123 InMemoryStruct<macho::SymbolTableEntry> Entry;
124 getSymbolTableEntry(DRI, Entry);
125 return MachOObj->getStringAtIndex(Entry->StringIndex);
126}
127
128uint64_t MachOObjectFile::getSymbolAddress(DataRefImpl DRI) const {
129 InMemoryStruct<macho::SymbolTableEntry> Entry;
130 getSymbolTableEntry(DRI, Entry);
131 return Entry->Value;
132}
133
134uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const {
135 return UnknownAddressOrSize;
136}
137
138char MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI) const {
139 InMemoryStruct<macho::SymbolTableEntry> Entry;
140 getSymbolTableEntry(DRI, Entry);
141
142 char Char;
143 switch (Entry->Type & macho::STF_TypeMask) {
144 case macho::STT_Undefined:
145 Char = 'u';
146 break;
147 case macho::STT_Absolute:
148 case macho::STT_Section:
149 Char = 's';
150 break;
151 default:
152 Char = '?';
153 break;
154 }
155
156 if (Entry->Flags & (macho::STF_External | macho::STF_PrivateExtern))
157 Char = toupper(Char);
158 return Char;
159}
160
161bool MachOObjectFile::isSymbolInternal(DataRefImpl DRI) const {
162 InMemoryStruct<macho::SymbolTableEntry> Entry;
163 getSymbolTableEntry(DRI, Entry);
164 return Entry->Flags & macho::STF_StabsEntryMask;
165}
166
167ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const {
168 // DRI.d.a = segment number; DRI.d.b = symbol index.
169 DataRefImpl DRI;
170 DRI.d.a = DRI.d.b = 0;
171 moveToNextSymbol(DRI);
172 return symbol_iterator(SymbolRef(DRI, this));
173}
174
175ObjectFile::symbol_iterator MachOObjectFile::end_symbols() const {
176 DataRefImpl DRI;
177 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
178 DRI.d.b = 0;
179 return symbol_iterator(SymbolRef(DRI, this));
180}
181
182
183/*===-- Sections ----------------------------------------------------------===*/
184
185void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
186 uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
187 while (DRI.d.a < LoadCommandCount) {
188 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
189 if (LCI.Command.Type == macho::LCT_Segment) {
190 InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
191 MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
192 if (DRI.d.b < SegmentLoadCmd->NumSections)
193 return;
194 } else if (LCI.Command.Type == macho::LCT_Segment64) {
195 InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
196 MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
197 if (DRI.d.b < Segment64LoadCmd->NumSections)
198 return;
199 }
200
201 DRI.d.a++;
202 DRI.d.b = 0;
203 }
204}
205
206SectionRef MachOObjectFile::getSectionNext(DataRefImpl DRI) const {
207 DRI.d.b++;
208 moveToNextSection(DRI);
209 return SectionRef(DRI, this);
210}
211
212void
213MachOObjectFile::getSection(DataRefImpl DRI,
214 InMemoryStruct<macho::Section> &Res) const {
215 InMemoryStruct<macho::SegmentLoadCommand> SLC;
216 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
217 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
218 MachOObj->ReadSection(LCI, DRI.d.b, Res);
219}
220
221StringRef MachOObjectFile::getSectionName(DataRefImpl DRI) const {
222 InMemoryStruct<macho::SegmentLoadCommand> SLC;
223 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
224 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
225 InMemoryStruct<macho::Section> Sect;
226 MachOObj->ReadSection(LCI, DRI.d.b, Sect);
227
228 static char Result[34];
229 strcpy(Result, SLC->Name);
230 strcat(Result, ",");
231 strcat(Result, Sect->Name);
232 return StringRef(Result);
233}
234
235uint64_t MachOObjectFile::getSectionAddress(DataRefImpl DRI) const {
236 InMemoryStruct<macho::Section> Sect;
237 getSection(DRI, Sect);
238 return Sect->Address;
239}
240
241uint64_t MachOObjectFile::getSectionSize(DataRefImpl DRI) const {
242 InMemoryStruct<macho::Section> Sect;
243 getSection(DRI, Sect);
244 return Sect->Size;
245}
246
247StringRef MachOObjectFile::getSectionContents(DataRefImpl DRI) const {
248 InMemoryStruct<macho::Section> Sect;
249 getSection(DRI, Sect);
250 return MachOObj->getData(Sect->Offset, Sect->Size);
251}
252
253bool MachOObjectFile::isSectionText(DataRefImpl DRI) const {
254 InMemoryStruct<macho::SegmentLoadCommand> SLC;
255 LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
256 MachOObj->ReadSegmentLoadCommand(LCI, SLC);
257 return !strcmp(SLC->Name, "__TEXT");
258}
259
260ObjectFile::section_iterator MachOObjectFile::begin_sections() const {
261 DataRefImpl DRI;
262 DRI.d.a = DRI.d.b = 0;
263 moveToNextSection(DRI);
264 return section_iterator(SectionRef(DRI, this));
265}
266
267ObjectFile::section_iterator MachOObjectFile::end_sections() const {
268 DataRefImpl DRI;
269 DRI.d.a = MachOObj->getHeader().NumLoadCommands;
270 DRI.d.b = 0;
271 return section_iterator(SectionRef(DRI, this));
272}
273
274/*===-- Miscellaneous -----------------------------------------------------===*/
275
276uint8_t MachOObjectFile::getBytesInAddress() const {
277 return MachOObj->is64Bit() ? 8 : 4;
278}
279
280StringRef MachOObjectFile::getFileFormatName() const {
281 if (!MachOObj->is64Bit()) {
282 switch (MachOObj->getHeader().CPUType) {
283 case 0x00000007:
284 return "MACHO32-i386";
285 case 0x01000007:
286 return "MACHO32-x86-64";
287 case 0x0000000c:
288 return "MACHO32-arm";
289 case 0x00000012:
290 return "MACHO32-ppc";
291 case 0x01000012:
292 return "MACHO32-ppc64";
293 }
294 }
295
296 switch (MachOObj->getHeader().CPUType) {
297 case 0x00000007:
298 return "MACHO64-i386";
299 case 0x01000007:
300 return "MACHO64-x86-64";
301 case 0x0000000c:
302 return "MACHO64-arm";
303 case 0x00000012:
304 return "MACHO64-ppc";
305 case 0x01000012:
306 return "MACHO64-ppc64";
307 default:
308 return "MACHO64-unknown";
309 }
310}
311
312unsigned MachOObjectFile::getArch() const {
313 switch (MachOObj->getHeader().CPUType) {
314 case 0x00000007:
315 return Triple::x86;
316 case 0x01000007:
317 return Triple::x86_64;
318 case 0x0000000c:
319 return Triple::arm;
320 case 0x00000012:
321 return Triple::ppc;
322 case 0x01000012:
323 return Triple::ppc64;
324 default:
325 return Triple::UnknownArch;
326 }
327}
328
329} // end namespace llvm
330