You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.3 KiB
100 lines
3.3 KiB
//===- Relocator.cpp ------------------------------------------------------===//
|
|
//
|
|
// The MCLinker Project
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "mcld/LD/Relocator.h"
|
|
|
|
#include "mcld/Module.h"
|
|
#include "mcld/Fragment/Fragment.h"
|
|
#include "mcld/LD/LDContext.h"
|
|
#include "mcld/LD/LDSection.h"
|
|
#include "mcld/LD/LDSymbol.h"
|
|
#include "mcld/LD/ResolveInfo.h"
|
|
#include "mcld/LD/SectionData.h"
|
|
#include "mcld/Support/Demangle.h"
|
|
#include "mcld/Support/MsgHandling.h"
|
|
|
|
#include <sstream>
|
|
|
|
namespace mcld {
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Relocator
|
|
//===----------------------------------------------------------------------===//
|
|
Relocator::~Relocator() {
|
|
}
|
|
|
|
void Relocator::partialScanRelocation(Relocation& pReloc,
|
|
Module& pModule) {
|
|
// if we meet a section symbol
|
|
if (pReloc.symInfo()->type() == ResolveInfo::Section) {
|
|
LDSymbol* input_sym = pReloc.symInfo()->outSymbol();
|
|
|
|
// 1. update the relocation target offset
|
|
assert(input_sym->hasFragRef());
|
|
uint64_t offset = input_sym->fragRef()->getOutputOffset();
|
|
pReloc.target() += offset;
|
|
|
|
// 2. get output section symbol
|
|
// get the output LDSection which the symbol defined in
|
|
const LDSection& out_sect =
|
|
input_sym->fragRef()->frag()->getParent()->getSection();
|
|
ResolveInfo* sym_info =
|
|
pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
|
|
// set relocation target symbol to the output section symbol's resolveInfo
|
|
pReloc.setSymInfo(sym_info);
|
|
}
|
|
}
|
|
|
|
void Relocator::issueUndefRef(Relocation& pReloc,
|
|
LDSection& pSection,
|
|
Input& pInput) {
|
|
FragmentRef::Offset undef_sym_pos = pReloc.targetRef().offset();
|
|
std::string sect_name(pSection.name());
|
|
// Drop .rel(a) prefix
|
|
sect_name = sect_name.substr(sect_name.find('.', /*pos=*/1));
|
|
|
|
std::string reloc_sym(pReloc.symInfo()->name());
|
|
reloc_sym = demangleName(reloc_sym);
|
|
|
|
std::stringstream ss;
|
|
ss << "0x" << std::hex << undef_sym_pos;
|
|
std::string undef_sym_pos_hex(ss.str());
|
|
|
|
if (sect_name.substr(0, 5) != ".text") {
|
|
// Function name is only valid for text section
|
|
fatal(diag::undefined_reference) << reloc_sym << pInput.path() << sect_name
|
|
<< undef_sym_pos_hex;
|
|
return;
|
|
}
|
|
|
|
std::string caller_file_name;
|
|
std::string caller_func_name;
|
|
for (LDContext::sym_iterator i = pInput.context()->symTabBegin(),
|
|
e = pInput.context()->symTabEnd();
|
|
i != e;
|
|
++i) {
|
|
LDSymbol& sym = **i;
|
|
if (sym.resolveInfo()->type() == ResolveInfo::File)
|
|
caller_file_name = sym.resolveInfo()->name();
|
|
|
|
if (sym.resolveInfo()->type() == ResolveInfo::Function &&
|
|
sym.value() <= undef_sym_pos &&
|
|
sym.value() + sym.size() > undef_sym_pos) {
|
|
caller_func_name = sym.name();
|
|
break;
|
|
}
|
|
}
|
|
|
|
caller_func_name = demangleName(caller_func_name);
|
|
|
|
fatal(diag::undefined_reference_text) << reloc_sym << pInput.path()
|
|
<< caller_file_name << caller_func_name;
|
|
}
|
|
|
|
} // namespace mcld
|