Skip to content

Commit

Permalink
Add 179294 back, but don't use bit fields so that it works on big end…
Browse files Browse the repository at this point in the history
…ian hosts.

Original message:

Print more information about relocations.

With this patch llvm-readobj now prints if a relocation is pcrel, its length,
if it is extern and if it is scattered.

It also refactors the code a bit to use bit fields instead of shifts and
masks all over the place.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179345 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
espindola committed Apr 12, 2013
1 parent 33c55bd commit e292347
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 90 deletions.
145 changes: 81 additions & 64 deletions include/llvm/Object/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,53 @@ namespace MachOFormat {
MachOInt32 Reserved3;
};

struct MachOInt24 {
uint8_t bytes[3];
operator uint32_t() const {
return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
}
};

template<endianness TargetEndianness>
struct RelocationEntry {
LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
MachOInt32 Word0;
MachOInt32 Word1;
MachOInt32 Address;
MachOInt24 SymbolNum;
uint8_t Bits;

unsigned getPCRel() const {
return Bits & 0x1;
}
unsigned getLength() const {
return (Bits >> 1) & 0x3;
}
unsigned getExternal() const {
return (Bits >> 3) & 0x1;
}
unsigned getType() const {
return Bits >> 4;
}
};

template<endianness TargetEndianness>
struct ScatteredRelocationEntry {
LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
MachOInt24 Address;
uint8_t Bits;
MachOInt32 Value;

unsigned getType() const {
return Bits & 0xf;
}
unsigned getLength() const {
return (Bits >> 4) & 0x3;
}
unsigned getPCRel() const {
return (Bits >> 6) & 0x1;
}
unsigned getScattered() const {
return Bits >> 7;
}
};

template<endianness TargetEndianness>
Expand Down Expand Up @@ -206,6 +248,8 @@ class MachOObjectFileBase : public ObjectFile {
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;
Expand Down Expand Up @@ -243,6 +287,11 @@ class MachOObjectFileBase : public ObjectFile {
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();
Expand Down Expand Up @@ -479,15 +528,12 @@ MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel,
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;
Expand All @@ -498,14 +544,10 @@ error_code
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;
}

Expand All @@ -514,8 +556,8 @@ error_code
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->getExternal();

DataRefImpl Sym;
moveToNextSymbol(Sym);
Expand All @@ -535,9 +577,7 @@ template<class MachOT>
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;
}

Expand All @@ -550,14 +590,8 @@ MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
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: {
Expand Down Expand Up @@ -650,30 +684,20 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
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->getPCRel();

switch (Type) {
case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD
Expand All @@ -691,7 +715,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
// 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->getType();
if (RType != 0)
report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
"X86_64_RELOC_SUBTRACTOR.");
Expand Down Expand Up @@ -738,12 +762,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
// 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->getType();
if (RType != 1)
report_fatal_error("Expected GENERIC_RELOC_PAIR after "
"GENERIC_RELOC_SECTDIFF.");
Expand All @@ -767,12 +791,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
// 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->getType();
if (RType != 1)
report_fatal_error("Expected GENERIC_RELOC_PAIR after "
"GENERIC_RELOC_LOCAL_SECTDIFF.");
Expand All @@ -785,7 +809,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
case macho::RIT_Generic_TLV: {
printRelocationTargetName(RE, fmt);
fmt << "@TLV";
if (isPCRel) fmt << "P";
if (IsPCRel) fmt << "P";
break;
}
default:
Expand All @@ -798,10 +822,10 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
// 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->getLength() >> 1) & 1;

if (isUpper)
fmt << ":upper16:(";
Expand All @@ -816,12 +840,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
// 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->getType();

if (RType != 1)
report_fatal_error("Expected ARM_RELOC_PAIR after "
Expand Down Expand Up @@ -860,15 +884,8 @@ error_code
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;

Expand All @@ -884,7 +901,7 @@ MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
RelPrev.d.a--;
const RelocationEntry *REPrev = getRelocation(RelPrev);

unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
unsigned PrevType = REPrev->getType();

if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
}
Expand Down
52 changes: 44 additions & 8 deletions lib/Object/MachOObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,46 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
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->getPCRel();
}
return RE->getPCRel();
}

unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const {
if (isScattered(RE)) {
const ScatteredRelocationEntry *SRE =
reinterpret_cast<const ScatteredRelocationEntry *>(RE);
return SRE->getLength();
}
return RE->getLength();
}

unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const {
if (isScattered(RE)) {
const ScatteredRelocationEntry *SRE =
reinterpret_cast<const ScatteredRelocationEntry *>(RE);
return SRE->getType();
}
return RE->getType();
}

ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
StringRef Magic = Buffer->getBuffer().slice(0, 4);
error_code ec;
Expand Down Expand Up @@ -435,16 +475,12 @@ void advanceTo(T &it, size_t Val) {
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;
Expand Down Expand Up @@ -486,8 +522,8 @@ MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
}

StringRef S;
bool isExtern = (RE->Word1 >> 27) & 1;
uint32_t Val = RE->Word1 & 0xFFFFFF;
bool isExtern = RE->getExternal();
uint32_t Val = RE->Address;

if (isExtern) {
symbol_iterator SI = begin_symbols();
Expand Down
14 changes: 7 additions & 7 deletions test/tools/llvm-readobj/relocations.test
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ ELF-NEXT: ]

MACHO-I386: Relocations [
MACHO-I386-NEXT: Section __text {
MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0
MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0
MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}}
MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}}
MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction
MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts
MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main
MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main
MACHO-I386-NEXT: }
MACHO-I386-NEXT: ]

MACHO-X86-64: Relocations [
MACHO-X86-64-NEXT: Section __text {
MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0
MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0
MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0
MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction
MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts
MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str
MACHO-X86-64-NEXT: }
MACHO-X86-64-NEXT:]
Loading

0 comments on commit e292347

Please sign in to comment.