1
1
mirror of https://github.com/rui314/mold.git synced 2024-10-05 09:07:10 +03:00
mold/mold.h

648 lines
14 KiB
C
Raw Normal View History

2020-10-04 12:00:33 +03:00
#pragma once
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
2020-10-09 14:47:45 +03:00
#include "llvm/BinaryFormat/Magic.h"
2020-10-10 06:47:12 +03:00
#include "llvm/Object/Archive.h"
2020-10-09 14:47:45 +03:00
#include "llvm/Object/ELF.h"
2020-10-04 12:00:33 +03:00
#include "llvm/Object/ELFTypes.h"
2020-10-12 07:30:34 +03:00
#include "llvm/Option/ArgList.h"
2020-10-04 12:00:33 +03:00
#include "llvm/Support/Error.h"
2020-10-10 12:48:38 +03:00
#include "llvm/Support/FileOutputBuffer.h"
2020-10-29 06:24:54 +03:00
#include "llvm/Support/Format.h"
2020-10-04 12:00:33 +03:00
#include "llvm/Support/MemoryBuffer.h"
2020-10-10 10:49:02 +03:00
#include "llvm/Support/Timer.h"
2020-10-11 12:18:19 +03:00
#include "tbb/blocked_range.h"
2020-10-09 14:47:45 +03:00
#include "tbb/concurrent_hash_map.h"
2020-10-18 07:34:37 +03:00
#include "tbb/concurrent_unordered_set.h"
2020-10-22 09:47:13 +03:00
#include "tbb/concurrent_vector.h"
2020-10-26 13:51:06 +03:00
#include "tbb/global_control.h"
2020-10-10 10:49:02 +03:00
#include "tbb/parallel_for_each.h"
2020-10-26 07:34:15 +03:00
#include "tbb/parallel_reduce.h"
2020-10-10 13:46:01 +03:00
#include "tbb/parallel_sort.h"
2020-10-11 12:18:19 +03:00
#include "tbb/partitioner.h"
2020-10-28 13:49:58 +03:00
#include "tbb/spin_mutex.h"
2020-10-26 13:51:06 +03:00
#include "tbb/task_arena.h"
2020-10-24 12:58:21 +03:00
#include "tbb/task_group.h"
2020-10-04 12:00:33 +03:00
2020-10-19 17:37:29 +03:00
#include <algorithm>
2020-10-10 13:15:16 +03:00
#include <atomic>
2020-10-30 06:47:35 +03:00
#include <bitset>
2020-10-04 12:00:33 +03:00
#include <cstdint>
2020-10-15 13:55:51 +03:00
#include <cstdlib>
#include <cstring>
2020-10-21 05:55:03 +03:00
#include <mutex>
2020-10-22 10:11:28 +03:00
#include <shared_mutex>
2020-10-04 12:00:33 +03:00
#include <string>
2020-10-24 12:58:21 +03:00
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>
2020-10-14 12:58:47 +03:00
#include <unordered_set>
2020-10-29 10:41:17 +03:00
#include <valarray>
2020-10-28 09:18:31 +03:00
#include <xmmintrin.h>
2020-10-04 12:00:33 +03:00
2020-10-25 08:28:50 +03:00
#define SECTOR_SIZE 512
2020-10-25 08:11:39 +03:00
#define PAGE_SIZE 4096
2020-10-29 16:32:55 +03:00
typedef uint8_t u8;
2020-10-29 14:16:20 +03:00
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
2020-10-30 05:40:38 +03:00
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
2020-10-04 12:00:33 +03:00
using llvm::ArrayRef;
2020-10-09 14:47:45 +03:00
using llvm::ErrorOr;
2020-10-10 06:47:12 +03:00
using llvm::Error;
2020-10-04 12:00:33 +03:00
using llvm::Expected;
using llvm::MemoryBufferRef;
using llvm::SmallVector;
using llvm::StringRef;
using llvm::Twine;
using llvm::object::ELF64LE;
2020-10-09 14:47:45 +03:00
using llvm::object::ELFFile;
2020-10-04 12:00:33 +03:00
2020-10-08 11:01:54 +03:00
class Symbol;
class ObjectFile;
class InputSection;
2020-10-04 12:00:33 +03:00
struct Config {
StringRef output;
2020-10-28 14:49:43 +03:00
bool print_map = false;
2020-10-04 12:00:33 +03:00
};
extern Config config;
[[noreturn]] inline void error(const Twine &msg) {
2020-10-27 09:10:34 +03:00
static std::mutex mu;
2020-10-28 13:51:49 +03:00
std::lock_guard lock(mu);
2020-10-27 09:10:34 +03:00
2020-10-04 12:00:33 +03:00
llvm::errs() << msg << "\n";
exit(1);
}
2020-10-09 14:47:45 +03:00
template <class T> T check(ErrorOr<T> e) {
if (auto ec = e.getError())
error(ec.message());
return std::move(*e);
}
template <class T> T check(Expected<T> e) {
if (!e)
error(llvm::toString(e.takeError()));
return std::move(*e);
}
template <class T>
T check2(ErrorOr<T> e, llvm::function_ref<std::string()> prefix) {
if (auto ec = e.getError())
error(prefix() + ": " + ec.message());
return std::move(*e);
}
template <class T>
T check2(Expected<T> e, llvm::function_ref<std::string()> prefix) {
if (!e)
error(prefix() + ": " + toString(e.takeError()));
return std::move(*e);
}
inline std::string toString(const Twine &s) { return s.str(); }
#define CHECK(E, S) check2((E), [&] { return toString(S); })
class Symbol;
class SymbolTable;
class InputSection;
2020-10-19 12:13:55 +03:00
class OutputSection;
2020-10-09 14:47:45 +03:00
class ObjectFile;
2020-10-19 15:32:57 +03:00
std::string toString(ObjectFile *);
2020-10-20 03:20:52 +03:00
template<typename T, typename Callable>
static void for_each(T &arr, Callable callback) {
2020-10-29 09:30:41 +03:00
#if 1
2020-10-20 03:20:52 +03:00
tbb::parallel_for_each(arr.begin(), arr.end(), callback);
2020-10-28 13:27:23 +03:00
#else
std::for_each(arr.begin(), arr.end(), callback);
#endif
2020-10-20 03:20:52 +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 {
template<>
struct tbb_hash_compare<StringRef> {
static size_t hash(const StringRef& k) {
return llvm::hash_value(k);
}
static bool equal(const StringRef& k1, const StringRef& k2) {
return k1 == k2;
}
};
}
2020-10-19 15:32:57 +03:00
template<typename ValueT>
class ConcurrentMap {
public:
typedef tbb::concurrent_hash_map<StringRef, ValueT> MapT;
ValueT *insert(StringRef key, const ValueT &val) {
2020-10-28 03:39:31 +03:00
typename MapT::const_accessor acc;
2020-10-19 15:32:57 +03:00
map.insert(acc, std::make_pair(key, val));
2020-10-28 03:39:31 +03:00
return const_cast<ValueT *>(&acc->second);
2020-10-19 15:32:57 +03:00
}
private:
MapT map;
};
//
// Symbol
//
2020-10-12 07:30:34 +03:00
class Symbol {
public:
2020-10-29 10:48:17 +03:00
Symbol(StringRef name) : name(name) {}
Symbol(const Symbol &other) : name(other.name), file(other.file) {}
2020-10-12 07:30:34 +03:00
2020-10-25 08:42:44 +03:00
static Symbol *intern(StringRef name) {
static ConcurrentMap<Symbol> map;
return map.insert(name, Symbol(name));
}
2020-10-18 14:19:57 +03:00
StringRef name;
ObjectFile *file = nullptr;
2020-10-26 16:07:51 +03:00
InputSection *input_section = nullptr;
2020-10-23 06:09:27 +03:00
u64 addr = 0;
2020-10-31 13:33:34 +03:00
uint32_t got_offset = ATOMIC_VAR_INIT(0);
uint32_t gotplt_offset = ATOMIC_VAR_INIT(0);
uint32_t gottp_offset = ATOMIC_VAR_INIT(0);
uint32_t plt_offset = ATOMIC_VAR_INIT(0);
2020-10-30 11:59:45 +03:00
2020-10-30 12:03:24 +03:00
tbb::spin_mutex mu;
2020-10-29 16:32:55 +03:00
u8 visibility = 0;
2020-10-30 09:54:12 +03:00
bool is_weak = false;
2020-10-30 10:00:25 +03:00
bool is_undef_weak = false;
2020-10-12 07:30:34 +03:00
};
2020-10-19 15:32:57 +03:00
inline std::string toString(Symbol sym) {
return (StringRef(sym.name) + "(" + toString(sym.file) + ")").str();
}
2020-10-18 13:00:39 +03:00
2020-10-12 07:30:34 +03:00
//
2020-10-20 09:33:40 +03:00
// input_chunks.cc
2020-10-12 07:30:34 +03:00
//
2020-10-25 03:26:51 +03:00
class InputSection {
2020-10-08 11:01:54 +03:00
public:
2020-10-25 07:17:10 +03:00
InputSection(ObjectFile *file, const ELF64LE::Shdr &shdr, StringRef name);
2020-10-23 03:21:40 +03:00
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf);
void relocate(u8 *buf);
2020-10-31 13:33:34 +03:00
std::tuple<i32, i32, i32> scan_relocations();
2020-10-23 03:21:40 +03:00
2020-10-19 17:37:29 +03:00
ObjectFile *file;
2020-10-22 12:29:35 +03:00
OutputSection *output_section;
2020-10-20 04:32:32 +03:00
ArrayRef<ELF64LE::Rela> rels;
2020-10-25 07:17:10 +03:00
const ELF64LE::Shdr &shdr;
2020-10-25 03:26:51 +03:00
StringRef name;
u64 offset;
2020-10-08 11:01:54 +03:00
};
2020-10-19 17:37:29 +03:00
std::string toString(InputSection *isec);
inline u64 align_to(u64 val, u64 align) {
2020-10-19 17:37:29 +03:00
assert(__builtin_popcount(align) == 1);
return (val + align - 1) & ~(align - 1);
}
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-10-25 08:17:05 +03:00
OutputChunk() { shdr.sh_addralign = 1; }
2020-10-29 16:32:55 +03:00
virtual void copy_to(u8 *buf) = 0;
virtual void relocate(u8 *buf) {}
2020-10-25 09:17:43 +03:00
2020-10-28 10:32:33 +03:00
bool is_bss() const { return shdr.sh_type == llvm::ELF::SHT_NOBITS; }
2020-10-13 14:35:35 +03:00
virtual u64 get_size() const = 0;
2020-10-25 09:17:43 +03:00
2020-10-22 13:35:16 +03:00
StringRef name;
2020-10-29 09:30:41 +03:00
int shndx = 0;
2020-10-26 04:03:17 +03:00
bool starts_new_ptload = false;
2020-10-25 07:17:10 +03:00
ELF64LE::Shdr shdr = {};
2020-10-29 12:31:06 +03:00
std::vector<InputSection *> sections;
2020-10-12 08:17:34 +03:00
};
2020-10-16 10:38:03 +03:00
// ELF header
2020-10-15 12:30:06 +03:00
class OutputEhdr : public OutputChunk {
2020-10-15 11:06:01 +03:00
public:
2020-10-25 07:17:10 +03:00
OutputEhdr() { shdr.sh_flags = llvm::ELF::SHF_ALLOC; }
2020-10-25 06:41:31 +03:00
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {}
void relocate(u8 *buf) override;
2020-10-16 10:38:03 +03:00
u64 get_size() const override {
2020-10-17 07:00:53 +03:00
return sizeof(ELF64LE::Ehdr);
2020-10-16 10:38:03 +03:00
}
2020-10-15 11:06:01 +03:00
};
2020-10-16 10:38:03 +03:00
// Section header
2020-10-15 12:30:06 +03:00
class OutputShdr : public OutputChunk {
2020-10-15 11:06:01 +03:00
public:
2020-10-25 07:17:10 +03:00
OutputShdr() { shdr.sh_flags = llvm::ELF::SHF_ALLOC; }
2020-10-25 06:41:31 +03:00
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {
2020-10-26 06:09:37 +03:00
auto *p = (ELF64LE::Shdr *)(buf + shdr.sh_offset);
2020-10-25 06:41:31 +03:00
for (ELF64LE::Shdr *ent : entries)
*p++ = *ent;
2020-10-16 10:38:03 +03:00
}
u64 get_size() const override {
2020-10-25 06:41:31 +03:00
return entries.size() * sizeof(ELF64LE::Shdr);
2020-10-16 10:38:03 +03:00
}
2020-10-15 13:52:44 +03:00
2020-10-25 06:41:31 +03:00
std::vector<ELF64LE::Shdr *> entries;
2020-10-15 11:06:01 +03:00
};
2020-10-16 10:38:03 +03:00
// Program header
2020-10-15 12:30:06 +03:00
class OutputPhdr : public OutputChunk {
2020-10-15 11:06:01 +03:00
public:
2020-10-25 07:17:10 +03:00
OutputPhdr() { shdr.sh_flags = llvm::ELF::SHF_ALLOC; }
2020-10-25 06:41:31 +03:00
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override;
2020-10-16 10:38:03 +03:00
u64 get_size() const override {
2020-10-25 04:47:57 +03:00
return entries.size() * sizeof(ELF64LE::Phdr);
2020-10-16 10:38:03 +03:00
}
2020-10-15 13:52:44 +03:00
2020-10-25 04:47:57 +03:00
void construct(std::vector<OutputChunk *> &sections);
private:
struct Phdr {
ELF64LE::Phdr phdr;
2020-10-25 06:30:30 +03:00
std::vector<OutputChunk *> members;
2020-10-25 04:47:57 +03:00
};
std::vector<Phdr> entries;
2020-10-15 11:06: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:
static OutputSection *get_instance(StringRef name, u64 flags, u32 type);
2020-10-22 10:35:17 +03:00
OutputSection(StringRef name, u64 flags, u32 type) {
2020-10-22 13:35:16 +03:00
this->name = name;
2020-10-25 07:17:10 +03:00
shdr.sh_flags = flags;
shdr.sh_type = type;
2020-10-28 08:06:35 +03:00
idx = instances.size();
instances.push_back(this);
2020-10-21 05:28:43 +03:00
}
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {
2020-10-26 04:26:51 +03:00
if (!is_bss())
2020-10-26 08:32:36 +03:00
for_each(sections, [&](InputSection *isec) { isec->copy_to(buf); });
2020-10-16 10:38:03 +03:00
}
2020-10-29 16:32:55 +03:00
void relocate(u8 *buf) override {
2020-10-26 04:26:51 +03:00
if (!is_bss())
2020-10-26 08:32:36 +03:00
for_each(sections, [&](InputSection *isec) { isec->relocate(buf); });
2020-10-20 04:21:02 +03:00
}
2020-10-17 07:00:53 +03:00
u64 get_size() const override {
2020-10-25 11:37:24 +03:00
return shdr.sh_size;
2020-10-16 10:38:03 +03:00
}
2020-10-15 12:30:06 +03:00
2020-10-29 12:31:06 +03:00
bool empty() const {
if (!sections.empty())
for (InputSection *isec : sections)
if (isec->shdr.sh_size)
return false;
return true;
}
2020-10-26 07:34:15 +03:00
2020-10-28 08:06:35 +03:00
static std::vector<OutputSection *> instances;
2020-10-29 12:31:06 +03:00
u32 idx;
2020-10-15 12:30:06 +03:00
};
2020-10-22 13:35:16 +03:00
class InterpSection : public OutputChunk {
public:
InterpSection() {
name = ".interp";
2020-10-25 07:17:10 +03:00
shdr.sh_flags = llvm::ELF::SHF_ALLOC;
shdr.sh_type = llvm::ELF::SHT_PROGBITS;
2020-10-22 13:35:16 +03:00
}
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {
2020-10-26 06:09:37 +03:00
memcpy(buf + shdr.sh_offset, path, sizeof(path));
2020-10-22 13:35:16 +03:00
}
u64 get_size() const override { return sizeof(path); }
2020-10-22 13:35:16 +03:00
private:
static constexpr char path[] = "/lib64/ld-linux-x86-64.so.2";
};
2020-10-29 11:54:21 +03:00
class GotSection : public OutputChunk {
public:
2020-10-30 11:58:04 +03:00
typedef enum : u8 { REGULAR, TP } Kind;
2020-10-30 11:42:39 +03:00
2020-10-29 11:54:21 +03:00
GotSection() {
2020-10-29 12:32:47 +03:00
name = ".got";
2020-10-29 14:19:41 +03:00
shdr.sh_flags = llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
2020-10-29 11:54:21 +03:00
shdr.sh_type = llvm::ELF::SHT_PROGBITS;
2020-10-29 12:42:54 +03:00
shdr.sh_addralign = 8;
2020-10-29 11:54:21 +03:00
}
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {}
2020-10-30 11:42:39 +03:00
void relocate(u8 *buf) override;
2020-10-29 12:38:02 +03:00
2020-10-29 11:54:21 +03:00
u64 get_size() const override { return size; }
u64 size = 0;
2020-10-30 11:58:04 +03:00
std::vector<std::pair<Kind, Symbol *>> symbols;
2020-10-29 11:54:21 +03:00
};
2020-11-01 02:55:13 +03:00
class RelSection : public OutputChunk {
public:
RelSection() {
name = ".rela.dyn";
shdr.sh_flags = llvm::ELF::SHF_ALLOC;
shdr.sh_type = llvm::ELF::SHT_RELA;
shdr.sh_addralign = 8;
}
void copy_to(u8 *buf) override {}
void relocate(u8 *buf) override;
u64 get_size() const override { return size; }
u64 size = 0;
};
2020-10-27 11:53:08 +03:00
class ShstrtabSection : public OutputChunk {
2020-10-22 13:36:57 +03:00
public:
2020-10-27 11:53:08 +03:00
ShstrtabSection() {
this->name = ".shstrtab";
2020-10-22 14:06:45 +03:00
contents = '\0';
2020-10-25 07:17:10 +03:00
shdr.sh_flags = 0;
shdr.sh_type = llvm::ELF::SHT_STRTAB;
2020-10-22 13:36:57 +03:00
}
u64 add_string(StringRef s) {
u64 ret = contents.size();
2020-10-22 14:06:45 +03:00
contents += s.str();
contents += '\0';
return ret;
}
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {
2020-10-26 06:09:37 +03:00
memcpy(buf + shdr.sh_offset, &contents[0], contents.size());
2020-10-22 14:06:45 +03:00
}
u64 get_size() const override { return contents.size(); }
2020-10-22 13:36:57 +03:00
private:
2020-10-22 14:06:45 +03:00
std::string contents;
2020-10-22 13:36:57 +03:00
};
2020-10-27 12:59:56 +03:00
class SymtabSection : public OutputChunk {
public:
SymtabSection() {
this->name = ".symtab";
shdr.sh_flags = 0;
shdr.sh_type = llvm::ELF::SHT_SYMTAB;
shdr.sh_entsize = sizeof(ELF64LE::Sym);
shdr.sh_addralign = 8;
}
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {}
u64 get_size() const override { return size; }
2020-10-27 12:59:56 +03:00
u64 size = 0;
2020-10-27 12:59:56 +03:00
private:
std::vector<ELF64LE::Sym> contents;
};
2020-10-27 11:53:08 +03:00
class StrtabSection : public OutputChunk {
public:
StrtabSection() {
this->name = ".strtab";
shdr.sh_flags = 0;
shdr.sh_type = llvm::ELF::SHT_STRTAB;
}
2020-10-29 16:32:55 +03:00
void copy_to(u8 *buf) override {}
u64 get_size() const override { return size; }
2020-10-27 11:53:08 +03:00
u64 size = 1;
2020-10-27 11:53:08 +03:00
};
2020-10-17 07:24:48 +03:00
namespace out {
extern OutputEhdr *ehdr;
extern OutputShdr *shdr;
extern OutputPhdr *phdr;
2020-10-25 06:30:30 +03:00
extern InterpSection *interp;
2020-10-29 11:54:21 +03:00
extern GotSection *got;
2020-10-27 11:53:08 +03:00
extern ShstrtabSection *shstrtab;
2020-10-27 11:32:53 +03:00
extern SymtabSection *symtab;
2020-10-27 11:53:08 +03:00
extern StrtabSection *strtab;
2020-11-01 04:53:19 +03:00
2020-10-30 11:08:35 +03:00
extern u64 tls_end;
2020-11-01 04:53:19 +03:00
2020-11-01 06:26:57 +03:00
extern ObjectFile *internal_file;
2020-11-01 04:53:19 +03:00
extern Symbol *__bss_start;
extern Symbol *__ehdr_start;
extern Symbol *end;
extern Symbol *_end;
extern Symbol *etext;
extern Symbol *_etext;
extern Symbol *edata;
extern Symbol *_edata;
2020-10-17 07:24:48 +03:00
}
2020-10-12 07:30:34 +03:00
//
// input_files.cc
//
struct ComdatGroup {
ComdatGroup(ObjectFile *file, u32 i)
: file(file), section_idx(i) {}
ComdatGroup(const ComdatGroup &other)
2020-10-23 06:43:22 +03:00
: file(other.file.load()), section_idx(other.section_idx) {}
2020-10-28 13:51:49 +03:00
tbb::spin_mutex mu;
2020-10-23 06:43:22 +03:00
std::atomic<ObjectFile *> file;
u32 section_idx;
};
struct StringPiece {
2020-10-22 18:34:46 +03:00
StringPiece(StringRef data) : data(data) {}
StringPiece(const StringPiece &other) : data(other.data) {}
2020-10-22 18:34:46 +03:00
StringRef data;
std::atomic_flag flag = ATOMIC_FLAG_INIT;
};
2020-10-22 14:01:10 +03:00
class ObjectFile {
2020-10-04 12:00:33 +03:00
public:
2020-10-14 12:42:54 +03:00
ObjectFile(MemoryBufferRef mb, StringRef archive_name);
2020-10-04 12:00:33 +03:00
2020-10-09 14:47:45 +03:00
void parse();
2020-10-04 12:00:33 +03:00
void register_defined_symbols();
2020-10-28 13:34:32 +03:00
void register_undefined_symbols(tbb::parallel_do_feeder<ObjectFile *> &feeder);
2020-10-30 09:38:13 +03:00
void hanlde_undefined_weak_symbols();
2020-10-19 15:50:33 +03:00
void eliminate_duplicate_comdat_groups();
2020-10-27 06:50:25 +03:00
void convert_common_symbols();
2020-10-31 13:33:34 +03:00
std::tuple<i32, i32, i32> scan_relocations();
2020-10-26 08:57:22 +03:00
void fix_sym_addrs();
2020-10-27 14:58:28 +03:00
void compute_symtab();
2020-10-27 15:45:19 +03:00
2020-10-29 16:32:55 +03:00
void write_local_symtab(u8 *buf, u64 symtab_off, u64 strtab_off);
void write_global_symtab(u8 *buf, u64 symtab_off, u64 strtab_off);
2020-10-27 13:03:57 +03:00
2020-10-18 13:05:28 +03:00
StringRef get_filename();
bool is_in_archive();
2020-10-13 14:35:35 +03:00
Symbol *get_symbol(u32 idx) const {
if (idx < first_global)
return nullptr;
return symbols[idx - first_global];
2020-10-26 08:52:55 +03:00
}
2020-10-26 08:43:52 +03:00
u64 get_symbol_addr(u32 idx) const {
if (idx < first_global) {
const ELF64LE::Sym &sym = elf_syms[idx];
2020-10-27 12:07:15 +03:00
if (sym.st_shndx == llvm::ELF::SHN_ABS)
return sym.st_value;
InputSection *isec = sections[sym.st_shndx];
if (isec)
return isec->output_section->shdr.sh_addr + isec->offset + sym.st_value;
return 0;
}
return symbols[idx - first_global]->addr;
2020-10-26 14:10:23 +03:00
}
2020-10-13 14:35:35 +03:00
std::vector<InputSection *> sections;
2020-10-14 12:42:54 +03:00
StringRef archive_name;
2020-10-16 10:38:03 +03:00
ELFFile<ELF64LE> obj;
2020-10-29 06:24:54 +03:00
std::vector<Symbol *> symbols;
u32 priority;
2020-10-29 10:48:17 +03:00
std::atomic_bool is_alive = ATOMIC_VAR_INIT(false);
2020-10-09 17:26:26 +03:00
u64 local_symtab_size = 0;
u64 local_strtab_size = 0;
u64 global_symtab_size = 0;
u64 global_strtab_size = 0;
2020-10-27 14:58:28 +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();
void remove_comdat_members(u32 section_idx);
2020-10-22 18:34:46 +03:00
void read_string_pieces(const ELF64LE::Shdr &shdr);
2020-10-19 14:05:34 +03:00
2020-10-09 14:47:45 +03:00
MemoryBufferRef mb;
std::vector<std::pair<ComdatGroup *, u32>> comdat_groups;
2020-10-22 18:52:36 +03:00
std::vector<StringPiece *> merged_strings_alloc;
std::vector<StringPiece *> merged_strings_noalloc;
2020-10-19 14:05:34 +03:00
2020-10-26 08:52:55 +03:00
int first_global = 0;
2020-10-27 02:45:20 +03:00
bool has_common_symbol;
2020-10-26 08:52:55 +03:00
2020-10-19 14:05:34 +03:00
ArrayRef<ELF64LE::Shdr> elf_sections;
2020-10-13 14:35:35 +03:00
ArrayRef<ELF64LE::Sym> elf_syms;
2020-10-26 15:44:08 +03:00
StringRef symbol_strtab;
2020-10-19 14:17:32 +03:00
const ELF64LE::Shdr *symtab_sec;
2020-10-27 14:24:28 +03:00
// For .strtab construction
std::vector<StringRef> local_symbols;
2020-10-04 12:00:33 +03:00
};
2020-10-12 07:30:34 +03:00
//
// writer.cc
//
void write();
2020-10-14 13:43:12 +03:00
//
// output_file.cc
//
class OutputFile {
public:
OutputFile(u64 size);
2020-10-14 13:43:12 +03:00
void commit();
private:
std::unique_ptr<llvm::FileOutputBuffer> output_buffer;
2020-10-29 16:32:55 +03:00
u8 *buf;
2020-10-14 13:43:12 +03:00
};
2020-10-29 06:24:54 +03:00
//
// mapfile.cc
//
2020-10-29 12:31:06 +03:00
void print_map(ArrayRef<ObjectFile *> files, ArrayRef<OutputChunk *> output_sections);
2020-10-29 06:24:54 +03:00
2020-10-12 07:30:34 +03:00
//
// main.cc
//
2020-10-09 14:47:45 +03:00
MemoryBufferRef readFile(StringRef path);
2020-10-13 14:35:35 +03:00
extern std::atomic_int num_defined;
extern std::atomic_int num_undefined;
2020-10-23 07:17:21 +03:00
extern std::atomic_int num_all_syms;
2020-10-22 19:14:11 +03:00
extern std::atomic_int num_comdats;
2020-10-23 07:17:21 +03:00
extern std::atomic_int num_regular_sections;
2020-10-10 13:15:16 +03:00
extern std::atomic_int num_files;
2020-10-20 08:27:00 +03:00
extern std::atomic_int num_relocs;
2020-10-23 07:23:12 +03:00
extern std::atomic_int num_relocs_alloc;
2020-10-22 18:52:36 +03:00
extern std::atomic_int num_string_pieces;
2020-10-27 18:26:31 +03:00
//
// Other
//
2020-10-28 09:18:31 +03:00
inline void memcpy_nontemporal(void *dst_, const void *src_, size_t n) {
2020-10-28 09:21:00 +03:00
#if 1
2020-10-28 09:18:31 +03:00
char *src = (char *)src_;
char *dst = (char *)dst_;
if ((uintptr_t)src % 16 || (uintptr_t)dst % 16) {
memcpy(dst, src, n);
return;
}
size_t i = 0;
for (; i + 16 < n; i += 16) {
__m128 val = __builtin_nontemporal_load((__m128 *)(src + i));
__builtin_nontemporal_store(val, (__m128 *)(dst + i));
2020-10-27 18:26:31 +03:00
}
2020-10-28 09:18:31 +03:00
memcpy(dst + i, src + i, n - i);
2020-10-28 08:41:55 +03:00
#else
2020-10-28 09:18:31 +03:00
memcpy(dst_, src_, n);
2020-10-28 08:41:55 +03:00
#endif
2020-10-27 18:26:31 +03:00
}