template<endianness TargetEndianness>
struct RelocationEntry {
LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
- MachOInt32 Word0;
- MachOInt32 Word1;
+ MachOInt32 Address;
+ unsigned SymbolNum : 24;
+ unsigned PCRel : 1;
+ unsigned Length : 2;
+ unsigned External : 1;
+ unsigned Type : 4;
+ };
+
+ template<endianness TargetEndianness>
+ struct ScatteredRelocationEntry {
+ LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
+ unsigned Address : 24;
+ unsigned Type : 4;
+ unsigned Length : 2;
+ unsigned PCRel : 1;
+ unsigned Scattered : 1;
+ MachOInt32 Value;
};
template<endianness TargetEndianness>
SymbolTableEntryBase;
typedef MachOFormat::SymtabLoadCommand<support::little> SymtabLoadCommand;
typedef MachOFormat::RelocationEntry<support::little> RelocationEntry;
+ typedef MachOFormat::ScatteredRelocationEntry<support::little>
+ ScatteredRelocationEntry;
typedef MachOFormat::SectionBase SectionBase;
typedef MachOFormat::LoadCommand<support::little> LoadCommand;
typedef MachOFormat::Header<support::little> Header;
const Header *getHeader() const;
unsigned getHeaderSize() const;
StringRef getData(size_t Offset, size_t Size) const;
+ const RelocationEntry *getRelocation(DataRefImpl Rel) const;
+ bool isScattered(const RelocationEntry *RE) const;
+ bool isPCRel(const RelocationEntry *RE) const;
+ unsigned getLength(const RelocationEntry *RE) const;
+ unsigned getType(const RelocationEntry *RE) const;
static inline bool classof(const Binary *v) {
return v->isMachO();
const Section *Sect = getSection(Sections[Rel.d.b]);
uint64_t SectAddress = Sect->Address;
const RelocationEntry *RE = getRelocation(Rel);
- unsigned Arch = getArch();
- bool isScattered = (Arch != Triple::x86_64) &&
- (RE->Word0 & macho::RF_Scattered);
uint64_t RelAddr;
- if (isScattered)
- RelAddr = RE->Word0 & 0xFFFFFF;
+ if (isScattered(RE))
+ RelAddr = RE->Address & 0xFFFFFF;
else
- RelAddr = RE->Word0;
+ RelAddr = RE->Address;
Res = SectAddress + RelAddr;
return object_error::success;
MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel,
uint64_t &Res) const {
const RelocationEntry *RE = getRelocation(Rel);
-
- unsigned Arch = getArch();
- bool isScattered = (Arch != Triple::x86_64) &&
- (RE->Word0 & macho::RF_Scattered);
- if (isScattered)
- Res = RE->Word0 & 0xFFFFFF;
+ if (isScattered(RE))
+ Res = RE->Address & 0xFFFFFF;
else
- Res = RE->Word0;
+ Res = RE->Address;
return object_error::success;
}
MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel,
SymbolRef &Res) const {
const RelocationEntry *RE = getRelocation(Rel);
- uint32_t SymbolIdx = RE->Word1 & 0xffffff;
- bool isExtern = (RE->Word1 >> 27) & 1;
+ uint32_t SymbolIdx = RE->SymbolNum;
+ bool isExtern = RE->External;
DataRefImpl Sym;
moveToNextSymbol(Sym);
error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel,
uint64_t &Res) const {
const RelocationEntry *RE = getRelocation(Rel);
- Res = RE->Word0;
- Res <<= 32;
- Res |= RE->Word1;
+ Res = getType(RE);
return object_error::success;
}
const RelocationEntry *RE = getRelocation(Rel);
unsigned Arch = getArch();
- bool isScattered = (Arch != Triple::x86_64) &&
- (RE->Word0 & macho::RF_Scattered);
- unsigned r_type;
- if (isScattered)
- r_type = (RE->Word0 >> 24) & 0xF;
- else
- r_type = (RE->Word1 >> 28) & 0xF;
+ unsigned r_type = getType(RE);
switch (Arch) {
case Triple::x86: {
const RelocationEntry *RE = getRelocation(Rel);
unsigned Arch = getArch();
- bool isScattered = (Arch != Triple::x86_64) &&
- (RE->Word0 & macho::RF_Scattered);
+ bool IsScattered = isScattered(RE);
std::string fmtbuf;
raw_string_ostream fmt(fmtbuf);
- unsigned Type;
- if (isScattered)
- Type = (RE->Word0 >> 24) & 0xF;
- else
- Type = (RE->Word1 >> 28) & 0xF;
-
- bool isPCRel;
- if (isScattered)
- isPCRel = ((RE->Word0 >> 30) & 1);
- else
- isPCRel = ((RE->Word1 >> 24) & 1);
+ unsigned Type = getType(RE);
+ bool IsPCRel = isPCRel(RE);
// Determine any addends that should be displayed with the relocation.
// These require decoding the relocation type, which is triple-specific.
// X86_64 has entirely custom relocation types.
if (Arch == Triple::x86_64) {
- bool isPCRel = ((RE->Word1 >> 24) & 1);
+ bool isPCRel = RE->PCRel;
switch (Type) {
case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
// X86_64_SUBTRACTOR must be followed by a relocation of type
// X86_64_RELOC_UNSIGNED.
// NOTE: Scattered relocations don't exist on x86_64.
- unsigned RType = (RENext->Word1 >> 28) & 0xF;
+ unsigned RType = RENext->Type;
if (RType != 0)
report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
"X86_64_RELOC_SUBTRACTOR.");
// X86 sect diff's must be followed by a relocation of type
// GENERIC_RELOC_PAIR.
bool isNextScattered = (Arch != Triple::x86_64) &&
- (RENext->Word0 & macho::RF_Scattered);
+ (RENext->Address & macho::RF_Scattered);
unsigned RType;
if (isNextScattered)
- RType = (RENext->Word0 >> 24) & 0xF;
+ RType = (RENext->Address >> 24) & 0xF;
else
- RType = (RENext->Word1 >> 28) & 0xF;
+ RType = RENext->Type;
if (RType != 1)
report_fatal_error("Expected GENERIC_RELOC_PAIR after "
"GENERIC_RELOC_SECTDIFF.");
// X86 sect diff's must be followed by a relocation of type
// GENERIC_RELOC_PAIR.
bool isNextScattered = (Arch != Triple::x86_64) &&
- (RENext->Word0 & macho::RF_Scattered);
+ (RENext->Address & macho::RF_Scattered);
unsigned RType;
if (isNextScattered)
- RType = (RENext->Word0 >> 24) & 0xF;
+ RType = (RENext->Address >> 24) & 0xF;
else
- RType = (RENext->Word1 >> 28) & 0xF;
+ RType = RENext->Type;
if (RType != 1)
report_fatal_error("Expected GENERIC_RELOC_PAIR after "
"GENERIC_RELOC_LOCAL_SECTDIFF.");
case macho::RIT_Generic_TLV: {
printRelocationTargetName(RE, fmt);
fmt << "@TLV";
- if (isPCRel) fmt << "P";
+ if (IsPCRel) fmt << "P";
break;
}
default:
// Half relocations steal a bit from the length field to encode
// whether this is an upper16 or a lower16 relocation.
bool isUpper;
- if (isScattered)
- isUpper = (RE->Word0 >> 28) & 1;
+ if (IsScattered)
+ isUpper = (RE->Address >> 28) & 1;
else
- isUpper = (RE->Word1 >> 25) & 1;
+ isUpper = (RE->Length >> 1) & 1;
if (isUpper)
fmt << ":upper16:(";
// ARM half relocs must be followed by a relocation of type
// ARM_RELOC_PAIR.
bool isNextScattered = (Arch != Triple::x86_64) &&
- (RENext->Word0 & macho::RF_Scattered);
+ (RENext->Address & macho::RF_Scattered);
unsigned RType;
if (isNextScattered)
- RType = (RENext->Word0 >> 24) & 0xF;
+ RType = (RENext->Address >> 24) & 0xF;
else
- RType = (RENext->Word1 >> 28) & 0xF;
+ RType = RENext->Type;
if (RType != 1)
report_fatal_error("Expected ARM_RELOC_PAIR after "
MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
bool &Result) const {
const RelocationEntry *RE = getRelocation(Rel);
-
unsigned Arch = getArch();
- bool isScattered = (Arch != Triple::x86_64) &&
- (RE->Word0 & macho::RF_Scattered);
- unsigned Type;
- if (isScattered)
- Type = (RE->Word0 >> 24) & 0xF;
- else
- Type = (RE->Word1 >> 28) & 0xF;
+ unsigned Type = getType(RE);
Result = false;
RelPrev.d.a--;
const RelocationEntry *REPrev = getRelocation(RelPrev);
- unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
+ unsigned PrevType = REPrev->Type;
if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
}
return ObjectFile::getData().substr(Offset, Size);
}
+const MachOObjectFileBase::RelocationEntry *
+MachOObjectFileBase::getRelocation(DataRefImpl Rel) const {
+ if (const MachOObjectFile32Le *O = dyn_cast<MachOObjectFile32Le>(this))
+ return O->getRelocation(Rel);
+ const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(this);
+ return O->getRelocation(Rel);
+}
+
+bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const {
+ unsigned Arch = getArch();
+ return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered);
+}
+
+bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const {
+ if (isScattered(RE)) {
+ const ScatteredRelocationEntry *SRE =
+ reinterpret_cast<const ScatteredRelocationEntry *>(RE);
+ return SRE->PCRel;
+ }
+ return RE->PCRel;
+}
+
+unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const {
+ if (isScattered(RE)) {
+ const ScatteredRelocationEntry *SRE =
+ reinterpret_cast<const ScatteredRelocationEntry *>(RE);
+ return SRE->Length;
+ }
+ return RE->Length;
+}
+
+unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const {
+ if (isScattered(RE)) {
+ const ScatteredRelocationEntry *SRE =
+ reinterpret_cast<const ScatteredRelocationEntry *>(RE);
+ return SRE->Type;
+ }
+ return RE->Type;
+}
+
ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
StringRef Magic = Buffer->getBuffer().slice(0, 4);
error_code ec;
void
MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
raw_string_ostream &fmt) const {
- 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;
+ if (isScattered(RE)) {
+ uint32_t Val = RE->SymbolNum;
error_code ec;
for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
}
StringRef S;
- bool isExtern = (RE->Word1 >> 27) & 1;
- uint32_t Val = RE->Word1 & 0xFFFFFF;
+ bool isExtern = RE->External;
+ uint32_t Val = RE->Address;
if (isExtern) {
symbol_iterator SI = begin_symbols();