16f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===- Relocator.cpp ------------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/Relocator.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Module.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Fragment.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDContext.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/Demangle.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
2187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <sstream>
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Relocator
276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
2837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::~Relocator() {
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
31f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid Relocator::partialScanRelocation(Relocation& pReloc,
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      Module& pModule) {
33f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // if we meet a section symbol
34f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
35f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    LDSymbol* input_sym = pReloc.symInfo()->outSymbol();
36f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // 1. update the relocation target offset
38f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    assert(input_sym->hasFragRef());
39f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    uint64_t offset = input_sym->fragRef()->getOutputOffset();
40f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pReloc.target() += offset;
41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
42f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // 2. get output section symbol
43f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // get the output LDSection which the symbol defined in
44f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    const LDSection& out_sect =
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        input_sym->fragRef()->frag()->getParent()->getSection();
46f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    ResolveInfo* sym_info =
4737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
48f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // set relocation target symbol to the output section symbol's resolveInfo
49f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pReloc.setSymInfo(sym_info);
50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
52f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid Relocator::issueUndefRef(Relocation& pReloc,
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                              LDSection& pSection,
5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              Input& pInput) {
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  FragmentRef::Offset undef_sym_pos = pReloc.targetRef().offset();
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  std::string sect_name(pSection.name());
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // Drop .rel(a) prefix
5937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  sect_name = sect_name.substr(sect_name.find('.', /*pos=*/1));
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  std::string reloc_sym(pReloc.symInfo()->name());
620dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  reloc_sym = demangleName(reloc_sym);
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  std::stringstream ss;
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ss << "0x" << std::hex << undef_sym_pos;
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  std::string undef_sym_pos_hex(ss.str());
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (sect_name.substr(0, 5) != ".text") {
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Function name is only valid for text section
7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    fatal(diag::undefined_reference) << reloc_sym << pInput.path() << sect_name
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     << undef_sym_pos_hex;
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  std::string caller_file_name;
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  std::string caller_func_name;
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (LDContext::sym_iterator i = pInput.context()->symTabBegin(),
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               e = pInput.context()->symTabEnd();
7937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       i != e;
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++i) {
8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    LDSymbol& sym = **i;
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (sym.resolveInfo()->type() == ResolveInfo::File)
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      caller_file_name = sym.resolveInfo()->name();
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (sym.resolveInfo()->type() == ResolveInfo::Function &&
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        sym.value() <= undef_sym_pos &&
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        sym.value() + sym.size() > undef_sym_pos) {
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      caller_func_name = sym.name();
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
930dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  caller_func_name = demangleName(caller_func_name);
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  fatal(diag::undefined_reference_text) << reloc_sym << pInput.path()
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                        << caller_file_name << caller_func_name;
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
100