Home | History | Annotate | Download | only in MC
      1 //===-- lib/MC/MCObjectSymbolizer.cpp -------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/MC/MCObjectSymbolizer.h"
     11 #include "llvm/ADT/SmallString.h"
     12 #include "llvm/MC/MCContext.h"
     13 #include "llvm/MC/MCExpr.h"
     14 #include "llvm/MC/MCInst.h"
     15 #include "llvm/MC/MCRelocationInfo.h"
     16 #include "llvm/MC/MCSymbol.h"
     17 #include "llvm/Object/MachO.h"
     18 #include "llvm/Object/ELF.h"
     19 #include "llvm/Support/raw_ostream.h"
     20 #include <algorithm>
     21 
     22 using namespace llvm;
     23 using namespace object;
     24 
     25 //===- MCMachObjectSymbolizer ---------------------------------------------===//
     26 
     27 namespace {
     28 class MCMachObjectSymbolizer : public MCObjectSymbolizer {
     29 public:
     30   MCMachObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo,
     31                          const object::MachOObjectFile *MachOOF)
     32     : MCObjectSymbolizer(Ctx, RelInfo, MachOOF)
     33   {}
     34 
     35   void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
     36                                        int64_t Value, uint64_t Address) {
     37     AddrToRelocMap::iterator RI = AddrToReloc.find(Address);
     38     if (RI != AddrToReloc.end()) {
     39       const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second);
     40       if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false)
     41         return;
     42     }
     43     uint64_t Addr = Value;
     44     SortedSectionList::const_iterator SI = findSectionContaining(Addr);
     45     if (SI != SortedSections.end()) {
     46       const SectionRef &S = *SI;
     47       StringRef Name; S.getName(Name);
     48       uint64_t SAddr; S.getAddress(SAddr);
     49       if (Name == "__cstring") {
     50         StringRef Contents;
     51         S.getContents(Contents);
     52         Contents = Contents.substr(Addr - SAddr);
     53         cStream << " ## literal pool for: "
     54                 << Contents.substr(0, Contents.find_first_of(0));
     55       }
     56     }
     57   }
     58 };
     59 } // End unnamed namespace
     60 
     61 //===- MCObjectSymbolizer -------------------------------------------------===//
     62 
     63 MCObjectSymbolizer::MCObjectSymbolizer(MCContext &Ctx,
     64                                        OwningPtr<MCRelocationInfo> &RelInfo,
     65                                        const ObjectFile *Obj)
     66     : MCSymbolizer(Ctx, RelInfo), Obj(Obj), SortedSections(), AddrToReloc() {
     67   error_code ec;
     68   for (section_iterator SI = Obj->begin_sections(),
     69                         SE = Obj->end_sections();
     70                         SI != SE;
     71                         SI.increment(ec)) {
     72     if (ec) break;
     73 
     74     section_iterator RelSecI = SI->getRelocatedSection();
     75     if (RelSecI == Obj->end_sections())
     76       continue;
     77 
     78     uint64_t StartAddr; RelSecI->getAddress(StartAddr);
     79     uint64_t Size; RelSecI->getSize(Size);
     80     bool RequiredForExec; RelSecI->isRequiredForExecution(RequiredForExec);
     81     if (RequiredForExec == false || Size == 0)
     82       continue;
     83     insertSection(*SI);
     84     for (relocation_iterator RI = SI->begin_relocations(),
     85                              RE = SI->end_relocations();
     86                              RI != RE;
     87                              RI.increment(ec)) {
     88       if (ec) break;
     89       // FIXME: libObject is inconsistent regarding error handling. The
     90       // overwhelming majority of methods always return object_error::success,
     91       // and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset
     92       // asserts when the file type isn't ET_REL.
     93       // This workaround handles x86-64 elf, the only one that has a relocinfo.
     94       uint64_t Offset;
     95       if (Obj->isELF()) {
     96         const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj);
     97         if (ELFObj == 0)
     98           break;
     99         if (ELFObj->getElfHeader()->e_type == ELF::ET_REL) {
    100           RI->getOffset(Offset);
    101           Offset += StartAddr;
    102         } else {
    103           RI->getAddress(Offset);
    104         }
    105       } else {
    106         RI->getOffset(Offset);
    107         Offset += StartAddr;
    108       }
    109       // At a specific address, only keep the first relocation.
    110       if (AddrToReloc.find(Offset) == AddrToReloc.end())
    111         AddrToReloc[Offset] = *RI;
    112     }
    113   }
    114 }
    115 
    116 bool MCObjectSymbolizer::
    117 tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream,
    118                          int64_t Value, uint64_t Address, bool IsBranch,
    119                          uint64_t Offset, uint64_t InstSize) {
    120   AddrToRelocMap::iterator RI = AddrToReloc.find(Address + Offset);
    121   if (RI != AddrToReloc.end()) {
    122     if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(RI->second)) {
    123       MI.addOperand(MCOperand::CreateExpr(RelExpr));
    124       return true;
    125     }
    126     // Only try to create a symbol+offset expression if there is no relocation.
    127     return false;
    128   }
    129 
    130   // Interpret Value as a branch target.
    131   if (IsBranch == false)
    132     return false;
    133   uint64_t UValue = Value;
    134   // FIXME: map instead of looping each time?
    135   error_code ec;
    136   for (symbol_iterator SI = Obj->begin_symbols(),
    137        SE = Obj->end_symbols();
    138        SI != SE;
    139        SI.increment(ec)) {
    140     if (ec) break;
    141     uint64_t SymAddr; SI->getAddress(SymAddr);
    142     uint64_t SymSize; SI->getSize(SymSize);
    143     StringRef SymName; SI->getName(SymName);
    144     SymbolRef::Type SymType; SI->getType(SymType);
    145     if (SymAddr == UnknownAddressOrSize || SymSize == UnknownAddressOrSize
    146         || SymName.empty() || SymType != SymbolRef::ST_Function)
    147       continue;
    148 
    149     if ( SymAddr == UValue ||
    150         (SymAddr <= UValue && SymAddr + SymSize > UValue)) {
    151       MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName);
    152       const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
    153       if (SymAddr != UValue) {
    154         const MCExpr *Off = MCConstantExpr::Create(UValue - SymAddr, Ctx);
    155         Expr = MCBinaryExpr::CreateAdd(Expr, Off, Ctx);
    156       }
    157       MI.addOperand(MCOperand::CreateExpr(Expr));
    158       return true;
    159     }
    160   }
    161   return false;
    162 }
    163 
    164 void MCObjectSymbolizer::
    165 tryAddingPcLoadReferenceComment(raw_ostream &cStream,
    166                                 int64_t Value, uint64_t Address) {
    167 }
    168 
    169 MCObjectSymbolizer *
    170 MCObjectSymbolizer::createObjectSymbolizer(MCContext &Ctx,
    171                                            OwningPtr<MCRelocationInfo> &RelInfo,
    172                                            const ObjectFile *Obj) {
    173   if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(Obj)) {
    174     return new MCMachObjectSymbolizer(Ctx, RelInfo, MachOOF);
    175   }
    176   return new MCObjectSymbolizer(Ctx, RelInfo, Obj);
    177 }
    178 
    179 // SortedSections implementation.
    180 
    181 static bool SectionStartsBefore(const SectionRef &S, uint64_t Addr) {
    182   uint64_t SAddr; S.getAddress(SAddr);
    183   return SAddr < Addr;
    184 }
    185 
    186 MCObjectSymbolizer::SortedSectionList::const_iterator
    187 MCObjectSymbolizer::findSectionContaining(uint64_t Addr) const {
    188   SortedSectionList::const_iterator
    189     EndIt = SortedSections.end(),
    190     It = std::lower_bound(SortedSections.begin(), EndIt,
    191                           Addr, SectionStartsBefore);
    192   if (It == EndIt)
    193     return It;
    194   uint64_t SAddr; It->getAddress(SAddr);
    195   uint64_t SSize; It->getSize(SSize);
    196   if (Addr >= SAddr + SSize)
    197     return EndIt;
    198   return It;
    199 }
    200 
    201 void MCObjectSymbolizer::insertSection(SectionRef Sec) {
    202   uint64_t SAddr; Sec.getAddress(SAddr);
    203   uint64_t SSize; Sec.getSize(SSize);
    204   SortedSectionList::iterator It = std::lower_bound(SortedSections.begin(),
    205                                                     SortedSections.end(),
    206                                                     SAddr,
    207                                                     SectionStartsBefore);
    208   if (It != SortedSections.end()) {
    209     uint64_t FoundSAddr; It->getAddress(FoundSAddr);
    210     if (FoundSAddr < SAddr + SSize)
    211       llvm_unreachable("Inserting overlapping sections");
    212   }
    213   SortedSections.insert(It, Sec);
    214 }
    215