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