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 //===----------------------------------------------------------------------===//
~Relocator()28 Relocator::~Relocator() {
29 }
30 
partialScanRelocation(Relocation & pReloc,Module & pModule)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 
issueUndefRef(Relocation & pReloc,LDSection & pSection,Input & pInput)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