Relocator.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
1//===- Relocator.cpp ------------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include <mcld/Config/Config.h> 10#include <mcld/Fragment/Fragment.h> 11#include <mcld/LD/LDContext.h> 12#include <mcld/LD/LDSection.h> 13#include <mcld/LD/LDSymbol.h> 14#include <mcld/LD/Relocator.h> 15#include <mcld/LD/ResolveInfo.h> 16#include <mcld/LD/SectionData.h> 17#include <mcld/Support/MsgHandling.h> 18#include <mcld/Module.h> 19#ifdef HAVE_CXXABI_H 20#include <cxxabi.h> 21#endif 22#include <sstream> 23 24using namespace mcld; 25 26//===----------------------------------------------------------------------===// 27// Helper functions 28//===----------------------------------------------------------------------===// 29std::string demangleSymbol(const std::string& mangled_name) { 30#ifdef HAVE_CXXABI_H 31 // __cxa_demangle needs manually handle the memory release, so we wrap 32 // it into this helper function. 33 size_t output_leng; 34 int status; 35 char* buffer = abi::__cxa_demangle(mangled_name.c_str(), /*buffer=*/0, 36 &output_leng, &status); 37 if (status != 0) { // Failed 38 return mangled_name; 39 } 40 std::string demangled_name(buffer); 41 free(buffer); 42 43 return demangled_name; 44#else 45 return mangled_name; 46#endif 47} 48 49 50//===----------------------------------------------------------------------===// 51// Relocator 52//===----------------------------------------------------------------------===// 53Relocator::~Relocator() 54{ 55} 56 57void Relocator::partialScanRelocation(Relocation& pReloc, 58 Module& pModule, 59 const LDSection& pSection) 60{ 61 // if we meet a section symbol 62 if (pReloc.symInfo()->type() == ResolveInfo::Section) { 63 LDSymbol* input_sym = pReloc.symInfo()->outSymbol(); 64 65 // 1. update the relocation target offset 66 assert(input_sym->hasFragRef()); 67 uint64_t offset = input_sym->fragRef()->getOutputOffset(); 68 pReloc.target() += offset; 69 70 // 2. get output section symbol 71 // get the output LDSection which the symbol defined in 72 const LDSection& out_sect = 73 input_sym->fragRef()->frag()->getParent()->getSection(); 74 ResolveInfo* sym_info = 75 pModule.getSectionSymbolSet().get(out_sect)->resolveInfo(); 76 // set relocation target symbol to the output section symbol's resolveInfo 77 pReloc.setSymInfo(sym_info); 78 } 79} 80 81void Relocator::issueUndefRef(Relocation& pReloc, 82 LDSection& pSection, 83 Input& pInput) 84{ 85 FragmentRef::Offset undef_sym_pos = pReloc.targetRef().offset(); 86 std::string sect_name(pSection.name()); 87 sect_name = sect_name.substr(sect_name.find('.', /*pos=*/1)); // Drop .rel(a) prefix 88 89 std::string reloc_sym(pReloc.symInfo()->name()); 90 if (reloc_sym.substr(0, 2) == "_Z") 91 reloc_sym = demangleSymbol(reloc_sym); 92 93 std::stringstream ss; 94 ss << "0x" << std::hex << undef_sym_pos; 95 std::string undef_sym_pos_hex(ss.str()); 96 97 if (sect_name.substr(0, 5) != ".text") { 98 // Function name is only valid for text section 99 fatal(diag::undefined_reference) << reloc_sym 100 << pInput.path() 101 << sect_name 102 << undef_sym_pos_hex; 103 return; 104 } 105 106 std::string caller_file_name; 107 std::string caller_func_name; 108 for (LDContext::sym_iterator i = pInput.context()->symTabBegin(), 109 e = pInput.context()->symTabEnd(); i != e; ++i) { 110 LDSymbol& sym = **i; 111 if (sym.resolveInfo()->type() == ResolveInfo::File) 112 caller_file_name = sym.resolveInfo()->name(); 113 114 if (sym.resolveInfo()->type() == ResolveInfo::Function && 115 sym.value() <= undef_sym_pos && 116 sym.value() + sym.size() > undef_sym_pos) { 117 caller_func_name = sym.name(); 118 break; 119 } 120 } 121 122 if (caller_func_name.substr(0, 2) == "_Z") 123 caller_func_name = demangleSymbol(caller_func_name); 124 125 fatal(diag::undefined_reference_text) << reloc_sym 126 << pInput.path() 127 << caller_file_name 128 << caller_func_name; 129} 130