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