blob: c846206e6e4b099c142f951deef9866a15c67bb3 [file] [log] [blame]
Eric Christopher7b015c72011-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 Anderson27c579d2011-10-11 17:32:27 +000015#include "llvm/Object/MachO.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/ADT/Triple.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000017#include "llvm/Object/MachOFormat.h"
Rafael Espindolac2413f52013-04-09 14:49:08 +000018#include "llvm/Support/Casting.h"
Rafael Espindola421305a2013-04-07 20:01:29 +000019#include "llvm/Support/DataExtractor.h"
Owen Andersonbc14bd32011-10-26 20:42:54 +000020#include "llvm/Support/Format.h"
Eric Christopher7b015c72011-04-22 03:19:48 +000021#include "llvm/Support/MemoryBuffer.h"
Eric Christopher7b015c72011-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 Anderson27c579d2011-10-11 17:32:27 +000030namespace object {
Eric Christopher7b015c72011-04-22 03:19:48 +000031
Rafael Espindolac2413f52013-04-09 14:49:08 +000032MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits,
33 error_code &ec)
Rafael Espindolad66c4142013-04-08 13:25:33 +000034 : ObjectFile(getMachOType(true, Is64bits), Object) {
Benjamin Kramer022ecdf2011-09-08 20:52:17 +000035}
36
Rafael Espindolac2413f52013-04-09 14:49:08 +000037bool MachOObjectFileBase::is64Bit() const {
Rafael Espindola641c9bc2013-04-10 15:33:44 +000038 return isa<MachOObjectFile64Le>(this);
Rafael Espindola31fce892013-04-07 15:46:05 +000039}
Benjamin Kramer022ecdf2011-09-08 20:52:17 +000040
Rafael Espindolac2413f52013-04-09 14:49:08 +000041const MachOObjectFileBase::LoadCommand *
42MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const {
Rafael Espindola224208b2013-04-07 18:08:12 +000043 uint64_t Offset;
Rafael Espindola60689982013-04-07 19:05:30 +000044 uint64_t NewOffset = getHeaderSize();
Rafael Espindolac2413f52013-04-09 14:49:08 +000045 const LoadCommand *Load;
Rafael Espindola224208b2013-04-07 18:08:12 +000046 unsigned I = 0;
47 do {
48 Offset = NewOffset;
Rafael Espindolac2413f52013-04-09 14:49:08 +000049 StringRef Data = getData(Offset, sizeof(LoadCommand));
50 Load = reinterpret_cast<const LoadCommand*>(Data.data());
Rafael Espindola224208b2013-04-07 18:08:12 +000051 NewOffset = Offset + Load->Size;
52 ++I;
53 } while (I != Index + 1);
54
Rafael Espindola3c50f062013-04-07 18:42:06 +000055 return Load;
Rafael Espindola5ffc0792013-04-07 16:07:35 +000056}
57
Rafael Espindolac2413f52013-04-09 14:49:08 +000058void MachOObjectFileBase::ReadULEB128s(uint64_t Index,
59 SmallVectorImpl<uint64_t> &Out) const {
Rafael Espindola421305a2013-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 Espindola5ffc0792013-04-07 16:07:35 +000068}
69
Rafael Espindolac2413f52013-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 Espindola5ffc0792013-04-07 16:07:35 +000073}
74
Rafael Espindolac2413f52013-04-09 14:49:08 +000075unsigned MachOObjectFileBase::getHeaderSize() const {
Rafael Espindola774a8ce2013-04-07 19:31:49 +000076 return is64Bit() ? macho::Header64Size : macho::Header32Size;
Rafael Espindola60689982013-04-07 19:05:30 +000077}
78
Rafael Espindolac2413f52013-04-09 14:49:08 +000079StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
Rafael Espindolac1f28b62013-04-07 19:42:15 +000080 return ObjectFile::getData().substr(Offset, Size);
Rafael Espindola60689982013-04-07 19:05:30 +000081}
82
Eric Christopher7b015c72011-04-22 03:19:48 +000083ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Rafael Espindolad66c4142013-04-08 13:25:33 +000084 StringRef Magic = Buffer->getBuffer().slice(0, 4);
Michael J. Spencerec29b122011-06-25 17:54:50 +000085 error_code ec;
Rafael Espindolad66c4142013-04-08 13:25:33 +000086 bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
Rafael Espindolac2413f52013-04-09 14:49:08 +000087 ObjectFile *Ret;
88 if (Is64Bits)
Rafael Espindola641c9bc2013-04-10 15:33:44 +000089 Ret = new MachOObjectFile64Le(Buffer, ec);
Rafael Espindolac2413f52013-04-09 14:49:08 +000090 else
Rafael Espindola641c9bc2013-04-10 15:33:44 +000091 Ret = new MachOObjectFile32Le(Buffer, ec);
Rafael Espindola17bece32013-04-07 16:58:48 +000092 if (ec)
Eric Christopher7b015c72011-04-22 03:19:48 +000093 return NULL;
Rafael Espindola17bece32013-04-07 16:58:48 +000094 return Ret;
Eric Christopher7b015c72011-04-22 03:19:48 +000095}
96
97/*===-- Symbols -----------------------------------------------------------===*/
98
Rafael Espindolac2413f52013-04-09 14:49:08 +000099void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
Rafael Espindolad6652592013-04-07 19:26:57 +0000100 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher7b015c72011-04-22 03:19:48 +0000101 while (DRI.d.a < LoadCommandCount) {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000102 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola3c50f062013-04-07 18:42:06 +0000103 if (Command->Type == macho::LCT_Symtab) {
Rafael Espindolac2413f52013-04-09 14:49:08 +0000104 const SymtabLoadCommand *SymtabLoadCmd =
105 reinterpret_cast<const SymtabLoadCommand*>(Command);
Eric Christopher7b015c72011-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 Espindolac2413f52013-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 Espindola5d6cec92013-04-09 00:22:58 +0000120 return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
Rafael Espindola15e2a9c2013-04-06 03:31:08 +0000121}
Eric Christopher7b015c72011-04-22 03:19:48 +0000122
Rafael Espindolac2413f52013-04-09 14:49:08 +0000123const MachOObjectFileBase::SymbolTableEntryBase *
124MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
125 const SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola2a34c2d2013-04-06 01:59:05 +0000126 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
127 unsigned Index = DRI.d.b;
Rafael Espindola5d6cec92013-04-09 00:22:58 +0000128
129 unsigned SymbolTableEntrySize = is64Bit() ?
Rafael Espindola641c9bc2013-04-10 15:33:44 +0000130 sizeof(MachOObjectFile64Le::SymbolTableEntry) :
131 sizeof(MachOObjectFile32Le::SymbolTableEntry);
Rafael Espindola5d6cec92013-04-09 00:22:58 +0000132
133 uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
134 StringRef Data = getData(Offset, SymbolTableEntrySize);
Rafael Espindolac2413f52013-04-09 14:49:08 +0000135 return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
Eric Christopher7b015c72011-04-22 03:19:48 +0000136}
137
Rafael Espindolac2413f52013-04-09 14:49:08 +0000138error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
139 SymbolRef &Result) const {
Eric Christopher7b015c72011-04-22 03:19:48 +0000140 DRI.d.b++;
141 moveToNextSymbol(DRI);
Michael J. Spencer1d6167f2011-06-25 17:55:23 +0000142 Result = SymbolRef(DRI, this);
143 return object_error::success;
Eric Christopher7b015c72011-04-22 03:19:48 +0000144}
145
Rafael Espindolac2413f52013-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 Espindola15e2a9c2013-04-06 03:31:08 +0000151
Rafael Espindola60689982013-04-07 19:05:30 +0000152 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
153 SymtabLoadCmd->StringTableSize);
Rafael Espindola15e2a9c2013-04-06 03:31:08 +0000154
Rafael Espindolac2413f52013-04-09 14:49:08 +0000155 const SymbolTableEntryBase *Entry =
Rafael Espindola5d6cec92013-04-09 00:22:58 +0000156 getSymbolTableEntryBase(DRI, SymtabLoadCmd);
157 uint32_t StringIndex = Entry->StringIndex;
Rafael Espindola15e2a9c2013-04-06 03:31:08 +0000158
159 const char *Start = &StringTable.data()[StringIndex];
160 Result = StringRef(Start);
161
Michael J. Spencer1d6167f2011-06-25 17:55:23 +0000162 return object_error::success;
Eric Christopher7b015c72011-04-22 03:19:48 +0000163}
164
Rafael Espindolac2413f52013-04-09 14:49:08 +0000165error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI,
166 char &Result) const {
167 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
Rafael Espindolaeb8b2112013-04-09 01:04:06 +0000168 uint8_t Type = Entry->Type;
169 uint16_t Flags = Entry->Flags;
Eric Christopher7b015c72011-04-22 03:19:48 +0000170
171 char Char;
Benjamin Kramer99582e92011-07-15 17:32:45 +0000172 switch (Type & macho::STF_TypeMask) {
Eric Christopher7b015c72011-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 Kramer99582e92011-07-15 17:32:45 +0000185 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei83c74e92013-02-12 21:21:59 +0000186 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer1d6167f2011-06-25 17:55:23 +0000187 Result = Char;
188 return object_error::success;
Eric Christopher7b015c72011-04-22 03:19:48 +0000189}
190
Rafael Espindolac2413f52013-04-09 14:49:08 +0000191error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI,
192 uint32_t &Result) const {
193 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
Rafael Espindolaeb8b2112013-04-09 01:04:06 +0000194 uint8_t MachOType = Entry->Type;
195 uint16_t MachOFlags = Entry->Flags;
Michael J. Spencer3217315392011-10-17 23:54:46 +0000196
Preston Gurd2138ef62012-04-12 20:13:57 +0000197 // TODO: Correctly set SF_ThreadLocal
David Meyer1df4b842012-02-28 23:47:53 +0000198 Result = SymbolRef::SF_None;
David Meyer7e4b9762012-02-29 02:11:55 +0000199
200 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
201 Result |= SymbolRef::SF_Undefined;
202
David Meyer1df4b842012-02-28 23:47:53 +0000203 if (MachOFlags & macho::STF_StabsEntryMask)
204 Result |= SymbolRef::SF_FormatSpecific;
205
Preston Gurd2138ef62012-04-12 20:13:57 +0000206 if (MachOType & MachO::NlistMaskExternal) {
David Meyer1df4b842012-02-28 23:47:53 +0000207 Result |= SymbolRef::SF_Global;
Preston Gurd2138ef62012-04-12 20:13:57 +0000208 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
209 Result |= SymbolRef::SF_Common;
210 }
David Meyer1df4b842012-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. Spencer3217315392011-10-17 23:54:46 +0000218 return object_error::success;
219}
220
Rafael Espindolac2413f52013-04-09 14:49:08 +0000221error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb,
222 section_iterator &Res) const {
223 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
Rafael Espindolaeb8b2112013-04-09 01:04:06 +0000224 uint8_t index = Entry->SectionIndex;
Michael J. Spencer3217315392011-10-17 23:54:46 +0000225
226 if (index == 0)
227 Res = end_sections();
228 else
Danil Malyshevcbe72fc2011-11-29 17:40:10 +0000229 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer3217315392011-10-17 23:54:46 +0000230
231 return object_error::success;
232}
233
Rafael Espindolac2413f52013-04-09 14:49:08 +0000234error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb,
235 SymbolRef::Type &Res) const {
236 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
Rafael Espindola5d6cec92013-04-09 00:22:58 +0000237 uint8_t n_type = Entry->Type;
238
Benjamin Kramer75d1cf332011-09-14 01:22:52 +0000239 Res = SymbolRef::ST_Other;
Owen Anderson34e17072011-10-12 22:23:12 +0000240
241 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersoncef56412011-10-21 19:26:54 +0000242 if (n_type & MachO::NlistMaskStab) {
243 Res = SymbolRef::ST_Debug;
Owen Anderson34e17072011-10-12 22:23:12 +0000244 return object_error::success;
Owen Andersoncef56412011-10-21 19:26:54 +0000245 }
Owen Anderson34e17072011-10-12 22:23:12 +0000246
Benjamin Kramer75d1cf332011-09-14 01:22:52 +0000247 switch (n_type & MachO::NlistMaskType) {
248 case MachO::NListTypeUndefined :
David Meyer7e4b9762012-02-29 02:11:55 +0000249 Res = SymbolRef::ST_Unknown;
Benjamin Kramer75d1cf332011-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 Espindolac2413f52013-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 Northover4f223bf72012-10-29 10:47:00 +0000261}
Benjamin Kramer75d1cf332011-09-14 01:22:52 +0000262
Rafael Espindolac2413f52013-04-09 14:49:08 +0000263symbol_iterator MachOObjectFileBase::begin_symbols() const {
Eric Christopher7b015c72011-04-22 03:19:48 +0000264 // DRI.d.a = segment number; DRI.d.b = symbol index.
265 DataRefImpl DRI;
Eric Christopher7b015c72011-04-22 03:19:48 +0000266 moveToNextSymbol(DRI);
267 return symbol_iterator(SymbolRef(DRI, this));
268}
269
Rafael Espindolac2413f52013-04-09 14:49:08 +0000270symbol_iterator MachOObjectFileBase::end_symbols() const {
Eric Christopher7b015c72011-04-22 03:19:48 +0000271 DataRefImpl DRI;
Rafael Espindolad6652592013-04-07 19:26:57 +0000272 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher7b015c72011-04-22 03:19:48 +0000273 return symbol_iterator(SymbolRef(DRI, this));
274}
275
Rafael Espindolac2413f52013-04-09 14:49:08 +0000276symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
Michael J. Spencer8c4729f2012-02-28 00:40:37 +0000277 // TODO: implement
Rafael Espindolac2413f52013-04-09 14:49:08 +0000278 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
Michael J. Spencer8c4729f2012-02-28 00:40:37 +0000279}
280
Rafael Espindolac2413f52013-04-09 14:49:08 +0000281symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
Michael J. Spencer8c4729f2012-02-28 00:40:37 +0000282 // TODO: implement
Rafael Espindolac2413f52013-04-09 14:49:08 +0000283 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
Michael J. Spencer8c4729f2012-02-28 00:40:37 +0000284}
Eric Christopher7b015c72011-04-22 03:19:48 +0000285
Rafael Espindolac2413f52013-04-09 14:49:08 +0000286library_iterator MachOObjectFileBase::begin_libraries_needed() const {
David Meyer2fc34c52012-03-01 01:36:50 +0000287 // TODO: implement
Rafael Espindolac2413f52013-04-09 14:49:08 +0000288 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer2fc34c52012-03-01 01:36:50 +0000289}
290
Rafael Espindolac2413f52013-04-09 14:49:08 +0000291library_iterator MachOObjectFileBase::end_libraries_needed() const {
David Meyer2fc34c52012-03-01 01:36:50 +0000292 // TODO: implement
Rafael Espindolac2413f52013-04-09 14:49:08 +0000293 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer2fc34c52012-03-01 01:36:50 +0000294}
295
Rafael Espindolac2413f52013-04-09 14:49:08 +0000296StringRef MachOObjectFileBase::getLoadName() const {
David Meyerc429b802012-03-01 22:19:54 +0000297 // TODO: Implement
Rafael Espindolac2413f52013-04-09 14:49:08 +0000298 report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
David Meyerc429b802012-03-01 22:19:54 +0000299}
300
Eric Christopher7b015c72011-04-22 03:19:48 +0000301/*===-- Sections ----------------------------------------------------------===*/
302
Rafael Espindolac2413f52013-04-09 14:49:08 +0000303std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
Michael J. Spencere5fd0042011-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 Espindolac2413f52013-04-09 14:49:08 +0000310const MachOObjectFileBase::SectionBase*
311MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const {
312 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola65d601f2013-04-08 23:57:13 +0000313 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
314
315 bool Is64 = is64Bit();
316 unsigned SegmentLoadSize =
Rafael Espindola641c9bc2013-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 Espindola65d601f2013-04-08 23:57:13 +0000321
322 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
Rafael Espindolac2413f52013-04-09 14:49:08 +0000323 return reinterpret_cast<const SectionBase*>(SectionAddr);
Benjamin Kramer56498d12011-07-15 00:14:48 +0000324}
325
Rafael Espindolaa9f810b2012-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 Espindolac2413f52013-04-09 14:49:08 +0000334ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
335 const SectionBase *Base = getSectionBase(DRI);
Rafael Espindola65d601f2013-04-08 23:57:13 +0000336 return ArrayRef<char>(Base->Name);
Rafael Espindolab0f76a42013-04-05 15:15:22 +0000337}
338
Rafael Espindolac2413f52013-04-09 14:49:08 +0000339error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
340 StringRef &Result) const {
Rafael Espindolab0f76a42013-04-05 15:15:22 +0000341 ArrayRef<char> Raw = getSectionRawName(DRI);
342 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolaa9f810b2012-12-21 03:47:03 +0000343 return object_error::success;
344}
345
Rafael Espindolab0f76a42013-04-05 15:15:22 +0000346ArrayRef<char>
Rafael Espindolac2413f52013-04-09 14:49:08 +0000347MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
348 const SectionBase *Base = getSectionBase(Sec);
Rafael Espindola65d601f2013-04-08 23:57:13 +0000349 return ArrayRef<char>(Base->SegmentName);
Rafael Espindolab0f76a42013-04-05 15:15:22 +0000350}
351
Rafael Espindolac2413f52013-04-09 14:49:08 +0000352StringRef
353MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const {
Rafael Espindolab0f76a42013-04-05 15:15:22 +0000354 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
355 return parseSegmentOrSectionName(Raw.data());
Eric Christopher7b015c72011-04-22 03:19:48 +0000356}
357
Rafael Espindolac2413f52013-04-09 14:49:08 +0000358error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
359 bool &Result) const {
Michael J. Spencer800619f2011-09-28 20:57:30 +0000360 // FIXME: Unimplemented.
361 Result = false;
362 return object_error::success;
363}
364
Rafael Espindolac2413f52013-04-09 14:49:08 +0000365error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
Andrew Kaylorb96a3202012-10-10 01:45:52 +0000366 bool &Result) const {
367 // FIXME: Unimplemented.
Preston Gurd2138ef62012-04-12 20:13:57 +0000368 Result = false;
369 return object_error::success;
370}
371
Rafael Espindolac2413f52013-04-09 14:49:08 +0000372error_code
373MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
374 bool &Result) const {
375 // FIXME: Unimplemented.
376 Result = true;
Preston Gurd2138ef62012-04-12 20:13:57 +0000377 return object_error::success;
378}
379
Rafael Espindolac2413f52013-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 Kaylor3f31fa02012-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 Espindolac2413f52013-04-09 14:49:08 +0000398relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000399 DataRefImpl ret;
Michael J. Spencere5fd0042011-10-07 19:25:32 +0000400 ret.d.b = getSectionIndex(Sec);
401 return relocation_iterator(RelocationRef(ret, this));
402}
Rafael Espindolac0406e12013-04-08 20:45:01 +0000403
Rafael Espindolac2413f52013-04-09 14:49:08 +0000404section_iterator MachOObjectFileBase::end_sections() const {
Eric Christopher7b015c72011-04-22 03:19:48 +0000405 DataRefImpl DRI;
Rafael Espindolad6652592013-04-07 19:26:57 +0000406 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher7b015c72011-04-22 03:19:48 +0000407 return section_iterator(SectionRef(DRI, this));
408}
409
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000410/*===-- Relocations -------------------------------------------------------===*/
411
Rafael Espindolac2413f52013-04-09 14:49:08 +0000412error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
413 RelocationRef &Res) const {
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000414 ++Rel.d.a;
Benjamin Kramer022ecdf2011-09-08 20:52:17 +0000415 Res = RelocationRef(Rel, this);
416 return object_error::success;
417}
Owen Anderson171f4852011-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 Espindolac2413f52013-04-09 14:49:08 +0000435void
436MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
437 raw_string_ostream &fmt) const {
Owen Andersonbc14bd32011-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 Andersondebe01c2011-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 Andersonbc14bd32011-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 Anderson171f4852011-10-24 23:20:07 +0000491
492 if (isExtern) {
493 symbol_iterator SI = begin_symbols();
494 advanceTo(SI, Val);
Owen Andersonbc14bd32011-10-26 20:42:54 +0000495 SI->getName(S);
Owen Anderson171f4852011-10-24 23:20:07 +0000496 } else {
497 section_iterator SI = begin_sections();
498 advanceTo(SI, Val);
Owen Andersonbc14bd32011-10-26 20:42:54 +0000499 SI->getName(S);
Owen Anderson171f4852011-10-24 23:20:07 +0000500 }
501
Owen Andersonbc14bd32011-10-26 20:42:54 +0000502 fmt << S;
Owen Anderson171f4852011-10-24 23:20:07 +0000503}
504
Rafael Espindolac2413f52013-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 Kramer022ecdf2011-09-08 20:52:17 +0000508}
509
Rafael Espindolac2413f52013-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 Meyer2fc34c52012-03-01 01:36:50 +0000513}
514
Rafael Espindolae4100992013-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 Meyer2fc34c52012-03-01 01:36:50 +0000521
Eric Christopher7b015c72011-04-22 03:19:48 +0000522/*===-- Miscellaneous -----------------------------------------------------===*/
523
Rafael Espindolac2413f52013-04-09 14:49:08 +0000524uint8_t MachOObjectFileBase::getBytesInAddress() const {
Rafael Espindola60689982013-04-07 19:05:30 +0000525 return is64Bit() ? 8 : 4;
Eric Christopher7b015c72011-04-22 03:19:48 +0000526}
527
Rafael Espindolac2413f52013-04-09 14:49:08 +0000528StringRef MachOObjectFileBase::getFileFormatName() const {
Rafael Espindola60689982013-04-07 19:05:30 +0000529 if (!is64Bit()) {
Rafael Espindolad6652592013-04-07 19:26:57 +0000530 switch (getHeader()->CPUType) {
Eric Christopherae95ad12011-04-22 06:34:01 +0000531 case llvm::MachO::CPUTypeI386:
Eric Christopher22a19812011-04-22 04:08:58 +0000532 return "Mach-O 32-bit i386";
Eric Christopherae95ad12011-04-22 06:34:01 +0000533 case llvm::MachO::CPUTypeARM:
Eric Christopher22a19812011-04-22 04:08:58 +0000534 return "Mach-O arm";
Eric Christopherae95ad12011-04-22 06:34:01 +0000535 case llvm::MachO::CPUTypePowerPC:
Eric Christopher22a19812011-04-22 04:08:58 +0000536 return "Mach-O 32-bit ppc";
537 default:
Rafael Espindolad6652592013-04-07 19:26:57 +0000538 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher22a19812011-04-22 04:08:58 +0000539 "64-bit object file when we're not 64-bit?");
540 return "Mach-O 32-bit unknown";
Eric Christopher7b015c72011-04-22 03:19:48 +0000541 }
542 }
543
Eric Christopher0ac16d52013-02-28 20:26:17 +0000544 // Make sure the cpu type has the correct mask.
Rafael Espindolad6652592013-04-07 19:26:57 +0000545 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopher0ac16d52013-02-28 20:26:17 +0000546 == llvm::MachO::CPUArchABI64 &&
547 "32-bit object file when we're 64-bit?");
548
Rafael Espindolad6652592013-04-07 19:26:57 +0000549 switch (getHeader()->CPUType) {
Eric Christopherae95ad12011-04-22 06:34:01 +0000550 case llvm::MachO::CPUTypeX86_64:
Eric Christopher22a19812011-04-22 04:08:58 +0000551 return "Mach-O 64-bit x86-64";
Eric Christopherae95ad12011-04-22 06:34:01 +0000552 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher22a19812011-04-22 04:08:58 +0000553 return "Mach-O 64-bit ppc64";
Eric Christopher7b015c72011-04-22 03:19:48 +0000554 default:
Eric Christopher22a19812011-04-22 04:08:58 +0000555 return "Mach-O 64-bit unknown";
Eric Christopher7b015c72011-04-22 03:19:48 +0000556 }
557}
558
Rafael Espindolac2413f52013-04-09 14:49:08 +0000559unsigned MachOObjectFileBase::getArch() const {
Rafael Espindolad6652592013-04-07 19:26:57 +0000560 switch (getHeader()->CPUType) {
Eric Christopherae95ad12011-04-22 06:34:01 +0000561 case llvm::MachO::CPUTypeI386:
Eric Christopher7b015c72011-04-22 03:19:48 +0000562 return Triple::x86;
Eric Christopherae95ad12011-04-22 06:34:01 +0000563 case llvm::MachO::CPUTypeX86_64:
Eric Christopher7b015c72011-04-22 03:19:48 +0000564 return Triple::x86_64;
Eric Christopherae95ad12011-04-22 06:34:01 +0000565 case llvm::MachO::CPUTypeARM:
Eric Christopher7b015c72011-04-22 03:19:48 +0000566 return Triple::arm;
Eric Christopherae95ad12011-04-22 06:34:01 +0000567 case llvm::MachO::CPUTypePowerPC:
Eric Christopher7b015c72011-04-22 03:19:48 +0000568 return Triple::ppc;
Eric Christopherae95ad12011-04-22 06:34:01 +0000569 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher7b015c72011-04-22 03:19:48 +0000570 return Triple::ppc64;
571 default:
572 return Triple::UnknownArch;
573 }
574}
575
Owen Anderson27c579d2011-10-11 17:32:27 +0000576} // end namespace object
Eric Christopher7b015c72011-04-22 03:19:48 +0000577} // end namespace llvm