#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCRelocationInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Object/MachO.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachO.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
namespace {
class MCMachObjectSymbolizer : public MCObjectSymbolizer {
+ const MachOObjectFile *MOOF;
+ // __TEXT;__stubs support.
+ uint64_t StubsStart;
+ uint64_t StubsCount;
+ uint64_t StubSize;
+ uint64_t StubsIndSymIndex;
+
public:
- MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo,
- const MachOObjectFile *MOOF) {}
+ MCMachObjectSymbolizer(MCContext &Ctx,
+ std::unique_ptr<MCRelocationInfo> &RelInfo,
+ const MachOObjectFile *MOOF);
- void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
- int64_t Value,
- uint64_t Address) LLVM_OVERRIDE;
+ StringRef findExternalFunctionAt(uint64_t Addr) override;
+
+ void tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value,
+ uint64_t Address) override;
};
} // End unnamed namespace
+MCMachObjectSymbolizer::MCMachObjectSymbolizer(
+ MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &RelInfo,
+ const MachOObjectFile *MOOF)
+ : MCObjectSymbolizer(Ctx, RelInfo, MOOF), MOOF(MOOF), StubsStart(0),
+ StubsCount(0), StubSize(0), StubsIndSymIndex(0) {
+
+ for (section_iterator SI = MOOF->section_begin(), SE = MOOF->section_end();
+ SI != SE; ++SI) {
+ StringRef Name; SI->getName(Name);
+ if (Name == "__stubs") {
+ SectionRef StubsSec = *SI;
+ if (MOOF->is64Bit()) {
+ MachO::section_64 S = MOOF->getSection64(StubsSec.getRawDataRefImpl());
+ StubsIndSymIndex = S.reserved1;
+ StubSize = S.reserved2;
+ } else {
+ MachO::section S = MOOF->getSection(StubsSec.getRawDataRefImpl());
+ StubsIndSymIndex = S.reserved1;
+ StubSize = S.reserved2;
+ }
+ assert(StubSize && "Mach-O stub entry size can't be zero!");
+ StubsSec.getAddress(StubsStart);
+ StubsSec.getSize(StubsCount);
+ StubsCount /= StubSize;
+ }
+ }
+}
+
+StringRef MCMachObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) {
+ // FIXME: also, this can all be done at the very beginning, by iterating over
+ // all stubs and creating the calls to outside functions. Is it worth it
+ // though?
+ if (!StubSize)
+ return StringRef();
+ uint64_t StubIdx = (Addr - StubsStart) / StubSize;
+ if (StubIdx >= StubsCount)
+ return StringRef();
+
+ uint32_t SymtabIdx =
+ MOOF->getIndirectSymbolTableEntry(MOOF->getDysymtabLoadCommand(), StubIdx);
+
+ StringRef SymName;
+ symbol_iterator SI = MOOF->symbol_begin();
+ for (uint32_t i = 0; i != SymtabIdx; ++i)
+ ++SI;
+ SI->getName(SymName);
+ assert(SI != MOOF->symbol_end() && "Stub wasn't found in the symbol table!");
+ assert(SymName.front() == '_' && "Mach-O symbol doesn't start with '_'!");
+ return SymName.substr(1);
+}
void MCMachObjectSymbolizer::
tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value,
//===- MCObjectSymbolizer -------------------------------------------------===//
-MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx,
- OwningPtr<MCRelocationInfo> &RelInfo,
- const ObjectFile *Obj)
- : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() {
-}
+MCObjectSymbolizer::MCObjectSymbolizer(
+ MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &RelInfo,
+ const ObjectFile *Obj)
+ : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() {}
bool MCObjectSymbolizer::
tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream,
int64_t Value, uint64_t Address, bool IsBranch,
uint64_t Offset, uint64_t InstSize) {
+ if (IsBranch) {
+ StringRef ExtFnName = findExternalFunctionAt((uint64_t)Value);
+ if (!ExtFnName.empty()) {
+ MCSymbol *Sym = Ctx.GetOrCreateSymbol(ExtFnName);
+ const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
+ MI.addOperand(MCOperand::CreateExpr(Expr));
+ return true;
+ }
+ }
+
if (const RelocationRef *R = findRelocationAt(Address + Offset)) {
if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(*R)) {
MI.addOperand(MCOperand::CreateExpr(RelExpr));
return false;
uint64_t UValue = Value;
// FIXME: map instead of looping each time?
- error_code ec;
- for (symbol_iterator SI = Obj->begin_symbols(), SE = Obj->end_symbols();
- SI != SE; SI.increment(ec)) {
- if (ec) break;
+ for (symbol_iterator SI = Obj->symbol_begin(), SE = Obj->symbol_end();
+ SI != SE; ++SI) {
uint64_t SymAddr; SI->getAddress(SymAddr);
uint64_t SymSize; SI->getSize(SymSize);
StringRef SymName; SI->getName(SymName);
return StringRef();
}
-MCObjectSymbolizer *
-MCObjectSymbolizer::createObjectSymbolizer(MCContext &Ctx,
- OwningPtr<MCRelocationInfo> &RelInfo,
- const ObjectFile *Obj) {
+MCObjectSymbolizer *MCObjectSymbolizer::createObjectSymbolizer(
+ MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &RelInfo,
+ const ObjectFile *Obj) {
if (const MachOObjectFile *MOOF = dyn_cast<MachOObjectFile>(Obj))
return new MCMachObjectSymbolizer(Ctx, RelInfo, MOOF);
return new MCObjectSymbolizer(Ctx, RelInfo, Obj);
}
void MCObjectSymbolizer::buildSectionList() {
- error_code ec;
- for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
- SI != SE; SI.increment(ec)) {
- if (ec) break;
-
+ for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
+ SI != SE; ++SI) {
bool RequiredForExec; SI->isRequiredForExecution(RequiredForExec);
if (RequiredForExec == false)
continue;
}
void MCObjectSymbolizer::buildRelocationByAddrMap() {
- error_code ec;
- for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
- SI != SE; SI.increment(ec)) {
- if (ec) break;
-
+ for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
+ SI != SE; ++SI) {
section_iterator RelSecI = SI->getRelocatedSection();
- if (RelSecI == Obj->end_sections())
+ if (RelSecI == Obj->section_end())
continue;
uint64_t StartAddr; RelSecI->getAddress(StartAddr);
bool RequiredForExec; RelSecI->isRequiredForExecution(RequiredForExec);
if (RequiredForExec == false || Size == 0)
continue;
- for (relocation_iterator RI = SI->begin_relocations(),
- RE = SI->end_relocations();
- RI != RE;
- RI.increment(ec)) {
- if (ec) break;
+ for (relocation_iterator RI = SI->relocation_begin(),
+ RE = SI->relocation_end();
+ RI != RE; ++RI) {
// FIXME: libObject is inconsistent regarding error handling. The
// overwhelming majority of methods always return object_error::success,
// and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset