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

1963 lines
49 KiB
C
Raw Normal View History

2020-10-04 12:00:33 +03:00
#pragma once
2020-11-09 06:30:13 +03:00
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
2020-12-16 05:46:15 +03:00
#include "elf.h"
2021-03-15 09:35:15 +03:00
#include "xxHash/xxhash.h"
2020-12-16 05:46:15 +03:00
2020-10-10 13:15:16 +03:00
#include <atomic>
2020-12-11 10:51:20 +03:00
#include <cassert>
2020-10-04 12:00:33 +03:00
#include <cstdint>
2021-04-08 18:29:01 +03:00
#include <fstream>
2021-01-16 05:57:36 +03:00
#include <functional>
2020-12-10 16:32:47 +03:00
#include <iostream>
2021-04-06 06:08:54 +03:00
#include <map>
2021-04-06 06:15:07 +03:00
#include <memory>
2020-10-21 05:55:03 +03:00
#include <mutex>
2020-12-10 06:54:10 +03:00
#include <span>
2021-01-09 05:19:57 +03:00
#include <sstream>
2020-10-04 12:00:33 +03:00
#include <string>
2020-12-10 07:44:58 +03:00
#include <string_view>
2021-01-16 05:57:36 +03:00
#include <tbb/concurrent_hash_map.h>
2021-04-06 12:02:50 +03:00
#include <tbb/concurrent_vector.h>
2021-01-25 09:23:04 +03:00
#include <tbb/enumerable_thread_specific.h>
2021-01-16 05:57:36 +03:00
#include <tbb/spin_mutex.h>
2021-03-12 05:45:52 +03:00
#include <tbb/task_group.h>
2021-03-13 18:58:13 +03:00
#include <unordered_set>
2021-01-16 05:56:47 +03:00
#include <vector>
2020-10-04 12:00:33 +03:00
2020-11-03 14:45:45 +03:00
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
2021-03-30 13:27:00 +03:00
static constexpr i32 SECTOR_SIZE = 512;
static constexpr i32 PAGE_SIZE = 4096;
static constexpr i32 SHA256_SIZE = 32;
2021-03-01 18:38:02 +03:00
2021-03-29 14:29:57 +03:00
template <typename E> class InputFile;
template <typename E> class InputSection;
template <typename E> class MergedSection;
template <typename E> class ObjectFile;
template <typename E> class OutputChunk;
template <typename E> class OutputSection;
template <typename E> class SharedFile;
template <typename E> class Symbol;
template <typename E> struct Context;
2021-03-29 08:05:55 +03:00
2021-03-29 14:29:57 +03:00
template <typename E> void cleanup();
2020-12-24 14:15:17 +03:00
2021-04-01 05:54:46 +03:00
template <typename E>
std::ostream &operator<<(std::ostream &out, const Symbol<E> &sym);
2020-10-19 15:32:57 +03:00
//
2021-04-01 05:54:46 +03:00
// Mergeable section fragments
2020-10-19 15:32:57 +03:00
//
2021-03-29 14:29:57 +03:00
template <typename E>
2021-01-22 09:10:32 +03:00
struct SectionFragment {
2021-03-29 14:29:57 +03:00
SectionFragment(MergedSection<E> *sec, std::string_view data)
2021-03-11 11:06:43 +03:00
: output_section(*sec), data(data) {}
2020-11-07 04:49:34 +03:00
2021-01-22 09:10:32 +03:00
SectionFragment(const SectionFragment &other)
2021-03-11 11:06:43 +03:00
: output_section(other.output_section), data(other.data),
offset(other.offset), alignment(other.alignment.load()),
is_alive(other.is_alive.load()) {}
2020-11-07 04:49:34 +03:00
2021-03-29 14:29:57 +03:00
inline u64 get_addr(Context<E> &ctx) const;
2020-11-07 14:05:51 +03:00
2021-03-29 14:29:57 +03:00
MergedSection<E> &output_section;
2021-01-22 10:59:37 +03:00
std::string_view data;
2021-01-22 14:35:33 +03:00
u32 offset = -1;
2021-03-11 07:17:08 +03:00
std::atomic_uint16_t alignment = 1;
2021-03-17 15:52:58 +03:00
std::atomic_bool is_alive = false;
2020-11-07 04:49:34 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-01-22 09:10:32 +03:00
struct SectionFragmentRef {
2021-03-29 14:29:57 +03:00
SectionFragment<E> *frag = nullptr;
2020-11-24 13:26:26 +03:00
i32 addend = 0;
2020-11-07 04:49:34 +03:00
};
2021-04-01 06:14:05 +03:00
struct SymbolAux {
i32 got_idx = -1;
i32 gotplt_idx = -1;
i32 gottp_idx = -1;
i32 tlsgd_idx = -1;
i32 tlsdesc_idx = -1;
i32 plt_idx = -1;
2021-04-01 07:20:02 +03:00
i32 pltgot_idx = -1;
2021-04-01 06:14:05 +03:00
i32 dynsym_idx = -1;
};
2021-04-01 05:54:46 +03:00
//
// Interned string
//
2020-10-12 07:30:34 +03:00
2021-04-01 05:54:46 +03:00
inline u64 hash_string(std::string_view str) {
return XXH3_64bits(str.data(), str.size());
}
2020-10-25 08:42:44 +03:00
2021-04-01 05:54:46 +03:00
namespace tbb {
template<> struct tbb_hash_compare<std::string_view> {
static size_t hash(const std::string_view &k) {
return hash_string(k);
2021-02-26 19:08:38 +03:00
}
2021-04-01 05:54:46 +03:00
static bool equal(const std::string_view &k1, const std::string_view &k2) {
return k1 == k2;
}
};
}
2020-10-30 11:59:45 +03:00
2021-04-01 05:54:46 +03:00
template<typename ValueT> class ConcurrentMap {
public:
ValueT *insert(std::string_view key, const ValueT &val) {
typename decltype(map)::const_accessor acc;
map.insert(acc, std::make_pair(key, val));
return const_cast<ValueT *>(&acc->second);
}
2020-11-03 16:24:50 +03:00
2021-04-01 05:54:46 +03:00
tbb::concurrent_hash_map<std::string_view, ValueT> map;
2020-10-12 07:30:34 +03:00
};
//
2020-11-06 02:49:41 +03:00
// input_sections.cc
2020-10-12 07:30:34 +03:00
//
2021-03-31 15:13:38 +03:00
enum {
2021-01-16 15:58:28 +03:00
R_NONE = 1,
2020-12-15 16:24:08 +03:00
R_ABS,
2021-02-20 15:09:31 +03:00
R_DYN,
R_BASEREL,
2020-12-15 16:24:08 +03:00
R_PC,
R_GOT,
2021-03-30 17:17:08 +03:00
R_GOTOFF,
2020-12-15 16:24:08 +03:00
R_GOTPC,
R_GOTPCREL,
R_TLSGD,
R_TLSGD_RELAX_LE,
R_TLSLD,
R_TLSLD_RELAX_LE,
2021-01-14 12:23:29 +03:00
R_DTPOFF,
2021-03-18 20:48:32 +03:00
R_DTPOFF_RELAX,
2020-12-15 16:24:08 +03:00
R_TPOFF,
R_GOTTPOFF,
2021-03-18 18:20:45 +03:00
R_GOTTPOFF_RELAX,
2021-03-18 08:49:57 +03:00
R_GOTPC_TLSDESC,
R_GOTPC_TLSDESC_RELAX_LE,
R_SIZE,
2021-03-18 08:49:57 +03:00
R_TLSDESC_CALL_RELAX,
2021-03-31 15:13:38 +03:00
R_END,
2020-12-15 16:24:08 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-01-25 03:57:02 +03:00
struct EhReloc {
2021-04-01 15:38:10 +03:00
EhReloc(Symbol<E> &sym, u8 type, u32 offset, i64 addend)
: sym(sym), type(type), offset(offset), addend(addend) {
assert(this->offset == offset);
assert(this->addend == addend);
}
2021-03-29 14:29:57 +03:00
Symbol<E> &sym;
2021-04-01 15:38:10 +03:00
u32 type : 8;
u32 offset : 24;
i32 addend;
2021-01-25 03:57:02 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
inline bool operator==(const EhReloc<E> &a, const EhReloc<E> &b) {
2021-01-25 04:42:38 +03:00
return std::tuple(&a.sym, a.type, a.offset, a.addend) ==
std::tuple(&b.sym, b.type, b.offset, b.addend);
2021-01-25 03:57:02 +03:00
}
2021-03-29 14:29:57 +03:00
template <typename E>
2021-01-25 03:57:02 +03:00
struct FdeRecord {
2021-03-29 14:29:57 +03:00
FdeRecord(std::string_view contents, std::vector<EhReloc<E>> &&rels,
2021-01-28 01:13:56 +03:00
u32 cie_idx)
2021-04-01 15:29:11 +03:00
: contents(contents), rels(std::move(rels)), cie_idx(cie_idx) {
assert(this->cie_idx == cie_idx);
}
2021-01-25 06:25:03 +03:00
FdeRecord(const FdeRecord &&other)
: contents(other.contents), rels(std::move(other.rels)),
2021-04-01 15:29:11 +03:00
offset(other.offset), cie_idx(other.cie_idx),
2021-01-28 01:13:56 +03:00
is_alive(other.is_alive.load()) {}
2021-01-25 06:25:03 +03:00
2021-01-25 03:57:02 +03:00
std::string_view contents;
2021-03-29 14:29:57 +03:00
std::vector<EhReloc<E>> rels;
2021-01-25 03:57:02 +03:00
u32 offset = -1;
2021-04-01 15:29:11 +03:00
u16 cie_idx = -1;
2021-01-25 06:25:03 +03:00
std::atomic_bool is_alive = true;
2021-01-25 03:57:02 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-01-25 03:57:02 +03:00
struct CieRecord {
bool should_merge(const CieRecord &other) const;
std::string_view contents;
2021-03-29 14:29:57 +03:00
std::vector<EhReloc<E>> rels;
std::vector<FdeRecord<E>> fdes;
2021-01-25 03:57:02 +03:00
// For .eh_frame
u32 offset = -1;
u32 leader_offset = -1;
u32 fde_size = -1;
// For .eh_frame_hdr
u32 num_fdes = 0;
u32 fde_idx = -1;
2021-01-30 08:30:31 +03:00
// For ICF
u32 icf_idx = -1;
2021-01-25 03:57:02 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-11 11:58:43 +03:00
class InputSection {
2020-11-08 06:26:40 +03:00
public:
2021-03-29 15:03:09 +03:00
InputSection(Context<E> &ctx, ObjectFile<E> &file, const ElfShdr<E> &shdr,
2021-04-05 17:47:31 +03:00
std::string_view name, i64 section_idx)
: file(file), shdr(shdr), name(name), section_idx(section_idx) {
if (name.starts_with(".zdebug"))
uncompress_old_style(ctx);
else if (shdr.sh_flags & SHF_COMPRESSED)
uncompress_new_style(ctx);
else if (shdr.sh_type != SHT_NOBITS)
contents = file.get_string(ctx, shdr);
output_section =
2021-04-07 09:38:31 +03:00
OutputSection<E>::get_instance(ctx, name, shdr.sh_type, shdr.sh_flags);
2021-04-05 17:47:31 +03:00
}
2020-11-08 06:26:40 +03:00
2021-03-29 14:29:57 +03:00
void scan_relocations(Context<E> &ctx);
2020-11-26 12:09:32 +03:00
void report_undefined_symbols();
2021-03-29 14:29:57 +03:00
void copy_buf(Context<E> &ctx);
void apply_reloc_alloc(Context<E> &ctx, u8 *base);
void apply_reloc_nonalloc(Context<E> &ctx, u8 *base);
2021-04-06 08:42:58 +03:00
inline void kill();
2021-03-11 11:58:43 +03:00
2021-01-29 06:45:37 +03:00
inline i64 get_priority() const;
2021-03-11 11:58:43 +03:00
inline u64 get_addr() const;
2021-03-30 13:27:00 +03:00
inline i64 get_addend(const ElfRel<E> &rel) const;
2021-04-01 19:23:05 +03:00
inline std::span<ElfRel<E>> get_rels(Context<E> &ctx) const;
2021-03-11 11:58:43 +03:00
2021-03-29 14:29:57 +03:00
ObjectFile<E> &file;
2021-03-29 15:03:09 +03:00
const ElfShdr<E> &shdr;
2021-03-29 14:29:57 +03:00
OutputSection<E> *output_section = nullptr;
2021-03-11 11:58:43 +03:00
std::string_view name;
std::string_view contents;
2020-11-08 06:26:40 +03:00
2021-04-01 14:33:24 +03:00
std::vector<u8> has_fragments;
2021-03-29 14:29:57 +03:00
std::vector<SectionFragmentRef<E>> rel_fragments;
2021-04-01 14:33:24 +03:00
std::vector<u8> rel_types;
2021-03-29 14:29:57 +03:00
std::span<FdeRecord<E>> fdes;
2021-03-16 17:44:01 +03:00
u32 offset = -1;
2021-01-29 05:32:27 +03:00
u32 section_idx = -1;
2021-04-01 19:23:05 +03:00
u32 relsec_idx = -1;
2021-03-16 17:44:01 +03:00
u32 reldyn_offset = 0;
2021-01-26 07:08:35 +03:00
// For COMDAT de-duplication and garbage collection
2021-03-13 12:24:03 +03:00
std::atomic_bool is_alive = true;
2021-01-26 07:08:35 +03:00
// For garbage collection
2021-01-24 10:12:34 +03:00
std::atomic_bool is_visited = false;
2021-01-26 07:08:35 +03:00
// For ICF
InputSection *leader = nullptr;
2021-01-27 14:45:32 +03:00
u32 icf_idx = -1;
2021-02-27 07:44:30 +03:00
bool icf_eligible = false;
bool icf_leaf = false;
2021-03-30 05:42:18 +03:00
2021-04-01 14:33:24 +03:00
bool is_ehframe = false;
2021-03-30 05:42:18 +03:00
private:
typedef enum { NONE, ERROR, COPYREL, PLT, DYNREL, BASEREL } Action;
2021-04-05 17:47:31 +03:00
void uncompress_old_style(Context<E> &ctx);
void uncompress_new_style(Context<E> &ctx);
void do_uncompress(Context<E> &ctx, std::string_view data, u64 size);
2021-03-31 15:13:38 +03:00
void dispatch(Context<E> &ctx, Action table[3][4], u16 rel_type, i64 i);
2020-11-08 08:13:59 +03:00
};
2020-10-12 08:17:34 +03:00
//
2020-10-20 09:33:40 +03:00
// output_chunks.cc
2020-10-12 08:17:34 +03:00
//
2021-03-29 14:29:57 +03:00
template <typename E>
bool is_relro(Context<E> &ctx, OutputChunk<E> *chunk);
2021-03-12 13:57:34 +03:00
2021-03-29 14:29:57 +03:00
template <typename E>
2020-10-15 12:30:06 +03:00
class OutputChunk {
2020-10-15 11:06:01 +03:00
public:
2020-11-08 10:09:01 +03:00
enum Kind : u8 { HEADER, REGULAR, SYNTHETIC };
2020-11-08 10:05:36 +03:00
2021-03-29 14:29:57 +03:00
virtual void copy_buf(Context<E> &ctx) {}
virtual void update_shdr(Context<E> &ctx) {}
2020-10-25 09:17:43 +03:00
2020-12-10 07:44:58 +03:00
std::string_view name;
2021-01-24 06:01:43 +03:00
i64 shndx = 0;
2020-11-29 13:58:02 +03:00
Kind kind;
bool new_page = false;
bool new_page_end = false;
2021-03-30 08:00:12 +03:00
ElfShdr<E> shdr = {};
2021-01-24 05:25:40 +03:00
protected:
2021-03-30 08:00:12 +03:00
OutputChunk(Kind kind) : kind(kind) {
shdr.sh_addralign = 1;
}
2020-10-12 08:17:34 +03:00
};
2020-11-16 18:17:01 +03:00
// ELF header
2021-03-29 14:29:57 +03:00
template <typename E>
class OutputEhdr : public OutputChunk<E> {
2020-11-16 18:17:01 +03:00
public:
2021-03-29 14:29:57 +03:00
OutputEhdr() : OutputChunk<E>(this->HEADER) {
this->shdr.sh_flags = SHF_ALLOC;
2021-03-29 15:02:12 +03:00
this->shdr.sh_size = sizeof(ElfEhdr<E>);
2020-11-16 18:17:01 +03:00
}
2021-03-29 14:29:57 +03:00
void copy_buf(Context<E> &ctx) override;
2020-11-16 18:17:01 +03:00
};
2020-11-16 18:23:51 +03:00
// Section header
2021-03-29 14:29:57 +03:00
template <typename E>
class OutputShdr : public OutputChunk<E> {
2020-11-16 18:23:51 +03:00
public:
2021-03-29 14:29:57 +03:00
OutputShdr() : OutputChunk<E>(this->HEADER) {
this->shdr.sh_flags = SHF_ALLOC;
2020-11-16 18:23:51 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-16 18:23:51 +03:00
};
2020-11-16 18:33:41 +03:00
// Program header
2021-03-29 14:29:57 +03:00
template <typename E>
class OutputPhdr : public OutputChunk<E> {
2020-10-15 11:06:01 +03:00
public:
2021-03-29 14:29:57 +03:00
OutputPhdr() : OutputChunk<E>(this->HEADER) {
this->shdr.sh_flags = SHF_ALLOC;
2020-11-08 10:05:36 +03:00
}
2020-11-16 18:33:41 +03:00
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-10-15 11:06:01 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class InterpSection : public OutputChunk<E> {
2020-11-16 19:05:01 +03:00
public:
2021-03-29 14:29:57 +03:00
InterpSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".interp";
this->shdr.sh_type = SHT_PROGBITS;
this->shdr.sh_flags = SHF_ALLOC;
2021-03-29 10:48:23 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-16 19:05:01 +03:00
};
2020-10-16 10:38:03 +03:00
// Sections
2021-03-29 14:29:57 +03:00
template <typename E>
class OutputSection : public OutputChunk<E> {
2020-10-15 12:30:06 +03:00
public:
2021-03-12 07:17:45 +03:00
static OutputSection *
2021-04-07 09:38:31 +03:00
get_instance(Context<E> &ctx, std::string_view name, u64 type, u64 flags);
2020-10-22 10:35:17 +03:00
2021-03-29 14:29:57 +03:00
void copy_buf(Context<E> &ctx) override;
2020-10-26 07:34:15 +03:00
2021-03-29 14:29:57 +03:00
std::vector<InputSection<E> *> members;
2020-10-29 12:31:06 +03:00
u32 idx;
2021-03-14 10:31:47 +03:00
private:
2021-04-07 09:38:31 +03:00
OutputSection(std::string_view name, u32 type, u64 flags, u32 idx);
2020-10-15 12:30:06 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class GotSection : public OutputChunk<E> {
2020-11-18 11:11:58 +03:00
public:
2021-03-29 14:29:57 +03:00
GotSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".got";
this->shdr.sh_type = SHT_PROGBITS;
this->shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
2021-03-31 04:12:16 +03:00
this->shdr.sh_addralign = E::got_size;
2020-11-18 11:11:58 +03:00
}
2020-11-18 14:29:24 +03:00
2021-03-29 14:29:57 +03:00
void add_got_symbol(Context<E> &ctx, Symbol<E> *sym);
2021-03-31 14:18:12 +03:00
void add_gottp_symbol(Context<E> &ctx, Symbol<E> *sym);
2021-03-29 14:29:57 +03:00
void add_tlsgd_symbol(Context<E> &ctx, Symbol<E> *sym);
void add_tlsdesc_symbol(Context<E> &ctx, Symbol<E> *sym);
void add_tlsld(Context<E> &ctx);
2021-01-14 13:58:21 +03:00
2021-03-29 14:29:57 +03:00
u64 get_tlsld_addr(Context<E> &ctx) const {
2021-01-14 13:58:21 +03:00
assert(tlsld_idx != -1);
2021-03-31 04:12:16 +03:00
return this->shdr.sh_addr + tlsld_idx * E::got_size;
2021-01-14 13:58:21 +03:00
}
2021-03-29 14:29:57 +03:00
i64 get_reldyn_size(Context<E> &ctx) const;
void copy_buf(Context<E> &ctx) override;
2020-11-18 14:29:24 +03:00
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> got_syms;
2021-03-31 14:18:12 +03:00
std::vector<Symbol<E> *> gottp_syms;
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> tlsgd_syms;
std::vector<Symbol<E> *> tlsdesc_syms;
2021-01-14 13:58:21 +03:00
u32 tlsld_idx = -1;
2020-11-18 11:11:58 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class GotPltSection : public OutputChunk<E> {
2020-11-13 06:43:59 +03:00
public:
2021-03-29 14:29:57 +03:00
GotPltSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".got.plt";
this->shdr.sh_type = SHT_PROGBITS;
this->shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
2021-03-31 04:12:16 +03:00
this->shdr.sh_addralign = E::got_size;
2020-11-13 06:43:59 +03:00
}
2021-03-29 14:29:57 +03:00
void copy_buf(Context<E> &ctx) override;
2020-11-13 06:43:59 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class PltSection : public OutputChunk<E> {
2020-11-01 11:46:08 +03:00
public:
2021-03-29 14:29:57 +03:00
PltSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".plt";
this->shdr.sh_type = SHT_PROGBITS;
this->shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
this->shdr.sh_addralign = 16;
2020-11-01 11:46:08 +03:00
}
2021-03-29 14:29:57 +03:00
void add_symbol(Context<E> &ctx, Symbol<E> *sym);
void copy_buf(Context<E> &ctx) override;
2020-11-17 15:02:14 +03:00
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> symbols;
2020-11-01 11:46:08 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class PltGotSection : public OutputChunk<E> {
2021-02-26 14:56:01 +03:00
public:
2021-03-29 14:29:57 +03:00
PltGotSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".plt.got";
this->shdr.sh_type = SHT_PROGBITS;
this->shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
this->shdr.sh_addralign = 8;
2021-02-26 14:56:01 +03:00
}
2021-03-29 14:29:57 +03:00
void add_symbol(Context<E> &ctx, Symbol<E> *sym);
void copy_buf(Context<E> &ctx) override;
2021-02-26 14:56:01 +03:00
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> symbols;
2021-02-26 14:56:01 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class RelPltSection : public OutputChunk<E> {
2020-11-01 02:55:13 +03:00
public:
2021-03-29 14:29:57 +03:00
RelPltSection() : OutputChunk<E>(this->SYNTHETIC) {
2021-03-30 17:56:48 +03:00
this->name = (E::rel_type == SHT_REL) ? ".rel.plt" : ".rela.plt";
this->shdr.sh_type = E::rel_type;
2021-03-29 14:29:57 +03:00
this->shdr.sh_flags = SHF_ALLOC;
2021-03-30 09:42:11 +03:00
this->shdr.sh_entsize = sizeof(ElfRel<E>);
2021-03-31 07:55:42 +03:00
this->shdr.sh_addralign = E::wordsize;
2020-11-01 02:55:13 +03:00
}
2020-11-17 07:34:02 +03:00
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-01 02:55:13 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class RelDynSection : public OutputChunk<E> {
2020-11-17 07:30:33 +03:00
public:
2021-03-29 14:29:57 +03:00
RelDynSection() : OutputChunk<E>(this->SYNTHETIC) {
2021-03-30 17:56:48 +03:00
this->name = (E::rel_type == SHT_REL) ? ".rel.dyn" : ".rela.dyn";
this->shdr.sh_type = E::rel_type;
2021-03-29 14:29:57 +03:00
this->shdr.sh_flags = SHF_ALLOC;
2021-03-30 09:42:11 +03:00
this->shdr.sh_entsize = sizeof(ElfRel<E>);
2021-03-31 07:55:42 +03:00
this->shdr.sh_addralign = E::wordsize;
2020-11-17 07:30:33 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void sort(Context<E> &ctx);
2020-11-17 07:30:33 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class StrtabSection : public OutputChunk<E> {
2020-11-12 16:10:47 +03:00
public:
2021-03-29 14:29:57 +03:00
StrtabSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".strtab";
this->shdr.sh_type = SHT_STRTAB;
this->shdr.sh_size = 1;
2020-11-12 16:10:47 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
2020-11-12 16:10:47 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class ShstrtabSection : public OutputChunk<E> {
2020-11-17 06:20:56 +03:00
public:
2021-03-29 14:29:57 +03:00
ShstrtabSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".shstrtab";
this->shdr.sh_type = SHT_STRTAB;
2020-11-17 06:20:56 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-17 06:20:56 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class DynstrSection : public OutputChunk<E> {
2020-11-17 07:19:54 +03:00
public:
2021-03-29 14:29:57 +03:00
DynstrSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".dynstr";
this->shdr.sh_type = SHT_STRTAB;
this->shdr.sh_flags = SHF_ALLOC;
2021-03-31 15:13:38 +03:00
this->shdr.sh_size = 1;
2020-11-17 07:19:54 +03:00
}
2021-01-24 06:01:43 +03:00
i64 add_string(std::string_view str);
i64 find_string(std::string_view str);
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-17 07:19:54 +03:00
2021-03-15 08:04:26 +03:00
i64 dynsym_offset = -1;
2020-11-17 07:19:54 +03:00
private:
2021-01-26 14:34:41 +03:00
std::unordered_map<std::string_view, i64> strings;
2020-11-17 07:19:54 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class DynamicSection : public OutputChunk<E> {
2020-11-16 18:43:32 +03:00
public:
2021-03-29 14:29:57 +03:00
DynamicSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".dynamic";
this->shdr.sh_type = SHT_DYNAMIC;
this->shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
2021-03-31 08:16:09 +03:00
this->shdr.sh_addralign = E::wordsize;
2021-03-29 15:07:44 +03:00
this->shdr.sh_entsize = sizeof(ElfDyn<E>);
2020-11-16 18:43:32 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-16 18:43:32 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class SymtabSection : public OutputChunk<E> {
2020-10-27 12:59:56 +03:00
public:
2021-03-29 14:29:57 +03:00
SymtabSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".symtab";
this->shdr.sh_type = SHT_SYMTAB;
this->shdr.sh_entsize = sizeof(ElfSym<E>);
2021-03-31 08:16:09 +03:00
this->shdr.sh_addralign = E::wordsize;
2020-10-27 12:59:56 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-10-27 12:59:56 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class DynsymSection : public OutputChunk<E> {
2020-11-16 17:40:01 +03:00
public:
2021-03-29 14:29:57 +03:00
DynsymSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".dynsym";
this->shdr.sh_type = SHT_DYNSYM;
this->shdr.sh_flags = SHF_ALLOC;
this->shdr.sh_entsize = sizeof(ElfSym<E>);
2021-03-31 07:55:42 +03:00
this->shdr.sh_addralign = E::wordsize;
2020-11-16 17:40:01 +03:00
}
2021-03-29 14:29:57 +03:00
void add_symbol(Context<E> &ctx, Symbol<E> *sym);
void sort_symbols(Context<E> &ctx);
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-16 17:40:01 +03:00
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> symbols;
2020-11-16 17:40:01 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class HashSection : public OutputChunk<E> {
2020-11-11 15:12:35 +03:00
public:
2021-03-29 14:29:57 +03:00
HashSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".hash";
this->shdr.sh_type = SHT_HASH;
this->shdr.sh_flags = SHF_ALLOC;
this->shdr.sh_entsize = 4;
this->shdr.sh_addralign = 4;
2020-11-11 15:12:35 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2021-01-23 09:01:49 +03:00
};
2020-11-12 11:15:59 +03:00
2021-03-29 14:29:57 +03:00
template <typename E>
class GnuHashSection : public OutputChunk<E> {
2021-01-23 09:01:49 +03:00
public:
2021-03-29 14:29:57 +03:00
GnuHashSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".gnu.hash";
this->shdr.sh_type = SHT_GNU_HASH;
this->shdr.sh_flags = SHF_ALLOC;
2021-03-31 07:55:42 +03:00
this->shdr.sh_addralign = E::wordsize;
2021-01-23 09:01:49 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2021-01-23 09:01:49 +03:00
2021-01-24 06:01:43 +03:00
static constexpr i64 LOAD_FACTOR = 8;
static constexpr i64 HEADER_SIZE = 16;
static constexpr i64 BLOOM_SHIFT = 26;
2021-03-31 07:55:42 +03:00
static constexpr i64 ELFCLASS_BITS = E::wordsize * 8;
2021-01-23 09:01:49 +03:00
2021-01-23 18:03:35 +03:00
u32 num_buckets = -1;
2021-01-23 09:01:49 +03:00
u32 symoffset = -1;
2021-01-23 18:03:35 +03:00
u32 num_bloom = 1;
2020-11-11 15:12:35 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class MergedSection : public OutputChunk<E> {
public:
2021-03-29 14:29:57 +03:00
static MergedSection<E> *
2021-04-07 09:38:31 +03:00
get_instance(Context<E> &ctx, std::string_view name, u64 type, u64 flags);
2020-11-07 04:13:19 +03:00
2021-03-29 14:29:57 +03:00
SectionFragment<E> *insert(std::string_view data, i64 alignment);
2021-03-11 11:06:43 +03:00
void assign_offsets();
2021-03-29 14:29:57 +03:00
void copy_buf(Context<E> &ctx) override;
2020-12-13 19:40:23 +03:00
2020-11-07 04:13:19 +03:00
private:
2021-03-29 18:50:02 +03:00
using MapTy =
tbb::concurrent_hash_map<std::string_view, SectionFragment<E>>;
2021-03-13 17:53:16 +03:00
static constexpr i64 NUM_SHARDS = 64;
2021-03-11 11:06:43 +03:00
2020-12-10 07:44:58 +03:00
MergedSection(std::string_view name, u64 flags, u32 type)
2021-03-29 14:29:57 +03:00
: OutputChunk<E>(this->SYNTHETIC) {
2020-11-08 10:05:36 +03:00
this->name = name;
2021-03-29 14:29:57 +03:00
this->shdr.sh_flags = flags;
this->shdr.sh_type = type;
2020-11-08 10:05:36 +03:00
}
2021-01-22 10:14:49 +03:00
2021-03-11 11:06:43 +03:00
MapTy maps[NUM_SHARDS];
2021-03-13 17:53:16 +03:00
i64 shard_offsets[NUM_SHARDS + 1] = {};
2021-03-13 17:34:51 +03:00
std::atomic_uint16_t max_alignment;
};
2021-03-29 14:29:57 +03:00
template <typename E>
class EhFrameSection : public OutputChunk<E> {
2021-01-17 10:55:39 +03:00
public:
2021-03-29 14:29:57 +03:00
EhFrameSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".eh_frame";
2021-03-31 07:02:19 +03:00
this->shdr.sh_type = SHT_PROGBITS;
2021-03-29 14:29:57 +03:00
this->shdr.sh_flags = SHF_ALLOC;
2021-03-31 07:55:42 +03:00
this->shdr.sh_addralign = E::wordsize;
2021-01-17 10:55:39 +03:00
}
2021-03-29 14:29:57 +03:00
void construct(Context<E> &ctx);
u64 get_addr(Context<E> &ctx, const Symbol<E> &sym);
2021-04-03 15:15:57 +03:00
void apply_reloc(Context<E> &ctx, EhReloc<E> &rel, u64 loc, u64 val);
void copy_buf(Context<E> &ctx) override;
2021-01-20 14:47:15 +03:00
2021-03-29 14:29:57 +03:00
std::vector<CieRecord<E> *> cies;
2021-01-21 15:18:25 +03:00
u32 num_fdes = 0;
2021-01-17 10:55:39 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class EhFrameHdrSection : public OutputChunk<E> {
2021-01-21 01:47:48 +03:00
public:
2021-03-29 14:29:57 +03:00
EhFrameHdrSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".eh_frame_hdr";
this->shdr.sh_type = SHT_PROGBITS;
this->shdr.sh_flags = SHF_ALLOC;
this->shdr.sh_addralign = 4;
this->shdr.sh_size = HEADER_SIZE;
2021-01-21 01:47:48 +03:00
}
2021-01-24 06:01:43 +03:00
static constexpr i64 HEADER_SIZE = 12;
2021-01-21 01:47:48 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class DynbssSection : public OutputChunk<E> {
2020-11-25 11:20:48 +03:00
public:
2021-03-29 14:29:57 +03:00
DynbssSection(bool is_relro) : OutputChunk<E>(this->SYNTHETIC) {
this->name = is_relro ? ".dynbss.rel.ro" : ".dynbss";
this->shdr.sh_type = SHT_NOBITS;
this->shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
this->shdr.sh_addralign = 64;
2020-11-25 11:20:48 +03:00
}
2021-03-29 14:29:57 +03:00
void add_symbol(Context<E> &ctx, Symbol<E> *sym);
2020-11-25 11:20:48 +03:00
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> symbols;
2020-11-25 11:20:48 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class VersymSection : public OutputChunk<E> {
2020-11-27 11:32:25 +03:00
public:
2021-03-29 14:29:57 +03:00
VersymSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".gnu.version";
this->shdr.sh_type = SHT_GNU_VERSYM;
this->shdr.sh_flags = SHF_ALLOC;
this->shdr.sh_entsize = 2;
this->shdr.sh_addralign = 2;
2020-11-27 11:32:25 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-29 05:40:57 +03:00
std::vector<u16> contents;
2020-11-27 11:32:25 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class VerneedSection : public OutputChunk<E> {
2020-11-27 11:32:25 +03:00
public:
2021-03-29 14:29:57 +03:00
VerneedSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".gnu.version_r";
this->shdr.sh_type = SHT_GNU_VERNEED;
this->shdr.sh_flags = SHF_ALLOC;
2021-03-31 08:16:09 +03:00
this->shdr.sh_addralign = E::wordsize;
2020-11-27 11:32:25 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2020-11-29 05:40:57 +03:00
std::vector<u8> contents;
2020-11-27 11:32:25 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class VerdefSection : public OutputChunk<E> {
2021-03-07 07:43:58 +03:00
public:
2021-03-29 14:29:57 +03:00
VerdefSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".gnu.version_d";
this->shdr.sh_type = SHT_GNU_VERDEF;
this->shdr.sh_flags = SHF_ALLOC;
this->shdr.sh_addralign = 8;
2021-03-07 07:43:58 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
2021-03-07 07:43:58 +03:00
std::vector<u8> contents;
};
2021-03-29 14:29:57 +03:00
template <typename E>
class BuildIdSection : public OutputChunk<E> {
2021-01-15 14:14:01 +03:00
public:
2021-03-29 14:29:57 +03:00
BuildIdSection() : OutputChunk<E>(this->SYNTHETIC) {
this->name = ".note.gnu.build-id";
this->shdr.sh_type = SHT_NOTE;
this->shdr.sh_flags = SHF_ALLOC;
this->shdr.sh_addralign = 4;
this->shdr.sh_size = 1;
2021-01-15 14:14:01 +03:00
}
2021-03-29 14:29:57 +03:00
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
void write_buildid(Context<E> &ctx, i64 filesize);
2021-01-26 13:46:34 +03:00
static constexpr i64 HEADER_SIZE = 16;
2021-01-15 14:14:01 +03:00
};
2020-12-10 07:44:58 +03:00
bool is_c_identifier(std::string_view name);
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 15:05:52 +03:00
std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx);
2020-11-04 04:43:05 +03:00
2020-10-12 07:30:34 +03:00
//
2020-11-03 04:54:10 +03:00
// object_file.cc
2020-10-12 07:30:34 +03:00
//
struct ComdatGroup {
2021-01-24 04:28:42 +03:00
ComdatGroup() = default;
ComdatGroup(const ComdatGroup &other)
2021-03-07 16:38:09 +03:00
: owner(other.owner.load()) {}
2021-03-16 17:53:14 +03:00
std::atomic_uint32_t owner = -1;
};
2021-03-29 14:29:57 +03:00
template <typename E>
2020-12-22 10:33:44 +03:00
class MemoryMappedFile {
public:
2021-04-06 11:43:31 +03:00
static MemoryMappedFile *open(Context<E> &ctx, std::string path);
2021-03-29 14:29:57 +03:00
static MemoryMappedFile *must_open(Context<E> &ctx, std::string path);
2020-12-22 12:33:16 +03:00
2021-04-06 11:43:31 +03:00
~MemoryMappedFile();
2020-12-22 10:33:44 +03:00
2021-04-07 09:38:31 +03:00
MemoryMappedFile *slice(Context<E> &ctx, std::string name, u64 start, u64 size);
2020-12-22 10:33:44 +03:00
2021-03-29 14:29:57 +03:00
u8 *data(Context<E> &ctx);
2021-01-24 06:01:43 +03:00
i64 size() const { return size_; }
2021-03-29 14:29:57 +03:00
std::string_view get_contents(Context<E> &ctx) {
2021-03-29 10:48:23 +03:00
return std::string_view((char *)data(ctx), size());
2021-01-24 06:01:43 +03:00
}
2020-12-12 07:04:38 +03:00
std::string name;
2021-01-24 06:01:43 +03:00
i64 mtime = 0;
2020-12-22 10:33:44 +03:00
private:
2021-04-06 11:43:31 +03:00
MemoryMappedFile(std::string name, u8 *data, u64 size, u64 mtime = 0)
: name(name), data_(data), size_(size), mtime(mtime) {}
2020-12-22 11:37:49 +03:00
std::mutex mu;
2020-12-22 10:33:44 +03:00
MemoryMappedFile *parent;
2020-12-22 11:37:49 +03:00
std::atomic<u8 *> data_;
2021-01-24 06:01:43 +03:00
i64 size_ = 0;
2020-12-12 07:04:38 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
2020-11-24 10:22:32 +03:00
class InputFile {
public:
2021-03-29 14:29:57 +03:00
InputFile(Context<E> &ctx, MemoryMappedFile<E> *mb);
2021-01-12 15:17:53 +03:00
InputFile() : name("<internal>") {}
2020-11-24 10:22:32 +03:00
2021-04-05 17:47:31 +03:00
inline std::string_view get_string(Context<E> &ctx, const ElfShdr<E> &shdr);
inline std::string_view get_string(Context<E> &ctx, i64 idx);
2021-03-12 05:45:52 +03:00
2021-04-06 11:43:31 +03:00
template<typename T> std::span<T>
get_data(Context<E> &ctx, const ElfShdr<E> &shdr);
template<typename T> std::span<T>
get_data(Context<E> &ctx, i64 idx);
ElfShdr<E> *find_section(i64 type);
2021-03-29 14:29:57 +03:00
MemoryMappedFile<E> *mb;
2021-03-29 15:03:09 +03:00
std::span<ElfShdr<E>> elf_sections;
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> symbols;
2020-12-12 06:41:09 +03:00
std::string name;
2021-01-12 15:17:53 +03:00
bool is_dso = false;
2020-12-12 06:41:09 +03:00
u32 priority;
2021-01-09 09:06:18 +03:00
std::atomic_bool is_alive = false;
2021-01-12 15:17:53 +03:00
std::string_view shstrtab;
2021-04-06 11:43:31 +03:00
protected:
std::vector<Symbol<E>> local_syms;
2020-11-24 10:22:32 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class ObjectFile : public InputFile<E> {
2020-10-04 12:00:33 +03:00
public:
2021-04-06 11:03:11 +03:00
static ObjectFile<E> *create(Context<E> &ctx, MemoryMappedFile<E> *mb,
std::string archive_name, bool is_in_lib);
2021-03-29 09:16:53 +03:00
2021-04-06 11:08:28 +03:00
static ObjectFile<E> *create_internal_file(Context<E> &ctx);
2021-03-29 09:16:53 +03:00
2021-03-29 14:29:57 +03:00
void parse(Context<E> &ctx);
void resolve_lazy_symbols(Context<E> &ctx);
void resolve_regular_symbols(Context<E> &ctx);
void mark_live_objects(Context<E> &ctx,
std::function<void(ObjectFile<E> *)> feeder);
void convert_undefined_weak_symbols(Context<E> &ctx);
2020-11-08 12:17:24 +03:00
void resolve_comdat_groups();
2020-10-19 15:50:33 +03:00
void eliminate_duplicate_comdat_groups();
2021-02-25 14:26:10 +03:00
void claim_unresolved_symbols();
2021-03-29 14:29:57 +03:00
void scan_relocations(Context<E> &ctx);
void convert_common_symbols(Context<E> &ctx);
void compute_symtab(Context<E> &ctx);
void write_symtab(Context<E> &ctx);
2020-10-27 13:03:57 +03:00
2021-03-29 14:29:57 +03:00
inline i64 get_shndx(const ElfSym<E> &esym);
inline InputSection<E> *get_section(const ElfSym<E> &esym);
inline std::span<Symbol<E> *> get_global_syms();
2020-11-03 13:33:46 +03:00
2020-12-13 12:26:23 +03:00
std::string archive_name;
2021-04-06 08:36:31 +03:00
std::vector<std::unique_ptr<InputSection<E>>> sections;
2021-03-29 14:29:57 +03:00
std::span<ElfSym<E>> elf_syms;
2021-01-24 06:01:43 +03:00
i64 first_global = 0;
2021-02-09 16:07:44 +03:00
const bool is_in_lib = false;
2021-03-29 14:29:57 +03:00
std::vector<CieRecord<E>> cies;
2021-03-09 17:43:36 +03:00
std::vector<const char *> symvers;
2021-03-29 14:29:57 +03:00
std::vector<SectionFragment<E> *> fragments;
2021-04-01 17:57:18 +03:00
std::vector<SectionFragmentRef<E>> sym_fragments;
2021-04-06 08:42:58 +03:00
std::vector<std::pair<ComdatGroup *, std::span<u32>>> comdat_groups;
2021-03-08 09:25:23 +03:00
bool exclude_libs = false;
2020-10-09 17:26:26 +03:00
2020-12-18 04:56:56 +03:00
u64 num_dynrel = 0;
2020-12-16 14:56:04 +03:00
u64 reldyn_offset = 0;
2020-11-29 12:45:33 +03:00
u64 local_symtab_offset = 0;
u64 global_symtab_offset = 0;
2021-01-25 11:13:40 +03:00
u64 num_local_symtab = 0;
u64 num_global_symtab = 0;
2020-11-29 12:45:33 +03:00
u64 strtab_offset = 0;
u64 strtab_size = 0;
2020-10-27 14:58:28 +03:00
2020-10-09 14:47:45 +03:00
private:
2021-04-06 11:08:28 +03:00
ObjectFile();
2021-04-06 11:03:11 +03:00
ObjectFile(Context<E> &ctx, MemoryMappedFile<E> *mb,
std::string archive_name, bool is_in_lib);
2021-03-29 14:29:57 +03:00
void initialize_sections(Context<E> &ctx);
void initialize_symbols(Context<E> &ctx);
void initialize_mergeable_sections(Context<E> &ctx);
void initialize_ehframe_sections(Context<E> &ctx);
void read_ehframe(Context<E> &ctx, InputSection<E> &isec);
void maybe_override_symbol(Context<E> &ctx, Symbol<E> &sym, i64 symidx);
void merge_visibility(Context<E> &ctx, Symbol<E> &sym, u8 visibility);
2020-10-19 14:05:34 +03:00
2020-10-27 02:45:20 +03:00
bool has_common_symbol;
2020-10-26 08:52:55 +03:00
2020-12-10 07:44:58 +03:00
std::string_view symbol_strtab;
2021-03-29 15:03:09 +03:00
const ElfShdr<E> *symtab_sec;
std::span<u32> symtab_shndx_sec;
2020-10-04 12:00:33 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
class SharedFile : public InputFile<E> {
2020-11-24 10:22:32 +03:00
public:
2021-04-06 12:13:53 +03:00
static SharedFile<E> *create(Context<E> &ctx, MemoryMappedFile<E> *mb);
2021-03-29 14:29:57 +03:00
void parse(Context<E> &ctx);
void resolve_symbols(Context<E> &ctx);
std::vector<Symbol<E> *> find_aliases(Symbol<E> *sym);
2021-03-29 14:29:57 +03:00
bool is_readonly(Context<E> &ctx, Symbol<E> *sym);
2020-11-24 10:22:32 +03:00
2020-12-10 07:44:58 +03:00
std::string_view soname;
std::vector<std::string_view> version_strings;
2021-03-29 14:29:57 +03:00
std::vector<Symbol<E> *> undefs;
2021-04-01 16:53:22 +03:00
std::vector<const ElfSym<E> *> elf_syms;
2020-11-24 10:22:32 +03:00
private:
2021-04-06 12:13:53 +03:00
SharedFile(Context<E> &ctx, MemoryMappedFile<E> *mb);
2021-03-29 14:29:57 +03:00
std::string_view get_soname(Context<E> &ctx);
void maybe_override_symbol(Symbol<E> &sym, const ElfSym<E> &esym);
std::vector<std::string_view> read_verdef(Context<E> &ctx);
2020-11-24 10:22:32 +03:00
2020-11-28 16:08:46 +03:00
std::vector<u16> versyms;
2020-12-10 07:44:58 +03:00
std::string_view symbol_strtab;
2021-03-29 15:03:09 +03:00
const ElfShdr<E> *symtab_sec;
2020-11-24 10:22:32 +03:00
};
2020-12-13 15:06:25 +03:00
//
// archive_file.cc
//
2021-03-29 14:29:57 +03:00
template <typename E>
std::vector<MemoryMappedFile<E> *>
read_fat_archive_members(Context<E> &ctx, MemoryMappedFile<E> *mb);
2021-03-29 10:48:23 +03:00
2021-03-29 14:29:57 +03:00
template <typename E>
std::vector<MemoryMappedFile<E> *>
read_thin_archive_members(Context<E> &ctx, MemoryMappedFile<E> *mb);
2020-12-12 06:48:00 +03:00
2020-11-29 04:31:04 +03:00
//
// linker_script.cc
//
2021-03-29 14:29:57 +03:00
template <typename E>
void parse_linker_script(Context<E> &ctx, MemoryMappedFile<E> *mb);
template <typename E>
void parse_version_script(Context<E> &ctx, std::string path);
template <typename E>
void parse_dynamic_list(Context<E> &ctx, std::string path);
2020-11-29 04:31:04 +03:00
2021-01-09 11:07:19 +03:00
//
// output_file.cc
//
2021-03-29 14:29:57 +03:00
template <typename E>
2021-01-09 11:07:19 +03:00
class OutputFile {
public:
2021-04-06 07:37:01 +03:00
static std::unique_ptr<OutputFile>
open(Context<E> &ctx, std::string path, u64 filesize);
2021-03-29 14:29:57 +03:00
virtual void close(Context<E> &ctx) = 0;
2021-04-06 07:37:01 +03:00
virtual ~OutputFile() {}
2021-01-09 11:07:19 +03:00
u8 *buf;
2021-01-09 11:07:19 +03:00
static inline char *tmpfile;
protected:
2021-03-29 10:48:23 +03:00
OutputFile(std::string path, u64 filesize)
: path(path), filesize(filesize) {}
2021-01-09 11:07:19 +03:00
std::string path;
u64 filesize;
2021-01-09 11:07:19 +03:00
};
2021-03-08 09:25:23 +03:00
//
// filepath.cc
//
2021-04-09 10:05:52 +03:00
std::string get_current_dir();
2021-03-08 09:25:23 +03:00
std::string path_dirname(std::string_view path);
2021-04-09 10:05:52 +03:00
std::string path_filename(std::string_view path);
2021-03-08 09:25:23 +03:00
std::string path_basename(std::string_view path);
2021-04-09 10:05:52 +03:00
std::string path_to_absolute(std::string_view path);
2021-03-16 18:26:28 +03:00
std::string path_clean(std::string_view path);
2021-03-08 09:25:23 +03:00
2021-03-17 10:48:36 +03:00
//
// glob.cc
//
class GlobPattern {
public:
GlobPattern(std::string_view pat);
2021-03-29 13:14:11 +03:00
bool match(std::string_view str) const;
2021-03-17 10:48:36 +03:00
private:
enum { EXACT, PREFIX, SUFFIX, GENERIC } kind;
2021-03-17 13:25:55 +03:00
std::string_view pat;
2021-03-17 10:48:36 +03:00
};
2020-11-29 04:31:04 +03:00
//
// perf.cc
//
class Counter {
public:
2021-01-25 09:23:04 +03:00
Counter(std::string_view name, i64 value = 0) : name(name), values(value) {
2020-11-29 04:31:04 +03:00
static std::mutex mu;
std::lock_guard lock(mu);
instances.push_back(this);
}
2021-01-29 15:44:46 +03:00
Counter &operator++(int) {
2021-03-07 14:41:51 +03:00
if (enabled)
values.local()++;
2021-01-29 15:44:46 +03:00
return *this;
}
Counter &operator+=(int delta) {
2021-03-07 14:41:51 +03:00
if (enabled)
values.local() += delta;
2021-01-29 15:44:46 +03:00
return *this;
2020-11-29 04:31:04 +03:00
}
static void print();
2021-03-07 14:41:51 +03:00
static inline bool enabled = false;
2020-11-29 04:31:04 +03:00
private:
2021-01-25 09:23:04 +03:00
i64 get_value();
2020-12-10 07:44:58 +03:00
std::string_view name;
2021-01-25 09:23:04 +03:00
tbb::enumerable_thread_specific<i64> values;
2020-11-29 04:31:04 +03:00
2021-01-09 13:02:03 +03:00
static inline std::vector<Counter *> instances;
2020-11-29 04:31:04 +03:00
};
2021-01-09 12:15:09 +03:00
struct TimerRecord {
2021-04-07 09:38:31 +03:00
TimerRecord(std::string name, TimerRecord *parent = nullptr);
2020-12-11 10:51:20 +03:00
void stop();
std::string name;
2021-04-07 09:38:31 +03:00
TimerRecord *parent;
tbb::concurrent_vector<TimerRecord *> children;
2021-01-24 07:26:03 +03:00
i64 start;
i64 end;
i64 user;
i64 sys;
2020-12-11 10:51:20 +03:00
bool stopped = false;
};
2021-04-07 09:38:31 +03:00
template <typename E>
2021-01-09 12:15:09 +03:00
class Timer {
public:
2021-04-07 09:38:31 +03:00
Timer(Context<E> &ctx, std::string name, Timer *parent = nullptr);
2021-01-09 12:15:09 +03:00
~Timer();
void stop();
2021-04-07 09:38:31 +03:00
static void print(Context<E> &ctx);
2021-01-09 12:15:09 +03:00
private:
TimerRecord *record;
};
2021-01-24 10:12:34 +03:00
//
// gc_sections.cc
//
2021-03-29 14:29:57 +03:00
template <typename E>
void gc_sections(Context<E> &ctx);
2021-01-24 10:12:34 +03:00
2021-01-26 07:08:35 +03:00
//
// icf.cc
//
2021-03-29 14:29:57 +03:00
template <typename E>
void icf_sections(Context<E> &ctx);
2021-01-26 07:08:35 +03:00
2020-11-29 04:31:04 +03:00
//
// mapfile.cc
//
2021-03-29 14:29:57 +03:00
template <typename E>
void print_map(Context<E> &ctx);
2020-11-29 04:31:04 +03:00
2021-01-09 15:21:45 +03:00
//
// subprocess.cc
//
2021-01-09 17:13:38 +03:00
inline char *socket_tmpfile;
2021-01-09 15:21:45 +03:00
std::function<void()> fork_child();
2021-03-29 14:29:57 +03:00
template <typename E>
bool resume_daemon(Context<E> &ctx, char **argv, i64 *code);
template <typename E>
void daemonize(Context<E> &ctx, char **argv,
2021-03-29 10:48:23 +03:00
std::function<void()> *wait_for_client,
2021-01-09 15:21:45 +03:00
std::function<void()> *on_complete);
2021-03-29 14:29:57 +03:00
template <typename E>
[[noreturn]]
void process_run_subcommand(Context<E> &ctx, int argc, char **argv);
2021-03-25 10:03:23 +03:00
2021-02-28 05:32:04 +03:00
// commandline.cc
//
2021-03-29 14:29:57 +03:00
template <typename E>
std::vector<std::string_view>
expand_response_files(Context<E> &ctx, char **argv);
2021-02-28 05:32:04 +03:00
bool read_flag(std::span<std::string_view> &args, std::string name);
2021-03-29 14:29:57 +03:00
template <typename E>
bool read_arg(Context<E> &ctx, std::span<std::string_view> &args,
2021-03-29 10:48:23 +03:00
std::string_view &arg,
2021-02-28 05:32:04 +03:00
std::string name);
2021-04-09 04:08:56 +03:00
template <typename E>
std::string create_response_file(Context<E> &ctx);
2021-03-29 14:29:57 +03:00
template <typename E>
void parse_nonpositional_args(Context<E> &ctx,
2021-03-05 13:38:37 +03:00
std::vector<std::string_view> &remaining);
2021-02-28 05:32:04 +03:00
2021-04-08 18:29:01 +03:00
//
// tar.cc
//
class TarFile {
public:
2021-04-08 19:59:13 +03:00
template <typename E>
static std::unique_ptr<TarFile>
open(Context<E> &ctx, std::string path, std::string basedir);
void append(std::string path, std::string_view data);
2021-04-08 18:29:01 +03:00
private:
2021-04-08 19:59:13 +03:00
TarFile(std::ofstream &&out, std::string basedir)
: out(std::move(out)), basedir(basedir) {}
2021-04-09 11:39:17 +03:00
std::mutex mu;
2021-04-08 18:29:01 +03:00
std::ofstream out;
std::string basedir;
};
2021-03-30 10:55:06 +03:00
//
// passes.cc
//
template <typename E> void apply_exclude_libs(Context<E> &ctx);
template <typename E> void create_synthetic_sections(Context<E> &ctx);
template <typename E> void set_file_priority(Context<E> &ctx);
template <typename E> void resolve_obj_symbols(Context<E> &ctx);
template <typename E> void resolve_dso_symbols(Context<E> &ctx);
template <typename E> void eliminate_comdats(Context<E> &ctx);
template <typename E> void convert_common_symbols(Context<E> &ctx);
template <typename E> void add_comment_string(Context<E> &ctx, std::string str);
template <typename E> void compute_merged_section_sizes(Context<E> &ctx);
template <typename E> void bin_sections(Context<E> &ctx);
template <typename E> void check_duplicate_symbols(Context<E> &ctx);
template <typename E> std::vector<OutputChunk<E> *>
collect_output_sections(Context<E> &ctx);
template <typename E> void compute_section_sizes(Context<E> &ctx);
template <typename E> void convert_undefined_weak_symbols(Context<E> &ctx);
template <typename E> void scan_rels(Context<E> &ctx);
template <typename E> void apply_version_script(Context<E> &ctx);
template <typename E> void parse_symbol_version(Context<E> &ctx);
template <typename E> void compute_import_export(Context<E> &ctx);
template <typename E> void fill_verdef(Context<E> &ctx);
template <typename E> void fill_verneed(Context<E> &ctx);
template <typename E> void clear_padding(Context<E> &ctx, i64 filesize);
template <typename E> i64 get_section_rank(Context<E> &ctx, OutputChunk<E> *chunk);
template <typename E> i64 set_osec_offsets(Context<E> &ctx);
template <typename E> void fix_synthetic_symbols(Context<E> &ctx);
2020-11-29 04:31:04 +03:00
//
// main.cc
//
2021-03-29 07:20:51 +03:00
struct BuildId {
2021-03-29 14:29:57 +03:00
template <typename E>
i64 size(Context<E> &ctx) const;
2021-03-29 07:20:51 +03:00
enum { NONE, HEX, HASH, UUID } kind = NONE;
std::vector<u8> value;
i64 hash_size = 0;
};
struct VersionPattern {
std::string_view pattern;
i16 ver_idx;
bool is_extern_cpp;
};
2021-04-06 06:08:54 +03:00
template <typename E, typename T>
class FileCache {
public:
void store(MemoryMappedFile<E> *mb, T *obj) {
Key k(mb->name, mb->size(), mb->mtime);
cache[k].push_back(obj);
}
std::vector<T *> get(MemoryMappedFile<E> *mb) {
Key k(mb->name, mb->size(), mb->mtime);
std::vector<T *> objs = cache[k];
cache[k].clear();
return objs;
}
T *get_one(MemoryMappedFile<E> *mb) {
std::vector<T *> objs = get(mb);
return objs.empty() ? nullptr : objs[0];
}
private:
typedef std::tuple<std::string, i64, i64> Key;
std::map<Key, std::vector<T *>> cache;
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 07:20:51 +03:00
struct Context {
2021-03-29 10:48:23 +03:00
Context() = default;
2021-03-29 14:29:57 +03:00
Context(const Context<E> &) = delete;
2021-03-29 10:48:23 +03:00
2021-03-29 07:20:51 +03:00
// Command-line arguments
struct {
BuildId build_id;
bool Bsymbolic = false;
bool Bsymbolic_functions = false;
bool allow_multiple_definition = false;
bool demangle = true;
bool discard_all = false;
bool discard_locals = false;
bool eh_frame_hdr = true;
bool export_dynamic = false;
bool fatal_warnings = false;
bool fork = true;
bool gc_sections = false;
bool hash_style_gnu = false;
bool hash_style_sysv = true;
bool icf = false;
bool is_static = false;
bool perf = false;
bool pic = false;
bool pie = false;
bool preload = false;
bool print_gc_sections = false;
bool print_icf_sections = false;
bool print_map = false;
bool quick_exit = true;
bool relax = true;
bool shared = false;
bool stats = false;
bool strip_all = false;
bool strip_debug = false;
bool trace = false;
bool warn_common = false;
bool z_copyreloc = true;
bool z_defs = false;
bool z_delete = true;
bool z_dlopen = true;
bool z_execstack = false;
2021-04-10 12:16:01 +03:00
bool z_initfirst = false;
2021-03-29 07:20:51 +03:00
bool z_now = false;
bool z_relro = true;
i16 default_version = VER_NDX_GLOBAL;
std::vector<std::string_view> version_definitions;
std::vector<VersionPattern> version_patterns;
i64 filler = -1;
i64 thread_count = -1;
std::string Map;
2021-04-09 10:05:52 +03:00
std::string chroot;
2021-04-09 04:08:56 +03:00
std::string directory;
2021-03-29 07:20:51 +03:00
std::string dynamic_linker;
std::string entry = "_start";
std::string fini = "_fini";
std::string init = "_init";
std::string output;
2021-04-09 04:08:56 +03:00
std::string reproduce;
2021-03-29 07:20:51 +03:00
std::string rpaths;
std::string soname;
std::string sysroot;
std::vector<std::string_view> auxiliary;
std::vector<std::string_view> exclude_libs;
std::vector<std::string_view> filter;
std::vector<std::string_view> library_paths;
std::vector<std::string_view> trace_symbol;
std::vector<std::string_view> undefined;
u64 image_base = 0x200000;
} arg;
2021-03-29 08:36:55 +03:00
void reset_reader_context(bool is_preloading) {
as_needed = false;
whole_archive = false;
this->is_preloading = is_preloading;
is_static = arg.is_static;
visited.clear();
}
2021-03-29 11:39:22 +03:00
// Reader context
2021-03-29 08:36:55 +03:00
bool as_needed;
bool whole_archive;
bool is_preloading;
bool is_static;
std::unordered_set<std::string_view> visited;
tbb::task_group tg;
2021-03-29 18:20:42 +03:00
bool has_error = false;
2021-03-29 11:39:22 +03:00
2021-03-29 18:21:29 +03:00
// Symbol table
ConcurrentMap<Symbol<E>> symbol_map;
2021-04-05 18:25:45 +03:00
ConcurrentMap<ComdatGroup> comdat_groups;
2021-04-07 09:38:31 +03:00
tbb::concurrent_vector<std::unique_ptr<MergedSection<E>>> merged_sections;
std::vector<std::unique_ptr<OutputSection<E>>> output_sections;
2021-04-06 06:08:54 +03:00
FileCache<E, ObjectFile<E>> obj_cache;
FileCache<E, SharedFile<E>> dso_cache;
2021-04-06 12:02:50 +03:00
2021-04-07 09:38:31 +03:00
tbb::concurrent_vector<std::unique_ptr<TimerRecord>> timer_records;
tbb::concurrent_vector<std::function<void()>> on_exit;
2021-04-06 12:02:50 +03:00
tbb::concurrent_vector<std::unique_ptr<ObjectFile<E>>> owning_objs;
2021-04-06 12:13:53 +03:00
tbb::concurrent_vector<std::unique_ptr<SharedFile<E>>> owning_dsos;
2021-04-06 12:02:50 +03:00
tbb::concurrent_vector<std::unique_ptr<std::vector<u8>>> owning_bufs;
2021-04-06 13:26:37 +03:00
tbb::concurrent_vector<std::unique_ptr<ElfShdr<E>>> owning_shdrs;
2021-04-07 09:38:31 +03:00
tbb::concurrent_vector<std::unique_ptr<MemoryMappedFile<E>>> owning_mbs;
2021-04-05 18:25:45 +03:00
2021-04-01 06:14:05 +03:00
// Symbol auxiliary data
std::vector<SymbolAux> symbol_aux;
2021-03-29 08:36:55 +03:00
// Fully-expanded command line args
2021-03-29 08:05:55 +03:00
std::vector<std::string_view> cmdline_args;
2021-04-09 04:08:56 +03:00
// Tar file for --reproduce
std::unique_ptr<TarFile> tar_file;
2021-03-29 07:20:51 +03:00
// Input files
2021-03-29 14:29:57 +03:00
std::vector<ObjectFile<E> *> objs;
std::vector<SharedFile<E> *> dsos;
ObjectFile<E> *internal_obj = nullptr;
2021-03-29 07:20:51 +03:00
// Output buffer
2021-03-29 18:20:42 +03:00
u8 *buf = nullptr;
2021-03-29 07:20:51 +03:00
2021-03-29 14:29:57 +03:00
std::vector<OutputChunk<E> *> chunks;
2021-03-31 14:18:12 +03:00
std::atomic_bool has_gottp_rel = false;
2021-03-29 07:20:51 +03:00
std::atomic_bool has_textrel = false;
// Output chunks
2021-04-06 06:25:15 +03:00
std::unique_ptr<OutputEhdr<E>> ehdr;
std::unique_ptr<OutputShdr<E>> shdr;
std::unique_ptr<OutputPhdr<E>> phdr;
std::unique_ptr<InterpSection<E>> interp;
2021-04-06 06:15:07 +03:00
std::unique_ptr<GotSection<E>> got;
2021-04-06 06:25:15 +03:00
std::unique_ptr<GotPltSection<E>> gotplt;
std::unique_ptr<RelPltSection<E>> relplt;
std::unique_ptr<RelDynSection<E>> reldyn;
std::unique_ptr<DynamicSection<E>> dynamic;
std::unique_ptr<StrtabSection<E>> strtab;
std::unique_ptr<DynstrSection<E>> dynstr;
std::unique_ptr<HashSection<E>> hash;
std::unique_ptr<GnuHashSection<E>> gnu_hash;
std::unique_ptr<ShstrtabSection<E>> shstrtab;
std::unique_ptr<PltSection<E>> plt;
std::unique_ptr<PltGotSection<E>> pltgot;
std::unique_ptr<SymtabSection<E>> symtab;
std::unique_ptr<DynsymSection<E>> dynsym;
std::unique_ptr<EhFrameSection<E>> eh_frame;
std::unique_ptr<EhFrameHdrSection<E>> eh_frame_hdr;
std::unique_ptr<DynbssSection<E>> dynbss;
std::unique_ptr<DynbssSection<E>> dynbss_relro;
std::unique_ptr<VersymSection<E>> versym;
std::unique_ptr<VerneedSection<E>> verneed;
std::unique_ptr<VerdefSection<E>> verdef;
std::unique_ptr<BuildIdSection<E>> buildid;
2021-03-29 07:20:51 +03:00
u64 tls_begin = -1;
u64 tls_end = -1;
// Linker-synthesized symbols
2021-03-29 14:29:57 +03:00
Symbol<E> *__bss_start = nullptr;
Symbol<E> *__ehdr_start = nullptr;
2021-03-31 16:31:47 +03:00
Symbol<E> *__rel_iplt_start = nullptr;
Symbol<E> *__rel_iplt_end = nullptr;
2021-03-29 14:29:57 +03:00
Symbol<E> *__init_array_start = nullptr;
Symbol<E> *__init_array_end = nullptr;
Symbol<E> *__fini_array_start = nullptr;
Symbol<E> *__fini_array_end = nullptr;
Symbol<E> *__preinit_array_start = nullptr;
Symbol<E> *__preinit_array_end = nullptr;
Symbol<E> *_DYNAMIC = nullptr;
Symbol<E> *_GLOBAL_OFFSET_TABLE_ = nullptr;
Symbol<E> *__GNU_EH_FRAME_HDR = nullptr;
Symbol<E> *_end = nullptr;
Symbol<E> *_etext = nullptr;
Symbol<E> *_edata = nullptr;
Symbol<E> *__executable_start = nullptr;
2021-03-29 07:20:51 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
MemoryMappedFile<E> *find_library(Context<E> &ctx, std::string path);
2021-03-11 14:19:37 +03:00
2021-03-29 14:29:57 +03:00
template <typename E>
void read_file(Context<E> &ctx, MemoryMappedFile<E> *mb);
2020-11-29 04:31:04 +03:00
2021-04-06 12:02:50 +03:00
template <typename E>
2021-04-06 12:18:45 +03:00
std::string_view save_string(Context<E> &ctx, const std::string &str);
2021-04-06 12:02:50 +03:00
2021-04-09 04:08:56 +03:00
std::string get_version_string();
2021-04-01 05:54:46 +03:00
//
// Symbol
//
enum {
NEEDS_GOT = 1 << 0,
NEEDS_PLT = 1 << 1,
2021-04-01 09:59:11 +03:00
NEEDS_GOTTP = 1 << 2,
NEEDS_TLSGD = 1 << 3,
NEEDS_TLSLD = 1 << 4,
NEEDS_COPYREL = 1 << 5,
NEEDS_DYNSYM = 1 << 6,
NEEDS_TLSDESC = 1 << 7,
2021-04-01 05:54:46 +03:00
};
template <typename E>
class Symbol {
public:
Symbol() = default;
2021-04-01 14:12:30 +03:00
Symbol(std::string_view name) : nameptr(name.data()), namelen(name.size()) {}
Symbol(const Symbol<E> &other) : Symbol(other.get_name()) {}
2021-04-01 05:54:46 +03:00
static Symbol<E> *intern(Context<E> &ctx, std::string_view key,
std::string_view name) {
return ctx.symbol_map.insert(key, {name});
}
static Symbol<E> *intern(Context<E> &ctx, std::string_view name) {
return intern(ctx, name, name);
}
u64 get_addr(Context<E> &ctx) const {
2021-04-01 17:57:18 +03:00
if (SectionFragment<E> *frag = get_frag()) {
2021-04-01 05:54:46 +03:00
assert(frag->is_alive);
return frag->get_addr(ctx) + value;
}
if (has_copyrel) {
return copyrel_readonly
? ctx.dynbss_relro->shdr.sh_addr + value
: ctx.dynbss->shdr.sh_addr + value;
}
2021-04-01 16:53:22 +03:00
if (has_plt(ctx) && esym().st_type == STT_GNU_IFUNC)
2021-04-01 05:54:46 +03:00
return get_plt_addr(ctx);
if (input_section) {
if (input_section->is_ehframe)
return ctx.eh_frame->get_addr(ctx, *this);
if (!input_section->is_alive) {
// The control can reach here if there's a relocation that refers
// a local symbol belonging to a comdat group section. This is a
// violation of the spec, as all relocations should use only global
// symbols of comdat members. However, .eh_frame tends to have such
// relocations.
return 0;
}
return input_section->get_addr() + value;
}
2021-04-01 07:20:02 +03:00
if (has_plt(ctx))
2021-04-01 05:54:46 +03:00
return get_plt_addr(ctx);
return value;
}
u64 get_got_addr(Context<E> &ctx) const {
2021-04-01 06:14:05 +03:00
return ctx.got->shdr.sh_addr + get_got_idx(ctx) * E::got_size;
2021-04-01 05:54:46 +03:00
}
u64 get_gotplt_addr(Context<E> &ctx) const {
2021-04-01 07:34:22 +03:00
assert(get_gotplt_idx(ctx) != -1);
2021-04-01 06:14:05 +03:00
return ctx.gotplt->shdr.sh_addr + get_gotplt_idx(ctx) * E::got_size;
2021-04-01 05:54:46 +03:00
}
u64 get_gottp_addr(Context<E> &ctx) const {
2021-04-01 07:34:22 +03:00
assert(get_gottp_idx(ctx) != -1);
2021-04-01 06:14:05 +03:00
return ctx.got->shdr.sh_addr + get_gottp_idx(ctx) * E::got_size;
2021-04-01 05:54:46 +03:00
}
u64 get_tlsgd_addr(Context<E> &ctx) const {
2021-04-01 07:34:22 +03:00
assert(get_tlsgd_idx(ctx) != -1);
2021-04-01 06:14:05 +03:00
return ctx.got->shdr.sh_addr + get_tlsgd_idx(ctx) * E::got_size;
2021-04-01 05:54:46 +03:00
}
u64 get_tlsdesc_addr(Context<E> &ctx) const {
2021-04-01 07:34:22 +03:00
assert(get_tlsdesc_idx(ctx) != -1);
2021-04-01 06:14:05 +03:00
return ctx.got->shdr.sh_addr + get_tlsdesc_idx(ctx) * E::got_size;
2021-04-01 05:54:46 +03:00
}
u64 get_plt_addr(Context<E> &ctx) const {
2021-04-01 07:20:02 +03:00
if (i32 idx = get_plt_idx(ctx); idx != -1)
return ctx.plt->shdr.sh_addr + idx * E::plt_size;
2021-04-01 07:42:11 +03:00
return ctx.pltgot->shdr.sh_addr + get_pltgot_idx(ctx) * E::pltgot_size;
2021-04-01 06:14:05 +03:00
}
void set_got_idx(Context<E> &ctx, i32 idx) const {
2021-04-01 06:14:27 +03:00
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].got_idx < 0);
2021-04-01 06:14:05 +03:00
ctx.symbol_aux[aux_idx].got_idx = idx;
}
void set_gotplt_idx(Context<E> &ctx, i32 idx) const {
2021-04-01 06:14:27 +03:00
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].gotplt_idx < 0);
2021-04-01 06:14:05 +03:00
ctx.symbol_aux[aux_idx].gotplt_idx = idx;
}
void set_gottp_idx(Context<E> &ctx, i32 idx) const {
2021-04-01 06:14:27 +03:00
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].gottp_idx < 0);
2021-04-01 06:14:05 +03:00
ctx.symbol_aux[aux_idx].gottp_idx = idx;
}
void set_tlsgd_idx(Context<E> &ctx, i32 idx) const {
2021-04-01 06:14:27 +03:00
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].tlsgd_idx < 0);
2021-04-01 06:14:05 +03:00
ctx.symbol_aux[aux_idx].tlsgd_idx = idx;
}
void set_tlsdesc_idx(Context<E> &ctx, i32 idx) const {
2021-04-01 06:14:27 +03:00
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].tlsdesc_idx < 0);
2021-04-01 06:14:05 +03:00
ctx.symbol_aux[aux_idx].tlsdesc_idx = idx;
}
void set_plt_idx(Context<E> &ctx, i32 idx) const {
2021-04-01 06:14:27 +03:00
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].plt_idx < 0);
2021-04-01 06:14:05 +03:00
ctx.symbol_aux[aux_idx].plt_idx = idx;
}
2021-04-01 07:20:02 +03:00
void set_pltgot_idx(Context<E> &ctx, i32 idx) const {
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].pltgot_idx < 0);
ctx.symbol_aux[aux_idx].pltgot_idx = idx;
}
2021-04-01 06:14:05 +03:00
void set_dynsym_idx(Context<E> &ctx, i32 idx) const {
2021-04-01 06:14:27 +03:00
assert(aux_idx != -1);
assert(ctx.symbol_aux[aux_idx].dynsym_idx < 0);
2021-04-01 06:14:05 +03:00
ctx.symbol_aux[aux_idx].dynsym_idx = idx;
}
2021-04-01 06:14:27 +03:00
i32 get_got_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].got_idx;
2021-04-01 06:14:05 +03:00
}
2021-04-01 06:14:27 +03:00
i32 get_gotplt_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].gotplt_idx;
2021-04-01 06:14:05 +03:00
}
2021-04-01 06:14:27 +03:00
i32 get_gottp_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].gottp_idx;
2021-04-01 06:14:05 +03:00
}
2021-04-01 06:14:27 +03:00
i32 get_tlsgd_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].tlsgd_idx;
2021-04-01 06:14:05 +03:00
}
2021-04-01 06:14:27 +03:00
i32 get_tlsdesc_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].tlsdesc_idx;
2021-04-01 06:14:05 +03:00
}
2021-04-01 06:14:27 +03:00
i32 get_plt_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].plt_idx;
2021-04-01 06:14:05 +03:00
}
2021-04-01 07:20:02 +03:00
i32 get_pltgot_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].pltgot_idx;
}
2021-04-01 06:14:27 +03:00
i32 get_dynsym_idx(Context<E> &ctx) const {
return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].dynsym_idx;
2021-04-01 05:54:46 +03:00
}
2021-04-01 16:40:36 +03:00
bool has_plt(Context<E> &ctx) const {
2021-04-01 07:20:02 +03:00
return get_plt_idx(ctx) != -1 || get_pltgot_idx(ctx) != -1;
}
2021-04-01 16:40:36 +03:00
bool has_got(Context<E> &ctx) const {
2021-04-01 07:20:02 +03:00
return get_got_idx(ctx) != -1;
}
2021-04-01 05:54:46 +03:00
bool is_alive() const {
2021-04-01 17:57:18 +03:00
if (SectionFragment<E> *frag = get_frag())
2021-04-01 05:54:46 +03:00
return frag->is_alive;
if (input_section)
return input_section->is_alive;
return true;
}
bool is_absolute(Context<E> &ctx) const {
if (file == ctx.internal_obj)
return false;
if (file->is_dso)
2021-04-01 16:53:22 +03:00
return esym().is_abs();
2021-04-01 05:54:46 +03:00
if (is_imported)
return false;
2021-04-01 17:57:18 +03:00
if (get_frag())
2021-04-01 05:54:46 +03:00
return false;
return input_section == nullptr;
}
bool is_relative(Context<E> &ctx) const {
return !is_absolute(ctx);
}
bool is_undef() const {
2021-04-01 16:53:22 +03:00
return esym().is_undef() && esym().st_bind != STB_WEAK;
2021-04-01 05:54:46 +03:00
}
bool is_undef_weak() const {
2021-04-01 16:53:22 +03:00
return esym().is_undef() && esym().st_bind == STB_WEAK;
2021-04-01 05:54:46 +03:00
}
u32 get_type() const {
2021-04-01 16:53:22 +03:00
if (esym().st_type == STT_GNU_IFUNC && file->is_dso)
2021-04-01 05:54:46 +03:00
return STT_FUNC;
2021-04-01 16:53:22 +03:00
return esym().st_type;
2021-04-01 05:54:46 +03:00
}
std::string_view get_version() const {
if (file->is_dso)
return ((SharedFile<E> *)file)->version_strings[ver_idx];
return "";
}
std::string_view get_demangled_name() const;
void clear() {
Symbol<E> null;
memcpy((char *)this, &null, sizeof(null));
}
2021-04-01 16:53:22 +03:00
const ElfSym<E> &esym() const {
if (file->is_dso)
return *((SharedFile<E> *)file)->elf_syms[sym_idx];
return ((ObjectFile<E> *)file)->elf_syms[sym_idx];
}
2021-04-01 17:57:18 +03:00
SectionFragment<E> *get_frag() const {
if (!file || file->is_dso)
return nullptr;
return ((ObjectFile<E> *)file)->sym_fragments[sym_idx].frag;
}
2021-04-01 14:12:30 +03:00
void set_name(std::string_view str) {
nameptr = str.data();
namelen = str.size();
}
std::string_view get_name() const {
return {nameptr, (size_t)namelen};
}
2021-04-01 05:54:46 +03:00
InputFile<E> *file = nullptr;
InputSection<E> *input_section = nullptr;
2021-04-01 14:12:30 +03:00
const char *nameptr = nullptr;
2021-04-01 05:54:46 +03:00
u64 value = -1;
2021-04-01 16:53:22 +03:00
i32 sym_idx = -1;
2021-04-01 14:12:30 +03:00
i32 namelen = 0;
2021-04-01 06:14:05 +03:00
i32 aux_idx = -1;
2021-04-01 05:54:46 +03:00
u16 shndx = 0;
u16 ver_idx = 0;
2021-04-01 09:59:11 +03:00
std::atomic_uint8_t flags = 0;
2021-04-01 06:14:05 +03:00
tbb::spin_mutex mu;
2021-04-01 05:54:46 +03:00
std::atomic_uint8_t visibility = STV_DEFAULT;
u8 is_lazy : 1 = false;
u8 is_weak : 1 = false;
u8 write_to_symtab : 1 = false;
u8 traced : 1 = false;
u8 has_copyrel : 1 = false;
u8 copyrel_readonly : 1 = false;
u8 is_imported : 1 = false;
u8 is_exported : 1 = false;
};
2021-03-29 07:20:51 +03:00
//
// Error output
//
2021-03-29 10:48:23 +03:00
inline thread_local bool opt_demangle = false;
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 07:20:51 +03:00
class SyncOut {
public:
2021-03-29 14:29:57 +03:00
SyncOut(Context<E> &ctx, std::ostream &out = std::cout) : out(out) {
2021-03-29 10:48:23 +03:00
opt_demangle = ctx.arg.demangle;
}
2021-03-29 07:20:51 +03:00
~SyncOut() {
std::lock_guard lock(mu);
out << ss.str() << "\n";
}
template <class T> SyncOut &operator<<(T &&val) {
ss << std::forward<T>(val);
return *this;
}
2021-03-29 13:14:11 +03:00
static inline std::mutex mu;
2021-03-29 07:20:51 +03:00
private:
std::ostream &out;
std::stringstream ss;
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 07:20:51 +03:00
class Fatal {
public:
2021-03-29 14:29:57 +03:00
Fatal(Context<E> &ctx) : out(ctx, std::cerr) {}
2021-03-29 10:48:23 +03:00
2021-03-29 07:20:51 +03:00
[[noreturn]] ~Fatal() {
out.~SyncOut();
2021-03-29 14:29:57 +03:00
cleanup<E>();
2021-03-29 07:20:51 +03:00
_exit(1);
}
template <class T> Fatal &operator<<(T &&val) {
out << std::forward<T>(val);
return *this;
}
private:
2021-03-29 14:29:57 +03:00
SyncOut<E> out;
2021-03-29 07:20:51 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 07:20:51 +03:00
class Error {
public:
2021-03-29 14:29:57 +03:00
Error(Context<E> &ctx) : out(ctx, std::cerr) {
2021-03-29 11:39:22 +03:00
ctx.has_error = true;
2021-03-29 07:20:51 +03:00
}
template <class T> Error &operator<<(T &&val) {
out << std::forward<T>(val);
return *this;
}
2021-03-29 14:29:57 +03:00
static void checkpoint(Context<E> &ctx) {
2021-03-29 11:39:22 +03:00
if (!ctx.has_error)
2021-03-29 07:20:51 +03:00
return;
2021-03-29 14:29:57 +03:00
cleanup<E>();
2021-03-29 07:20:51 +03:00
_exit(1);
}
private:
2021-03-29 14:29:57 +03:00
SyncOut<E> out;
2021-03-29 07:20:51 +03:00
};
2021-03-29 14:29:57 +03:00
template <typename E>
2021-03-29 07:20:51 +03:00
class Warn {
public:
2021-03-29 14:29:57 +03:00
Warn(Context<E> &ctx) : out(ctx, std::cerr) {
2021-03-29 07:20:51 +03:00
if (ctx.arg.fatal_warnings)
2021-03-29 11:39:22 +03:00
ctx.has_error = true;
2021-03-29 07:20:51 +03:00
}
template <class T> Warn &operator<<(T &&val) {
out << std::forward<T>(val);
return *this;
}
private:
2021-03-29 14:29:57 +03:00
SyncOut<E> out;
2021-03-29 07:20:51 +03:00
};
2021-03-29 14:55:27 +03:00
#define unreachable(ctx) \
do { \
Fatal(ctx) << "internal error at " << __FILE__ << ":" << __LINE__; \
} while (0)
2021-03-29 07:20:51 +03:00
2021-03-29 14:29:57 +03:00
template <typename E>
std::ostream &operator<<(std::ostream &out, const InputFile<E> &file);
2021-03-29 07:20:51 +03:00
2020-11-29 04:31:04 +03:00
//
// Inline objects and functions
//
2021-03-29 14:29:57 +03:00
template <typename E>
inline std::ostream &
operator<<(std::ostream &out, const InputSection<E> &isec) {
2021-03-29 07:20:51 +03:00
out << isec.file << ":(" << isec.name << ")";
return out;
2020-11-29 04:31:04 +03:00
}
inline u64 align_to(u64 val, u64 align) {
if (align == 0)
return val;
2020-11-29 04:31:04 +03:00
assert(__builtin_popcount(align) == 1);
return (val + align - 1) & ~(align - 1);
}
2021-01-23 09:01:49 +03:00
inline u64 next_power_of_two(u64 val) {
2021-03-11 19:17:46 +03:00
assert(val >> 63 == 0);
if (val == 0 || val == 1)
2021-01-23 09:01:49 +03:00
return 1;
2021-03-11 19:17:46 +03:00
return (u64)1 << (64 - __builtin_clzl(val - 1));
2021-01-23 09:01:49 +03:00
}
2021-03-29 17:50:19 +03:00
2021-03-29 14:29:57 +03:00
template <typename E>
inline u64 SectionFragment<E>::get_addr(Context<E> &ctx) const {
2021-03-11 11:06:43 +03:00
return output_section.shdr.sh_addr + offset;
2020-11-15 08:07:40 +03:00
}
2021-04-06 08:42:58 +03:00
template <typename E>
inline void InputSection<E>::kill() {
if (is_alive.exchange(false)) {
is_alive = false;
for (FdeRecord<E> &fde : fdes)
fde.is_alive = false;
}
}
2021-03-29 14:29:57 +03:00
template <typename E>
inline u64 InputSection<E>::get_addr() const {
2020-11-25 09:13:06 +03:00
return output_section->shdr.sh_addr + offset;
}
2021-03-29 14:29:57 +03:00
template <typename E>
inline i64 InputSection<E>::get_priority() const {
2021-03-11 13:48:18 +03:00
return ((i64)file.priority << 32) | section_idx;
2021-01-29 06:45:37 +03:00
}
2021-03-30 13:27:00 +03:00
template <>
inline i64 InputSection<X86_64>::get_addend(const ElfRel<X86_64> &rel) const {
return rel.r_addend;
}
template <>
inline i64 InputSection<I386>::get_addend(const ElfRel<I386> &rel) const {
u8 *buf = (u8 *)contents.data();
return *(i32 *)(buf + rel.r_offset);
}
2021-04-01 19:23:05 +03:00
template <typename E>
inline std::span<ElfRel<E>> InputSection<E>::get_rels(Context<E> &ctx) const {
if (relsec_idx == -1)
return {};
return file.template get_data<ElfRel<E>>(ctx, file.elf_sections[relsec_idx]);
}
2021-04-05 17:47:31 +03:00
template <typename E>
inline std::string_view
InputFile<E>::get_string(Context<E> &ctx, const ElfShdr<E> &shdr) {
u8 *begin = mb->data(ctx) + shdr.sh_offset;
u8 *end = begin + shdr.sh_size;
if (mb->data(ctx) + mb->size() < end)
Fatal(ctx) << *this << ": shdr corrupted";
return {(char *)begin, (char *)end};
}
template <typename E>
inline std::string_view InputFile<E>::get_string(Context<E> &ctx, i64 idx) {
assert(idx < elf_sections.size());
if (elf_sections.size() <= idx)
Fatal(ctx) << *this << ": invalid section index: " << idx;
return this->get_string(ctx, elf_sections[idx]);
}
2021-03-29 14:29:57 +03:00
template <typename E>
inline i64 ObjectFile<E>::get_shndx(const ElfSym<E> &esym) {
2021-03-22 12:19:07 +03:00
assert(&elf_syms[0] <= &esym);
assert(&esym < &elf_syms[elf_syms.size()]);
2021-03-05 06:24:06 +03:00
if (esym.st_shndx == SHN_XINDEX)
return symtab_shndx_sec[&esym - &elf_syms[0]];
return esym.st_shndx;
}
2021-03-29 14:29:57 +03:00
template <typename E>
inline InputSection<E> *ObjectFile<E>::get_section(const ElfSym<E> &esym) {
2021-04-06 08:36:31 +03:00
return sections[get_shndx(esym)].get();
2021-03-05 06:24:06 +03:00
}
2021-03-29 14:29:57 +03:00
template <typename E>
std::span<Symbol<E> *> ObjectFile<E>::get_global_syms() {
return std::span<Symbol<E> *>(this->symbols).subspan(first_global);
2021-03-10 15:37:25 +03:00
}
2020-12-10 07:44:58 +03:00
inline u32 elf_hash(std::string_view name) {
2020-11-29 06:59:08 +03:00
u32 h = 0;
2020-11-29 15:05:39 +03:00
for (u8 c : name) {
2020-11-29 06:59:08 +03:00
h = (h << 4) + c;
u32 g = h & 0xf0000000;
if (g != 0)
h ^= g >> 24;
h &= ~g;
}
return h;
}
2021-03-31 07:56:35 +03:00
inline u32 djb_hash(std::string_view name) {
2021-01-23 09:01:49 +03:00
u32 h = 5381;
for (u8 c : name)
h = (h << 5) + h + c;
return h;
}
2020-12-10 07:44:58 +03:00
inline void write_string(u8 *buf, std::string_view str) {
2020-11-15 08:07:40 +03:00
memcpy(buf, str.data(), str.size());
buf[str.size()] = '\0';
}
2020-11-16 18:43:32 +03:00
template <typename T>
inline void write_vector(u8 *buf, const std::vector<T> &vec) {
memcpy(buf, vec.data(), vec.size() * sizeof(T));
}
2020-12-20 09:51:37 +03:00
template <typename T, typename U>
2020-12-20 10:17:24 +03:00
inline void append(std::vector<T> &vec1, std::vector<U> vec2) {
2020-12-20 09:51:37 +03:00
vec1.insert(vec1.end(), vec2.begin(), vec2.end());
}
2020-11-24 08:31:05 +03:00
template <typename T>
2020-11-17 13:56:02 +03:00
inline std::vector<T> flatten(std::vector<std::vector<T>> &vec) {
std::vector<T> ret;
for (std::vector<T> &v : vec)
2020-12-20 09:51:37 +03:00
append(ret, v);
2020-11-17 13:56:02 +03:00
return ret;
}
2020-12-13 16:31:50 +03:00
template <typename T, typename U>
inline void erase(std::vector<T> &vec, U pred) {
vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end());
}
2020-12-21 12:42:14 +03:00
template <typename T, typename U>
inline void sort(T &vec, U less) {
std::stable_sort(vec.begin(), vec.end(), less);
}