blob: 627e7485a6bb15e48c9bd8e0cda005113681fbaf [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
Rafael Espindolae2923472013-04-12 00:17:33 +000083const MachOObjectFileBase::RelocationEntry *
84MachOObjectFileBase::getRelocation(DataRefImpl Rel) const {
85 if (const MachOObjectFile32Le *O = dyn_cast<MachOObjectFile32Le>(this))
86 return O->getRelocation(Rel);
87 const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(this);
88 return O->getRelocation(Rel);
89}
90
91bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const {
92 unsigned Arch = getArch();
93 return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered);
94}
95
96bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const {
97 if (isScattered(RE)) {
98 const ScatteredRelocationEntry *SRE =
99 reinterpret_cast<const ScatteredRelocationEntry *>(RE);
100 return SRE->getPCRel();
101 }
102 return RE->getPCRel();
103}
104
105unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const {
106 if (isScattered(RE)) {
107 const ScatteredRelocationEntry *SRE =
108 reinterpret_cast<const ScatteredRelocationEntry *>(RE);
109 return SRE->getLength();
110 }
111 return RE->getLength();
112}
113
114unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const {
115 if (isScattered(RE)) {
116 const ScatteredRelocationEntry *SRE =
117 reinterpret_cast<const ScatteredRelocationEntry *>(RE);
118 return SRE->getType();
119 }
120 return RE->getType();
121}
122
Eric Christopher6256b032011-04-22 03:19:48 +0000123ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
Rafael Espindola9d55c092013-04-08 13:25:33 +0000124 StringRef Magic = Buffer->getBuffer().slice(0, 4);
Michael J. Spencer001c9202011-06-25 17:54:50 +0000125 error_code ec;
Rafael Espindola9d55c092013-04-08 13:25:33 +0000126 bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000127 ObjectFile *Ret;
128 if (Is64Bits)
Rafael Espindolab08c6df2013-04-10 15:33:44 +0000129 Ret = new MachOObjectFile64Le(Buffer, ec);
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000130 else
Rafael Espindolab08c6df2013-04-10 15:33:44 +0000131 Ret = new MachOObjectFile32Le(Buffer, ec);
Rafael Espindola6f1f3392013-04-07 16:58:48 +0000132 if (ec)
Eric Christopher6256b032011-04-22 03:19:48 +0000133 return NULL;
Rafael Espindola6f1f3392013-04-07 16:58:48 +0000134 return Ret;
Eric Christopher6256b032011-04-22 03:19:48 +0000135}
136
137/*===-- Symbols -----------------------------------------------------------===*/
138
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000139void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000140 uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000141 while (DRI.d.a < LoadCommandCount) {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000142 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola6ab85a82013-04-07 18:42:06 +0000143 if (Command->Type == macho::LCT_Symtab) {
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000144 const SymtabLoadCommand *SymtabLoadCmd =
145 reinterpret_cast<const SymtabLoadCommand*>(Command);
Eric Christopher6256b032011-04-22 03:19:48 +0000146 if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
147 return;
148 }
149
150 DRI.d.a++;
151 DRI.d.b = 0;
152 }
153}
154
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000155const MachOObjectFileBase::SymbolTableEntryBase *
156MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const {
157 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
158 const SymtabLoadCommand *SymtabLoadCmd =
159 reinterpret_cast<const SymtabLoadCommand*>(Command);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000160 return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
Rafael Espindola82a21072013-04-06 03:31:08 +0000161}
Eric Christopher6256b032011-04-22 03:19:48 +0000162
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000163const MachOObjectFileBase::SymbolTableEntryBase *
164MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
165 const SymtabLoadCommand *SymtabLoadCmd) const {
Rafael Espindola00555c12013-04-06 01:59:05 +0000166 uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
167 unsigned Index = DRI.d.b;
Rafael Espindola7df9c572013-04-09 00:22:58 +0000168
169 unsigned SymbolTableEntrySize = is64Bit() ?
Rafael Espindolab08c6df2013-04-10 15:33:44 +0000170 sizeof(MachOObjectFile64Le::SymbolTableEntry) :
171 sizeof(MachOObjectFile32Le::SymbolTableEntry);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000172
173 uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
174 StringRef Data = getData(Offset, SymbolTableEntrySize);
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000175 return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000176}
177
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000178error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
179 SymbolRef &Result) const {
Eric Christopher6256b032011-04-22 03:19:48 +0000180 DRI.d.b++;
181 moveToNextSymbol(DRI);
Michael J. Spencer25b15772011-06-25 17:55:23 +0000182 Result = SymbolRef(DRI, this);
183 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000184}
185
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000186error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI,
187 StringRef &Result) const {
188 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
189 const SymtabLoadCommand *SymtabLoadCmd =
190 reinterpret_cast<const SymtabLoadCommand*>(Command);
Rafael Espindola82a21072013-04-06 03:31:08 +0000191
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000192 StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
193 SymtabLoadCmd->StringTableSize);
Rafael Espindola82a21072013-04-06 03:31:08 +0000194
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000195 const SymbolTableEntryBase *Entry =
Rafael Espindola7df9c572013-04-09 00:22:58 +0000196 getSymbolTableEntryBase(DRI, SymtabLoadCmd);
197 uint32_t StringIndex = Entry->StringIndex;
Rafael Espindola82a21072013-04-06 03:31:08 +0000198
199 const char *Start = &StringTable.data()[StringIndex];
200 Result = StringRef(Start);
201
Michael J. Spencer25b15772011-06-25 17:55:23 +0000202 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000203}
204
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000205error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI,
206 char &Result) const {
207 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000208 uint8_t Type = Entry->Type;
209 uint16_t Flags = Entry->Flags;
Eric Christopher6256b032011-04-22 03:19:48 +0000210
211 char Char;
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000212 switch (Type & macho::STF_TypeMask) {
Eric Christopher6256b032011-04-22 03:19:48 +0000213 case macho::STT_Undefined:
214 Char = 'u';
215 break;
216 case macho::STT_Absolute:
217 case macho::STT_Section:
218 Char = 's';
219 break;
220 default:
221 Char = '?';
222 break;
223 }
224
Benjamin Kramer32fb2af2011-07-15 17:32:45 +0000225 if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000226 Char = toupper(static_cast<unsigned char>(Char));
Michael J. Spencer25b15772011-06-25 17:55:23 +0000227 Result = Char;
228 return object_error::success;
Eric Christopher6256b032011-04-22 03:19:48 +0000229}
230
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000231error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI,
232 uint32_t &Result) const {
233 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000234 uint8_t MachOType = Entry->Type;
235 uint16_t MachOFlags = Entry->Flags;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000236
Preston Gurdc68dda82012-04-12 20:13:57 +0000237 // TODO: Correctly set SF_ThreadLocal
David Meyerc46255a2012-02-28 23:47:53 +0000238 Result = SymbolRef::SF_None;
David Meyer2c677272012-02-29 02:11:55 +0000239
240 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
241 Result |= SymbolRef::SF_Undefined;
242
David Meyerc46255a2012-02-28 23:47:53 +0000243 if (MachOFlags & macho::STF_StabsEntryMask)
244 Result |= SymbolRef::SF_FormatSpecific;
245
Preston Gurdc68dda82012-04-12 20:13:57 +0000246 if (MachOType & MachO::NlistMaskExternal) {
David Meyerc46255a2012-02-28 23:47:53 +0000247 Result |= SymbolRef::SF_Global;
Preston Gurdc68dda82012-04-12 20:13:57 +0000248 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
249 Result |= SymbolRef::SF_Common;
250 }
David Meyerc46255a2012-02-28 23:47:53 +0000251
252 if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
253 Result |= SymbolRef::SF_Weak;
254
255 if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
256 Result |= SymbolRef::SF_Absolute;
257
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000258 return object_error::success;
259}
260
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000261error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb,
262 section_iterator &Res) const {
263 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
Rafael Espindola8faf7df2013-04-09 01:04:06 +0000264 uint8_t index = Entry->SectionIndex;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000265
266 if (index == 0)
267 Res = end_sections();
268 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000269 Res = section_iterator(SectionRef(Sections[index-1], this));
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000270
271 return object_error::success;
272}
273
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000274error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb,
275 SymbolRef::Type &Res) const {
276 const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
Rafael Espindola7df9c572013-04-09 00:22:58 +0000277 uint8_t n_type = Entry->Type;
278
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000279 Res = SymbolRef::ST_Other;
Owen Anderson10a8c622011-10-12 22:23:12 +0000280
281 // If this is a STAB debugging symbol, we can do nothing more.
Owen Andersona48aab92011-10-21 19:26:54 +0000282 if (n_type & MachO::NlistMaskStab) {
283 Res = SymbolRef::ST_Debug;
Owen Anderson10a8c622011-10-12 22:23:12 +0000284 return object_error::success;
Owen Andersona48aab92011-10-21 19:26:54 +0000285 }
Owen Anderson10a8c622011-10-12 22:23:12 +0000286
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000287 switch (n_type & MachO::NlistMaskType) {
288 case MachO::NListTypeUndefined :
David Meyer2c677272012-02-29 02:11:55 +0000289 Res = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000290 break;
291 case MachO::NListTypeSection :
292 Res = SymbolRef::ST_Function;
293 break;
294 }
295 return object_error::success;
296}
297
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000298error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb,
299 uint64_t &Val) const {
300 report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase");
Tim Northovera41dce32012-10-29 10:47:00 +0000301}
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000302
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000303symbol_iterator MachOObjectFileBase::begin_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000304 // DRI.d.a = segment number; DRI.d.b = symbol index.
305 DataRefImpl DRI;
Eric Christopher6256b032011-04-22 03:19:48 +0000306 moveToNextSymbol(DRI);
307 return symbol_iterator(SymbolRef(DRI, this));
308}
309
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000310symbol_iterator MachOObjectFileBase::end_symbols() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000311 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000312 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000313 return symbol_iterator(SymbolRef(DRI, this));
314}
315
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000316symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000317 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000318 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000319}
320
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000321symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000322 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000323 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000324}
Eric Christopher6256b032011-04-22 03:19:48 +0000325
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000326library_iterator MachOObjectFileBase::begin_libraries_needed() const {
David Meyer5c2b4ea2012-03-01 01:36:50 +0000327 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000328 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer5c2b4ea2012-03-01 01:36:50 +0000329}
330
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000331library_iterator MachOObjectFileBase::end_libraries_needed() const {
David Meyer5c2b4ea2012-03-01 01:36:50 +0000332 // TODO: implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000333 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer5c2b4ea2012-03-01 01:36:50 +0000334}
335
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000336StringRef MachOObjectFileBase::getLoadName() const {
David Meyer97f77872012-03-01 22:19:54 +0000337 // TODO: Implement
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000338 report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
David Meyer97f77872012-03-01 22:19:54 +0000339}
340
Eric Christopher6256b032011-04-22 03:19:48 +0000341/*===-- Sections ----------------------------------------------------------===*/
342
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000343std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000344 SectionList::const_iterator loc =
345 std::find(Sections.begin(), Sections.end(), Sec);
346 assert(loc != Sections.end() && "Sec is not a valid section!");
347 return std::distance(Sections.begin(), loc);
348}
349
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000350const MachOObjectFileBase::SectionBase*
351MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const {
352 const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
Rafael Espindola33885892013-04-08 23:57:13 +0000353 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
354
355 bool Is64 = is64Bit();
356 unsigned SegmentLoadSize =
Rafael Espindolab08c6df2013-04-10 15:33:44 +0000357 Is64 ? sizeof(MachOObjectFile64Le::SegmentLoadCommand) :
358 sizeof(MachOObjectFile32Le::SegmentLoadCommand);
359 unsigned SectionSize = Is64 ? sizeof(MachOObjectFile64Le::Section) :
360 sizeof(MachOObjectFile32Le::Section);
Rafael Espindola33885892013-04-08 23:57:13 +0000361
362 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000363 return reinterpret_cast<const SectionBase*>(SectionAddr);
Benjamin Kramer7d145782011-07-15 00:14:48 +0000364}
365
Rafael Espindolacef81b32012-12-21 03:47:03 +0000366static StringRef parseSegmentOrSectionName(const char *P) {
367 if (P[15] == 0)
368 // Null terminated.
369 return P;
370 // Not null terminated, so this is a 16 char string.
371 return StringRef(P, 16);
372}
373
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000374ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
375 const SectionBase *Base = getSectionBase(DRI);
Rafael Espindola33885892013-04-08 23:57:13 +0000376 return ArrayRef<char>(Base->Name);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000377}
378
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000379error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
380 StringRef &Result) const {
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000381 ArrayRef<char> Raw = getSectionRawName(DRI);
382 Result = parseSegmentOrSectionName(Raw.data());
Rafael Espindolacef81b32012-12-21 03:47:03 +0000383 return object_error::success;
384}
385
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000386ArrayRef<char>
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000387MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
388 const SectionBase *Base = getSectionBase(Sec);
Rafael Espindola33885892013-04-08 23:57:13 +0000389 return ArrayRef<char>(Base->SegmentName);
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000390}
391
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000392StringRef
393MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const {
Rafael Espindolaf16c2bb2013-04-05 15:15:22 +0000394 ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
395 return parseSegmentOrSectionName(Raw.data());
Eric Christopher6256b032011-04-22 03:19:48 +0000396}
397
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000398error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
399 bool &Result) const {
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000400 // FIXME: Unimplemented.
401 Result = false;
402 return object_error::success;
403}
404
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000405error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000406 bool &Result) const {
407 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000408 Result = false;
409 return object_error::success;
410}
411
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000412error_code
413MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
414 bool &Result) const {
415 // FIXME: Unimplemented.
416 Result = true;
Preston Gurdc68dda82012-04-12 20:13:57 +0000417 return object_error::success;
418}
419
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000420error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
421 bool &Result) const {
422 // FIXME: Unimplemented.
423 Result = false;
424 return object_error::success;
425}
426
427error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec,
428 bool &Result) const {
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000429 // Consider using the code from isSectionText to look for __const sections.
430 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
431 // to use section attributes to distinguish code from data.
432
433 // FIXME: Unimplemented.
434 Result = false;
435 return object_error::success;
436}
437
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000438relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000439 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000440 ret.d.b = getSectionIndex(Sec);
441 return relocation_iterator(RelocationRef(ret, this));
442}
Rafael Espindola335f1d42013-04-08 20:45:01 +0000443
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000444section_iterator MachOObjectFileBase::end_sections() const {
Eric Christopher6256b032011-04-22 03:19:48 +0000445 DataRefImpl DRI;
Rafael Espindola433611b2013-04-07 19:26:57 +0000446 DRI.d.a = getHeader()->NumLoadCommands;
Eric Christopher6256b032011-04-22 03:19:48 +0000447 return section_iterator(SectionRef(DRI, this));
448}
449
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000450/*===-- Relocations -------------------------------------------------------===*/
451
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000452error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
453 RelocationRef &Res) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000454 ++Rel.d.a;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000455 Res = RelocationRef(Rel, this);
456 return object_error::success;
457}
Owen Andersond8fa76d2011-10-24 23:20:07 +0000458
459// Helper to advance a section or symbol iterator multiple increments at a time.
460template<class T>
461error_code advance(T &it, size_t Val) {
462 error_code ec;
463 while (Val--) {
464 it.increment(ec);
465 }
466 return ec;
467}
468
469template<class T>
470void advanceTo(T &it, size_t Val) {
471 if (error_code ec = advance(it, Val))
472 report_fatal_error(ec.message());
473}
474
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000475void
476MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
477 raw_string_ostream &fmt) const {
Owen Anderson1832f4d2011-10-26 20:42:54 +0000478 // Target of a scattered relocation is an address. In the interest of
479 // generating pretty output, scan through the symbol table looking for a
480 // symbol that aligns with that address. If we find one, print it.
481 // Otherwise, we just print the hex address of the target.
Rafael Espindolae2923472013-04-12 00:17:33 +0000482 if (isScattered(RE)) {
483 uint32_t Val = RE->SymbolNum;
Owen Anderson1832f4d2011-10-26 20:42:54 +0000484
485 error_code ec;
486 for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
487 SI.increment(ec)) {
488 if (ec) report_fatal_error(ec.message());
489
490 uint64_t Addr;
491 StringRef Name;
492
493 if ((ec = SI->getAddress(Addr)))
494 report_fatal_error(ec.message());
495 if (Addr != Val) continue;
496 if ((ec = SI->getName(Name)))
497 report_fatal_error(ec.message());
498 fmt << Name;
499 return;
500 }
501
Owen Andersonb28bdbf2011-10-27 21:53:50 +0000502 // If we couldn't find a symbol that this relocation refers to, try
503 // to find a section beginning instead.
504 for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
505 SI.increment(ec)) {
506 if (ec) report_fatal_error(ec.message());
507
508 uint64_t Addr;
509 StringRef Name;
510
511 if ((ec = SI->getAddress(Addr)))
512 report_fatal_error(ec.message());
513 if (Addr != Val) continue;
514 if ((ec = SI->getName(Name)))
515 report_fatal_error(ec.message());
516 fmt << Name;
517 return;
518 }
519
Owen Anderson1832f4d2011-10-26 20:42:54 +0000520 fmt << format("0x%x", Val);
521 return;
522 }
523
524 StringRef S;
Rafael Espindolae2923472013-04-12 00:17:33 +0000525 bool isExtern = RE->getExternal();
526 uint32_t Val = RE->Address;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000527
528 if (isExtern) {
529 symbol_iterator SI = begin_symbols();
530 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000531 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000532 } else {
533 section_iterator SI = begin_sections();
534 advanceTo(SI, Val);
Owen Anderson1832f4d2011-10-26 20:42:54 +0000535 SI->getName(S);
Owen Andersond8fa76d2011-10-24 23:20:07 +0000536 }
537
Owen Anderson1832f4d2011-10-26 20:42:54 +0000538 fmt << S;
Owen Andersond8fa76d2011-10-24 23:20:07 +0000539}
540
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000541error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData,
542 LibraryRef &Res) const {
543 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000544}
545
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000546error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData,
547 StringRef &Res) const {
548 report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
David Meyer5c2b4ea2012-03-01 01:36:50 +0000549}
550
Rafael Espindola8bf80062013-04-11 02:21:31 +0000551error_code MachOObjectFileBase::getRelocationAdditionalInfo(DataRefImpl Rel,
552 int64_t &Res) const {
553 Res = 0;
554 return object_error::success;
555}
556
David Meyer5c2b4ea2012-03-01 01:36:50 +0000557
Eric Christopher6256b032011-04-22 03:19:48 +0000558/*===-- Miscellaneous -----------------------------------------------------===*/
559
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000560uint8_t MachOObjectFileBase::getBytesInAddress() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000561 return is64Bit() ? 8 : 4;
Eric Christopher6256b032011-04-22 03:19:48 +0000562}
563
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000564StringRef MachOObjectFileBase::getFileFormatName() const {
Rafael Espindola0f08eb12013-04-07 19:05:30 +0000565 if (!is64Bit()) {
Rafael Espindola433611b2013-04-07 19:26:57 +0000566 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +0000567 case llvm::MachO::CPUTypeI386:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000568 return "Mach-O 32-bit i386";
Eric Christopherf4b2f932011-04-22 06:34:01 +0000569 case llvm::MachO::CPUTypeARM:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000570 return "Mach-O arm";
Eric Christopherf4b2f932011-04-22 06:34:01 +0000571 case llvm::MachO::CPUTypePowerPC:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000572 return "Mach-O 32-bit ppc";
573 default:
Rafael Espindola433611b2013-04-07 19:26:57 +0000574 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000575 "64-bit object file when we're not 64-bit?");
576 return "Mach-O 32-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +0000577 }
578 }
579
Eric Christopherb3e6b042013-02-28 20:26:17 +0000580 // Make sure the cpu type has the correct mask.
Rafael Espindola433611b2013-04-07 19:26:57 +0000581 assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
Eric Christopherb3e6b042013-02-28 20:26:17 +0000582 == llvm::MachO::CPUArchABI64 &&
583 "32-bit object file when we're 64-bit?");
584
Rafael Espindola433611b2013-04-07 19:26:57 +0000585 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +0000586 case llvm::MachO::CPUTypeX86_64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000587 return "Mach-O 64-bit x86-64";
Eric Christopherf4b2f932011-04-22 06:34:01 +0000588 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000589 return "Mach-O 64-bit ppc64";
Eric Christopher6256b032011-04-22 03:19:48 +0000590 default:
Eric Christopher9ab1d7f2011-04-22 04:08:58 +0000591 return "Mach-O 64-bit unknown";
Eric Christopher6256b032011-04-22 03:19:48 +0000592 }
593}
594
Rafael Espindolaf6cfc152013-04-09 14:49:08 +0000595unsigned MachOObjectFileBase::getArch() const {
Rafael Espindola433611b2013-04-07 19:26:57 +0000596 switch (getHeader()->CPUType) {
Eric Christopherf4b2f932011-04-22 06:34:01 +0000597 case llvm::MachO::CPUTypeI386:
Eric Christopher6256b032011-04-22 03:19:48 +0000598 return Triple::x86;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000599 case llvm::MachO::CPUTypeX86_64:
Eric Christopher6256b032011-04-22 03:19:48 +0000600 return Triple::x86_64;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000601 case llvm::MachO::CPUTypeARM:
Eric Christopher6256b032011-04-22 03:19:48 +0000602 return Triple::arm;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000603 case llvm::MachO::CPUTypePowerPC:
Eric Christopher6256b032011-04-22 03:19:48 +0000604 return Triple::ppc;
Eric Christopherf4b2f932011-04-22 06:34:01 +0000605 case llvm::MachO::CPUTypePowerPC64:
Eric Christopher6256b032011-04-22 03:19:48 +0000606 return Triple::ppc64;
607 default:
608 return Triple::UnknownArch;
609 }
610}
611
Owen Andersonf7c93a32011-10-11 17:32:27 +0000612} // end namespace object
Eric Christopher6256b032011-04-22 03:19:48 +0000613} // end namespace llvm