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