//===----------------------------------------------------------------------===//
#include "llvm/Object/MachO.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Format.h"
SwapValue(C.count);
}
+template<>
+void SwapStruct(MachO::version_min_command&C) {
+ SwapValue(C.cmd);
+ SwapValue(C.cmdsize);
+ SwapValue(C.version);
+ SwapValue(C.reserved);
+}
+
template<>
void SwapStruct(MachO::data_in_code_entry &C) {
SwapValue(C.offset);
// Helper to advance a section or symbol iterator multiple increments at a time.
template<class T>
-static error_code advance(T &it, size_t Val) {
- error_code ec;
- while (Val--) {
- it.increment(ec);
- }
- return ec;
-}
-
-template<class T>
-static void advanceTo(T &it, size_t Val) {
- if (error_code ec = advance(it, Val))
- report_fatal_error(ec.message());
+static void advance(T &it, size_t Val) {
+ while (Val--)
+ ++it;
}
static unsigned getCPUType(const MachOObjectFile *O) {
if (IsScattered) {
uint32_t Val = O->getPlainRelocationSymbolNum(RE);
- error_code ec;
- for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
- SI != SE; SI.increment(ec)) {
- if (ec) report_fatal_error(ec.message());
-
+ for (const SymbolRef &Symbol : O->symbols()) {
+ error_code ec;
uint64_t Addr;
StringRef Name;
- if ((ec = SI->getAddress(Addr)))
+ if ((ec = Symbol.getAddress(Addr)))
report_fatal_error(ec.message());
- if (Addr != Val) continue;
- if ((ec = SI->getName(Name)))
+ if (Addr != Val)
+ continue;
+ if ((ec = Symbol.getName(Name)))
report_fatal_error(ec.message());
fmt << Name;
return;
// If we couldn't find a symbol that this relocation refers to, try
// to find a section beginning instead.
- for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
- SI != SE; SI.increment(ec)) {
- if (ec) report_fatal_error(ec.message());
-
+ for (const SectionRef &Section : O->sections()) {
+ error_code ec;
uint64_t Addr;
StringRef Name;
- if ((ec = SI->getAddress(Addr)))
+ if ((ec = Section.getAddress(Addr)))
report_fatal_error(ec.message());
- if (Addr != Val) continue;
- if ((ec = SI->getName(Name)))
+ if (Addr != Val)
+ continue;
+ if ((ec = Section.getName(Name)))
report_fatal_error(ec.message());
fmt << Name;
return;
uint64_t Val = O->getPlainRelocationSymbolNum(RE);
if (isExtern) {
- symbol_iterator SI = O->begin_symbols();
- advanceTo(SI, Val);
+ symbol_iterator SI = O->symbol_begin();
+ advance(SI, Val);
SI->getName(S);
} else {
- section_iterator SI = O->begin_sections();
+ section_iterator SI = O->section_begin();
// Adjust for the fact that sections are 1-indexed.
- advanceTo(SI, Val - 1);
+ advance(SI, Val - 1);
SI->getName(S);
}
return Sect.flags;
}
-MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
- bool IsLittleEndian, bool Is64bits,
- error_code &ec)
- : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
+MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian,
+ bool Is64bits, error_code &EC,
+ bool BufferOwned)
+ : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned),
SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) {
uint32_t LoadCommandCount = this->getHeader().ncmds;
MachO::LoadCommandType SegmentLoadType = is64Bit() ?
}
}
-error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
- SymbolRef &Res) const {
+void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
unsigned SymbolTableEntrySize = is64Bit() ?
sizeof(MachO::nlist_64) :
sizeof(MachO::nlist);
Symb.p += SymbolTableEntrySize;
- Res = SymbolRef(Symb, this);
- return object_error::success;
}
error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
uint32_t &Result) const {
- uint32_t flags;
- this->getSymbolFlags(DRI, flags);
+ uint32_t flags = getSymbolFlags(DRI);
if (flags & SymbolRef::SF_Common) {
nlist_base Entry = getSymbolTableEntryBase(this, DRI);
Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
SectionIndex = Entry.n_sect;
if (!SectionIndex) {
- uint32_t flags = SymbolRef::SF_None;
- this->getSymbolFlags(DRI, flags);
+ uint32_t flags = getSymbolFlags(DRI);
if (flags & SymbolRef::SF_Common)
Result = Value;
else
}
// Unfortunately symbols are unsorted so we need to touch all
// symbols from load command
- error_code ec;
- for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E;
- I.increment(ec)) {
- DataRefImpl DRI = I->getRawDataRefImpl();
+ for (const SymbolRef &Symbol : symbols()) {
+ DataRefImpl DRI = Symbol.getRawDataRefImpl();
Entry = getSymbolTableEntryBase(this, DRI);
getSymbolAddress(DRI, Value);
if (Entry.n_sect == SectionIndex && Value > BeginOffset)
return object_error::success;
}
-error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
- uint32_t &Result) const {
+uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
nlist_base Entry = getSymbolTableEntryBase(this, DRI);
uint8_t MachOType = Entry.n_type;
uint16_t MachOFlags = Entry.n_desc;
- // TODO: Correctly set SF_ThreadLocal
- Result = SymbolRef::SF_None;
+ uint32_t Result = SymbolRef::SF_None;
if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)
Result |= SymbolRef::SF_Undefined;
if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Result |= SymbolRef::SF_Absolute;
- return object_error::success;
+ return Result;
}
error_code
uint8_t index = Entry.n_sect;
if (index == 0) {
- Res = end_sections();
+ Res = section_end();
} else {
DataRefImpl DRI;
DRI.d.a = index - 1;
report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
}
-error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
- SectionRef &Res) const {
+void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
Sec.d.a++;
- Res = SectionRef(Sec, this);
- return object_error::success;
}
error_code
return relocation_iterator(RelocationRef(Ret, this));
}
-error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
- RelocationRef &Res) const {
+bool MachOObjectFile::section_rel_empty(DataRefImpl Sec) const {
+ if (is64Bit()) {
+ MachO::section_64 Sect = getSection64(Sec);
+ return Sect.nreloc == 0;
+ } else {
+ MachO::section Sect = getSection(Sec);
+ return Sect.nreloc == 0;
+ }
+}
+
+void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
const MachO::any_relocation_info *P =
reinterpret_cast<const MachO::any_relocation_info *>(Rel.p);
Rel.p = reinterpret_cast<uintptr_t>(P + 1);
- Res = RelocationRef(Rel, this);
- return object_error::success;
}
error_code
uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
bool isExtern = getPlainRelocationExternal(RE);
if (!isExtern)
- return end_symbols();
+ return symbol_end();
MachO::symtab_command S = getSymtabLoadCommand();
unsigned SymbolTableEntrySize = is64Bit() ?
"GENERIC_RELOC_LOCAL_SECTDIFF",
"GENERIC_RELOC_TLV" };
- if (RType > 6)
+ if (RType > 5)
res = "Unknown";
else
res = Table[RType];
res = Table[RType];
break;
}
+ case Triple::arm64:
+ case Triple::aarch64: {
+ static const char *const Table[] = {
+ "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR",
+ "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21",
+ "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21",
+ "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
+ "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
+ "ARM64_RELOC_ADDEND"
+ };
+
+ if (RType >= array_lengthof(Table))
+ res = "Unknown";
+ else
+ res = Table[RType];
+ break;
+ }
case Triple::ppc: {
static const char *const Table[] = {
"PPC_RELOC_VANILLA",
"PPC_RELOC_LO14_SECTDIFF",
"PPC_RELOC_LOCAL_SECTDIFF" };
- res = Table[RType];
+ if (RType > 15)
+ res = "Unknown";
+ else
+ res = Table[RType];
break;
}
case Triple::UnknownArch:
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
-symbol_iterator MachOObjectFile::begin_symbols() const {
+basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const {
DataRefImpl DRI;
if (!SymtabLoadCmd)
- return symbol_iterator(SymbolRef(DRI, this));
+ return basic_symbol_iterator(SymbolRef(DRI, this));
MachO::symtab_command Symtab = getSymtabLoadCommand();
DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
- return symbol_iterator(SymbolRef(DRI, this));
+ return basic_symbol_iterator(SymbolRef(DRI, this));
}
-symbol_iterator MachOObjectFile::end_symbols() const {
+basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {
DataRefImpl DRI;
if (!SymtabLoadCmd)
- return symbol_iterator(SymbolRef(DRI, this));
+ return basic_symbol_iterator(SymbolRef(DRI, this));
MachO::symtab_command Symtab = getSymtabLoadCommand();
unsigned SymbolTableEntrySize = is64Bit() ?
unsigned Offset = Symtab.symoff +
Symtab.nsyms * SymbolTableEntrySize;
DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
- return symbol_iterator(SymbolRef(DRI, this));
+ return basic_symbol_iterator(SymbolRef(DRI, this));
}
-symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
- // TODO: implement
- report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
-}
-
-symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
- // TODO: implement
- report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
-}
-
-section_iterator MachOObjectFile::begin_sections() const {
+section_iterator MachOObjectFile::section_begin() const {
DataRefImpl DRI;
return section_iterator(SectionRef(DRI, this));
}
-section_iterator MachOObjectFile::end_sections() const {
+section_iterator MachOObjectFile::section_end() const {
DataRefImpl DRI;
DRI.d.a = Sections.size();
return section_iterator(SectionRef(DRI, this));
}
-library_iterator MachOObjectFile::begin_libraries_needed() const {
+library_iterator MachOObjectFile::needed_library_begin() const {
// TODO: implement
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
-library_iterator MachOObjectFile::end_libraries_needed() const {
+library_iterator MachOObjectFile::needed_library_end() const {
// TODO: implement
report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
}
switch (CPUType) {
case llvm::MachO::CPU_TYPE_X86_64:
return "Mach-O 64-bit x86-64";
+ case llvm::MachO::CPU_TYPE_ARM64:
+ return "Mach-O arm64";
case llvm::MachO::CPU_TYPE_POWERPC64:
return "Mach-O 64-bit ppc64";
default:
return Triple::x86_64;
case llvm::MachO::CPU_TYPE_ARM:
return Triple::arm;
+ case llvm::MachO::CPU_TYPE_ARM64:
+ return Triple::arm64;
case llvm::MachO::CPU_TYPE_POWERPC:
return Triple::ppc;
case llvm::MachO::CPU_TYPE_POWERPC64:
MachOObjectFile::getRelocationSection(
const MachO::any_relocation_info &RE) const {
if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
- return *end_sections();
+ return *section_end();
unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
DataRefImpl DRI;
DRI.d.a = SecNum;
return getStruct<MachO::linker_options_command>(this, L.Ptr);
}
+MachO::version_min_command
+MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::version_min_command>(this, L.Ptr);
+}
+
MachO::any_relocation_info
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
const char *P = reinterpret_cast<const char *>(Rel.p);
}
}
-ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
+ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer,
+ bool BufferOwned) {
StringRef Magic = Buffer->getBuffer().slice(0, 4);
- error_code ec;
- OwningPtr<ObjectFile> Ret;
+ error_code EC;
+ std::unique_ptr<MachOObjectFile> Ret;
if (Magic == "\xFE\xED\xFA\xCE")
- Ret.reset(new MachOObjectFile(Buffer, false, false, ec));
+ Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned));
else if (Magic == "\xCE\xFA\xED\xFE")
- Ret.reset(new MachOObjectFile(Buffer, true, false, ec));
+ Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned));
else if (Magic == "\xFE\xED\xFA\xCF")
- Ret.reset(new MachOObjectFile(Buffer, false, true, ec));
+ Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned));
else if (Magic == "\xCF\xFA\xED\xFE")
- Ret.reset(new MachOObjectFile(Buffer, true, true, ec));
+ Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned));
else {
delete Buffer;
- return NULL;
+ return object_error::parse_failed;
}
- if (ec)
- return NULL;
- return Ret.take();
+ if (EC)
+ return EC;
+ return Ret.release();
}
} // end namespace object