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"
|
|
|
|
|
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-01-16 05:57:36 +03:00
|
|
|
#include <functional>
|
2020-12-10 16:32:47 +03:00
|
|
|
#include <iostream>
|
2021-01-18 15:40:56 +03:00
|
|
|
#include <map>
|
2020-10-21 05:55:03 +03:00
|
|
|
#include <mutex>
|
2021-01-19 07:26:41 +03:00
|
|
|
#include <set>
|
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-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-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
|
|
|
#define SECTOR_SIZE 512
|
|
|
|
#define PAGE_SIZE 4096
|
2020-11-11 10:53:41 +03:00
|
|
|
#define GOT_SIZE 8
|
|
|
|
#define PLT_SIZE 16
|
2021-01-15 16:34:52 +03:00
|
|
|
#define SHA256_SIZE 32
|
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;
|
|
|
|
|
2020-11-08 06:26:40 +03:00
|
|
|
class InputChunk;
|
2020-11-24 10:22:32 +03:00
|
|
|
class InputFile;
|
2020-11-03 14:45:45 +03:00
|
|
|
class InputSection;
|
2020-11-08 07:01:46 +03:00
|
|
|
class MergeableSection;
|
2020-11-24 10:22:32 +03:00
|
|
|
class MergedSection;
|
2020-11-03 14:45:45 +03:00
|
|
|
class ObjectFile;
|
2020-11-04 08:03:01 +03:00
|
|
|
class OutputChunk;
|
2020-11-03 14:45:45 +03:00
|
|
|
class OutputSection;
|
2020-11-24 10:22:32 +03:00
|
|
|
class SharedFile;
|
|
|
|
class Symbol;
|
2020-10-08 11:01:54 +03:00
|
|
|
|
2020-10-04 12:00:33 +03:00
|
|
|
struct Config {
|
2020-12-10 08:32:42 +03:00
|
|
|
std::string dynamic_linker = "/lib64/ld-linux-x86-64.so.2";
|
2020-12-14 04:07:14 +03:00
|
|
|
std::string entry = "_start";
|
2020-12-10 08:32:42 +03:00
|
|
|
std::string output;
|
2021-01-15 05:17:52 +03:00
|
|
|
std::string rpaths;
|
2021-01-15 14:14:01 +03:00
|
|
|
bool build_id = false;
|
2020-12-20 04:20:24 +03:00
|
|
|
bool discard_all = false;
|
2020-12-20 04:12:10 +03:00
|
|
|
bool discard_locals = false;
|
2021-01-21 11:11:16 +03:00
|
|
|
bool eh_frame_hdr = true;
|
2020-12-01 15:43:30 +03:00
|
|
|
bool export_dynamic = false;
|
2020-12-20 02:31:17 +03:00
|
|
|
bool fork = true;
|
2021-01-24 10:12:34 +03:00
|
|
|
bool gc_sections = false;
|
2021-01-23 09:01:49 +03:00
|
|
|
bool hash_style_gnu = false;
|
|
|
|
bool hash_style_sysv = true;
|
2020-11-04 12:47:13 +03:00
|
|
|
bool is_static = false;
|
2020-12-13 16:41:50 +03:00
|
|
|
bool perf = false;
|
2020-12-16 14:56:04 +03:00
|
|
|
bool pie = false;
|
2020-12-22 15:38:41 +03:00
|
|
|
bool preload = false;
|
2021-01-24 10:12:34 +03:00
|
|
|
bool print_gc_sections = false;
|
2020-11-11 03:02:36 +03:00
|
|
|
bool print_map = false;
|
2021-01-23 09:01:49 +03:00
|
|
|
bool quick_exit = true;
|
2021-01-14 07:19:21 +03:00
|
|
|
bool relax = true;
|
2020-12-21 10:32:43 +03:00
|
|
|
bool stat = false;
|
2020-12-20 04:27:01 +03:00
|
|
|
bool strip_all = false;
|
2020-12-11 06:43:14 +03:00
|
|
|
bool trace = false;
|
2020-12-17 16:29:43 +03:00
|
|
|
bool z_now = false;
|
2021-01-24 06:01:43 +03:00
|
|
|
i64 filler = -1;
|
|
|
|
i64 thread_count = -1;
|
2020-11-20 13:27:39 +03:00
|
|
|
std::string sysroot;
|
2020-12-10 07:44:58 +03:00
|
|
|
std::vector<std::string> globals;
|
2020-12-21 10:32:43 +03:00
|
|
|
std::vector<std::string_view> library_paths;
|
|
|
|
std::vector<std::string_view> trace_symbol;
|
|
|
|
std::vector<std::string_view> version_script;
|
2020-11-17 09:05:53 +03:00
|
|
|
u64 image_base = 0x200000;
|
2020-10-04 12:00:33 +03:00
|
|
|
};
|
|
|
|
|
2020-11-29 05:06:11 +03:00
|
|
|
inline Config config;
|
|
|
|
|
2020-12-24 14:15:17 +03:00
|
|
|
void cleanup();
|
|
|
|
|
2021-01-13 17:52:11 +03:00
|
|
|
class SyncOut {
|
2021-01-09 05:19:57 +03:00
|
|
|
public:
|
2021-01-13 17:52:11 +03:00
|
|
|
SyncOut(std::ostream &out = std::cout) : out(out) {}
|
|
|
|
|
|
|
|
~SyncOut() {
|
2021-01-09 05:19:57 +03:00
|
|
|
static std::mutex mu;
|
|
|
|
std::lock_guard lock(mu);
|
2021-01-13 17:52:11 +03:00
|
|
|
out << ss.str() << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T> SyncOut &operator<<(T &&val) {
|
|
|
|
ss << std::forward<T>(val);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::ostream &out;
|
|
|
|
std::stringstream ss;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Error {
|
|
|
|
public:
|
|
|
|
Error() {
|
|
|
|
has_error = true;
|
2021-01-09 05:19:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T> Error &operator<<(T &&val) {
|
|
|
|
out << std::forward<T>(val);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-01-13 17:52:11 +03:00
|
|
|
static void checkpoint() {
|
|
|
|
if (!has_error)
|
|
|
|
return;
|
|
|
|
cleanup();
|
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
|
2021-01-09 05:19:57 +03:00
|
|
|
private:
|
2021-01-13 17:52:11 +03:00
|
|
|
static inline std::atomic_bool has_error = false;
|
|
|
|
SyncOut out{std::cerr};
|
2021-01-09 05:19:57 +03:00
|
|
|
};
|
2020-10-04 12:00:33 +03:00
|
|
|
|
2021-01-13 17:52:11 +03:00
|
|
|
class Fatal {
|
2021-01-09 06:33:52 +03:00
|
|
|
public:
|
2021-01-13 17:52:11 +03:00
|
|
|
[[noreturn]] ~Fatal() {
|
|
|
|
out.~SyncOut();
|
|
|
|
cleanup();
|
|
|
|
_exit(1);
|
2021-01-09 06:33:52 +03:00
|
|
|
}
|
|
|
|
|
2021-01-13 17:52:11 +03:00
|
|
|
template <class T> Fatal &operator<<(T &&val) {
|
2021-01-09 06:33:52 +03:00
|
|
|
out << std::forward<T>(val);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2021-01-13 17:52:11 +03:00
|
|
|
SyncOut out{std::cerr};
|
2021-01-09 06:33:52 +03:00
|
|
|
};
|
|
|
|
|
2020-11-30 11:52:08 +03:00
|
|
|
#define unreachable() \
|
2021-01-24 04:28:42 +03:00
|
|
|
do { Fatal() << "internal error at " << __FILE__ << ":" << __LINE__; } while (0)
|
2020-11-30 11:52:08 +03:00
|
|
|
|
2021-01-09 06:41:32 +03:00
|
|
|
std::ostream &operator<<(std::ostream &out, const InputFile &file);
|
2020-10-19 15:32:57 +03:00
|
|
|
|
2020-10-12 07:30:34 +03:00
|
|
|
//
|
2020-10-19 15:32:57 +03:00
|
|
|
// Interned string
|
2020-10-12 07:30:34 +03:00
|
|
|
//
|
|
|
|
|
2020-10-19 12:13:55 +03:00
|
|
|
namespace tbb {
|
2021-01-22 11:03:05 +03:00
|
|
|
template<> struct tbb_hash_compare<std::string_view> {
|
|
|
|
static size_t hash(const std::string_view &k) {
|
2020-12-10 16:35:36 +03:00
|
|
|
return std::hash<std::string_view>()(k);
|
2020-10-19 12:13:55 +03:00
|
|
|
}
|
|
|
|
|
2021-01-22 11:03:05 +03:00
|
|
|
static bool equal(const std::string_view &k1, const std::string_view &k2) {
|
2020-10-19 12:13:55 +03:00
|
|
|
return k1 == k2;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-01-22 11:03:05 +03:00
|
|
|
template<typename ValueT> class ConcurrentMap {
|
2020-12-23 11:23:58 +03:00
|
|
|
public:
|
|
|
|
ValueT *insert(std::string_view key, const ValueT &val) {
|
2021-01-22 10:14:49 +03:00
|
|
|
typename decltype(map)::const_accessor acc;
|
2021-01-09 09:10:46 +03:00
|
|
|
map.insert(acc, std::make_pair(key, val));
|
2020-12-23 11:23:58 +03:00
|
|
|
return const_cast<ValueT *>(&acc->second);
|
|
|
|
}
|
|
|
|
|
2021-01-22 10:14:49 +03:00
|
|
|
tbb::concurrent_hash_map<std::string_view, ValueT> map;
|
2020-12-23 11:23:58 +03:00
|
|
|
};
|
|
|
|
|
2020-10-19 15:32:57 +03:00
|
|
|
//
|
|
|
|
// Symbol
|
|
|
|
//
|
|
|
|
|
2021-01-22 09:10:32 +03:00
|
|
|
struct SectionFragment {
|
2021-01-22 10:59:37 +03:00
|
|
|
SectionFragment(std::string_view data) : data(data) {}
|
2020-11-07 04:49:34 +03:00
|
|
|
|
2021-01-22 09:10:32 +03:00
|
|
|
SectionFragment(const SectionFragment &other)
|
2021-01-22 10:59:37 +03:00
|
|
|
: isec(other.isec.load()), data(other.data),
|
2021-01-22 14:35:33 +03:00
|
|
|
offset(other.offset) {}
|
2020-11-07 04:49:34 +03:00
|
|
|
|
2020-11-07 14:05:51 +03:00
|
|
|
inline u64 get_addr() const;
|
|
|
|
|
2021-01-09 09:06:18 +03:00
|
|
|
std::atomic<MergeableSection *> isec = nullptr;
|
2021-01-22 10:59:37 +03:00
|
|
|
std::string_view data;
|
2021-01-22 14:35:33 +03:00
|
|
|
u32 offset = -1;
|
2021-01-24 15:10:19 +03:00
|
|
|
u16 alignment = 1;
|
2021-01-25 07:47:48 +03:00
|
|
|
std::atomic_bool is_alive = !config.gc_sections;
|
2020-11-07 04:49:34 +03:00
|
|
|
};
|
|
|
|
|
2021-01-22 09:10:32 +03:00
|
|
|
struct SectionFragmentRef {
|
|
|
|
SectionFragment *frag = nullptr;
|
2020-11-24 13:26:26 +03:00
|
|
|
i32 addend = 0;
|
2020-11-07 04:49:34 +03:00
|
|
|
};
|
|
|
|
|
2021-01-22 11:13:52 +03:00
|
|
|
struct SectionFragmentKey {
|
|
|
|
std::string_view data;
|
|
|
|
u32 alignment;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace tbb {
|
|
|
|
template<> struct tbb_hash_compare<SectionFragmentKey> {
|
|
|
|
static size_t hash(const SectionFragmentKey &k) {
|
|
|
|
return std::hash<std::string_view>()(k.data) ^ std::hash<u32>()(k.alignment);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool equal(const SectionFragmentKey &k1, const SectionFragmentKey &k2) {
|
|
|
|
return k1.data == k2.data && k1.alignment == k2.alignment;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-12-16 12:38:13 +03:00
|
|
|
enum {
|
|
|
|
NEEDS_GOT = 1 << 0,
|
|
|
|
NEEDS_PLT = 1 << 1,
|
|
|
|
NEEDS_GOTTPOFF = 1 << 2,
|
|
|
|
NEEDS_TLSGD = 1 << 3,
|
|
|
|
NEEDS_TLSLD = 1 << 4,
|
|
|
|
NEEDS_COPYREL = 1 << 5,
|
2020-12-16 14:56:04 +03:00
|
|
|
NEEDS_DYNSYM = 1 << 6,
|
2020-12-16 12:38:13 +03:00
|
|
|
};
|
|
|
|
|
2020-10-12 07:30:34 +03:00
|
|
|
class Symbol {
|
|
|
|
public:
|
2021-01-24 04:28:42 +03:00
|
|
|
Symbol() = default;
|
2021-01-22 10:33:05 +03:00
|
|
|
Symbol(std::string_view name) : name(name) {}
|
2021-01-09 10:11:54 +03:00
|
|
|
Symbol(const Symbol &other) : name(other.name) {}
|
2020-10-12 07:30:34 +03:00
|
|
|
|
2021-01-22 10:01:54 +03:00
|
|
|
static Symbol *intern(std::string_view name) {
|
|
|
|
static ConcurrentMap<Symbol> map;
|
2021-01-22 10:33:05 +03:00
|
|
|
return map.insert(name, {name});
|
2021-01-22 10:01:54 +03:00
|
|
|
}
|
2020-10-25 08:42:44 +03:00
|
|
|
|
2020-11-06 06:50:26 +03:00
|
|
|
inline u64 get_addr() const;
|
2020-11-15 07:01:38 +03:00
|
|
|
inline u64 get_got_addr() const;
|
|
|
|
inline u64 get_gotplt_addr() const;
|
2020-11-21 04:48:51 +03:00
|
|
|
inline u64 get_gottpoff_addr() const;
|
2020-11-21 04:48:23 +03:00
|
|
|
inline u64 get_tlsgd_addr() const;
|
2020-11-15 07:01:38 +03:00
|
|
|
inline u64 get_plt_addr() const;
|
2020-11-06 06:50:26 +03:00
|
|
|
|
2021-01-13 09:42:07 +03:00
|
|
|
bool is_absolute() const;
|
|
|
|
|
|
|
|
bool is_relative() const {
|
|
|
|
return !is_absolute();
|
2020-12-17 08:32:18 +03:00
|
|
|
}
|
|
|
|
|
2020-12-10 07:44:58 +03:00
|
|
|
std::string_view name;
|
2020-11-24 10:22:32 +03:00
|
|
|
InputFile *file = nullptr;
|
2020-12-10 09:10:18 +03:00
|
|
|
const ElfSym *esym = nullptr;
|
2020-11-08 09:56:17 +03:00
|
|
|
InputSection *input_section = nullptr;
|
2021-01-22 09:10:32 +03:00
|
|
|
SectionFragmentRef frag_ref;
|
2020-10-23 06:09:27 +03:00
|
|
|
|
2020-11-26 07:34:42 +03:00
|
|
|
u64 value = -1;
|
2020-11-15 07:01:38 +03:00
|
|
|
u32 got_idx = -1;
|
|
|
|
u32 gotplt_idx = -1;
|
2020-11-21 04:48:51 +03:00
|
|
|
u32 gottpoff_idx = -1;
|
2020-11-21 04:48:23 +03:00
|
|
|
u32 tlsgd_idx = -1;
|
2020-11-15 07:01:38 +03:00
|
|
|
u32 plt_idx = -1;
|
2020-11-15 08:07:40 +03:00
|
|
|
u32 dynsym_idx = -1;
|
2020-12-14 11:27:47 +03:00
|
|
|
u16 shndx = 0;
|
2020-11-28 16:04:23 +03:00
|
|
|
u16 ver_idx = 0;
|
2020-10-30 11:59:45 +03:00
|
|
|
|
2021-01-11 08:47:06 +03:00
|
|
|
std::atomic_uint8_t flags = 0;
|
|
|
|
u8 st_type = STT_NOTYPE;
|
|
|
|
|
2020-11-03 16:24:50 +03:00
|
|
|
tbb::spin_mutex mu;
|
|
|
|
|
2020-12-13 14:18:49 +03:00
|
|
|
u8 is_placeholder : 1 = false;
|
|
|
|
u8 is_imported : 1 = false;
|
|
|
|
u8 is_weak : 1 = false;
|
|
|
|
u8 is_undef_weak : 1 = false;
|
2020-12-20 04:12:10 +03:00
|
|
|
u8 write_symtab : 1 = false;
|
2020-12-13 14:18:49 +03:00
|
|
|
u8 traced : 1 = false;
|
2021-01-14 14:27:32 +03:00
|
|
|
u8 has_relplt : 1 = false;
|
2021-01-14 14:31:39 +03:00
|
|
|
u8 has_copyrel : 1 = false;
|
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
|
|
|
//
|
|
|
|
|
2020-11-08 06:26:40 +03:00
|
|
|
class InputChunk {
|
2020-10-08 11:01:54 +03:00
|
|
|
public:
|
2020-11-17 07:56:40 +03:00
|
|
|
virtual void copy_buf() {}
|
2020-11-29 13:58:02 +03:00
|
|
|
inline u64 get_addr() const;
|
2021-01-22 11:13:52 +03:00
|
|
|
std::string_view get_contents() const;
|
2020-10-23 03:21:40 +03:00
|
|
|
|
2020-10-19 17:37:29 +03:00
|
|
|
ObjectFile *file;
|
2020-12-10 09:59:24 +03:00
|
|
|
const ElfShdr &shdr;
|
2020-11-08 06:26:40 +03:00
|
|
|
OutputSection *output_section = nullptr;
|
2020-11-07 06:14:37 +03:00
|
|
|
|
2020-12-10 07:44:58 +03:00
|
|
|
std::string_view name;
|
2020-11-07 15:53:21 +03:00
|
|
|
u32 offset;
|
2020-11-08 08:13:59 +03:00
|
|
|
|
|
|
|
protected:
|
2020-12-10 09:59:24 +03:00
|
|
|
InputChunk(ObjectFile *file, const ElfShdr &shdr, std::string_view name);
|
2020-11-08 06:26:40 +03:00
|
|
|
};
|
|
|
|
|
2020-12-15 16:24:08 +03:00
|
|
|
enum RelType : u8 {
|
2021-01-16 15:58:28 +03:00
|
|
|
R_NONE = 1,
|
2020-12-15 16:24:08 +03:00
|
|
|
R_ABS,
|
2021-01-13 15:57:12 +03:00
|
|
|
R_ABS_DYN,
|
2020-12-16 14:56:04 +03:00
|
|
|
R_DYN,
|
2020-12-15 16:24:08 +03:00
|
|
|
R_PC,
|
|
|
|
R_GOT,
|
|
|
|
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,
|
2020-12-15 16:24:08 +03:00
|
|
|
R_TPOFF,
|
|
|
|
R_GOTTPOFF,
|
|
|
|
};
|
|
|
|
|
2021-01-25 03:57:02 +03:00
|
|
|
struct EhReloc {
|
2021-01-25 04:42:38 +03:00
|
|
|
Symbol &sym;
|
2021-01-25 03:57:02 +03:00
|
|
|
u32 type;
|
|
|
|
u32 offset;
|
|
|
|
i64 addend;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline bool operator==(const EhReloc &a, const EhReloc &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
|
|
|
}
|
|
|
|
|
|
|
|
struct FdeRecord {
|
2021-01-25 06:25:03 +03:00
|
|
|
FdeRecord(std::string_view contents, std::vector<EhReloc> &&rels)
|
|
|
|
: contents(contents), rels(std::move(rels)) {}
|
|
|
|
|
|
|
|
FdeRecord(const FdeRecord &&other)
|
|
|
|
: contents(other.contents), rels(std::move(other.rels)),
|
2021-01-25 07:30:27 +03:00
|
|
|
offset(other.offset), 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;
|
|
|
|
std::vector<EhReloc> rels;
|
|
|
|
u32 offset = -1;
|
2021-01-25 06:25:03 +03:00
|
|
|
std::atomic_bool is_alive = true;
|
2021-01-25 03:57:02 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CieRecord {
|
|
|
|
bool should_merge(const CieRecord &other) const;
|
|
|
|
|
|
|
|
std::string_view contents;
|
|
|
|
std::vector<EhReloc> rels;
|
|
|
|
std::vector<FdeRecord> fdes;
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
};
|
|
|
|
|
2020-11-08 06:26:40 +03:00
|
|
|
class InputSection : public InputChunk {
|
|
|
|
public:
|
2020-12-10 09:59:24 +03:00
|
|
|
InputSection(ObjectFile *file, const ElfShdr &shdr, std::string_view name)
|
2020-11-29 11:47:51 +03:00
|
|
|
: InputChunk(file, shdr, name) {}
|
2020-11-08 06:26:40 +03:00
|
|
|
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-26 12:09:32 +03:00
|
|
|
void scan_relocations();
|
|
|
|
void report_undefined_symbols();
|
2020-11-08 06:26:40 +03:00
|
|
|
|
2020-12-10 13:54:01 +03:00
|
|
|
std::span<ElfRela> rels;
|
2021-01-24 16:14:51 +03:00
|
|
|
std::vector<bool> has_fragments;
|
2021-01-22 09:10:32 +03:00
|
|
|
std::vector<SectionFragmentRef> rel_fragments;
|
2020-12-15 16:24:08 +03:00
|
|
|
std::vector<RelType> rel_types;
|
2021-01-25 03:57:02 +03:00
|
|
|
std::span<FdeRecord> fdes;
|
2020-12-16 14:56:04 +03:00
|
|
|
u64 reldyn_offset = 0;
|
2020-12-01 15:07:00 +03:00
|
|
|
bool is_comdat_member = false;
|
2021-01-20 12:26:57 +03:00
|
|
|
bool is_ehframe = false;
|
2021-01-16 15:52:49 +03:00
|
|
|
|
2021-01-24 10:12:34 +03:00
|
|
|
bool is_alive = true;
|
|
|
|
std::atomic_bool is_visited = false;
|
|
|
|
|
2021-01-16 15:58:28 +03:00
|
|
|
void apply_reloc_alloc(u8 *base);
|
|
|
|
void apply_reloc_nonalloc(u8 *base);
|
2020-11-08 08:13:59 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
class MergeableSection : public InputChunk {
|
|
|
|
public:
|
2021-01-22 11:13:52 +03:00
|
|
|
MergeableSection(InputSection *isec);
|
2020-11-07 15:53:21 +03:00
|
|
|
|
2020-11-08 08:13:59 +03:00
|
|
|
MergedSection &parent;
|
2021-01-22 09:10:32 +03:00
|
|
|
std::vector<SectionFragment *> fragments;
|
|
|
|
std::vector<u32> frag_offsets;
|
2020-11-08 08:13:59 +03:00
|
|
|
u32 size = 0;
|
2021-01-22 13:24:09 +03:00
|
|
|
u32 padding = 0;
|
2020-10-08 11:01:54 +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
|
|
|
//
|
|
|
|
|
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
|
|
|
|
2020-11-17 07:56:40 +03:00
|
|
|
virtual void copy_buf() {}
|
2020-11-25 11:20:48 +03:00
|
|
|
virtual void update_shdr() {}
|
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;
|
2020-10-26 04:03:17 +03:00
|
|
|
bool starts_new_ptload = false;
|
2021-01-24 05:25:40 +03:00
|
|
|
ElfShdr shdr = { .sh_addralign = 1 };
|
|
|
|
|
|
|
|
protected:
|
|
|
|
OutputChunk(Kind kind) : kind(kind) {}
|
2020-10-12 08:17:34 +03:00
|
|
|
};
|
|
|
|
|
2020-11-16 18:17:01 +03:00
|
|
|
// ELF header
|
|
|
|
class OutputEhdr : public OutputChunk {
|
|
|
|
public:
|
|
|
|
OutputEhdr() : OutputChunk(HEADER) {
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-12-10 15:13:02 +03:00
|
|
|
shdr.sh_size = sizeof(ElfEhdr);
|
2020-11-16 18:17:01 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-16 18:17:01 +03:00
|
|
|
};
|
|
|
|
|
2020-11-16 18:23:51 +03:00
|
|
|
// Section header
|
|
|
|
class OutputShdr : public OutputChunk {
|
|
|
|
public:
|
|
|
|
OutputShdr() : OutputChunk(HEADER) {
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-11-16 18:23:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void update_shdr() override;
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-16 18:23:51 +03:00
|
|
|
};
|
|
|
|
|
2020-11-16 18:33:41 +03:00
|
|
|
// Program header
|
|
|
|
class OutputPhdr : public OutputChunk {
|
2020-10-15 11:06:01 +03:00
|
|
|
public:
|
2020-11-16 18:33:41 +03:00
|
|
|
OutputPhdr() : OutputChunk(HEADER) {
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-11-08 10:05:36 +03:00
|
|
|
}
|
2020-11-16 18:33:41 +03:00
|
|
|
|
|
|
|
void update_shdr() override;
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-10-15 11:06:01 +03:00
|
|
|
};
|
|
|
|
|
2020-11-16 19:05:01 +03:00
|
|
|
class InterpSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
InterpSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".interp";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_PROGBITS;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-11-16 19:05:01 +03:00
|
|
|
shdr.sh_size = config.dynamic_linker.size() + 1;
|
|
|
|
}
|
|
|
|
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-16 19:05:01 +03:00
|
|
|
};
|
|
|
|
|
2020-10-16 10:38:03 +03:00
|
|
|
// Sections
|
2020-10-15 12:30:06 +03:00
|
|
|
class OutputSection : public OutputChunk {
|
|
|
|
public:
|
2021-01-24 06:01:43 +03:00
|
|
|
static OutputSection *get_instance(std::string_view name, u64 type, u64 flags);
|
2020-10-22 10:35:17 +03:00
|
|
|
|
2020-12-10 07:44:58 +03:00
|
|
|
OutputSection(std::string_view name, u32 type, u64 flags)
|
2020-11-08 10:09:01 +03:00
|
|
|
: OutputChunk(REGULAR) {
|
2020-10-22 13:35:16 +03:00
|
|
|
this->name = name;
|
2020-10-25 07:17:10 +03:00
|
|
|
shdr.sh_type = type;
|
2020-11-13 06:43:59 +03:00
|
|
|
shdr.sh_flags = flags;
|
2020-10-28 08:06:35 +03:00
|
|
|
idx = instances.size();
|
|
|
|
instances.push_back(this);
|
2020-10-21 05:28:43 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-10-26 07:34:15 +03:00
|
|
|
|
2020-11-06 15:17:35 +03:00
|
|
|
static inline std::vector<OutputSection *> instances;
|
2020-10-29 12:31:06 +03:00
|
|
|
|
2021-01-17 10:40:35 +03:00
|
|
|
std::vector<InputSection *> members;
|
2020-10-29 12:31:06 +03:00
|
|
|
u32 idx;
|
2020-10-15 12:30:06 +03:00
|
|
|
};
|
|
|
|
|
2020-11-18 11:11:58 +03:00
|
|
|
class GotSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
GotSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".got";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_PROGBITS;
|
|
|
|
shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
|
2020-11-18 11:11:58 +03:00
|
|
|
shdr.sh_addralign = GOT_SIZE;
|
|
|
|
}
|
2020-11-18 14:29:24 +03:00
|
|
|
|
2020-11-21 06:49:28 +03:00
|
|
|
void add_got_symbol(Symbol *sym);
|
2020-11-21 04:48:51 +03:00
|
|
|
void add_gottpoff_symbol(Symbol *sym);
|
2020-11-21 04:48:23 +03:00
|
|
|
void add_tlsgd_symbol(Symbol *sym);
|
2021-01-14 13:58:21 +03:00
|
|
|
void add_tlsld();
|
|
|
|
|
|
|
|
u64 get_tlsld_addr() const {
|
|
|
|
assert(tlsld_idx != -1);
|
|
|
|
return shdr.sh_addr + tlsld_idx * GOT_SIZE;
|
|
|
|
}
|
|
|
|
|
2020-11-18 14:29:24 +03:00
|
|
|
void copy_buf() override;
|
|
|
|
|
|
|
|
std::vector<Symbol *> got_syms;
|
2020-11-21 04:48:51 +03:00
|
|
|
std::vector<Symbol *> gottpoff_syms;
|
2020-11-21 04:48:23 +03:00
|
|
|
std::vector<Symbol *> tlsgd_syms;
|
2021-01-14 13:58:21 +03:00
|
|
|
u32 tlsld_idx = -1;
|
2020-11-18 11:11:58 +03:00
|
|
|
};
|
|
|
|
|
2020-11-13 06:43:59 +03:00
|
|
|
class GotPltSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
GotPltSection() : OutputChunk(SYNTHETIC) {
|
2020-11-16 19:05:01 +03:00
|
|
|
name = ".got.plt";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_PROGBITS;
|
|
|
|
shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
|
2020-11-13 06:43:59 +03:00
|
|
|
shdr.sh_addralign = GOT_SIZE;
|
2020-12-07 10:12:19 +03:00
|
|
|
shdr.sh_size = GOT_SIZE * 3;
|
2020-11-13 06:43:59 +03:00
|
|
|
}
|
|
|
|
|
2020-11-18 15:45:49 +03:00
|
|
|
void copy_buf() override;
|
2020-11-13 06:43:59 +03:00
|
|
|
};
|
|
|
|
|
2020-11-01 11:46:08 +03:00
|
|
|
class PltSection : public OutputChunk {
|
|
|
|
public:
|
2020-11-08 10:05:36 +03:00
|
|
|
PltSection() : OutputChunk(SYNTHETIC) {
|
2020-11-16 19:05:01 +03:00
|
|
|
name = ".plt";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_PROGBITS;
|
|
|
|
shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
|
2020-11-01 11:46:08 +03:00
|
|
|
shdr.sh_addralign = 8;
|
2020-11-13 06:30:27 +03:00
|
|
|
shdr.sh_size = PLT_SIZE;
|
2020-11-01 11:46:08 +03:00
|
|
|
}
|
|
|
|
|
2020-11-18 15:45:49 +03:00
|
|
|
void add_symbol(Symbol *sym);
|
|
|
|
void copy_buf() override;
|
2020-11-17 15:02:14 +03:00
|
|
|
|
2020-11-18 15:45:49 +03:00
|
|
|
std::vector<Symbol *> symbols;
|
2020-11-01 11:46:08 +03:00
|
|
|
};
|
|
|
|
|
2020-11-01 10:22:47 +03:00
|
|
|
class RelPltSection : public OutputChunk {
|
2020-11-01 02:55:13 +03:00
|
|
|
public:
|
2020-11-08 10:05:36 +03:00
|
|
|
RelPltSection() : OutputChunk(SYNTHETIC) {
|
2020-11-16 19:05:01 +03:00
|
|
|
name = ".rela.plt";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_RELA;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-12-10 15:11:10 +03:00
|
|
|
shdr.sh_entsize = sizeof(ElfRela);
|
2020-11-01 02:55:13 +03:00
|
|
|
shdr.sh_addralign = 8;
|
|
|
|
}
|
2020-11-17 07:34:02 +03:00
|
|
|
|
|
|
|
void update_shdr() override;
|
2020-11-18 15:45:49 +03:00
|
|
|
void copy_buf() override;
|
2020-11-01 02:55:13 +03:00
|
|
|
};
|
|
|
|
|
2020-11-17 07:30:33 +03:00
|
|
|
class RelDynSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
RelDynSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".rela.dyn";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_RELA;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-12-10 15:11:10 +03:00
|
|
|
shdr.sh_entsize = sizeof(ElfRela);
|
2020-11-17 07:30:33 +03:00
|
|
|
shdr.sh_addralign = 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
void update_shdr() override;
|
2020-11-18 14:29:24 +03:00
|
|
|
void copy_buf() override;
|
2020-11-17 07:30:33 +03:00
|
|
|
};
|
|
|
|
|
2020-11-12 16:10:47 +03:00
|
|
|
class StrtabSection : public OutputChunk {
|
|
|
|
public:
|
2020-11-19 10:13:19 +03:00
|
|
|
StrtabSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".strtab";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_STRTAB;
|
2020-11-12 16:10:47 +03:00
|
|
|
shdr.sh_size = 1;
|
|
|
|
}
|
|
|
|
|
2020-11-29 12:58:36 +03:00
|
|
|
void update_shdr() override;
|
2020-11-12 16:10:47 +03:00
|
|
|
};
|
|
|
|
|
2020-11-17 06:20:56 +03:00
|
|
|
class ShstrtabSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
ShstrtabSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".shstrtab";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_STRTAB;
|
2020-11-17 06:20:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void update_shdr() override;
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-17 06:20:56 +03:00
|
|
|
};
|
|
|
|
|
2020-11-17 07:19:54 +03:00
|
|
|
class DynstrSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
DynstrSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".dynstr";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_STRTAB;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-11-17 07:19:54 +03:00
|
|
|
shdr.sh_size = 1;
|
|
|
|
}
|
|
|
|
|
2021-01-24 06:01:43 +03:00
|
|
|
i64 add_string(std::string_view str);
|
|
|
|
i64 find_string(std::string_view str);
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-17 07:19:54 +03:00
|
|
|
|
|
|
|
private:
|
2020-12-10 07:44:58 +03:00
|
|
|
std::vector<std::string_view> contents;
|
2020-11-17 07:19:54 +03:00
|
|
|
};
|
|
|
|
|
2020-11-16 18:43:32 +03:00
|
|
|
class DynamicSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
DynamicSection() : OutputChunk(SYNTHETIC) {
|
2020-11-16 19:05:01 +03:00
|
|
|
name = ".dynamic";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_DYNAMIC;
|
|
|
|
shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
|
2020-11-16 18:43:32 +03:00
|
|
|
shdr.sh_addralign = 8;
|
2020-12-10 15:15:47 +03:00
|
|
|
shdr.sh_entsize = sizeof(ElfDyn);
|
2020-11-16 18:43:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void update_shdr() override;
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-16 18:43:32 +03:00
|
|
|
};
|
|
|
|
|
2020-10-27 12:59:56 +03:00
|
|
|
class SymtabSection : public OutputChunk {
|
|
|
|
public:
|
2020-11-17 07:32:22 +03:00
|
|
|
SymtabSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".symtab";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_SYMTAB;
|
2020-12-10 09:10:18 +03:00
|
|
|
shdr.sh_entsize = sizeof(ElfSym);
|
2020-10-27 12:59:56 +03:00
|
|
|
shdr.sh_addralign = 8;
|
2020-12-10 09:10:18 +03:00
|
|
|
shdr.sh_size = sizeof(ElfSym);
|
2020-10-27 12:59:56 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 07:32:22 +03:00
|
|
|
void update_shdr() override;
|
2020-11-17 08:28:53 +03:00
|
|
|
void copy_buf() override;
|
2020-10-27 12:59:56 +03:00
|
|
|
};
|
|
|
|
|
2020-11-16 17:40:01 +03:00
|
|
|
class DynsymSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
DynsymSection() : OutputChunk(SYNTHETIC) {
|
2020-11-16 19:05:01 +03:00
|
|
|
name = ".dynsym";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_DYNSYM;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-12-10 09:10:18 +03:00
|
|
|
shdr.sh_entsize = sizeof(ElfSym);
|
2020-11-16 17:40:01 +03:00
|
|
|
shdr.sh_addralign = 8;
|
2020-12-10 09:10:18 +03:00
|
|
|
shdr.sh_size = sizeof(ElfSym);
|
2020-11-16 17:40:01 +03:00
|
|
|
}
|
|
|
|
|
2020-11-17 14:22:52 +03:00
|
|
|
void add_symbol(Symbol *sym);
|
2021-01-14 11:23:14 +03:00
|
|
|
void sort_symbols();
|
2020-11-16 19:30:24 +03:00
|
|
|
void update_shdr() override;
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2020-11-16 17:40:01 +03:00
|
|
|
|
2021-01-23 09:01:49 +03:00
|
|
|
std::vector<Symbol *> symbols = {nullptr};
|
|
|
|
std::vector<u32> name_indices = {(u32)-1};
|
2020-11-16 17:40:01 +03:00
|
|
|
};
|
|
|
|
|
2020-11-11 15:12:35 +03:00
|
|
|
class HashSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
HashSection() : OutputChunk(SYNTHETIC) {
|
2020-11-16 19:05:01 +03:00
|
|
|
name = ".hash";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_HASH;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-11-11 15:12:35 +03:00
|
|
|
shdr.sh_entsize = 4;
|
|
|
|
shdr.sh_addralign = 4;
|
|
|
|
}
|
|
|
|
|
2020-11-16 18:10:38 +03:00
|
|
|
void update_shdr() override;
|
2020-11-17 07:56:40 +03:00
|
|
|
void copy_buf() override;
|
2021-01-23 09:01:49 +03:00
|
|
|
};
|
2020-11-12 11:15:59 +03:00
|
|
|
|
2021-01-23 09:01:49 +03:00
|
|
|
class GnuHashSection : public OutputChunk {
|
|
|
|
public:
|
2021-01-24 04:28:42 +03:00
|
|
|
GnuHashSection() : OutputChunk(SYNTHETIC) {
|
2021-01-23 09:01:49 +03:00
|
|
|
name = ".gnu.hash";
|
|
|
|
shdr.sh_type = SHT_GNU_HASH;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
|
|
|
shdr.sh_addralign = 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
void update_shdr() override;
|
|
|
|
void copy_buf() override;
|
|
|
|
|
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;
|
|
|
|
static constexpr i64 ELFCLASS_BITS = 64;
|
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
|
|
|
};
|
|
|
|
|
2020-11-07 15:53:21 +03:00
|
|
|
class MergedSection : public OutputChunk {
|
2020-11-07 03:57:23 +03:00
|
|
|
public:
|
2021-01-24 06:01:43 +03:00
|
|
|
static MergedSection *get_instance(std::string_view name, u64 type, u64 flags);
|
2020-11-07 14:29:06 +03:00
|
|
|
|
2020-11-07 15:53:21 +03:00
|
|
|
static inline std::vector<MergedSection *> instances;
|
2021-01-22 10:14:49 +03:00
|
|
|
|
2021-01-22 13:47:11 +03:00
|
|
|
SectionFragment *insert(std::string_view data, u32 alignment) {
|
2021-01-22 11:13:52 +03:00
|
|
|
typename decltype(map)::const_accessor acc;
|
|
|
|
map.insert(acc, std::pair(SectionFragmentKey{data, alignment},
|
|
|
|
SectionFragment(data)));
|
|
|
|
return const_cast<SectionFragment *>(&acc->second);
|
2021-01-22 10:14:49 +03:00
|
|
|
}
|
2020-11-07 04:13:19 +03:00
|
|
|
|
2020-12-13 19:40:23 +03:00
|
|
|
void copy_buf() override;
|
|
|
|
|
2020-11-07 04:13:19 +03:00
|
|
|
private:
|
2020-12-10 07:44:58 +03:00
|
|
|
MergedSection(std::string_view name, u64 flags, u32 type)
|
2020-11-08 10:05:36 +03:00
|
|
|
: OutputChunk(SYNTHETIC) {
|
|
|
|
this->name = name;
|
|
|
|
shdr.sh_flags = flags;
|
|
|
|
shdr.sh_type = type;
|
|
|
|
}
|
2021-01-22 10:14:49 +03:00
|
|
|
|
2021-01-22 11:13:52 +03:00
|
|
|
tbb::concurrent_hash_map<SectionFragmentKey, SectionFragment> map;
|
2020-11-07 03:57:23 +03:00
|
|
|
};
|
|
|
|
|
2021-01-17 10:55:39 +03:00
|
|
|
class EhFrameSection : public OutputChunk {
|
|
|
|
public:
|
2021-01-19 09:16:20 +03:00
|
|
|
EhFrameSection() : OutputChunk(SYNTHETIC) {
|
2021-01-17 10:55:39 +03:00
|
|
|
name = ".eh_frame";
|
2021-01-22 14:28:07 +03:00
|
|
|
shdr.sh_type = SHT_X86_64_UNWIND;
|
2021-01-17 10:55:39 +03:00
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2021-01-18 15:33:04 +03:00
|
|
|
shdr.sh_addralign = 8;
|
2021-01-17 10:55:39 +03:00
|
|
|
}
|
|
|
|
|
2021-01-19 09:16:20 +03:00
|
|
|
void construct();
|
2021-01-17 10:55:39 +03:00
|
|
|
void copy_buf() override;
|
2021-01-20 15:33:49 +03:00
|
|
|
u64 get_addr(const Symbol &sym);
|
2021-01-20 14:47:15 +03:00
|
|
|
|
2021-01-19 09:16:20 +03:00
|
|
|
std::vector<CieRecord *> cies;
|
2021-01-21 15:18:25 +03:00
|
|
|
u32 num_fdes = 0;
|
2021-01-17 10:55:39 +03:00
|
|
|
};
|
|
|
|
|
2021-01-21 01:47:48 +03:00
|
|
|
class EhFrameHdrSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
EhFrameHdrSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".eh_frame_hdr";
|
|
|
|
shdr.sh_type = SHT_PROGBITS;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
|
|
|
shdr.sh_addralign = 4;
|
|
|
|
shdr.sh_size = HEADER_SIZE;
|
|
|
|
}
|
|
|
|
|
2021-01-24 06:01:43 +03:00
|
|
|
static constexpr i64 HEADER_SIZE = 12;
|
2021-01-21 01:47:48 +03:00
|
|
|
};
|
|
|
|
|
2020-11-25 11:20:48 +03:00
|
|
|
class CopyrelSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
CopyrelSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".bss";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_NOBITS;
|
|
|
|
shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
|
2020-11-25 11:20:48 +03:00
|
|
|
shdr.sh_addralign = 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
void add_symbol(Symbol *sym);
|
|
|
|
|
|
|
|
std::vector<Symbol *> symbols;
|
|
|
|
};
|
|
|
|
|
2020-11-27 11:32:25 +03:00
|
|
|
class VersymSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
VersymSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".gnu.version";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_GNU_VERSYM;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-11-29 10:37:14 +03:00
|
|
|
shdr.sh_entsize = 2;
|
2020-11-27 11:32:25 +03:00
|
|
|
shdr.sh_addralign = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void update_shdr() override;
|
|
|
|
void copy_buf() override;
|
2020-11-29 05:40:57 +03:00
|
|
|
|
|
|
|
std::vector<u16> contents;
|
2020-11-27 11:32:25 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
class VerneedSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
VerneedSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".gnu.version_r";
|
2020-12-10 15:38:37 +03:00
|
|
|
shdr.sh_type = SHT_GNU_VERNEED;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
2020-11-29 07:42:27 +03:00
|
|
|
shdr.sh_addralign = 8;
|
2020-11-27 11:32:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void update_shdr() override;
|
|
|
|
void copy_buf() override;
|
2020-11-29 05:40:57 +03:00
|
|
|
|
|
|
|
std::vector<u8> contents;
|
2020-11-27 11:32:25 +03:00
|
|
|
};
|
|
|
|
|
2021-01-15 14:14:01 +03:00
|
|
|
class BuildIdSection : public OutputChunk {
|
|
|
|
public:
|
|
|
|
BuildIdSection() : OutputChunk(SYNTHETIC) {
|
|
|
|
name = ".note.gnu.build-id";
|
|
|
|
shdr.sh_type = SHT_NOTE;
|
|
|
|
shdr.sh_flags = SHF_ALLOC;
|
|
|
|
shdr.sh_addralign = 4;
|
2021-01-15 16:34:52 +03:00
|
|
|
shdr.sh_size = 16 + SHA256_SIZE;
|
2021-01-15 14:14:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void copy_buf() override;
|
2021-01-24 05:41:36 +03:00
|
|
|
void write_buildid(u8 *digest);
|
2021-01-15 14:14:01 +03:00
|
|
|
};
|
|
|
|
|
2020-12-10 07:44:58 +03:00
|
|
|
bool is_c_identifier(std::string_view name);
|
2020-12-10 15:13:02 +03:00
|
|
|
std::vector<ElfPhdr> create_phdr();
|
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
|
|
|
//
|
|
|
|
|
2020-10-23 02:40:54 +03:00
|
|
|
struct ComdatGroup {
|
2021-01-24 04:28:42 +03:00
|
|
|
ComdatGroup() = default;
|
2020-10-23 02:40:54 +03:00
|
|
|
ComdatGroup(const ComdatGroup &other)
|
2021-01-24 04:28:42 +03:00
|
|
|
: owner(other.owner.load()), section_idx(other.section_idx) {}
|
2020-10-23 02:40:54 +03:00
|
|
|
|
2021-01-24 04:28:42 +03:00
|
|
|
std::atomic<ObjectFile *> owner = nullptr;
|
|
|
|
u32 section_idx = -1;
|
2020-10-23 02:40:54 +03:00
|
|
|
};
|
|
|
|
|
2020-12-22 10:33:44 +03:00
|
|
|
class MemoryMappedFile {
|
|
|
|
public:
|
2020-12-22 12:33:16 +03:00
|
|
|
static MemoryMappedFile *open(std::string path);
|
|
|
|
static MemoryMappedFile *must_open(std::string path);
|
|
|
|
|
|
|
|
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
|
|
|
MemoryMappedFile() = delete;
|
2020-12-22 10:33:44 +03:00
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
MemoryMappedFile *slice(std::string name, u64 start, u64 size);
|
2020-12-22 10:33:44 +03:00
|
|
|
|
|
|
|
u8 *data();
|
2021-01-24 06:01:43 +03:00
|
|
|
i64 size() const { return size_; }
|
|
|
|
|
|
|
|
std::string_view get_contents() {
|
|
|
|
return std::string_view((char *)data(), size());
|
|
|
|
}
|
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:
|
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
|
|
|
};
|
|
|
|
|
2020-11-24 10:22:32 +03:00
|
|
|
class InputFile {
|
|
|
|
public:
|
2020-12-22 11:37:49 +03:00
|
|
|
InputFile(MemoryMappedFile *mb);
|
2021-01-12 15:17:53 +03:00
|
|
|
InputFile() : name("<internal>") {}
|
2020-11-24 10:22:32 +03:00
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
MemoryMappedFile *mb;
|
2020-12-12 06:36:16 +03:00
|
|
|
std::span<ElfShdr> elf_sections;
|
2020-11-24 10:22:32 +03:00
|
|
|
std::vector<Symbol *> 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;
|
2020-12-12 06:38:30 +03:00
|
|
|
|
2020-12-22 10:33:44 +03:00
|
|
|
std::string_view get_string(const ElfShdr &shdr);
|
2021-01-24 06:01:43 +03:00
|
|
|
std::string_view get_string(i64 idx);
|
2020-12-12 06:38:30 +03:00
|
|
|
|
2020-12-12 06:46:24 +03:00
|
|
|
protected:
|
2020-12-22 10:33:44 +03:00
|
|
|
template<typename T> std::span<T> get_data(const ElfShdr &shdr);
|
2021-01-24 06:01:43 +03:00
|
|
|
template<typename T> std::span<T> get_data(i64 idx);
|
|
|
|
ElfShdr *find_section(i64 type);
|
2021-01-12 15:17:53 +03:00
|
|
|
|
|
|
|
std::string_view shstrtab;
|
2020-11-24 10:22:32 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
class ObjectFile : public InputFile {
|
2020-10-04 12:00:33 +03:00
|
|
|
public:
|
2020-12-22 11:37:49 +03:00
|
|
|
ObjectFile(MemoryMappedFile *mb, std::string archive_name);
|
2021-01-12 15:17:53 +03:00
|
|
|
ObjectFile();
|
2020-10-04 12:00:33 +03:00
|
|
|
|
2020-12-19 12:31:46 +03:00
|
|
|
void parse();
|
2020-11-05 06:20:16 +03:00
|
|
|
void resolve_symbols();
|
2021-01-24 07:34:12 +03:00
|
|
|
void mark_live_objects(std::function<void(ObjectFile *)> feeder);
|
2020-11-19 10:09:07 +03:00
|
|
|
void handle_undefined_weak_symbols();
|
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-01-25 04:03:34 +03:00
|
|
|
void scan_relocations();
|
2020-10-27 06:50:25 +03:00
|
|
|
void convert_common_symbols();
|
2020-10-27 14:58:28 +03:00
|
|
|
void compute_symtab();
|
2020-11-29 12:31:19 +03:00
|
|
|
void write_symtab();
|
2021-01-25 07:30:27 +03:00
|
|
|
void kill(i64 shndx);
|
2020-10-27 13:03:57 +03:00
|
|
|
|
2020-11-17 07:48:11 +03:00
|
|
|
static ObjectFile *create_internal_file();
|
2020-11-03 13:33:46 +03:00
|
|
|
|
2020-12-13 12:26:23 +03:00
|
|
|
std::string archive_name;
|
2020-11-08 06:10:08 +03:00
|
|
|
std::vector<InputSection *> sections;
|
2020-12-10 12:23:13 +03:00
|
|
|
std::span<ElfSym> elf_syms;
|
2021-01-24 06:01:43 +03:00
|
|
|
i64 first_global = 0;
|
2021-01-12 15:17:53 +03:00
|
|
|
const bool is_in_archive = false;
|
2021-01-19 08:36:26 +03:00
|
|
|
std::vector<CieRecord> cies;
|
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;
|
2020-10-29 10:27:11 +03:00
|
|
|
u64 local_symtab_size = 0;
|
2020-11-29 12:45:33 +03:00
|
|
|
u64 global_symtab_offset = 0;
|
2020-10-29 10:27:11 +03:00
|
|
|
u64 global_symtab_size = 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-12-13 19:12:55 +03:00
|
|
|
std::vector<MergeableSection *> mergeable_sections;
|
2020-11-07 15:53:21 +03:00
|
|
|
|
2020-10-09 14:47:45 +03:00
|
|
|
private:
|
2020-10-19 14:05:34 +03:00
|
|
|
void initialize_sections();
|
|
|
|
void initialize_symbols();
|
2021-01-19 08:36:26 +03:00
|
|
|
void initialize_mergeable_sections();
|
2021-01-20 16:41:32 +03:00
|
|
|
void initialize_ehframe_sections();
|
2021-01-19 08:36:26 +03:00
|
|
|
void read_ehframe(InputSection &isec);
|
2021-01-24 06:01:43 +03:00
|
|
|
void maybe_override_symbol(Symbol &sym, i64 symidx);
|
2020-10-19 14:05:34 +03:00
|
|
|
|
2020-12-10 14:11:45 +03:00
|
|
|
std::vector<std::pair<ComdatGroup *, std::span<u32>>> comdat_groups;
|
2021-01-22 09:10:32 +03:00
|
|
|
std::vector<SectionFragmentRef> sym_fragments;
|
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;
|
2020-12-10 09:59:24 +03:00
|
|
|
const ElfShdr *symtab_sec;
|
2020-10-04 12:00:33 +03:00
|
|
|
};
|
|
|
|
|
2020-11-24 10:22:32 +03:00
|
|
|
class SharedFile : public InputFile {
|
|
|
|
public:
|
2020-12-22 11:37:49 +03:00
|
|
|
SharedFile(MemoryMappedFile *mb, bool as_needed) : InputFile(mb) {
|
2020-11-30 10:43:47 +03:00
|
|
|
is_alive = !as_needed;
|
|
|
|
}
|
2020-11-24 10:22:32 +03:00
|
|
|
|
2020-12-19 12:31:46 +03:00
|
|
|
void parse();
|
2020-11-24 10:22:32 +03:00
|
|
|
void resolve_symbols();
|
2020-12-10 14:12:43 +03:00
|
|
|
std::span<Symbol *> find_aliases(Symbol *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;
|
2020-11-24 10:22:32 +03:00
|
|
|
|
|
|
|
private:
|
2020-12-13 14:40:01 +03:00
|
|
|
std::string_view get_soname();
|
2020-12-10 09:10:18 +03:00
|
|
|
void maybe_override_symbol(Symbol &sym, const ElfSym &esym);
|
2020-12-10 07:44:58 +03:00
|
|
|
std::vector<std::string_view> read_verdef();
|
2020-11-24 10:22:32 +03:00
|
|
|
|
2020-12-10 09:10:18 +03:00
|
|
|
std::vector<const ElfSym *> elf_syms;
|
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;
|
2020-12-10 09:59:24 +03:00
|
|
|
const ElfShdr *symtab_sec;
|
2020-11-24 10:22:32 +03:00
|
|
|
};
|
|
|
|
|
2021-01-10 11:30:39 +03:00
|
|
|
inline std::ostream &operator<<(std::ostream &out, const InputChunk &isec) {
|
|
|
|
out << *isec.file << ":(" << isec.name << ")";
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2020-12-13 15:06:25 +03:00
|
|
|
//
|
|
|
|
// archive_file.cc
|
|
|
|
//
|
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
std::vector<MemoryMappedFile *> read_archive_members(MemoryMappedFile *mb);
|
2020-12-22 14:10:04 +03:00
|
|
|
std::vector<MemoryMappedFile *> read_fat_archive_members(MemoryMappedFile *mb);
|
|
|
|
std::vector<MemoryMappedFile *> read_thin_archive_members(MemoryMappedFile *mb);
|
2020-12-12 06:48:00 +03:00
|
|
|
|
2020-11-29 04:31:04 +03:00
|
|
|
//
|
|
|
|
// linker_script.cc
|
|
|
|
//
|
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
void parse_linker_script(MemoryMappedFile *mb, bool as_needed);
|
2020-12-10 07:44:58 +03:00
|
|
|
void parse_version_script(std::string path);
|
2020-11-29 04:31:04 +03:00
|
|
|
|
2021-01-09 11:07:19 +03:00
|
|
|
//
|
|
|
|
// output_file.cc
|
|
|
|
//
|
|
|
|
|
|
|
|
class OutputFile {
|
|
|
|
public:
|
|
|
|
static OutputFile *open(std::string path, u64 filesize);
|
|
|
|
virtual void close() = 0;
|
|
|
|
|
|
|
|
u8 *buf;
|
|
|
|
static inline char *tmpfile;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
OutputFile(std::string path, u64 filesize) : path(path), filesize(filesize) {}
|
|
|
|
|
|
|
|
std::string path;
|
|
|
|
u64 filesize;
|
|
|
|
};
|
|
|
|
|
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-25 09:23:04 +03:00
|
|
|
void inc(i64 delta = 1) {
|
2020-11-29 04:31:04 +03:00
|
|
|
if (enabled)
|
2021-01-25 09:23:04 +03:00
|
|
|
values.local() += delta;
|
2020-11-29 04:31:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void print();
|
2021-01-09 13:02:03 +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 {
|
|
|
|
TimerRecord(std::string name);
|
2020-12-11 10:51:20 +03:00
|
|
|
void stop();
|
|
|
|
|
|
|
|
std::string name;
|
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-01-09 12:15:09 +03:00
|
|
|
class Timer {
|
|
|
|
public:
|
|
|
|
Timer(std::string name);
|
|
|
|
~Timer();
|
|
|
|
void stop();
|
|
|
|
static void print();
|
|
|
|
|
|
|
|
private:
|
|
|
|
static inline std::vector<TimerRecord *> records;
|
|
|
|
TimerRecord *record;
|
|
|
|
};
|
|
|
|
|
2021-01-24 10:12:34 +03:00
|
|
|
//
|
|
|
|
// gc_sections.cc
|
|
|
|
//
|
|
|
|
|
|
|
|
void gc_sections();
|
|
|
|
|
2020-11-29 04:31:04 +03:00
|
|
|
//
|
|
|
|
// mapfile.cc
|
|
|
|
//
|
|
|
|
|
|
|
|
void print_map();
|
|
|
|
|
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-01-24 06:01:43 +03:00
|
|
|
bool resume_daemon(char **argv, i64 *code);
|
2021-01-09 15:21:45 +03:00
|
|
|
void daemonize(char **argv, std::function<void()> *wait_for_client,
|
|
|
|
std::function<void()> *on_complete);
|
|
|
|
|
2020-11-29 04:31:04 +03:00
|
|
|
//
|
|
|
|
// main.cc
|
|
|
|
//
|
|
|
|
|
2020-12-22 11:37:49 +03:00
|
|
|
MemoryMappedFile *find_library(std::string path, std::span<std::string_view> lib_paths);
|
|
|
|
void read_file(MemoryMappedFile *mb, bool as_needed);
|
2020-11-29 04:31:04 +03:00
|
|
|
|
|
|
|
//
|
|
|
|
// Inline objects and functions
|
|
|
|
//
|
|
|
|
|
|
|
|
namespace out {
|
|
|
|
inline std::vector<ObjectFile *> objs;
|
|
|
|
inline std::vector<SharedFile *> dsos;
|
|
|
|
inline std::vector<OutputChunk *> chunks;
|
|
|
|
inline u8 *buf;
|
|
|
|
|
2021-01-13 09:42:07 +03:00
|
|
|
inline ObjectFile *internal_file;
|
|
|
|
|
2020-11-29 04:31:04 +03:00
|
|
|
inline OutputEhdr *ehdr;
|
|
|
|
inline OutputShdr *shdr;
|
|
|
|
inline OutputPhdr *phdr;
|
|
|
|
inline InterpSection *interp;
|
|
|
|
inline GotSection *got;
|
|
|
|
inline GotPltSection *gotplt;
|
|
|
|
inline RelPltSection *relplt;
|
|
|
|
inline RelDynSection *reldyn;
|
|
|
|
inline DynamicSection *dynamic;
|
|
|
|
inline StrtabSection *strtab;
|
|
|
|
inline DynstrSection *dynstr;
|
|
|
|
inline HashSection *hash;
|
2021-01-23 09:01:49 +03:00
|
|
|
inline GnuHashSection *gnu_hash;
|
2020-11-29 04:31:04 +03:00
|
|
|
inline ShstrtabSection *shstrtab;
|
|
|
|
inline PltSection *plt;
|
|
|
|
inline SymtabSection *symtab;
|
|
|
|
inline DynsymSection *dynsym;
|
2021-01-21 01:47:48 +03:00
|
|
|
inline EhFrameSection *eh_frame;
|
|
|
|
inline EhFrameHdrSection *eh_frame_hdr;
|
2020-11-29 04:31:04 +03:00
|
|
|
inline CopyrelSection *copyrel;
|
2020-11-29 05:57:58 +03:00
|
|
|
inline VersymSection *versym;
|
|
|
|
inline VerneedSection *verneed;
|
2021-01-15 14:14:01 +03:00
|
|
|
inline BuildIdSection *buildid;
|
2020-11-29 04:31:04 +03:00
|
|
|
|
2021-01-14 07:19:21 +03:00
|
|
|
inline u64 tls_begin;
|
2020-11-29 04:31:04 +03:00
|
|
|
inline u64 tls_end;
|
|
|
|
|
|
|
|
inline Symbol *__bss_start;
|
|
|
|
inline Symbol *__ehdr_start;
|
|
|
|
inline Symbol *__rela_iplt_start;
|
|
|
|
inline Symbol *__rela_iplt_end;
|
|
|
|
inline Symbol *__init_array_start;
|
|
|
|
inline Symbol *__init_array_end;
|
|
|
|
inline Symbol *__fini_array_start;
|
|
|
|
inline Symbol *__fini_array_end;
|
|
|
|
inline Symbol *__preinit_array_start;
|
|
|
|
inline Symbol *__preinit_array_end;
|
|
|
|
inline Symbol *_DYNAMIC;
|
|
|
|
inline Symbol *_GLOBAL_OFFSET_TABLE_;
|
|
|
|
inline Symbol *_end;
|
|
|
|
inline Symbol *_etext;
|
|
|
|
inline Symbol *_edata;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline u64 align_to(u64 val, u64 align) {
|
2021-01-22 13:24:09 +03:00
|
|
|
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) {
|
|
|
|
if (!val)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
val--;
|
|
|
|
val |= val >> 1;
|
|
|
|
val |= val >> 2;
|
|
|
|
val |= val >> 4;
|
|
|
|
val |= val >> 8;
|
|
|
|
val |= val >> 16;
|
|
|
|
val |= val >> 32;
|
|
|
|
return val + 1;
|
|
|
|
}
|
|
|
|
|
2021-01-13 09:42:07 +03:00
|
|
|
inline bool Symbol::is_absolute() const {
|
|
|
|
return input_section == nullptr && file != out::internal_file;
|
|
|
|
}
|
|
|
|
|
2020-11-15 08:07:40 +03:00
|
|
|
inline u64 Symbol::get_addr() const {
|
2021-01-25 07:47:48 +03:00
|
|
|
if (frag_ref.frag) {
|
|
|
|
if (frag_ref.frag->is_alive)
|
|
|
|
return frag_ref.frag->get_addr() + frag_ref.addend;
|
|
|
|
return 0; // todo: do not return 0
|
|
|
|
}
|
2020-12-01 15:43:30 +03:00
|
|
|
|
2021-01-14 14:31:39 +03:00
|
|
|
if (has_copyrel)
|
|
|
|
return out::copyrel->shdr.sh_addr + value;
|
2020-12-01 15:43:30 +03:00
|
|
|
|
2020-12-01 11:16:28 +03:00
|
|
|
if (input_section) {
|
2021-01-20 14:47:15 +03:00
|
|
|
if (input_section->is_ehframe)
|
2021-01-21 01:47:48 +03:00
|
|
|
return out::eh_frame->get_addr(*this);
|
2021-01-20 14:47:15 +03:00
|
|
|
|
2020-12-01 15:43:30 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-11-25 09:13:06 +03:00
|
|
|
return input_section->get_addr() + value;
|
2020-12-01 11:16:28 +03:00
|
|
|
}
|
2020-12-01 15:43:30 +03:00
|
|
|
|
2021-01-12 06:35:24 +03:00
|
|
|
if (file && file->is_dso)
|
2020-11-26 07:34:42 +03:00
|
|
|
return get_plt_addr();
|
2020-12-01 15:43:30 +03:00
|
|
|
|
2020-11-15 08:07:40 +03:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline u64 Symbol::get_got_addr() const {
|
|
|
|
assert(got_idx != -1);
|
2020-11-17 14:47:22 +03:00
|
|
|
return out::got->shdr.sh_addr + got_idx * GOT_SIZE;
|
2020-11-15 08:07:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
inline u64 Symbol::get_gotplt_addr() const {
|
|
|
|
assert(gotplt_idx != -1);
|
2020-11-17 14:47:22 +03:00
|
|
|
return out::gotplt->shdr.sh_addr + gotplt_idx * GOT_SIZE;
|
2020-11-15 08:07:40 +03:00
|
|
|
}
|
|
|
|
|
2020-11-21 04:48:51 +03:00
|
|
|
inline u64 Symbol::get_gottpoff_addr() const {
|
|
|
|
assert(gottpoff_idx != -1);
|
|
|
|
return out::got->shdr.sh_addr + gottpoff_idx * GOT_SIZE;
|
2020-11-15 08:07:40 +03:00
|
|
|
}
|
|
|
|
|
2020-11-21 04:48:23 +03:00
|
|
|
inline u64 Symbol::get_tlsgd_addr() const {
|
|
|
|
assert(tlsgd_idx != -1);
|
|
|
|
return out::got->shdr.sh_addr + tlsgd_idx * GOT_SIZE;
|
2020-11-15 08:07:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
inline u64 Symbol::get_plt_addr() const {
|
|
|
|
assert(plt_idx != -1);
|
2020-11-17 14:47:22 +03:00
|
|
|
return out::plt->shdr.sh_addr + plt_idx * PLT_SIZE;
|
2020-11-15 08:07:40 +03:00
|
|
|
}
|
|
|
|
|
2021-01-22 09:10:32 +03:00
|
|
|
inline u64 SectionFragment::get_addr() const {
|
2021-01-25 07:47:48 +03:00
|
|
|
if (!is_alive)
|
|
|
|
return 0; // todo: remove
|
|
|
|
|
2020-11-15 08:07:40 +03:00
|
|
|
MergeableSection *is = isec.load();
|
2021-01-22 14:35:33 +03:00
|
|
|
return is->parent.shdr.sh_addr + is->offset + offset;
|
2020-11-15 08:07:40 +03:00
|
|
|
}
|
|
|
|
|
2020-11-25 09:13:06 +03:00
|
|
|
inline u64 InputChunk::get_addr() const {
|
|
|
|
return output_section->shdr.sh_addr + offset;
|
|
|
|
}
|
|
|
|
|
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-01-23 09:01:49 +03:00
|
|
|
inline u32 gnu_hash(std::string_view name) {
|
|
|
|
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);
|
|
|
|
}
|