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/Fragment/Fragment.h> 10#include <mcld/LD/LDContext.h> 11#include <mcld/LD/LDSection.h> 12#include <mcld/LD/LDSymbol.h> 13#include <mcld/LD/Relocator.h> 14#include <mcld/LD/ResolveInfo.h> 15#include <mcld/LD/SectionData.h> 16#include <mcld/Support/Demangle.h> 17#include <mcld/Support/MsgHandling.h> 18#include <mcld/Module.h> 19#include <sstream> 20 21using namespace mcld; 22 23//===----------------------------------------------------------------------===// 24// Relocator 25//===----------------------------------------------------------------------===// 26Relocator::~Relocator() 27{ 28} 29 30void Relocator::partialScanRelocation(Relocation& pReloc, 31 Module& pModule, 32 const LDSection& pSection) 33{ 34 // if we meet a section symbol 35 if (pReloc.symInfo()->type() == ResolveInfo::Section) { 36 LDSymbol* input_sym = pReloc.symInfo()->outSymbol(); 37 38 // 1. update the relocation target offset 39 assert(input_sym->hasFragRef()); 40 uint64_t offset = input_sym->fragRef()->getOutputOffset(); 41 pReloc.target() += offset; 42 43 // 2. get output section symbol 44 // get the output LDSection which the symbol defined in 45 const LDSection& out_sect = 46 input_sym->fragRef()->frag()->getParent()->getSection(); 47 ResolveInfo* sym_info = 48 pModule.getSectionSymbolSet().get(out_sect)->resolveInfo(); 49 // set relocation target symbol to the output section symbol's resolveInfo 50 pReloc.setSymInfo(sym_info); 51 } 52} 53 54void Relocator::issueUndefRef(Relocation& pReloc, 55 LDSection& pSection, 56 Input& pInput) 57{ 58 FragmentRef::Offset undef_sym_pos = pReloc.targetRef().offset(); 59 std::string sect_name(pSection.name()); 60 sect_name = sect_name.substr(sect_name.find('.', /*pos=*/1)); // Drop .rel(a) prefix 61 62 std::string reloc_sym(pReloc.symInfo()->name()); 63 reloc_sym = demangleName(reloc_sym); 64 65 std::stringstream ss; 66 ss << "0x" << std::hex << undef_sym_pos; 67 std::string undef_sym_pos_hex(ss.str()); 68 69 if (sect_name.substr(0, 5) != ".text") { 70 // Function name is only valid for text section 71 fatal(diag::undefined_reference) << reloc_sym 72 << pInput.path() 73 << sect_name 74 << undef_sym_pos_hex; 75 return; 76 } 77 78 std::string caller_file_name; 79 std::string caller_func_name; 80 for (LDContext::sym_iterator i = pInput.context()->symTabBegin(), 81 e = pInput.context()->symTabEnd(); i != e; ++i) { 82 LDSymbol& sym = **i; 83 if (sym.resolveInfo()->type() == ResolveInfo::File) 84 caller_file_name = sym.resolveInfo()->name(); 85 86 if (sym.resolveInfo()->type() == ResolveInfo::Function && 87 sym.value() <= undef_sym_pos && 88 sym.value() + sym.size() > undef_sym_pos) { 89 caller_func_name = sym.name(); 90 break; 91 } 92 } 93 94 caller_func_name = demangleName(caller_func_name); 95 96 fatal(diag::undefined_reference_text) << reloc_sym 97 << pInput.path() 98 << caller_file_name 99 << caller_func_name; 100} 101