blob: c846206e6e4b099c142f951deef9866a15c67bb3 [file] [log] [blame]
Eric Christopher6256b032011-04-22 03:19:48 +00001//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the MachOObjectFile class, which binds the MachOObject
11// class to the generic ObjectFile wrapper.
12//
13//===----------------------------------------------------------------------===//
14
Owen Andersonf7c93a32011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000016#include "llvm/ADT/Triple.h"
Eric Christopher6256b032011-04-22 03:19:48 +000017#include "llvm/Object/MachOFormat.h"
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000018#include "llvm/Support/Casting.h"
Rafael Espindola8764c892013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Owen Anderson1832f4d2011-10-26 20:42:54 +000020#include "llvm/Support/Format.h"
Eric Christopher6256b032011-04-22 03:19:48 +000021#include "llvm/Support/MemoryBuffer.h"
Eric Christopher6256b032011-04-22 03:19:48 +000022#include <cctype>
23#include <cstring>
24#include <limits>
25
26using namespace llvm;
27using namespace object;
28
29namespace llvm {
Owen Andersonf7c93a32011-10-11 17:32:27 +000030namespace object {
Eric Christopher6256b032011-04-22 03:19:48 +000031
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000032MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits,
33 error_code &ec)
Rafael Espindola9d55c092013-04-08 13:25:33 +000034 : ObjectFile(getMachOType(true, Is64bits), Object) {
Benjamin Kramer0fcab072011-09-08 20:52:17 +000035}
36
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000037bool MachOObjectFileBase::is64Bit() const {
Rafael Espindolab08c6df2013-04-10 15:33:44 +000038 return isa<MachOObjectFile64Le>(this);
Rafael Espindola0be4eaf2013-04-07 15:46:05 +000039}
Benjamin Kramer0fcab072011-09-08 20:52:17 +000040
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000041const MachOObjectFileBase::LoadCommand *
42MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const {
Rafael Espindola77638d92013-04-07 18:08:12 +000043 uint64_t Offset;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000044 uint64_t NewOffset = getHeaderSize();
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000045 const LoadCommand *Load;
Rafael Espindola77638d92013-04-07 18:08:12 +000046 unsigned I = 0;
47 do {
48 Offset = NewOffset;
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000049 StringRef Data = getData(Offset, sizeof(LoadCommand));
50 Load = reinterpret_cast<const LoadCommand*>(Data.data());
Rafael Espindola77638d92013-04-07 18:08:12 +000051 NewOffset = Offset + Load->Size;
52 ++I;
53 } while (I != Index + 1);
54
Rafael Espindola6ab85a82013-04-07 18:42:06 +000055 return Load;
Rafael Espindola3eff3182013-04-07 16:07:35 +000056}
57
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000058void MachOObjectFileBase::ReadULEB128s(uint64_t Index,
59 SmallVectorImpl<uint64_t> &Out) const {
Rafael Espindola8764c892013-04-07 20:01:29 +000060 DataExtractor extractor(ObjectFile::getData(), true, 0);
61
62 uint32_t offset = Index;
63 uint64_t data = 0;
64 while (uint64_t delta = extractor.getULEB128(&offset)) {
65 data += delta;
66 Out.push_back(data);
67 }
Rafael Espindola3eff3182013-04-07 16:07:35 +000068}
69
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000070const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const {
71 StringRef Data = getData(0, sizeof(Header));
72 return reinterpret_cast<const Header*>(Data.data());
Rafael Espindola3eff3182013-04-07 16:07:35 +000073}
74
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000075unsigned MachOObjectFileBase::getHeaderSize() const {
Rafael Espindolac90cc182013-04-07 19:31:49 +000076 return is64Bit() ? macho::Header64Size : macho::Header32Size;
Rafael Espindola0f08eb12013-04-07 19:05:30 +000077}
78
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000079StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
Rafael Espindolaf1cc8002013-04-07 19:42:15 +000080 return ObjectFile::getData().substr(Offset, Size);
Rafael Espindola0f08eb12013-04-07 19:05:30 +000081}
82
Eric Christopher6256b032011-04-22 03:19:48 +000083ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Rafael Espindola9d55c092013-04-08 13:25:33 +000084 StringRef Magic = Buffer->getBuffer().slice(0, 4);
Michael J. Spencer001c9202011-06-25 17:54:50 +000085 error_code ec;
Rafael Espindola9d55c092013-04-08 13:25:33 +000086 bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000087 ObjectFile *Ret;
88 if (Is64Bits)
Rafael Espindolab08c6df2013-04-10 15:33:44 +000089 Ret = new MachOObjectFile64Le(Buffer, ec);
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000090 else
Rafael Espindolab08c6df2013-04-10 15:33:44 +000091 Ret = new MachOObjectFile32Le(Buffer, ec);
Rafael Espindola6f1f3392013-04-07 16:58:48 +000092 if (ec)
Eric Christopher6256b032011-04-22 03:19:48 +000093 return NULL;
Rafael Espindola6f1f3392013-04-07 16:58:48 +000094 return Ret;
Eric Christopher6256b032011-04-22 03:19:48 +000095}
96
97/*===-- Symbols -----------------------------------------------------------===*/
98
Rafael Espindolaf6cfc152013-04-09 14:49:08 +000099void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000100 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000101 while (DRI.d.a < LoadCommandCount) {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000102 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000103 if (Command->Type == macho::LCT_Symtab) {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000104 const SymtabLoadCommand *SymtabLoadCmd =
105 reinterpret_cast<const SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000106 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
107 return;
108 }
109
110 DRI.d.a++;
111 DRI.d.b = 0;
112 }
113}
114
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000115const MachOObjectFileBase::SymbolTableEntryBase *
116MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const {
117 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
118 const SymtabLoadCommand *SymtabLoadCmd =
119 reinterpret_cast<const SymtabLoadCommand*>(Command);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000120 return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
Rafael Espindola82a21072013-04-06 03:31:08 +0000121}
Eric Christopher6256b032011-04-22 03:19:48 +0000122
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000123const MachOObjectFileBase::SymbolTableEntryBase *
124MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
125 const SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000126 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
127 unsigned Index = DRI.d.b;
Rafael Espindola7df9c572013-04-09 00:22:58 +0000128
129 unsigned SymbolTableEntrySize = is64Bit() ?
Rafael Espindolab08c6df2013-04-10 15:33:44 +0000130 sizeof(MachOObjectFile64Le::SymbolTableEntry) :
131 sizeof(MachOObjectFile32Le::SymbolTableEntry);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000132
133 uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
134 StringRef Data = getData(Offset, SymbolTableEntrySize);
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000135 return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000136}
137
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000138error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
139 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000140 DRI.d.b++;
141 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000142 Result = SymbolRef(DRI, this);
143 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000144}
145
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000146error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI,
147 StringRef &Result) const {
148 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
149 const SymtabLoadCommand *SymtabLoadCmd =
150 reinterpret_cast<const SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000151
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000152 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
153 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000154
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000155 const SymbolTableEntryBase *Entry =
Rafael Espindola7df9c572013-04-09 00:22:58 +0000156 getSymbolTableEntryBase(DRI, SymtabLoadCmd);
157 uint32_t StringIndex = Entry->StringIndex;
Rafael Espindola82a21072013-04-06 03:31:08 +0000158
159 const char *Start = &StringTable.data()[StringIndex];
160 Result = StringRef(Start);
161
Michael J. Spencer25b15772011-06-25 17:55:23 +0000162 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000163}
164
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000165error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI,
166 char &Result) const {
167 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000168 uint8_t Type = Entry->Type;
169 uint16_t Flags = Entry->Flags;
Eric Christopher6256b032011-04-22 03:19:48 +0000170
171 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000172 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000173 case macho::STT_Undefined:
174 Char = 'u';
175 break;
176 case macho::STT_Absolute:
177 case macho::STT_Section:
178 Char = 's';
179 break;
180 default:
181 Char = '?';
182 break;
183 }
184
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000185 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000186 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000187 Result = Char;
188 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000189}
190
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000191error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI,
192 uint32_t &Result) const {
193 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000194 uint8_t MachOType = Entry->Type;
195 uint16_t MachOFlags = Entry->Flags;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000196
Preston Gurdc68dda82012-04-12 20:13:57 +0000197 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000198 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000199
200 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
201 Result |= SymbolRef::SF_Undefined;
202
David Meyerc46255a2012-02-28 23:47:53 +0000203 if (MachOFlags & macho::STF_StabsEntryMask)
204 Result |= SymbolRef::SF_FormatSpecific;
205
Preston Gurdc68dda82012-04-12 20:13:57 +0000206 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000207 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000208 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
209 Result |= SymbolRef::SF_Common;
210 }
David Meyerc46255a2012-02-28 23:47:53 +0000211
212 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
213 Result |= SymbolRef::SF_Weak;
214
215 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
216 Result |= SymbolRef::SF_Absolute;
217
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000218 return object_error::success;
219}
220
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000221error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb,
222 section_iterator &Res) const {
223 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000224 uint8_t index = Entry->SectionIndex;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000225
226 if (index == 0)
227 Res = end_sections();
228 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000229 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000230
231 return object_error::success;
232}
233
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000234error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb,
235 SymbolRef::Type &Res) const {
236 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000237 uint8_t n_type = Entry->Type;
238
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000239 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000240
241 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000242 if (n_type & MachO::NlistMaskStab) {
243 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000244 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000245 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000246
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000247 switch (n_type & MachO::NlistMaskType) {
248 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000249 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000250 break;
251 case MachO::NListTypeSection :
252 Res = SymbolRef::ST_Function;
253 break;
254 }
255 return object_error::success;
256}
257
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000258error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb,
259 uint64_t &Val) const {
260 report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase");
Tim Northovera41dce32012-10-29 10:47:00 +0000261}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000262
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000263symbol_iterator MachOObjectFileBase::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000264 // DRI.d.a = segment number; DRI.d.b = symbol index.
265 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000266 moveToNextSymbol(DRI);
267 return symbol_iterator(SymbolRef(DRI, this));
268}
269
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000270symbol_iterator MachOObjectFileBase::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000271 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000272 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000273 return symbol_iterator(SymbolRef(DRI, this));
274}
275
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000276symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000277 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000278 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000279}
280
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000281symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000282 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000283 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000284}
Eric Christopher6256b032011-04-22 03:19:48 +0000285
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000286library_iterator MachOObjectFileBase::begin_libraries_needed() const {
David Meyer5c2b4ea2012-03-01 01:36:50 +0000287 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000288 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer5c2b4ea2012-03-01 01:36:50 +0000289}
290
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000291library_iterator MachOObjectFileBase::end_libraries_needed() const {
David Meyer5c2b4ea2012-03-01 01:36:50 +0000292 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000293 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer5c2b4ea2012-03-01 01:36:50 +0000294}
295
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000296StringRef MachOObjectFileBase::getLoadName() const {
David Meyer97f77872012-03-01 22:19:54 +0000297 // TODO: Implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000298 report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
David Meyer97f77872012-03-01 22:19:54 +0000299}
300
Eric Christopher6256b032011-04-22 03:19:48 +0000301/*===-- Sections ----------------------------------------------------------===*/
302
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000303std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000304 SectionList::const_iterator loc =
305 std::find(Sections.begin(), Sections.end(), Sec);
306 assert(loc != Sections.end() && "Sec is not a valid section!");
307 return std::distance(Sections.begin(), loc);
308}
309
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000310const MachOObjectFileBase::SectionBase*
311MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const {
312 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola33885892013-04-08 23:57:13 +0000313 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
314
315 bool Is64 = is64Bit();
316 unsigned SegmentLoadSize =
Rafael Espindolab08c6df2013-04-10 15:33:44 +0000317 Is64 ? sizeof(MachOObjectFile64Le::SegmentLoadCommand) :
318 sizeof(MachOObjectFile32Le::SegmentLoadCommand);
319 unsigned SectionSize = Is64 ? sizeof(MachOObjectFile64Le::Section) :
320 sizeof(MachOObjectFile32Le::Section);
Rafael Espindola33885892013-04-08 23:57:13 +0000321
322 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000323 return reinterpret_cast<const SectionBase*>(SectionAddr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000324}
325
Rafael Espindolacef81b32012-12-21 03:47:03 +0000326static StringRef parseSegmentOrSectionName(const char *P) {
327 if (P[15] == 0)
328 // Null terminated.
329 return P;
330 // Not null terminated, so this is a 16 char string.
331 return StringRef(P, 16);
332}
333
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000334ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
335 const SectionBase *Base = getSectionBase(DRI);
Rafael Espindola33885892013-04-08 23:57:13 +0000336 return ArrayRef<char>(Base->Name);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000337}
338
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000339error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
340 StringRef &Result) const {
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000341 ArrayRef<char> Raw = getSectionRawName(DRI);
342 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000343 return object_error::success;
344}
345
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000346ArrayRef<char>
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000347MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
348 const SectionBase *Base = getSectionBase(Sec);
Rafael Espindola33885892013-04-08 23:57:13 +0000349 return ArrayRef<char>(Base->SegmentName);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000350}
351
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000352StringRef
353MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const {
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000354 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
355 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000356}
357
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000358error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
359 bool &Result) const {
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000360 // FIXME: Unimplemented.
361 Result = false;
362 return object_error::success;
363}
364
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000365error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000366 bool &Result) const {
367 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000368 Result = false;
369 return object_error::success;
370}
371
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000372error_code
373MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
374 bool &Result) const {
375 // FIXME: Unimplemented.
376 Result = true;
Preston Gurdc68dda82012-04-12 20:13:57 +0000377 return object_error::success;
378}
379
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000380error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
381 bool &Result) const {
382 // FIXME: Unimplemented.
383 Result = false;
384 return object_error::success;
385}
386
387error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec,
388 bool &Result) const {
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000389 // Consider using the code from isSectionText to look for __const sections.
390 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
391 // to use section attributes to distinguish code from data.
392
393 // FIXME: Unimplemented.
394 Result = false;
395 return object_error::success;
396}
397
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000398relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000399 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000400 ret.d.b = getSectionIndex(Sec);
401 return relocation_iterator(RelocationRef(ret, this));
402}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000403
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000404section_iterator MachOObjectFileBase::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000405 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000406 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000407 return section_iterator(SectionRef(DRI, this));
408}
409
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000410/*===-- Relocations -------------------------------------------------------===*/
411
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000412error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
413 RelocationRef &Res) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000414 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000415 Res = RelocationRef(Rel, this);
416 return object_error::success;
417}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000418
419// Helper to advance a section or symbol iterator multiple increments at a time.
420template<class T>
421error_code advance(T &it, size_t Val) {
422 error_code ec;
423 while (Val--) {
424 it.increment(ec);
425 }
426 return ec;
427}
428
429template<class T>
430void advanceTo(T &it, size_t Val) {
431 if (error_code ec = advance(it, Val))
432 report_fatal_error(ec.message());
433}
434
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000435void
436MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
437 raw_string_ostream &fmt) const {
Owen Anderson1832f4d2011-10-26 20:42:54 +0000438 unsigned Arch = getArch();
439 bool isScattered = (Arch != Triple::x86_64) &&
440 (RE->Word0 & macho::RF_Scattered);
441
442 // Target of a scattered relocation is an address. In the interest of
443 // generating pretty output, scan through the symbol table looking for a
444 // symbol that aligns with that address. If we find one, print it.
445 // Otherwise, we just print the hex address of the target.
446 if (isScattered) {
447 uint32_t Val = RE->Word1;
448
449 error_code ec;
450 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
451 SI.increment(ec)) {
452 if (ec) report_fatal_error(ec.message());
453
454 uint64_t Addr;
455 StringRef Name;
456
457 if ((ec = SI->getAddress(Addr)))
458 report_fatal_error(ec.message());
459 if (Addr != Val) continue;
460 if ((ec = SI->getName(Name)))
461 report_fatal_error(ec.message());
462 fmt << Name;
463 return;
464 }
465
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000466 // If we couldn't find a symbol that this relocation refers to, try
467 // to find a section beginning instead.
468 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
469 SI.increment(ec)) {
470 if (ec) report_fatal_error(ec.message());
471
472 uint64_t Addr;
473 StringRef Name;
474
475 if ((ec = SI->getAddress(Addr)))
476 report_fatal_error(ec.message());
477 if (Addr != Val) continue;
478 if ((ec = SI->getName(Name)))
479 report_fatal_error(ec.message());
480 fmt << Name;
481 return;
482 }
483
Owen Anderson1832f4d2011-10-26 20:42:54 +0000484 fmt << format("0x%x", Val);
485 return;
486 }
487
488 StringRef S;
489 bool isExtern = (RE->Word1 >> 27) & 1;
490 uint32_t Val = RE->Word1 & 0xFFFFFF;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000491
492 if (isExtern) {
493 symbol_iterator SI = begin_symbols();
494 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000495 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000496 } else {
497 section_iterator SI = begin_sections();
498 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000499 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000500 }
501
Owen Anderson1832f4d2011-10-26 20:42:54 +0000502 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000503}
504
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000505error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData,
506 LibraryRef &Res) const {
507 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000508}
509
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000510error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData,
511 StringRef &Res) const {
512 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer5c2b4ea2012-03-01 01:36:50 +0000513}
514
Rafael Espindola8bf80062013-04-11 02:21:31 +0000515error_code MachOObjectFileBase::getRelocationAdditionalInfo(DataRefImpl Rel,
516 int64_t &Res) const {
517 Res = 0;
518 return object_error::success;
519}
520
David Meyer5c2b4ea2012-03-01 01:36:50 +0000521
Eric Christopher6256b032011-04-22 03:19:48 +0000522/*===-- Miscellaneous -----------------------------------------------------===*/
523
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000524uint8_t MachOObjectFileBase::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000525 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +0000526}
527
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000528StringRef MachOObjectFileBase::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000529 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +0000530 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +0000531 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000532 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +0000533 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000534 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +0000535 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000536 return "Mach-O 32-bit ppc";
537 default:
Rafael Espindola433611b2013-04-07 19:26:57 +0000538 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000539 "64-bit object file when we're not 64-bit?");
540 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +0000541 }
542 }
543
Eric Christopherb3e6b042013-02-28 20:26:17 +0000544 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +0000545 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +0000546 == llvm::MachO::CPUArchABI64 &&
547 "32-bit object file when we're 64-bit?");
548
Rafael Espindola433611b2013-04-07 19:26:57 +0000549 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +0000550 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000551 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +0000552 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000553 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +0000554 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000555 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +0000556 }
557}
558
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000559unsigned MachOObjectFileBase::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000560 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +0000561 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +0000562 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000563 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +0000564 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000565 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +0000566 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000567 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +0000568 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000569 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +0000570 return Triple::ppc64;
571 default:
572 return Triple::UnknownArch;
573 }
574}
575
Owen Andersonf7c93a32011-10-11 17:32:27 +0000576} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +0000577} // end namespace llvm