2011-04-22 03:19:48 +00:00
|
|
|
//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines the MachOObjectFile class, which binds the MachOObject
|
|
|
|
// class to the generic ObjectFile wrapper.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-10-11 17:32:27 +00:00
|
|
|
#include "llvm/Object/MachO.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2011-04-22 03:19:48 +00:00
|
|
|
#include "llvm/Object/MachOFormat.h"
|
2013-04-09 14:49:08 +00:00
|
|
|
#include "llvm/Support/Casting.h"
|
2013-04-07 20:01:29 +00:00
|
|
|
#include "llvm/Support/DataExtractor.h"
|
2011-10-26 20:42:54 +00:00
|
|
|
#include "llvm/Support/Format.h"
|
2011-04-22 03:19:48 +00:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include <cctype>
|
|
|
|
#include <cstring>
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace object;
|
|
|
|
|
|
|
|
namespace llvm {
|
2011-10-11 17:32:27 +00:00
|
|
|
namespace object {
|
2011-04-22 03:19:48 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits,
|
|
|
|
error_code &ec)
|
2013-04-08 13:25:33 +00:00
|
|
|
: ObjectFile(getMachOType(true, Is64bits), Object) {
|
2011-09-08 20:52:17 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
bool MachOObjectFileBase::is64Bit() const {
|
2013-04-10 15:33:44 +00:00
|
|
|
return isa<MachOObjectFile64Le>(this);
|
2013-04-07 15:46:05 +00:00
|
|
|
}
|
2011-09-08 20:52:17 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
const MachOObjectFileBase::LoadCommand *
|
|
|
|
MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const {
|
2013-04-07 18:08:12 +00:00
|
|
|
uint64_t Offset;
|
2013-04-07 19:05:30 +00:00
|
|
|
uint64_t NewOffset = getHeaderSize();
|
2013-04-09 14:49:08 +00:00
|
|
|
const LoadCommand *Load;
|
2013-04-07 18:08:12 +00:00
|
|
|
unsigned I = 0;
|
|
|
|
do {
|
|
|
|
Offset = NewOffset;
|
2013-04-09 14:49:08 +00:00
|
|
|
StringRef Data = getData(Offset, sizeof(LoadCommand));
|
|
|
|
Load = reinterpret_cast<const LoadCommand*>(Data.data());
|
2013-04-07 18:08:12 +00:00
|
|
|
NewOffset = Offset + Load->Size;
|
|
|
|
++I;
|
|
|
|
} while (I != Index + 1);
|
|
|
|
|
2013-04-07 18:42:06 +00:00
|
|
|
return Load;
|
2013-04-07 16:07:35 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
void MachOObjectFileBase::ReadULEB128s(uint64_t Index,
|
|
|
|
SmallVectorImpl<uint64_t> &Out) const {
|
2013-04-07 20:01:29 +00:00
|
|
|
DataExtractor extractor(ObjectFile::getData(), true, 0);
|
|
|
|
|
|
|
|
uint32_t offset = Index;
|
|
|
|
uint64_t data = 0;
|
|
|
|
while (uint64_t delta = extractor.getULEB128(&offset)) {
|
|
|
|
data += delta;
|
|
|
|
Out.push_back(data);
|
|
|
|
}
|
2013-04-07 16:07:35 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const {
|
|
|
|
StringRef Data = getData(0, sizeof(Header));
|
|
|
|
return reinterpret_cast<const Header*>(Data.data());
|
2013-04-07 16:07:35 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
unsigned MachOObjectFileBase::getHeaderSize() const {
|
2013-04-07 19:31:49 +00:00
|
|
|
return is64Bit() ? macho::Header64Size : macho::Header32Size;
|
2013-04-07 19:05:30 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
|
2013-04-07 19:42:15 +00:00
|
|
|
return ObjectFile::getData().substr(Offset, Size);
|
2013-04-07 19:05:30 +00:00
|
|
|
}
|
|
|
|
|
2011-04-22 03:19:48 +00:00
|
|
|
ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
|
2013-04-08 13:25:33 +00:00
|
|
|
StringRef Magic = Buffer->getBuffer().slice(0, 4);
|
2011-06-25 17:54:50 +00:00
|
|
|
error_code ec;
|
2013-04-08 13:25:33 +00:00
|
|
|
bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE";
|
2013-04-09 14:49:08 +00:00
|
|
|
ObjectFile *Ret;
|
|
|
|
if (Is64Bits)
|
2013-04-10 15:33:44 +00:00
|
|
|
Ret = new MachOObjectFile64Le(Buffer, ec);
|
2013-04-09 14:49:08 +00:00
|
|
|
else
|
2013-04-10 15:33:44 +00:00
|
|
|
Ret = new MachOObjectFile32Le(Buffer, ec);
|
2013-04-07 16:58:48 +00:00
|
|
|
if (ec)
|
2011-04-22 03:19:48 +00:00
|
|
|
return NULL;
|
2013-04-07 16:58:48 +00:00
|
|
|
return Ret;
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*===-- Symbols -----------------------------------------------------------===*/
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const {
|
2013-04-07 19:26:57 +00:00
|
|
|
uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
|
2011-04-22 03:19:48 +00:00
|
|
|
while (DRI.d.a < LoadCommandCount) {
|
2013-04-09 14:49:08 +00:00
|
|
|
const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
|
2013-04-07 18:42:06 +00:00
|
|
|
if (Command->Type == macho::LCT_Symtab) {
|
2013-04-09 14:49:08 +00:00
|
|
|
const SymtabLoadCommand *SymtabLoadCmd =
|
|
|
|
reinterpret_cast<const SymtabLoadCommand*>(Command);
|
2011-04-22 03:19:48 +00:00
|
|
|
if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DRI.d.a++;
|
|
|
|
DRI.d.b = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
const MachOObjectFileBase::SymbolTableEntryBase *
|
|
|
|
MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const {
|
|
|
|
const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
|
|
|
|
const SymtabLoadCommand *SymtabLoadCmd =
|
|
|
|
reinterpret_cast<const SymtabLoadCommand*>(Command);
|
2013-04-09 00:22:58 +00:00
|
|
|
return getSymbolTableEntryBase(DRI, SymtabLoadCmd);
|
2013-04-06 03:31:08 +00:00
|
|
|
}
|
2011-04-22 03:19:48 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
const MachOObjectFileBase::SymbolTableEntryBase *
|
|
|
|
MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI,
|
|
|
|
const SymtabLoadCommand *SymtabLoadCmd) const {
|
2013-04-06 01:59:05 +00:00
|
|
|
uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset;
|
|
|
|
unsigned Index = DRI.d.b;
|
2011-04-22 03:19:48 +00:00
|
|
|
|
2013-04-09 00:22:58 +00:00
|
|
|
unsigned SymbolTableEntrySize = is64Bit() ?
|
2013-04-10 15:33:44 +00:00
|
|
|
sizeof(MachOObjectFile64Le::SymbolTableEntry) :
|
|
|
|
sizeof(MachOObjectFile32Le::SymbolTableEntry);
|
2011-07-15 17:32:45 +00:00
|
|
|
|
2013-04-09 00:22:58 +00:00
|
|
|
uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize;
|
|
|
|
StringRef Data = getData(Offset, SymbolTableEntrySize);
|
2013-04-09 14:49:08 +00:00
|
|
|
return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
|
2013-04-06 03:31:08 +00:00
|
|
|
}
|
2011-07-15 17:32:45 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI,
|
|
|
|
SymbolRef &Result) const {
|
2011-04-22 03:19:48 +00:00
|
|
|
DRI.d.b++;
|
|
|
|
moveToNextSymbol(DRI);
|
2011-06-25 17:55:23 +00:00
|
|
|
Result = SymbolRef(DRI, this);
|
|
|
|
return object_error::success;
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI,
|
|
|
|
StringRef &Result) const {
|
|
|
|
const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
|
|
|
|
const SymtabLoadCommand *SymtabLoadCmd =
|
|
|
|
reinterpret_cast<const SymtabLoadCommand*>(Command);
|
2013-04-06 03:31:08 +00:00
|
|
|
|
2013-04-07 19:05:30 +00:00
|
|
|
StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset,
|
|
|
|
SymtabLoadCmd->StringTableSize);
|
2013-04-06 03:31:08 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
const SymbolTableEntryBase *Entry =
|
2013-04-09 00:22:58 +00:00
|
|
|
getSymbolTableEntryBase(DRI, SymtabLoadCmd);
|
|
|
|
uint32_t StringIndex = Entry->StringIndex;
|
2013-04-06 03:31:08 +00:00
|
|
|
|
|
|
|
const char *Start = &StringTable.data()[StringIndex];
|
|
|
|
Result = StringRef(Start);
|
|
|
|
|
2011-06-25 17:55:23 +00:00
|
|
|
return object_error::success;
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI,
|
|
|
|
char &Result) const {
|
|
|
|
const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
|
2013-04-09 01:04:06 +00:00
|
|
|
uint8_t Type = Entry->Type;
|
|
|
|
uint16_t Flags = Entry->Flags;
|
2011-04-22 03:19:48 +00:00
|
|
|
|
|
|
|
char Char;
|
2011-07-15 17:32:45 +00:00
|
|
|
switch (Type & macho::STF_TypeMask) {
|
2011-04-22 03:19:48 +00:00
|
|
|
case macho::STT_Undefined:
|
|
|
|
Char = 'u';
|
|
|
|
break;
|
|
|
|
case macho::STT_Absolute:
|
|
|
|
case macho::STT_Section:
|
|
|
|
Char = 's';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Char = '?';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-07-15 17:32:45 +00:00
|
|
|
if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
|
2013-02-12 21:21:59 +00:00
|
|
|
Char = toupper(static_cast<unsigned char>(Char));
|
2011-06-25 17:55:23 +00:00
|
|
|
Result = Char;
|
|
|
|
return object_error::success;
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI,
|
|
|
|
uint32_t &Result) const {
|
|
|
|
const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
|
2013-04-09 01:04:06 +00:00
|
|
|
uint8_t MachOType = Entry->Type;
|
|
|
|
uint16_t MachOFlags = Entry->Flags;
|
2011-04-22 03:19:48 +00:00
|
|
|
|
2012-04-12 20:13:57 +00:00
|
|
|
// TODO: Correctly set SF_ThreadLocal
|
2012-02-28 23:47:53 +00:00
|
|
|
Result = SymbolRef::SF_None;
|
2012-02-29 02:11:55 +00:00
|
|
|
|
|
|
|
if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
|
|
|
|
Result |= SymbolRef::SF_Undefined;
|
|
|
|
|
2012-02-28 23:47:53 +00:00
|
|
|
if (MachOFlags & macho::STF_StabsEntryMask)
|
|
|
|
Result |= SymbolRef::SF_FormatSpecific;
|
2011-10-17 23:54:22 +00:00
|
|
|
|
2012-04-12 20:13:57 +00:00
|
|
|
if (MachOType & MachO::NlistMaskExternal) {
|
2012-02-28 23:47:53 +00:00
|
|
|
Result |= SymbolRef::SF_Global;
|
2012-04-12 20:13:57 +00:00
|
|
|
if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
|
|
|
|
Result |= SymbolRef::SF_Common;
|
|
|
|
}
|
2011-10-17 23:54:22 +00:00
|
|
|
|
2012-02-28 23:47:53 +00:00
|
|
|
if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
|
|
|
|
Result |= SymbolRef::SF_Weak;
|
2011-10-17 23:54:46 +00:00
|
|
|
|
2012-02-28 23:47:53 +00:00
|
|
|
if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
|
|
|
|
Result |= SymbolRef::SF_Absolute;
|
2011-10-17 23:54:46 +00:00
|
|
|
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb,
|
|
|
|
section_iterator &Res) const {
|
|
|
|
const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
|
2013-04-09 01:04:06 +00:00
|
|
|
uint8_t index = Entry->SectionIndex;
|
2011-10-17 23:54:46 +00:00
|
|
|
|
|
|
|
if (index == 0)
|
|
|
|
Res = end_sections();
|
|
|
|
else
|
2011-11-29 17:40:10 +00:00
|
|
|
Res = section_iterator(SectionRef(Sections[index-1], this));
|
2011-10-17 23:54:46 +00:00
|
|
|
|
|
|
|
return object_error::success;
|
2011-09-14 01:22:52 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb,
|
|
|
|
SymbolRef::Type &Res) const {
|
|
|
|
const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
|
2013-04-09 00:22:58 +00:00
|
|
|
uint8_t n_type = Entry->Type;
|
|
|
|
|
2011-09-14 01:22:52 +00:00
|
|
|
Res = SymbolRef::ST_Other;
|
2011-10-12 22:23:12 +00:00
|
|
|
|
|
|
|
// If this is a STAB debugging symbol, we can do nothing more.
|
2011-10-21 19:26:54 +00:00
|
|
|
if (n_type & MachO::NlistMaskStab) {
|
|
|
|
Res = SymbolRef::ST_Debug;
|
2011-10-12 22:23:12 +00:00
|
|
|
return object_error::success;
|
2011-10-21 19:26:54 +00:00
|
|
|
}
|
2011-10-12 22:23:12 +00:00
|
|
|
|
2011-09-14 01:22:52 +00:00
|
|
|
switch (n_type & MachO::NlistMaskType) {
|
|
|
|
case MachO::NListTypeUndefined :
|
2012-02-29 02:11:55 +00:00
|
|
|
Res = SymbolRef::ST_Unknown;
|
2011-09-14 01:22:52 +00:00
|
|
|
break;
|
|
|
|
case MachO::NListTypeSection :
|
|
|
|
Res = SymbolRef::ST_Function;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb,
|
|
|
|
uint64_t &Val) const {
|
|
|
|
report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase");
|
2012-10-29 10:47:00 +00:00
|
|
|
}
|
2011-09-14 01:22:52 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
symbol_iterator MachOObjectFileBase::begin_symbols() const {
|
2011-04-22 03:19:48 +00:00
|
|
|
// DRI.d.a = segment number; DRI.d.b = symbol index.
|
|
|
|
DataRefImpl DRI;
|
|
|
|
moveToNextSymbol(DRI);
|
|
|
|
return symbol_iterator(SymbolRef(DRI, this));
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
symbol_iterator MachOObjectFileBase::end_symbols() const {
|
2011-04-22 03:19:48 +00:00
|
|
|
DataRefImpl DRI;
|
2013-04-07 19:26:57 +00:00
|
|
|
DRI.d.a = getHeader()->NumLoadCommands;
|
2011-04-22 03:19:48 +00:00
|
|
|
return symbol_iterator(SymbolRef(DRI, this));
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const {
|
2012-02-28 00:40:37 +00:00
|
|
|
// TODO: implement
|
2013-04-09 14:49:08 +00:00
|
|
|
report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
|
2012-02-28 00:40:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const {
|
2012-02-28 00:40:37 +00:00
|
|
|
// TODO: implement
|
2013-04-09 14:49:08 +00:00
|
|
|
report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase");
|
2012-02-28 00:40:37 +00:00
|
|
|
}
|
2011-04-22 03:19:48 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
library_iterator MachOObjectFileBase::begin_libraries_needed() const {
|
2012-03-01 01:36:50 +00:00
|
|
|
// TODO: implement
|
2013-04-09 14:49:08 +00:00
|
|
|
report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
|
2012-03-01 01:36:50 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
library_iterator MachOObjectFileBase::end_libraries_needed() const {
|
2012-03-01 01:36:50 +00:00
|
|
|
// TODO: implement
|
2013-04-09 14:49:08 +00:00
|
|
|
report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
|
2012-03-01 01:36:50 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
StringRef MachOObjectFileBase::getLoadName() const {
|
2012-03-01 22:19:54 +00:00
|
|
|
// TODO: Implement
|
2013-04-09 14:49:08 +00:00
|
|
|
report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase");
|
2012-03-01 22:19:54 +00:00
|
|
|
}
|
|
|
|
|
2011-04-22 03:19:48 +00:00
|
|
|
/*===-- Sections ----------------------------------------------------------===*/
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const {
|
2011-10-07 19:25:32 +00:00
|
|
|
SectionList::const_iterator loc =
|
|
|
|
std::find(Sections.begin(), Sections.end(), Sec);
|
|
|
|
assert(loc != Sections.end() && "Sec is not a valid section!");
|
|
|
|
return std::distance(Sections.begin(), loc);
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
const MachOObjectFileBase::SectionBase*
|
|
|
|
MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const {
|
|
|
|
const LoadCommand *Command = getLoadCommandInfo(DRI.d.a);
|
2013-04-08 23:57:13 +00:00
|
|
|
uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command);
|
|
|
|
|
|
|
|
bool Is64 = is64Bit();
|
|
|
|
unsigned SegmentLoadSize =
|
2013-04-10 15:33:44 +00:00
|
|
|
Is64 ? sizeof(MachOObjectFile64Le::SegmentLoadCommand) :
|
|
|
|
sizeof(MachOObjectFile32Le::SegmentLoadCommand);
|
|
|
|
unsigned SectionSize = Is64 ? sizeof(MachOObjectFile64Le::Section) :
|
|
|
|
sizeof(MachOObjectFile32Le::Section);
|
2013-04-08 23:57:13 +00:00
|
|
|
|
|
|
|
uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
|
2013-04-09 14:49:08 +00:00
|
|
|
return reinterpret_cast<const SectionBase*>(SectionAddr);
|
2011-07-15 00:14:48 +00:00
|
|
|
}
|
|
|
|
|
Add a function to get the segment name of a section.
On MachO, sections also have segment names. When a tool looking at a .o file
prints a segment name, this is what they mean. In reality, a .o has only one
anonymous, segment.
This patch adds a MachO only function to fetch that segment name. I named it
getSectionFinalSegmentName since the main use for the name seems to be inform
the linker with segment this section should go to.
The patch also changes MachOObjectFile::getSectionName to return just the
section name instead of computing SegmentName,SectionName.
The main difference from the previous patch is that it doesn't use
InMemoryStruct. It is extremely dangerous: if the endians match it returns
a pointer to the file buffer, if not, it returns a pointer to an internal buffer
that is overwritten in the next API call.
We should change all of this code to use
support::detail::packed_endian_specific_integral like ELF, but since these
functions only handle strings, they work with big and little endian machines
as is.
I have tested this by installing ubuntu 12.10 ppc on qemu, that is why it took
so long :-)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@170838 91177308-0d34-0410-b5e6-96231b3b80d8
2012-12-21 03:47:03 +00:00
|
|
|
static StringRef parseSegmentOrSectionName(const char *P) {
|
|
|
|
if (P[15] == 0)
|
|
|
|
// Null terminated.
|
|
|
|
return P;
|
|
|
|
// Not null terminated, so this is a 16 char string.
|
|
|
|
return StringRef(P, 16);
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const {
|
|
|
|
const SectionBase *Base = getSectionBase(DRI);
|
2013-04-08 23:57:13 +00:00
|
|
|
return ArrayRef<char>(Base->Name);
|
2013-04-05 15:15:22 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI,
|
|
|
|
StringRef &Result) const {
|
2013-04-05 15:15:22 +00:00
|
|
|
ArrayRef<char> Raw = getSectionRawName(DRI);
|
|
|
|
Result = parseSegmentOrSectionName(Raw.data());
|
Add a function to get the segment name of a section.
On MachO, sections also have segment names. When a tool looking at a .o file
prints a segment name, this is what they mean. In reality, a .o has only one
anonymous, segment.
This patch adds a MachO only function to fetch that segment name. I named it
getSectionFinalSegmentName since the main use for the name seems to be inform
the linker with segment this section should go to.
The patch also changes MachOObjectFile::getSectionName to return just the
section name instead of computing SegmentName,SectionName.
The main difference from the previous patch is that it doesn't use
InMemoryStruct. It is extremely dangerous: if the endians match it returns
a pointer to the file buffer, if not, it returns a pointer to an internal buffer
that is overwritten in the next API call.
We should change all of this code to use
support::detail::packed_endian_specific_integral like ELF, but since these
functions only handle strings, they work with big and little endian machines
as is.
I have tested this by installing ubuntu 12.10 ppc on qemu, that is why it took
so long :-)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@170838 91177308-0d34-0410-b5e6-96231b3b80d8
2012-12-21 03:47:03 +00:00
|
|
|
return object_error::success;
|
|
|
|
}
|
2011-07-15 00:14:48 +00:00
|
|
|
|
2013-04-05 15:15:22 +00:00
|
|
|
ArrayRef<char>
|
2013-04-09 14:49:08 +00:00
|
|
|
MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
|
|
|
|
const SectionBase *Base = getSectionBase(Sec);
|
2013-04-08 23:57:13 +00:00
|
|
|
return ArrayRef<char>(Base->SegmentName);
|
2013-04-05 15:15:22 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
StringRef
|
|
|
|
MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const {
|
2013-04-05 15:15:22 +00:00
|
|
|
ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI);
|
|
|
|
return parseSegmentOrSectionName(Raw.data());
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI,
|
|
|
|
bool &Result) const {
|
2011-09-28 20:57:30 +00:00
|
|
|
// FIXME: Unimplemented.
|
|
|
|
Result = false;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI,
|
|
|
|
bool &Result) const {
|
2011-09-28 20:57:30 +00:00
|
|
|
// FIXME: Unimplemented.
|
|
|
|
Result = false;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code
|
|
|
|
MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec,
|
|
|
|
bool &Result) const {
|
2012-10-10 01:45:52 +00:00
|
|
|
// FIXME: Unimplemented.
|
2012-04-12 20:13:57 +00:00
|
|
|
Result = true;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec,
|
|
|
|
bool &Result) const {
|
2012-10-10 01:45:52 +00:00
|
|
|
// FIXME: Unimplemented.
|
2012-04-12 20:13:57 +00:00
|
|
|
Result = false;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec,
|
|
|
|
bool &Result) const {
|
2012-10-10 01:41:33 +00:00
|
|
|
// Consider using the code from isSectionText to look for __const sections.
|
|
|
|
// Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
|
|
|
|
// to use section attributes to distinguish code from data.
|
|
|
|
|
|
|
|
// FIXME: Unimplemented.
|
|
|
|
Result = false;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const {
|
2011-10-07 19:25:32 +00:00
|
|
|
DataRefImpl ret;
|
|
|
|
ret.d.b = getSectionIndex(Sec);
|
|
|
|
return relocation_iterator(RelocationRef(ret, this));
|
|
|
|
}
|
2013-04-08 20:45:01 +00:00
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
section_iterator MachOObjectFileBase::end_sections() const {
|
2011-04-22 03:19:48 +00:00
|
|
|
DataRefImpl DRI;
|
2013-04-07 19:26:57 +00:00
|
|
|
DRI.d.a = getHeader()->NumLoadCommands;
|
2011-04-22 03:19:48 +00:00
|
|
|
return section_iterator(SectionRef(DRI, this));
|
|
|
|
}
|
|
|
|
|
2011-09-08 20:52:17 +00:00
|
|
|
/*===-- Relocations -------------------------------------------------------===*/
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel,
|
|
|
|
RelocationRef &Res) const {
|
2011-09-08 20:52:17 +00:00
|
|
|
++Rel.d.a;
|
|
|
|
Res = RelocationRef(Rel, this);
|
|
|
|
return object_error::success;
|
|
|
|
}
|
2011-10-24 23:20:07 +00:00
|
|
|
|
|
|
|
// Helper to advance a section or symbol iterator multiple increments at a time.
|
|
|
|
template<class T>
|
|
|
|
error_code advance(T &it, size_t Val) {
|
|
|
|
error_code ec;
|
|
|
|
while (Val--) {
|
|
|
|
it.increment(ec);
|
|
|
|
}
|
|
|
|
return ec;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
void advanceTo(T &it, size_t Val) {
|
|
|
|
if (error_code ec = advance(it, Val))
|
|
|
|
report_fatal_error(ec.message());
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
void
|
|
|
|
MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
|
|
|
|
raw_string_ostream &fmt) const {
|
2011-10-26 20:42:54 +00:00
|
|
|
unsigned Arch = getArch();
|
|
|
|
bool isScattered = (Arch != Triple::x86_64) &&
|
|
|
|
(RE->Word0 & macho::RF_Scattered);
|
|
|
|
|
|
|
|
// Target of a scattered relocation is an address. In the interest of
|
|
|
|
// generating pretty output, scan through the symbol table looking for a
|
|
|
|
// symbol that aligns with that address. If we find one, print it.
|
|
|
|
// Otherwise, we just print the hex address of the target.
|
|
|
|
if (isScattered) {
|
|
|
|
uint32_t Val = RE->Word1;
|
|
|
|
|
|
|
|
error_code ec;
|
|
|
|
for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
|
|
|
|
SI.increment(ec)) {
|
|
|
|
if (ec) report_fatal_error(ec.message());
|
|
|
|
|
|
|
|
uint64_t Addr;
|
|
|
|
StringRef Name;
|
|
|
|
|
|
|
|
if ((ec = SI->getAddress(Addr)))
|
|
|
|
report_fatal_error(ec.message());
|
|
|
|
if (Addr != Val) continue;
|
|
|
|
if ((ec = SI->getName(Name)))
|
|
|
|
report_fatal_error(ec.message());
|
|
|
|
fmt << Name;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-27 21:53:50 +00:00
|
|
|
// If we couldn't find a symbol that this relocation refers to, try
|
|
|
|
// to find a section beginning instead.
|
|
|
|
for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
|
|
|
|
SI.increment(ec)) {
|
|
|
|
if (ec) report_fatal_error(ec.message());
|
|
|
|
|
|
|
|
uint64_t Addr;
|
|
|
|
StringRef Name;
|
|
|
|
|
|
|
|
if ((ec = SI->getAddress(Addr)))
|
|
|
|
report_fatal_error(ec.message());
|
|
|
|
if (Addr != Val) continue;
|
|
|
|
if ((ec = SI->getName(Name)))
|
|
|
|
report_fatal_error(ec.message());
|
|
|
|
fmt << Name;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-26 20:42:54 +00:00
|
|
|
fmt << format("0x%x", Val);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef S;
|
|
|
|
bool isExtern = (RE->Word1 >> 27) & 1;
|
|
|
|
uint32_t Val = RE->Word1 & 0xFFFFFF;
|
2011-10-24 23:20:07 +00:00
|
|
|
|
|
|
|
if (isExtern) {
|
|
|
|
symbol_iterator SI = begin_symbols();
|
|
|
|
advanceTo(SI, Val);
|
2011-10-26 20:42:54 +00:00
|
|
|
SI->getName(S);
|
2011-10-24 23:20:07 +00:00
|
|
|
} else {
|
|
|
|
section_iterator SI = begin_sections();
|
|
|
|
advanceTo(SI, Val);
|
2011-10-26 20:42:54 +00:00
|
|
|
SI->getName(S);
|
2011-10-24 23:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-10-26 20:42:54 +00:00
|
|
|
fmt << S;
|
2011-10-24 23:20:07 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData,
|
|
|
|
LibraryRef &Res) const {
|
|
|
|
report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
|
2012-03-01 01:36:50 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData,
|
|
|
|
StringRef &Res) const {
|
|
|
|
report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase");
|
2012-03-01 01:36:50 +00:00
|
|
|
}
|
|
|
|
|
2013-04-11 02:21:31 +00:00
|
|
|
error_code MachOObjectFileBase::getRelocationAdditionalInfo(DataRefImpl Rel,
|
|
|
|
int64_t &Res) const {
|
|
|
|
Res = 0;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2012-03-01 01:36:50 +00:00
|
|
|
|
2011-04-22 03:19:48 +00:00
|
|
|
/*===-- Miscellaneous -----------------------------------------------------===*/
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
uint8_t MachOObjectFileBase::getBytesInAddress() const {
|
2013-04-07 19:05:30 +00:00
|
|
|
return is64Bit() ? 8 : 4;
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
StringRef MachOObjectFileBase::getFileFormatName() const {
|
2013-04-07 19:05:30 +00:00
|
|
|
if (!is64Bit()) {
|
2013-04-07 19:26:57 +00:00
|
|
|
switch (getHeader()->CPUType) {
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypeI386:
|
2011-04-22 04:08:58 +00:00
|
|
|
return "Mach-O 32-bit i386";
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypeARM:
|
2011-04-22 04:08:58 +00:00
|
|
|
return "Mach-O arm";
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypePowerPC:
|
2011-04-22 04:08:58 +00:00
|
|
|
return "Mach-O 32-bit ppc";
|
|
|
|
default:
|
2013-04-07 19:26:57 +00:00
|
|
|
assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 &&
|
2011-04-22 04:08:58 +00:00
|
|
|
"64-bit object file when we're not 64-bit?");
|
|
|
|
return "Mach-O 32-bit unknown";
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-28 20:26:17 +00:00
|
|
|
// Make sure the cpu type has the correct mask.
|
2013-04-07 19:26:57 +00:00
|
|
|
assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64)
|
2013-02-28 20:26:17 +00:00
|
|
|
== llvm::MachO::CPUArchABI64 &&
|
|
|
|
"32-bit object file when we're 64-bit?");
|
|
|
|
|
2013-04-07 19:26:57 +00:00
|
|
|
switch (getHeader()->CPUType) {
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypeX86_64:
|
2011-04-22 04:08:58 +00:00
|
|
|
return "Mach-O 64-bit x86-64";
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypePowerPC64:
|
2011-04-22 04:08:58 +00:00
|
|
|
return "Mach-O 64-bit ppc64";
|
2011-04-22 03:19:48 +00:00
|
|
|
default:
|
2011-04-22 04:08:58 +00:00
|
|
|
return "Mach-O 64-bit unknown";
|
2011-04-22 03:19:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-09 14:49:08 +00:00
|
|
|
unsigned MachOObjectFileBase::getArch() const {
|
2013-04-07 19:26:57 +00:00
|
|
|
switch (getHeader()->CPUType) {
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypeI386:
|
2011-04-22 03:19:48 +00:00
|
|
|
return Triple::x86;
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypeX86_64:
|
2011-04-22 03:19:48 +00:00
|
|
|
return Triple::x86_64;
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypeARM:
|
2011-04-22 03:19:48 +00:00
|
|
|
return Triple::arm;
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypePowerPC:
|
2011-04-22 03:19:48 +00:00
|
|
|
return Triple::ppc;
|
2011-04-22 06:34:01 +00:00
|
|
|
case llvm::MachO::CPUTypePowerPC64:
|
2011-04-22 03:19:48 +00:00
|
|
|
return Triple::ppc64;
|
|
|
|
default:
|
|
|
|
return Triple::UnknownArch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-11 17:32:27 +00:00
|
|
|
} // end namespace object
|
2011-04-22 03:19:48 +00:00
|
|
|
} // end namespace llvm
|