1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-11 05:46:58 +03:00
mold/elf/input-sections.cc

190 lines
5.5 KiB
C++
Raw Normal View History

2020-10-20 08:54:35 +03:00
#include "mold.h"
2020-10-13 14:35:35 +03:00
2021-01-24 15:10:19 +03:00
#include <limits>
namespace mold::elf {
2021-09-11 08:54:55 +03:00
template <typename E>
bool CieRecord<E>::equals(const CieRecord<E> &other) const {
if (get_contents() != other.get_contents())
return false;
std::span<ElfRel<E>> x = get_rels();
std::span<ElfRel<E>> y = other.get_rels();
if (x.size() != y.size())
return false;
for (i64 i = 0; i < x.size(); i++) {
if (x[i].r_offset - input_offset != y[i].r_offset - other.input_offset ||
x[i].r_type != y[i].r_type ||
file.symbols[x[i].r_sym] != other.file.symbols[y[i].r_sym] ||
input_section.get_addend(x[i]) != other.input_section.get_addend(y[i]))
return false;
}
return true;
}
template <typename E>
InputSection<E>::InputSection(Context<E> &ctx, ObjectFile<E> &file,
const ElfShdr<E> &shdr, std::string_view name,
std::string_view contents, i64 section_idx)
: file(file), shdr(shdr), nameptr(name.data()), namelen(name.size()),
contents(contents), section_idx(section_idx) {
// As a special case, we want to map .ctors and .dtors to
// .init_array and .fini_array, respectively. However, old CRT
// object files are not compatible with this translation, so we need
// to keep them as-is if a section came from crtbegin.o or crtend.o.
//
// Yeah, this is an ugly hack, but the fundamental problem is that
// we have two different mechanism, ctors/dtors and init_array/fini_array
// for the same purpose. The latter was introduced to replace the
// former, but as it is often the case, the former still lingers
// around, so we need to keep this code to conver the old mechanism
// to the new one.
std::string_view stem = path_filename(file.filename);
if (stem != "crtbegin.o" && stem != "crtend.o" &&
stem != "crtbeginS.o" && stem != "crtendS.o" &&
stem != "crtbeginT.o" && stem != "crtendT.o") {;
if (name == ".ctors" || name.starts_with(".ctors."))
name = ".init_array";
else if (name == ".dtors" || name.starts_with(".dtors."))
name = ".fini_array";
}
output_section =
OutputSection<E>::get_instance(ctx, name, shdr.sh_type, shdr.sh_flags);
}
2021-03-29 14:29:57 +03:00
template <typename E>
2021-05-06 05:29:02 +03:00
void InputSection<E>::write_to(Context<E> &ctx, u8 *buf) {
2021-03-11 13:59:01 +03:00
if (shdr.sh_type == SHT_NOBITS || shdr.sh_size == 0)
2020-10-20 04:00:53 +03:00
return;
2020-10-27 13:35:49 +03:00
2020-11-07 18:33:13 +03:00
// Copy data
2021-05-06 05:29:02 +03:00
memcpy(buf, contents.data(), contents.size());
2020-10-23 03:21:40 +03:00
2020-11-07 18:33:13 +03:00
// Apply relocations
2021-03-11 13:59:01 +03:00
if (shdr.sh_flags & SHF_ALLOC)
2021-05-06 05:29:02 +03:00
apply_reloc_alloc(ctx, buf);
2021-01-16 15:58:28 +03:00
else
2021-05-06 05:29:02 +03:00
apply_reloc_nonalloc(ctx, buf);
2021-05-30 19:10:00 +03:00
// As a special case, .ctors and .dtors section contents are
// reversed. These sections are now obsolete and mapped to
// .init_array and .fini_array, but they have to be reversed to
// maintain the original semantics.
bool init_fini = output_section->name == ".init_array" ||
output_section->name == ".fini_array";
bool ctors_dtors = name().starts_with(".ctors") ||
name().starts_with(".dtors");
if (init_fini && ctors_dtors)
std::reverse((typename E::WordTy *)buf,
(typename E::WordTy *)(buf + shdr.sh_size));
2021-01-16 15:52:49 +03:00
}
2021-03-29 14:29:57 +03:00
template <typename E>
static i64 get_output_type(Context<E> &ctx) {
2021-03-29 07:20:51 +03:00
if (ctx.arg.shared)
2021-03-19 04:58:59 +03:00
return 0;
2021-03-29 07:20:51 +03:00
if (ctx.arg.pie)
2021-03-19 04:58:59 +03:00
return 1;
return 2;
}
2021-03-29 14:29:57 +03:00
template <typename E>
static i64 get_sym_type(Context<E> &ctx, Symbol<E> &sym) {
2021-03-29 10:48:23 +03:00
if (sym.is_absolute(ctx))
2021-02-20 15:06:20 +03:00
return 0;
2021-03-04 10:16:37 +03:00
if (!sym.is_imported)
2021-02-20 15:06:20 +03:00
return 1;
2021-03-05 04:35:08 +03:00
if (sym.get_type() != STT_FUNC)
2021-02-20 15:06:20 +03:00
return 2;
return 3;
}
2021-03-30 05:42:18 +03:00
template <typename E>
2021-09-25 15:28:28 +03:00
void InputSection<E>::dispatch(Context<E> &ctx, Action table[3][4], i64 i,
const ElfRel<E> &rel, Symbol<E> &sym) {
Action action = table[get_output_type(ctx)][get_sym_type(ctx, sym)];
bool is_code = (shdr.sh_flags & SHF_EXECINSTR);
bool is_writable = (shdr.sh_flags & SHF_WRITE);
2021-03-30 05:42:18 +03:00
auto error = [&]() {
Error(ctx) << *this << ": " << rel << " relocation against symbol `"
<< sym << "' can not be used; recompile with -fPIC";
};
2021-03-30 05:42:18 +03:00
switch (action) {
case NONE:
return;
case ERROR:
error();
return;
2021-03-30 05:42:18 +03:00
case COPYREL:
if (!ctx.arg.z_copyreloc) {
error();
return;
}
if (sym.esym().st_visibility == STV_PROTECTED) {
Error(ctx) << *this
<< ": cannot make copy relocation for protected symbol '"
<< sym << "', defined in " << *sym.file;
return;
}
2021-03-30 05:42:18 +03:00
sym.flags |= NEEDS_COPYREL;
return;
case PLT:
sym.flags |= NEEDS_PLT;
return;
case DYNREL:
2021-06-17 07:32:39 +03:00
if (!is_writable) {
if (!is_code || ctx.arg.z_text) {
error();
return;
}
2021-06-17 07:32:39 +03:00
ctx.has_textrel = true;
}
2021-03-30 05:42:18 +03:00
sym.flags |= NEEDS_DYNSYM;
2021-09-28 07:03:18 +03:00
needs_dynrel[i] = true;
2021-03-30 05:42:18 +03:00
file.num_dynrel++;
return;
case BASEREL:
2021-06-17 07:32:39 +03:00
if (!is_writable) {
if (!is_code || ctx.arg.z_text) {
error();
return;
}
2021-06-17 07:32:39 +03:00
ctx.has_textrel = true;
}
2021-09-28 07:03:18 +03:00
needs_baserel[i] = true;
2021-03-30 05:42:18 +03:00
file.num_dynrel++;
return;
default:
2021-09-30 18:35:42 +03:00
unreachable();
2021-03-30 05:42:18 +03:00
}
}
template <typename E>
void InputSection<E>::report_undef(Context<E> &ctx, Symbol<E> &sym) {
switch (ctx.arg.unresolved_symbols) {
case UnresolvedKind::ERROR:
Error(ctx) << "undefined symbol: " << file << ": " << sym;
break;
case UnresolvedKind::WARN:
Warn(ctx) << "undefined symbol: " << file << ": " << sym;
break;
case UnresolvedKind::IGNORE:
break;
}
}
#define INSTANTIATE(E) \
2021-09-11 08:54:55 +03:00
template class CieRecord<E>; \
template class InputSection<E>;
INSTANTIATE(X86_64);
INSTANTIATE(I386);
2021-12-11 15:33:39 +03:00
INSTANTIATE(ARM64);
} // namespace mold::elf