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