2020-10-09 14:47:45 +03:00
|
|
|
#include "chibild.h"
|
2020-10-04 12:00:33 +03:00
|
|
|
|
|
|
|
using namespace llvm;
|
2020-10-09 14:47:45 +03:00
|
|
|
using namespace llvm::ELF;
|
2020-10-04 12:00:33 +03:00
|
|
|
|
2020-10-13 14:35:35 +03:00
|
|
|
std::atomic_int num_defined;
|
|
|
|
std::atomic_int num_undefined;
|
2020-10-10 13:15:16 +03:00
|
|
|
std::atomic_int num_files;
|
|
|
|
|
2020-10-14 12:42:54 +03:00
|
|
|
ObjectFile::ObjectFile(MemoryBufferRef mb, StringRef archive_name)
|
|
|
|
: mb(mb), archive_name(archive_name) {}
|
2020-10-04 12:00:33 +03:00
|
|
|
|
2020-10-09 14:47:45 +03:00
|
|
|
MemoryBufferRef readFile(StringRef path) {
|
|
|
|
auto mbOrErr = MemoryBuffer::getFile(path, -1, false);
|
|
|
|
if (auto ec = mbOrErr.getError())
|
|
|
|
error("cannot open " + path + ": " + ec.message());
|
2020-10-04 12:00:33 +03:00
|
|
|
|
2020-10-09 14:47:45 +03:00
|
|
|
std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
|
|
|
|
MemoryBufferRef mbref = mb->getMemBufferRef();
|
|
|
|
mb.release();
|
|
|
|
return mbref;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const ELF64LE::Shdr
|
|
|
|
*findSection(ArrayRef<ELF64LE::Shdr> sections, uint32_t type) {
|
|
|
|
for (const ELF64LE::Shdr &sec : sections)
|
|
|
|
if (sec.sh_type == type)
|
|
|
|
return &sec;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-10-11 11:20:38 +03:00
|
|
|
llvm::Timer parse1_timer("parse1", "parse1", timers);
|
|
|
|
llvm::Timer parse2_timer("parse2", "parse2", timers);
|
2020-10-10 13:05:30 +03:00
|
|
|
|
2020-10-09 14:47:45 +03:00
|
|
|
void ObjectFile::parse() {
|
2020-10-10 13:15:16 +03:00
|
|
|
num_files++;
|
|
|
|
|
2020-10-10 13:05:30 +03:00
|
|
|
parse1_timer.startTimer();
|
|
|
|
|
2020-10-13 14:35:35 +03:00
|
|
|
// Initialize sections.
|
2020-10-09 14:47:45 +03:00
|
|
|
ELFFile<ELF64LE> obj = check(ELFFile<ELF64LE>::create(mb.getBuffer()));
|
|
|
|
ArrayRef<ELF64LE::Shdr> sections = CHECK(obj.sections(), this);
|
2020-10-13 14:35:35 +03:00
|
|
|
StringRef section_strtab = CHECK(obj.getSectionStringTable(sections), this);
|
|
|
|
|
|
|
|
this->sections.reserve(sections.size());
|
|
|
|
for (const ELF64LE::Shdr &shdr : sections) {
|
|
|
|
StringRef name = CHECK(obj.getSectionName(shdr, section_strtab), this);
|
|
|
|
this->sections.push_back(new InputSection(this, &shdr, name));
|
|
|
|
}
|
2020-10-09 14:47:45 +03:00
|
|
|
|
|
|
|
// Find a symbol table.
|
|
|
|
bool is_dso = (identify_magic(mb.getBuffer()) == file_magic::elf_shared_object);
|
|
|
|
|
|
|
|
const ELF64LE::Shdr *symtab_sec
|
|
|
|
= findSection(sections, is_dso ? SHT_DYNSYM : SHT_SYMTAB);
|
|
|
|
|
2020-10-10 10:49:02 +03:00
|
|
|
if (!symtab_sec)
|
|
|
|
return;
|
|
|
|
|
2020-10-13 14:35:35 +03:00
|
|
|
this->first_global = symtab_sec->sh_info;
|
2020-10-09 14:47:45 +03:00
|
|
|
|
2020-10-13 14:35:35 +03:00
|
|
|
// Parse symbols
|
|
|
|
this->elf_syms = CHECK(obj.symbols(symtab_sec), this);
|
2020-10-09 14:47:45 +03:00
|
|
|
StringRef string_table =
|
|
|
|
CHECK(obj.getStringTableForSymtab(*symtab_sec, sections), this);
|
2020-10-09 15:50:13 +03:00
|
|
|
|
2020-10-13 14:35:35 +03:00
|
|
|
this->symbol_instances.resize(elf_syms.size());
|
|
|
|
this->symbols.resize(elf_syms.size());
|
2020-10-10 06:18:11 +03:00
|
|
|
|
2020-10-10 13:15:16 +03:00
|
|
|
parse1_timer.stopTimer();
|
|
|
|
parse2_timer.startTimer();
|
|
|
|
|
2020-10-09 17:26:26 +03:00
|
|
|
for (int i = 0; i < elf_syms.size(); i++) {
|
|
|
|
StringRef name;
|
2020-10-12 09:33:57 +03:00
|
|
|
if (first_global <= i)
|
2020-10-13 14:35:35 +03:00
|
|
|
name = CHECK(this->elf_syms[i].getName(string_table), this);
|
|
|
|
this->symbol_instances[i] = {name, this};
|
2020-10-09 17:26:26 +03:00
|
|
|
}
|
2020-10-12 09:33:57 +03:00
|
|
|
|
|
|
|
for (int i = 0; i < first_global; i++)
|
2020-10-13 14:35:35 +03:00
|
|
|
this->symbols[i] = &this->symbol_instances[i];
|
2020-10-12 09:33:57 +03:00
|
|
|
|
2020-10-10 13:05:30 +03:00
|
|
|
parse2_timer.stopTimer();
|
2020-10-10 06:18:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectFile::register_defined_symbols() {
|
2020-10-12 09:33:57 +03:00
|
|
|
for (int i = first_global; i < symbol_instances.size(); i++) {
|
2020-10-13 14:35:35 +03:00
|
|
|
if (!elf_syms[i].isDefined())
|
|
|
|
continue;
|
|
|
|
|
2020-10-10 06:18:11 +03:00
|
|
|
Symbol &sym = symbol_instances[i];
|
2020-10-12 09:33:57 +03:00
|
|
|
symbols[i] = symbol_table.add(sym.name, sym);
|
2020-10-13 14:35:35 +03:00
|
|
|
num_defined++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectFile::register_undefined_symbols() {
|
|
|
|
for (int i = first_global; i < symbol_instances.size(); i++) {
|
|
|
|
if (elf_syms[i].isDefined())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Symbol &sym = symbol_instances[i];
|
|
|
|
symbols[i] = symbol_table.get(sym.name);
|
|
|
|
num_undefined++;
|
2020-10-09 16:29:25 +03:00
|
|
|
}
|
2020-10-09 14:47:45 +03:00
|
|
|
}
|
|
|
|
|
2020-10-14 10:33:12 +03:00
|
|
|
StringRef ObjectFile::get_filename() {
|
2020-10-09 14:47:45 +03:00
|
|
|
return mb.getBufferIdentifier();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string toString(ObjectFile *obj) {
|
2020-10-14 10:33:12 +03:00
|
|
|
return obj->get_filename().str();
|
2020-10-09 14:47:45 +03:00
|
|
|
}
|