From 33e23adbb2d08fad48cbaea20919f29a29a40207 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 19:47:48 +0900 Subject: [PATCH 01/21] Make IsAddrInFiniarray working when fini_array_ is NULL --- elf_binary.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/elf_binary.cc b/elf_binary.cc index 79857fe..da3e0f0 100644 --- a/elf_binary.cc +++ b/elf_binary.cc @@ -77,9 +77,14 @@ bool ELFBinary::IsAddrInInitarray(uintptr_t addr) const { } bool ELFBinary::IsAddrInFiniarray(uintptr_t addr) const { - CHECK(fini_array_addr_ != 0); - LOG(INFO) << SOLD_LOG_BITS(addr) << SOLD_LOG_BITS(fini_array_addr_) << SOLD_LOG_BITS(fini_arraysz_); - return reinterpret_cast(fini_array_addr_) <= addr && addr < reinterpret_cast(fini_array_addr_ + fini_arraysz_); + if (fini_array_addr_ != 0) { + LOG(INFO) << SOLD_LOG_BITS(addr) << SOLD_LOG_BITS(fini_array_addr_) << SOLD_LOG_BITS(fini_arraysz_); + return reinterpret_cast(fini_array_addr_) <= addr && + addr < reinterpret_cast(fini_array_addr_ + fini_arraysz_); + } else { + LOG(WARNING) << SOLD_LOG_KEY(fini_array_addr_); + return false; + } } bool ELFBinary::IsVaddrInTLSData(uintptr_t vaddr) const { From 49c4900154b2973506e1ade56841bf7e3c25593b Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 19:50:09 +0900 Subject: [PATCH 02/21] IsAddrInBinary --- elf_binary.cc | 13 +++++++++++++ elf_binary.h | 1 + 2 files changed, 14 insertions(+) diff --git a/elf_binary.cc b/elf_binary.cc index da3e0f0..a2ed4a4 100644 --- a/elf_binary.cc +++ b/elf_binary.cc @@ -597,6 +597,19 @@ void ELFBinary::ParseFuncArray(uintptr_t* array, uintptr_t size, std::vectorp_vaddr <= addr && addr < phdr->p_vaddr + phdr->p_memsz) { + return true; + } + } + if (tls() != nullptr && tls()->p_vaddr == addr) { + return true; + } + return false; +} + Elf_Addr ELFBinary::OffsetFromAddr(const Elf_Addr addr) const { for (Elf_Phdr* phdr : loads_) { if (phdr->p_vaddr <= addr && addr < phdr->p_vaddr + phdr->p_memsz) { diff --git a/elf_binary.h b/elf_binary.h index 1ed42b2..a1c34bd 100644 --- a/elf_binary.h +++ b/elf_binary.h @@ -108,6 +108,7 @@ class ELFBinary { std::pair GetVersion(int index, const std::map& filename_to_soname); + bool IsAddrInBinary(const Elf_Addr addr) const; Elf_Addr OffsetFromAddr(const Elf_Addr addr) const; Elf_Addr AddrFromOffset(const Elf_Addr offset) const; From 32b4d4a0a67e9095d55d79d3650a494159ae6faa Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 19:53:20 +0900 Subject: [PATCH 03/21] Record addresses of locations which symbols refer to --- elf_binary.cc | 7 +++++++ elf_binary.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/elf_binary.cc b/elf_binary.cc index a2ed4a4..626a9cb 100644 --- a/elf_binary.cc +++ b/elf_binary.cc @@ -199,9 +199,16 @@ void ELFBinary::ReadDynSymtab(const std::map& filename syms_.push_back(Syminfo{symname, soname, version, v, sym}); CHECK(duplicate_check.insert({symname, soname, version}).second) << SOLD_LOG_KEY(symname) << SOLD_LOG_KEY(soname) << SOLD_LOG_KEY(version); + const void* symp = nullptr; + if (IsAddrInBinary(sym->st_value)) { + symp = reinterpret_cast(head() + OffsetFromAddr(sym->st_value)); + } + LOG(INFO) << SOLD_LOG_BITS(symp) << SOLD_LOG_BITS(sym->st_size); + symps_.emplace_back(symp); LOG(INFO) << "duplicate_check: " << SOLD_LOG_KEY(symname) << SOLD_LOG_KEY(version); } + CHECK_EQ(syms_.size(), symps_.size()); LOG(INFO) << "nsyms_ = " << nsyms_; } diff --git a/elf_binary.h b/elf_binary.h index a1c34bd..3129ecd 100644 --- a/elf_binary.h +++ b/elf_binary.h @@ -75,6 +75,7 @@ class ELFBinary { const std::vector& fini_array() const { return fini_array_; } const std::vector& GetSymbolMap() const { return syms_; } + const std::vector symps() const { return symps_; } Range GetRange() const; @@ -164,6 +165,8 @@ class ELFBinary { // This is the name on the filsysytem std::string name_; std::vector syms_; + // Addresses of locations which symbols refer to + std::vector symps_; int nsyms_{0}; From 6325418d79cd54bccfe1bfd173199099e52dd0d5 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 19:54:03 +0900 Subject: [PATCH 04/21] Fix a comment --- elf_binary.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elf_binary.h b/elf_binary.h index 3129ecd..7ad6932 100644 --- a/elf_binary.h +++ b/elf_binary.h @@ -162,7 +162,7 @@ class ELFBinary { std::vector init_array_; std::vector fini_array_; - // This is the name on the filsysytem + // This is the name on the filesystem std::string name_; std::vector syms_; // Addresses of locations which symbols refer to From 5733154ad6c8a093f26e97644d83e437bf47d27f Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 19:55:12 +0900 Subject: [PATCH 05/21] Check VERSYM_VERSION --- elf_binary.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/elf_binary.cc b/elf_binary.cc index 626a9cb..fdd1b2f 100644 --- a/elf_binary.cc +++ b/elf_binary.cc @@ -277,7 +277,8 @@ std::pair ELFBinary::GetVersion(int index, const std:: if (vd->vd_flags & VER_FLG_BASE) { soname = std::string(strtab_ + vda->vda_name); } - if (vd->vd_ndx == versym_[index]) { + LOG(INFO) << SOLD_LOG_BITS(vd->vd_ndx); + if (vd->vd_ndx == (VERSYM_VERSION & versym_[index])) { version = std::string(strtab_ + vda->vda_name); } From 381af6f95effee9950bfee7ece2094ee854af663 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 19:55:32 +0900 Subject: [PATCH 06/21] Kinder log message --- elf_binary.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elf_binary.cc b/elf_binary.cc index fdd1b2f..bf81806 100644 --- a/elf_binary.cc +++ b/elf_binary.cc @@ -290,7 +290,7 @@ std::pair ELFBinary::GetVersion(int index, const std:: } } - LOG(WARNING) << "Find no entry corresponds to " << versym_[index]; + LOG(WARNING) << "Find no entry corresponds to " << SOLD_LOG_BITS(versym_[index]); return std::make_pair("", ""); } } From f9ecad9cae872e0d5172c8a56e19ac8d31ff0cc2 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:04:32 +0900 Subject: [PATCH 07/21] Change the signature of ResolveCopy --- symtab_builder.cc | 21 ++++++++++++++++----- symtab_builder.h | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/symtab_builder.cc b/symtab_builder.cc index e24dced..e6f0094 100644 --- a/symtab_builder.cc +++ b/symtab_builder.cc @@ -122,8 +122,9 @@ bool SymtabBuilder::Resolve(const std::string& name, const std::string& soname, } } -// Returns the index of symbol(name, soname, version) -uintptr_t SymtabBuilder::ResolveCopy(const std::string& name, const std::string& soname, const std::string version) { +// Returns and fills st_value to index true when the symbol specified +// with (name, soname, version) is defined. +bool SymtabBuilder::ResolveCopy(const std::string& name, const std::string& soname, const std::string version, uintptr_t* val_or_index) { // TODO(hamaji): Refactor. Symbol sym{}; sym.sym.st_name = 0; @@ -162,12 +163,22 @@ uintptr_t SymtabBuilder::ResolveCopy(const std::string& name, const std::string& sym.index = AddSym(s); CHECK(syms_.emplace(std::make_tuple(name, soname, version), sym).second); } else { - LOG(INFO) << "Symbol " << name << " not found for copy"; - CHECK(false); + LOG(FATAL) << "Symbol " << name << " not found for copy"; } } - return sym.index; + if (!IsDefined(sym.sym)) { + *val_or_index = sym.index; + return false; + } else { + // *val_or_index = sym.sym.st_value; + // Destination + std::cerr << SOLD_LOG_KEY(name) << SOLD_LOG_BITS(sym.sym.st_value) << std::endl; + // current master + // return false; + *val_or_index = sym.index; + return true; + } } // Make a new symbol table(symtab_) from exposed_syms_. diff --git a/symtab_builder.h b/symtab_builder.h index 28089d0..0aedae2 100644 --- a/symtab_builder.h +++ b/symtab_builder.h @@ -32,7 +32,7 @@ class SymtabBuilder { bool Resolve(const std::string& name, const std::string& filename, const std::string version_name, uintptr_t& val_or_index); - uintptr_t ResolveCopy(const std::string& name, const std::string& filename, const std::string version_name); + bool ResolveCopy(const std::string& name, const std::string& soname, const std::string version, uintptr_t* index); void Build(StrtabBuilder& strtab, VersionBuilder& version); From 0b99057c8ef5b56e77cac04b07499d0e0d25b873 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:07:30 +0900 Subject: [PATCH 08/21] We need space of BSS to copy the value of global variables --- sold.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sold.cc b/sold.cc index dbea65f..ecda676 100644 --- a/sold.cc +++ b/sold.cc @@ -143,7 +143,7 @@ void Sold::BuildLoads() { file_offset += phdr->p_vaddr & 0xfff; load.emit.p_offset = file_offset; - file_offset = AlignNext(file_offset + phdr->p_filesz); + file_offset = AlignNext(file_offset + phdr->p_memsz); load.emit.p_vaddr += offset; load.emit.p_paddr += offset; // TODO(hamaji): Add PF_W only for GOT. From 3e2e8f9b0df99c388e6641210078f903e5424450 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:09:07 +0900 Subject: [PATCH 09/21] Copy the value of global variables --- sold.h | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/sold.h b/sold.h index 36b3510..f56a0e3 100644 --- a/sold.h +++ b/sold.h @@ -266,14 +266,56 @@ class Sold { void EmitCode(FILE* fp) { CHECK(ftell(fp) == CodeOffset()); - for (const Load& load : loads_) { + std::set processed_reloc_copy_index; + for (int i = 0; i < loads_.size(); i++) { + const Load& load = loads_[i]; ELFBinary* bin = load.bin; Elf_Phdr* phdr = load.orig; LOG(INFO) << "Emitting code of " << bin->name() << " from " << HexString(ftell(fp)) << " => " << HexString(load.emit.p_offset) << " + " << HexString(phdr->p_filesz); EmitPad(fp, load.emit.p_offset); WriteBuf(fp, bin->head() + phdr->p_offset, phdr->p_filesz); + // To process reloc_copy_, try to emit bss section as much as possible + bool emit_bss = (i == loads_.size() - 1) || load.emit.p_vaddr + load.emit.p_memsz <= loads_[i + 1].emit.p_vaddr; + if (emit_bss) { + EmitPad(fp, load.emit.p_offset + load.emit.p_memsz); + } else { + CHECK_GT(loads_.size() - 1, i); + EmitPad(fp, loads_[i + 1].emit.p_offset); + } + if (!emit_bss) { + LOG(INFO) << SOLD_LOG_BITS(load.emit.p_vaddr + load.emit.p_memsz) << SOLD_LOG_BITS(loads_[i + 1].emit.p_vaddr); + } + for (int j = 0; j < reloc_copy_.size(); j++) { + auto t = reloc_copy_[j]; + uintptr_t reloc_dest = std::get<0>(t); + const void* reloc_src = std::get<1>(t); + Elf_Xword reloc_size = std::get<2>(t); + bool in_load = load.emit.p_vaddr <= reloc_dest && reloc_dest < (load.emit.p_vaddr + load.emit.p_memsz); + bool in_bss = + (load.emit.p_vaddr + load.emit.p_filesz) <= reloc_dest && reloc_dest < (load.emit.p_vaddr + load.emit.p_memsz); + LOG(INFO) << SOLD_LOG_BITS(reloc_dest) << SOLD_LOG_BITS(load.emit.p_offset) << SOLD_LOG_BITS(load.emit.p_memsz) + << SOLD_LOG_BITS(load.emit.p_vaddr) << SOLD_LOG_KEY(in_load) << SOLD_LOG_KEY(in_bss) << SOLD_LOG_KEY(emit_bss) + << SOLD_LOG_BITS(load.orig->p_offset) << SOLD_LOG_BITS(reloc_size); + if (in_load) { + if (reloc_size == 1) { + LOG(INFO) << SOLD_LOG_BITS(*reinterpret_cast(reloc_src)); + } else if (reloc_size == 2) { + LOG(INFO) << SOLD_LOG_BITS(*reinterpret_cast(reloc_src)); + } else if (reloc_size == 4) { + LOG(INFO) << SOLD_LOG_BITS(*reinterpret_cast(reloc_src)); + } else if (reloc_size == 8) { + LOG(INFO) << SOLD_LOG_BITS(*reinterpret_cast(reloc_src)); + } else { + LOG(FATAL) << SOLD_LOG_BITS(reloc_size); + } + CHECK(reloc_dest - load.emit.p_vaddr + load.emit.p_offset + reloc_size <= ftell(fp)); + CHECK(processed_reloc_copy_index.insert(j).second); + MemcpyFile(fp, reloc_dest - load.emit.p_vaddr + load.emit.p_offset, reloc_src, reloc_size); + } + } } + CHECK_EQ(processed_reloc_copy_index.size(), reloc_copy_.size()); } // Emit TLS initialization image @@ -470,4 +512,6 @@ class Sold { std::map bin_to_init_array_offset_; std::map bin_to_fini_array_offset_; TLS tls_; + // + std::vector> reloc_copy_; }; From ce96e1272fd627059bc793d948b9b469c2b29b92 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:10:23 +0900 Subject: [PATCH 10/21] Signature was changed --- sold.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sold.cc b/sold.cc index ecda676..883b343 100644 --- a/sold.cc +++ b/sold.cc @@ -635,7 +635,8 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o case R_X86_64_DTPMOD64: { // TODO(akawashiro) Refactor out for Arch64 const std::string name = bin->Str(sym->st_name); - uintptr_t index = syms_.ResolveCopy(name, soname, version_name); + uintptr_t index; + syms_.ResolveCopy(name, soname, version_name, &index); newrel.r_info = ELF_R_INFO(index, type); if (bin->tls() == NULL) { @@ -714,7 +715,8 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o case R_X86_64_DTPOFF64: case R_X86_64_TPOFF64: { const std::string name = bin->Str(sym->st_name); - uintptr_t index = syms_.ResolveCopy(name, soname, version_name); + uintptr_t index; + syms_.ResolveCopy(name, soname, version_name, &index); newrel.r_info = ELF_R_INFO(index, type); LOG(INFO) << ShowRelocationType(type) << " relocation: " << SOLD_LOG_KEY(*rel) << SOLD_LOG_KEY(newrel) << SOLD_LOG_64BITS(bin->OffsetFromAddr(rel->r_offset)); @@ -827,7 +829,8 @@ void Sold::RelocateSymbol_aarch64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t const std::string name = bin->Str(sym->st_name); if (name == "") { LOG(INFO) << SOLD_LOG_KEY(name) << "R_AARCH64_TLSDESC in local dynamic"; - uintptr_t index = syms_.ResolveCopy(name, soname, version_name); + uintptr_t index; + syms_.ResolveCopy(name, soname, version_name, &index); newrel.r_info = ELF_R_INFO(index, type); const bool is_bss = bin->IsOffsetInTLSBSS(newrel.r_addend); if (is_bss) { @@ -842,7 +845,8 @@ void Sold::RelocateSymbol_aarch64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t break; } else { LOG(INFO) << SOLD_LOG_KEY(name) << "R_AARCH64_TLSDESC in generic dynamic"; - uintptr_t index = syms_.ResolveCopy(name, soname, version_name); + uintptr_t index; + syms_.ResolveCopy(name, soname, version_name, &index); newrel.r_info = ELF_R_INFO(index, type); break; } @@ -850,7 +854,8 @@ void Sold::RelocateSymbol_aarch64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t case R_AARCH64_COPY: { const std::string name = bin->Str(sym->st_name); - uintptr_t index = syms_.ResolveCopy(name, soname, version_name); + uintptr_t index; + syms_.ResolveCopy(name, soname, version_name, &index); newrel.r_info = ELF_R_INFO(index, type); break; } From ffa69548c80a70f056efd20a036b913afa2e2ea6 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:12:22 +0900 Subject: [PATCH 11/21] load_defined_syms flag --- sold.cc | 3 ++- sold.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sold.cc b/sold.cc index 883b343..58ea50d 100644 --- a/sold.cc +++ b/sold.cc @@ -477,7 +477,7 @@ uintptr_t Sold::RemapTLS(const char* msg, ELFBinary* bin, uintptr_t off) { // Push symbols of bin to symtab. // When the same symbol is already in symtab, LoadDynSymtab selects a more // concretely defined one. -void Sold::LoadDynSymtab(ELFBinary* bin, std::vector& symtab) { +void Sold::LoadDynSymtab(ELFBinary* bin, std::vector& symtab, bool load_defined_syms) { bin->ReadDynSymtab(filename_to_soname_); uintptr_t offset = offsets_[bin]; @@ -485,6 +485,7 @@ void Sold::LoadDynSymtab(ELFBinary* bin, std::vector& symtab) { for (const auto& p : bin->GetSymbolMap()) { const std::string& name = p.name; Elf_Sym* sym = p.sym; + if (!load_defined_syms && IsDefined(*sym)) continue; if (IsTLS(*sym) && sym->st_shndx != SHN_UNDEF) { sym->st_value = RemapTLS("symbol", bin, sym->st_value); } else if (sym->st_value) { diff --git a/sold.h b/sold.h index f56a0e3..b5f399a 100644 --- a/sold.h +++ b/sold.h @@ -361,8 +361,9 @@ class Sold { std::vector syms; for (ELFBinary* bin : link_binaries_) { - LoadDynSymtab(bin, syms); + LoadDynSymtab(bin, syms, true); } + for (auto s : syms) { LOG(INFO) << "SYM " << s.name; } @@ -389,7 +390,7 @@ class Sold { uintptr_t RemapTLS(const char* msg, ELFBinary* bin, uintptr_t off); - void LoadDynSymtab(ELFBinary* bin, std::vector& symtab); + void LoadDynSymtab(ELFBinary* bin, std::vector& symtab, bool load_defined_syms); void CopyPublicSymbols(); From d772a4197d021079d9b69e8a88ad413d4464ad41 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:13:25 +0900 Subject: [PATCH 12/21] Support R_X86_64_IRELATIVE --- sold.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sold.cc b/sold.cc index 58ea50d..371fa10 100644 --- a/sold.cc +++ b/sold.cc @@ -599,7 +599,8 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o // erase the relocation entry. The address needs to be fixed at // runtime by ASLR function so we set RELATIVE to these resolved symbols. switch (type) { - case R_X86_64_RELATIVE: { + case R_X86_64_RELATIVE: + case R_X86_64_IRELATIVE: { if (IsDefined(*sym)) { LOG(WARNING) << "The symbol associated with R_X86_64_RELATIVE is defined. Because this relocation type doesn't need any " From a07010407bbd21a07278c766bc9d7d04bc0579e1 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:14:22 +0900 Subject: [PATCH 13/21] Extend PT_LOAD for copying --- sold.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sold.cc b/sold.cc index 371fa10..884f199 100644 --- a/sold.cc +++ b/sold.cc @@ -279,8 +279,13 @@ void Sold::EmitPhdrs(FILE* fp) { phdrs.push_back(phdr); } - for (const Load& load : loads_) { - phdrs.push_back(load.emit); + // I agree this is very bad hack. But I need this to make reloc_copy_ working. + for (int i = 0; i < loads_.size(); i++) { + Elf_Phdr p = loads_[i].emit; + if (i == loads_.size() - 1 || loads_[i].emit.p_vaddr + loads_[i].emit.p_memsz <= loads_[i + 1].emit.p_vaddr) { + p.p_filesz = p.p_memsz; + } + phdrs.emplace_back(p); } if (tls_.memsz) { From a69b18eb105ef94ba3beceaabaab508598000bbe Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:16:49 +0900 Subject: [PATCH 14/21] Add more logs --- sold.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sold.cc b/sold.cc index 884f199..0390138 100644 --- a/sold.cc +++ b/sold.cc @@ -399,7 +399,7 @@ void Sold::DecideMemOffset() { const Range range = bin->GetRange() + offset; CHECK(range.start == offset) << "sold cannot handle other than shared objects."; offsets_.emplace(bin, range.start); - LOG(INFO) << "Assigned: " << bin->soname() << " " << HexString(range.start, 8) << "-" << HexString(range.end, 8); + LOG(INFO) << "Assigned: " << bin->filename() << " " << HexString(range.start, 8) << "-" << HexString(range.end, 8); offset = range.end; } tls_offset_ = offset; @@ -527,6 +527,7 @@ void Sold::LoadDynSymtab(ELFBinary* bin, std::vector& symtab, bool load // Push all global symbols of main_binary_ into public_syms_. // Push all TLS symbols into public_syms_. // TODO(akawashiro) Does public_syms_ overlap with exposed_syms_? +// TODO(akawashiro): Is this working? void Sold::CopyPublicSymbols() { for (const auto& p : main_binary_->GetSymbolMap()) { const Elf_Sym* sym = p.sym; @@ -597,7 +598,7 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o newrels.emplace_back(newrel); } - LOG(INFO) << "Relocate " << bin->Str(sym->st_name) << " at " << rel->r_offset; + LOG(INFO) << "Relocate " << bin->Str(sym->st_name) << " at " << rel->r_offset << " type=" << ShowRelocationType(type); for (auto newrel : newrels) { // Even if we found a defined symbol in src_syms_, we cannot @@ -612,6 +613,7 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o "symbol, something wrong may have happened."; } newrel.r_addend += offset; + LOG(INFO) << SOLD_LOG_BITS(newrel.r_offset) << SOLD_LOG_BITS(newrel.r_addend); break; } @@ -621,9 +623,12 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o if (syms_.Resolve(bin->Str(sym->st_name), soname, version_name, val_or_index)) { newrel.r_info = ELF_R_INFO(0, R_X86_64_RELATIVE); newrel.r_addend = val_or_index; + + LOG(INFO) << SOLD_LOG_BITS(newrel.r_offset) << SOLD_LOG_BITS(newrel.r_addend); } else { newrel.r_info = ELF_R_INFO(val_or_index, type); } + LOG(INFO) << SOLD_LOG_BITS(newrel.r_offset) << SOLD_LOG_BITS(newrel.r_addend); break; } @@ -635,6 +640,7 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o } else { newrel.r_info = ELF_R_INFO(val_or_index, type); } + LOG(INFO) << SOLD_LOG_BITS(newrel.r_offset) << SOLD_LOG_BITS(newrel.r_addend); break; } @@ -742,6 +748,8 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o CHECK(false); } + LOG(INFO) << SOLD_LOG_BITS(newrel.r_offset) << SOLD_LOG_BITS(newrel.r_addend) << " " << ShowRelocationType(type) << " " + << SOLD_LOG_BITS(rel->r_addend) << SOLD_LOG_BITS(rel->r_offset); rels_.push_back(newrel); } } From d2055e3fc1e2130291231ac0072475264dc0c9a9 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:17:18 +0900 Subject: [PATCH 15/21] Collect reloc_copy info --- sold.cc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/sold.cc b/sold.cc index 0390138..ac37a55 100644 --- a/sold.cc +++ b/sold.cc @@ -738,8 +738,32 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o case R_X86_64_COPY: { const std::string name = bin->Str(sym->st_name); - uintptr_t index = syms_.ResolveCopy(name, soname, version_name); - newrel.r_info = ELF_R_INFO(index, type); + uintptr_t val_or_index; + + bool is_defined = syms_.ResolveCopy(name, soname, version_name, &val_or_index); + if (is_defined && is_executable_) { + const void* reloc_src = nullptr; + for (const ELFBinary* bin : link_binaries_) { + if (bin == main_binary_.get()) continue; + for (int i = 0; i < bin->GetSymbolMap().size(); i++) { + const Syminfo& s = bin->GetSymbolMap()[i]; + if (s.name == name && s.soname == soname && s.version == version_name) { + reloc_src = bin->symps()[i]; + } + } + } + + if (reloc_src != nullptr) { + CHECK(reloc_src != nullptr) << name; + void* reloc_dest = reinterpret_cast(bin->head_mut() + bin->OffsetFromAddr(rel->r_offset)); + reloc_copy_.emplace_back(std::make_tuple(newrel.r_offset, reloc_src, sym->st_size)); + goto skip_newrel; + } else { + newrel.r_info = ELF_R_INFO(val_or_index, type); + } + } else { + newrel.r_info = ELF_R_INFO(val_or_index, type); + } break; } @@ -751,6 +775,7 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o LOG(INFO) << SOLD_LOG_BITS(newrel.r_offset) << SOLD_LOG_BITS(newrel.r_addend) << " " << ShowRelocationType(type) << " " << SOLD_LOG_BITS(rel->r_addend) << SOLD_LOG_BITS(rel->r_offset); rels_.push_back(newrel); + skip_newrel:; } } From 7bc0ef48185416ebf42408cddac883b689c41762 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:17:31 +0900 Subject: [PATCH 16/21] Format --- sold.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sold.cc b/sold.cc index ac37a55..0392e81 100644 --- a/sold.cc +++ b/sold.cc @@ -657,8 +657,7 @@ void Sold::RelocateSymbol_x86_64(ELFBinary* bin, const Elf_Rel* rel, uintptr_t o break; } - uint64_t* mod_on_got = - reinterpret_cast(bin->head_mut() + bin->OffsetFromAddr(rel->r_offset)); + uint64_t* mod_on_got = reinterpret_cast(bin->head_mut() + bin->OffsetFromAddr(rel->r_offset)); uint64_t* offset_on_got = mod_on_got + 1; const bool is_bss = bin->IsOffsetInTLSBSS(*offset_on_got); From 1eb250930341e2e5475f3d87d7c45290857c317f Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:17:59 +0900 Subject: [PATCH 17/21] Improve extern test --- feature_unit_tests/extern/hoge.c | 1 + feature_unit_tests/extern/main.c | 9 ++++----- feature_unit_tests/extern/test.sh | 3 --- feature_unit_tests/run-all-tests.sh | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/feature_unit_tests/extern/hoge.c b/feature_unit_tests/extern/hoge.c index 15e3789..21523fb 100644 --- a/feature_unit_tests/extern/hoge.c +++ b/feature_unit_tests/extern/hoge.c @@ -2,4 +2,5 @@ int hoge_var = 0xdeadbeef; void inc() { hoge_var++; + printf("%s:%d hoge_var = %x &hoge_var = %x\n", __FILE__, __LINE__, hoge_var, &hoge_var); } diff --git a/feature_unit_tests/extern/main.c b/feature_unit_tests/extern/main.c index 6a65e3b..d45a25b 100644 --- a/feature_unit_tests/extern/main.c +++ b/feature_unit_tests/extern/main.c @@ -6,13 +6,12 @@ int fuga_var = 0xaaaaaaaa; void inc(); int main() { - printf("hoge_var = %x &hoge_var = %x\n", hoge_var, &hoge_var); - printf("hoge_var = %x &hoge_var = %x\n", *((&hoge_var - 1)), (&hoge_var - 1)); - printf("hoge_var = %x &hoge_var = %x\n", *((&hoge_var - 2)), (&hoge_var - 2)); + printf("%s:%d hoge_var = %x &hoge_var = %x\n", __FILE__, __LINE__, hoge_var, &hoge_var); + printf("%s:%d *((&hoge_var - 1)) = %x &(&hoge_var - 1) = %x\n", __FILE__, __LINE__, *((&hoge_var - 1)), (&hoge_var - 1)); + printf("%s:%d *((&hoge_var - 2)) = %x &(&hoge_var - 2) = %x\n", __FILE__, __LINE__, *((&hoge_var - 2)), (&hoge_var - 2)); assert(hoge_var == 0xdeadbeef); inc(); - printf("hoge_var = %x &hoge_var = %x\n", hoge_var, &hoge_var); + printf("%s:%d hoge_var = %x &hoge_var = %x\n", __FILE__, __LINE__, hoge_var, &hoge_var); assert(hoge_var == 0xdeadbeef + 1); - hoge_var = 3; return 0; } diff --git a/feature_unit_tests/extern/test.sh b/feature_unit_tests/extern/test.sh index 670ed92..4b4dd6a 100755 --- a/feature_unit_tests/extern/test.sh +++ b/feature_unit_tests/extern/test.sh @@ -1,8 +1,5 @@ #! /bin/bash -eux -pushd ~/sold/build -ninja -popd gcc hoge.c -fPIC -shared -Wl,-soname,libhoge.so -o libhoge.so gcc main.c libhoge.so -rdynamic -export-dynamic # GLOG_logtostderr=1 ../../build/print_dynsymtab libhoge.so diff --git a/feature_unit_tests/run-all-tests.sh b/feature_unit_tests/run-all-tests.sh index 6cb6860..9f01b4e 100755 --- a/feature_unit_tests/run-all-tests.sh +++ b/feature_unit_tests/run-all-tests.sh @@ -3,8 +3,7 @@ unexpected_failed_tests= unexpected_succeeded_tests= -# TODO(akawashiro): extern -for dir in hello-g++ hello-gcc just-return-g++ just-return-gcc simple-lib-g++ simple-lib-gcc version-gcc tls-lib-gcc tls-lib-gcc-without-base tls-multiple-lib-gcc tls-thread-g++ call_once-g++ inheritance-g++ typeid-g++ dynamic_cast-g++ tls-dlopen-gcc static-in-function-g++ static-in-class-g++ tls-multiple-module-g++ exception-g++ stb_gnu_unique_tls setjmp-gcc tls-bss-gcc tls-bss-g++ hello-g++-aarch64 hello-gcc-aarch64 just-return-g++-aarch64 simple-lib-g++-aarch64 simple-lib-gcc-aarch64 version-gcc-aarch64 tls-bss-gcc-aarch64 tls-bss-g++-aarch64 just-return-gcc-aarch64 setjmp-gcc-aarch64 exception-g++-aarch64 typeid-g++-aarch64 inheritance-g++-aarch64 dynamic_cast-g++-aarch64 static-in-class-g++-aarch64 static-in-function-g++-aarch64 tls-lib-gcc-aarch64 stb_gnu_unique_tls-aarch64 tls-multiple-module-g++-aarch64 tls-dlopen-gcc-aarch64 call_once-g++-aarch64 tls-thread-g++-aarch64 tls-lib-gcc-without-base-aarch64 +for dir in extern hello-g++ hello-gcc just-return-g++ just-return-gcc simple-lib-g++ simple-lib-gcc version-gcc tls-lib-gcc tls-lib-gcc-without-base tls-multiple-lib-gcc tls-thread-g++ call_once-g++ inheritance-g++ typeid-g++ dynamic_cast-g++ tls-dlopen-gcc static-in-function-g++ static-in-class-g++ tls-multiple-module-g++ exception-g++ stb_gnu_unique_tls setjmp-gcc tls-bss-gcc tls-bss-g++ hello-g++-aarch64 hello-gcc-aarch64 just-return-g++-aarch64 simple-lib-g++-aarch64 simple-lib-gcc-aarch64 version-gcc-aarch64 tls-bss-gcc-aarch64 tls-bss-g++-aarch64 just-return-gcc-aarch64 setjmp-gcc-aarch64 exception-g++-aarch64 typeid-g++-aarch64 inheritance-g++-aarch64 dynamic_cast-g++-aarch64 static-in-class-g++-aarch64 static-in-function-g++-aarch64 tls-lib-gcc-aarch64 stb_gnu_unique_tls-aarch64 tls-multiple-module-g++-aarch64 tls-dlopen-gcc-aarch64 call_once-g++-aarch64 tls-thread-g++-aarch64 tls-lib-gcc-without-base-aarch64 do pushd `pwd` cd $dir From 0f5063526a653f1e540929c3787b8f8fbc47faa8 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:19:49 +0900 Subject: [PATCH 18/21] Remove unused code --- symtab_builder.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/symtab_builder.cc b/symtab_builder.cc index e6f0094..f5dd382 100644 --- a/symtab_builder.cc +++ b/symtab_builder.cc @@ -171,11 +171,6 @@ bool SymtabBuilder::ResolveCopy(const std::string& name, const std::string& sona *val_or_index = sym.index; return false; } else { - // *val_or_index = sym.sym.st_value; - // Destination - std::cerr << SOLD_LOG_KEY(name) << SOLD_LOG_BITS(sym.sym.st_value) << std::endl; - // current master - // return false; *val_or_index = sym.index; return true; } From f73cacfac9d5019386a6323a3124228276cbac14 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 20:23:46 +0900 Subject: [PATCH 19/21] WIP --- symtab_builder.cc | 15 +++++++++++---- tests/exe.cc | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/symtab_builder.cc b/symtab_builder.cc index f5dd382..d320493 100644 --- a/symtab_builder.cc +++ b/symtab_builder.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -30,6 +31,7 @@ SymtabBuilder::SymtabBuilder() { si.sym = NULL; Symbol sym{}; + sym.sym.st_size = 0; AddSym(si); CHECK(syms_.emplace(std::make_tuple("", "", ""), sym).second); @@ -75,6 +77,11 @@ bool SymtabBuilder::Resolve(const std::string& name, const std::string& soname, auto found = syms_.find({name, soname, version}); if (found != syms_.end()) { + std::string s; + for (const auto& t : syms_) { + s += std::get<0>(t.first) + ", "; + } + LOG(INFO) << SOLD_LOG_KEY(name) << SOLD_LOG_KEY(soname) << SOLD_LOG_KEY(version) << SOLD_LOG_KEY(found->second.index) << s; sym = found->second; } else { Elf_Versym versym = 0; @@ -106,10 +113,10 @@ bool SymtabBuilder::Resolve(const std::string& name, const std::string& soname, CHECK(syms_.emplace(std::make_tuple(name, soname, version), sym).second); } } else { - LOG(INFO) << "Symbol (" << name << ", " << soname << ", " << version << ") not found"; - Syminfo s{name, soname, version, VER_NDX_LOCAL, NULL}; - sym.index = AddSym(s); - CHECK(syms_.emplace(std::make_tuple(name, soname, version), sym).second); + LOG(FATAL) << "Symbol (" << name << ", " << soname << ", " << version << ") not found"; + // Syminfo s{name, soname, version, VER_NDX_LOCAL, NULL}; + // sym.index = AddSym(s); + // CHECK(syms_.emplace(std::make_tuple(name, soname, version), sym).second); } } diff --git a/tests/exe.cc b/tests/exe.cc index 846c2b7..1bdf230 100644 --- a/tests/exe.cc +++ b/tests/exe.cc @@ -20,7 +20,7 @@ int main(int argc, char** argv) { if (lib_add_42_via_base(10) != 52) abort(); if (in_both_lib_and_base() != 100) abort(); - fprintf(stderr, "Use stderr from main\n"); + // fprintf(stderr, "Use stderr from main\n"); lib_use_stderr(); if (g_init != 42) abort(); From 79e1b685231ea9f2204459b2bf3b3e4ca8fb2037 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 21:14:24 +0900 Subject: [PATCH 20/21] WIP --- tests/exe.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/exe.cc b/tests/exe.cc index 1bdf230..846c2b7 100644 --- a/tests/exe.cc +++ b/tests/exe.cc @@ -20,7 +20,7 @@ int main(int argc, char** argv) { if (lib_add_42_via_base(10) != 52) abort(); if (in_both_lib_and_base() != 100) abort(); - // fprintf(stderr, "Use stderr from main\n"); + fprintf(stderr, "Use stderr from main\n"); lib_use_stderr(); if (g_init != 42) abort(); From 2a8235925cd058a1bd0d515a621b84e238796e73 Mon Sep 17 00:00:00 2001 From: Akira Kawata Date: Sun, 28 Nov 2021 22:38:49 +0900 Subject: [PATCH 21/21] WIP --- feature_unit_tests/run-all-tests.sh | 2 +- feature_unit_tests/stdcerr-main-gcc/hoge.c | 5 +++++ feature_unit_tests/stdcerr-main-gcc/main.c | 9 +++++++++ feature_unit_tests/stdcerr-main-gcc/test.sh | 7 +++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 feature_unit_tests/stdcerr-main-gcc/hoge.c create mode 100644 feature_unit_tests/stdcerr-main-gcc/main.c create mode 100755 feature_unit_tests/stdcerr-main-gcc/test.sh diff --git a/feature_unit_tests/run-all-tests.sh b/feature_unit_tests/run-all-tests.sh index 9f01b4e..1bc5820 100755 --- a/feature_unit_tests/run-all-tests.sh +++ b/feature_unit_tests/run-all-tests.sh @@ -3,7 +3,7 @@ unexpected_failed_tests= unexpected_succeeded_tests= -for dir in extern hello-g++ hello-gcc just-return-g++ just-return-gcc simple-lib-g++ simple-lib-gcc version-gcc tls-lib-gcc tls-lib-gcc-without-base tls-multiple-lib-gcc tls-thread-g++ call_once-g++ inheritance-g++ typeid-g++ dynamic_cast-g++ tls-dlopen-gcc static-in-function-g++ static-in-class-g++ tls-multiple-module-g++ exception-g++ stb_gnu_unique_tls setjmp-gcc tls-bss-gcc tls-bss-g++ hello-g++-aarch64 hello-gcc-aarch64 just-return-g++-aarch64 simple-lib-g++-aarch64 simple-lib-gcc-aarch64 version-gcc-aarch64 tls-bss-gcc-aarch64 tls-bss-g++-aarch64 just-return-gcc-aarch64 setjmp-gcc-aarch64 exception-g++-aarch64 typeid-g++-aarch64 inheritance-g++-aarch64 dynamic_cast-g++-aarch64 static-in-class-g++-aarch64 static-in-function-g++-aarch64 tls-lib-gcc-aarch64 stb_gnu_unique_tls-aarch64 tls-multiple-module-g++-aarch64 tls-dlopen-gcc-aarch64 call_once-g++-aarch64 tls-thread-g++-aarch64 tls-lib-gcc-without-base-aarch64 +for dir in stdcerr-main-gcc extern hello-g++ hello-gcc just-return-g++ just-return-gcc simple-lib-g++ simple-lib-gcc version-gcc tls-lib-gcc tls-lib-gcc-without-base tls-multiple-lib-gcc tls-thread-g++ call_once-g++ inheritance-g++ typeid-g++ dynamic_cast-g++ tls-dlopen-gcc static-in-function-g++ static-in-class-g++ tls-multiple-module-g++ exception-g++ stb_gnu_unique_tls setjmp-gcc tls-bss-gcc tls-bss-g++ hello-g++-aarch64 hello-gcc-aarch64 just-return-g++-aarch64 simple-lib-g++-aarch64 simple-lib-gcc-aarch64 version-gcc-aarch64 tls-bss-gcc-aarch64 tls-bss-g++-aarch64 just-return-gcc-aarch64 setjmp-gcc-aarch64 exception-g++-aarch64 typeid-g++-aarch64 inheritance-g++-aarch64 dynamic_cast-g++-aarch64 static-in-class-g++-aarch64 static-in-function-g++-aarch64 tls-lib-gcc-aarch64 stb_gnu_unique_tls-aarch64 tls-multiple-module-g++-aarch64 tls-dlopen-gcc-aarch64 call_once-g++-aarch64 tls-thread-g++-aarch64 tls-lib-gcc-without-base-aarch64 do pushd `pwd` cd $dir diff --git a/feature_unit_tests/stdcerr-main-gcc/hoge.c b/feature_unit_tests/stdcerr-main-gcc/hoge.c new file mode 100644 index 0000000..a4b30b6 --- /dev/null +++ b/feature_unit_tests/stdcerr-main-gcc/hoge.c @@ -0,0 +1,5 @@ +#include + +void hello_from_hoge() { + fprintf(stderr, "%s:%d hello from stderr\n", __FILE__, __LINE__); +} diff --git a/feature_unit_tests/stdcerr-main-gcc/main.c b/feature_unit_tests/stdcerr-main-gcc/main.c new file mode 100644 index 0000000..cf157ae --- /dev/null +++ b/feature_unit_tests/stdcerr-main-gcc/main.c @@ -0,0 +1,9 @@ +#include + +void hello_from_hoge(); + +int main() { + fprintf(stderr, "%s:%d hello from stderr\n", __FILE__, __LINE__); + hello_from_hoge(); + return 0; +} diff --git a/feature_unit_tests/stdcerr-main-gcc/test.sh b/feature_unit_tests/stdcerr-main-gcc/test.sh new file mode 100755 index 0000000..5c7cf18 --- /dev/null +++ b/feature_unit_tests/stdcerr-main-gcc/test.sh @@ -0,0 +1,7 @@ +#! /bin/bash -eux + +gcc -o libhoge.so -shared -fpic -fPIC -Wl,-soname,libhoge.so hoge.c +gcc -o main main.c libhoge.so +GLOG_log_dir=. LD_LIBRARY_PATH=. $(git rev-parse --show-toplevel)/build/sold -i main -o main.soldout --section-headers + +LD_LIBRARY_PATH=. ./main.soldout