1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-20 09:27:45 +03:00
mold/chibild.h

311 lines
6.0 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-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-10 10:49:02 +03:00
#include "tbb/parallel_for_each.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-04 12:00:33 +03:00
2020-10-10 13:15:16 +03:00
#include <atomic>
2020-10-04 12:00:33 +03:00
#include <cstdint>
2020-10-15 13:55:51 +03:00
#include <cstdlib>
#include <cstring>
2020-10-04 12:00:33 +03:00
#include <string>
2020-10-14 12:58:47 +03:00
#include <unordered_set>
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;
};
extern Config config;
[[noreturn]] inline void error(const Twine &msg) {
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-12 07:30:34 +03:00
//
// symtab.cc
//
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-12 07:30:34 +03:00
class Symbol {
public:
2020-10-18 14:19:57 +03:00
static Symbol *intern(StringRef name);
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-18 14:19:57 +03:00
StringRef name;
ObjectFile *file = nullptr;
std::atomic_flag lock = ATOMIC_FLAG_INIT;
2020-10-12 07:30:34 +03:00
};
2020-10-18 13:00:39 +03:00
std::string toString(Symbol);
2020-10-12 07:30:34 +03:00
//
// input_sections.cc
//
2020-10-17 07:52:46 +03:00
class InputChunk {
public:
virtual void copy_to(uint8_t *buf) = 0;
virtual void relocate(uint8_t *buf) {}
StringRef name;
};
class InputSection : public InputChunk {
2020-10-08 11:01:54 +03:00
public:
2020-10-13 14:35:35 +03:00
InputSection(ObjectFile *file, const ELF64LE::Shdr *hdr, StringRef name);
2020-10-16 10:38:03 +03:00
void copy_to(uint8_t *buf);
2020-10-15 13:27:35 +03:00
uint64_t get_size() const;
2020-10-08 11:01:54 +03:00
2020-10-19 12:13:55 +03:00
OutputSection *output_section = nullptr;
StringRef output_section_name;
2020-10-14 10:27:45 +03:00
uint64_t output_file_offset;
2020-10-15 13:27:35 +03:00
int64_t offset = -1;
2020-10-13 14:35:35 +03:00
private:
const ELF64LE::Shdr *hdr;
ObjectFile *file;
2020-10-08 11:01:54 +03:00
};
2020-10-17 07:52:46 +03:00
class StringTableSection : public InputChunk {
public:
StringTableSection(StringRef name) {
this->name = name;
}
uint64_t addString(StringRef s);
void copy_to(uint8_t *buf) override;
};
2020-10-12 08:17:34 +03:00
//
// output_sections.cc
//
2020-10-15 12:30:06 +03:00
class OutputChunk {
2020-10-15 11:06:01 +03:00
public:
2020-10-16 10:38:03 +03:00
virtual void copy_to(uint8_t *buf) = 0;
2020-10-17 07:00:53 +03:00
virtual void relocate(uint8_t *buf) = 0;
2020-10-15 13:27:35 +03:00
virtual void set_offset(uint64_t off) { offset = off; }
uint64_t get_offset() const { return offset; }
virtual uint64_t get_size() const = 0;
2020-10-13 14:35:35 +03:00
2020-10-15 13:27:35 +03:00
protected:
int64_t offset = -1;
int64_t size = -1;
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-17 07:00:53 +03:00
void copy_to(uint8_t *buf) override {}
void relocate(uint8_t *buf) override;
2020-10-16 10:38:03 +03:00
uint64_t 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-16 10:38:03 +03:00
void copy_to(uint8_t *buf) override {
memcpy(buf + offset, &hdr[0], get_size());
}
2020-10-17 07:00:53 +03:00
void relocate(uint8_t *buf) override {}
2020-10-16 10:38:03 +03:00
uint64_t get_size() const override {
return hdr.size() * sizeof(hdr[0]);
}
2020-10-15 13:52:44 +03:00
2020-10-15 11:06:01 +03:00
std::vector<ELF64LE::Shdr> hdr;
};
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-16 10:38:03 +03:00
void copy_to(uint8_t *buf) override {
memcpy(buf + offset, &hdr[0], get_size());
}
2020-10-17 07:00:53 +03:00
void relocate(uint8_t *buf) override {}
2020-10-16 10:38:03 +03:00
uint64_t get_size() const override {
return hdr.size() * sizeof(hdr[0]);
}
2020-10-15 13:52:44 +03:00
2020-10-15 11:06:01 +03:00
std::vector<ELF64LE::Phdr> hdr;
};
2020-10-16 10:38:03 +03:00
// Sections
2020-10-15 12:30:06 +03:00
class OutputSection : public OutputChunk {
public:
2020-10-16 10:38:03 +03:00
OutputSection(StringRef name) : name(name) {}
void copy_to(uint8_t *buf) override {
for (InputSection *sec : sections)
sec->copy_to(buf);
}
2020-10-17 07:00:53 +03:00
void relocate(uint8_t *buf) override {}
2020-10-16 10:38:03 +03:00
uint64_t get_size() const override {
assert(size >= 0);
return size;
}
2020-10-15 12:30:06 +03:00
2020-10-15 13:27:35 +03:00
void set_offset(uint64_t off) override;
2020-10-15 12:30:06 +03:00
std::vector<InputSection *> sections;
StringRef name;
private:
uint64_t file_offset = 0;
uint64_t on_file_size = -1;
};
2020-10-17 07:24:48 +03:00
namespace out {
extern OutputEhdr *ehdr;
extern OutputShdr *shdr;
extern OutputPhdr *phdr;
}
2020-10-12 07:30:34 +03:00
//
// input_files.cc
//
2020-10-12 08:17:34 +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();
void register_undefined_symbols();
2020-10-18 13:05:28 +03:00
StringRef get_filename();
bool is_in_archive();
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-18 13:25:39 +03:00
uint32_t priority;
2020-10-18 15:03:51 +03:00
std::atomic_bool is_alive;
2020-10-09 17:26:26 +03:00
2020-10-09 14:47:45 +03:00
private:
MemoryBufferRef mb;
2020-10-04 12:00:33 +03:00
std::vector<Symbol *> symbols;
2020-10-13 14:35:35 +03:00
ArrayRef<ELF64LE::Sym> elf_syms;
2020-10-12 09:33:57 +03:00
int first_global = 0;
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(uint64_t size);
void commit();
private:
std::unique_ptr<llvm::FileOutputBuffer> output_buffer;
uint8_t *buf;
};
2020-10-12 07:30:34 +03:00
//
// main.cc
//
2020-10-09 14:47:45 +03:00
MemoryBufferRef readFile(StringRef path);
std::string toString(ObjectFile *);
2020-10-09 16:29:25 +03:00
extern SymbolTable symbol_table;
2020-10-13 14:35:35 +03:00
extern std::atomic_int num_defined;
extern std::atomic_int num_undefined;
2020-10-10 13:15:16 +03:00
extern std::atomic_int num_files;