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>
|
|
|
|
|
2021-09-02 12:19:43 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-06-20 11:16:11 +03:00
|
|
|
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" &&
|
2021-07-16 09:32:08 +03:00
|
|
|
stem != "crtbeginS.o" && stem != "crtendS.o" &&
|
|
|
|
stem != "crtbeginT.o" && stem != "crtendT.o") {;
|
2021-06-20 11:16:11 +03:00
|
|
|
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)];
|
2021-08-30 15:01:19 +03:00
|
|
|
bool is_code = (shdr.sh_flags & SHF_EXECINSTR);
|
2021-06-12 09:02:11 +03:00
|
|
|
bool is_writable = (shdr.sh_flags & SHF_WRITE);
|
2021-03-30 05:42:18 +03:00
|
|
|
|
2021-08-30 15:01:19 +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:
|
2021-08-30 15:01:19 +03:00
|
|
|
error();
|
|
|
|
return;
|
2021-03-30 05:42:18 +03:00
|
|
|
case COPYREL:
|
2021-08-30 15:01:19 +03:00
|
|
|
if (!ctx.arg.z_copyreloc) {
|
|
|
|
error();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (sym.esym().st_visibility == STV_PROTECTED) {
|
2021-09-25 16:20:08 +03:00
|
|
|
Error(ctx) << *this
|
|
|
|
<< ": cannot make copy relocation for protected symbol '"
|
|
|
|
<< sym << "', defined in " << *sym.file;
|
2021-08-30 15:01:19 +03:00
|
|
|
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) {
|
2021-08-30 15:01:19 +03:00
|
|
|
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) {
|
2021-08-30 15:01:19 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-13 14:45:02 +03:00
|
|
|
template <typename E>
|
|
|
|
void InputSection<E>::report_undef(Context<E> &ctx, Symbol<E> &sym) {
|
2021-06-18 10:33:09 +03:00
|
|
|
switch (ctx.arg.unresolved_symbols) {
|
|
|
|
case UnresolvedKind::ERROR:
|
2021-06-13 14:45:02 +03:00
|
|
|
Error(ctx) << "undefined symbol: " << file << ": " << sym;
|
2021-06-18 10:33:09 +03:00
|
|
|
break;
|
|
|
|
case UnresolvedKind::WARN:
|
|
|
|
Warn(ctx) << "undefined symbol: " << file << ": " << sym;
|
|
|
|
break;
|
|
|
|
case UnresolvedKind::IGNORE:
|
|
|
|
break;
|
|
|
|
}
|
2021-06-13 14:45:02 +03:00
|
|
|
}
|
|
|
|
|
2021-07-03 15:12:08 +03:00
|
|
|
#define INSTANTIATE(E) \
|
2021-09-11 08:54:55 +03:00
|
|
|
template class CieRecord<E>; \
|
2021-07-03 15:12:08 +03:00
|
|
|
template class InputSection<E>;
|
|
|
|
|
|
|
|
INSTANTIATE(X86_64);
|
|
|
|
INSTANTIATE(I386);
|
2021-12-11 15:33:39 +03:00
|
|
|
INSTANTIATE(ARM64);
|
2021-09-02 12:19:43 +03:00
|
|
|
|
|
|
|
} // namespace mold::elf
|