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/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 
     21 using namespace mcld;
     22 
     23 //===----------------------------------------------------------------------===//
     24 // Relocator
     25 //===----------------------------------------------------------------------===//
     26 Relocator::~Relocator()
     27 {
     28 }
     29 
     30 void 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 
     54 void 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