From 1cb8a19bcb32a8319bdb34a18c29b9f44b02af17 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 21 Jul 2015 20:46:21 +0000 Subject: [PATCH] Don't assume ELFFile iterates over the program headers. It will stop doing so shortly. llvm-svn: 242832 --- lld/lib/ReaderWriter/ELF/DynamicFile.cpp | 33 ++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/lld/lib/ReaderWriter/ELF/DynamicFile.cpp b/lld/lib/ReaderWriter/ELF/DynamicFile.cpp index a8209de..33044a2 100644 --- a/lld/lib/ReaderWriter/ELF/DynamicFile.cpp +++ b/lld/lib/ReaderWriter/ELF/DynamicFile.cpp @@ -55,6 +55,8 @@ template bool DynamicFile::canParse(file_magic magic) { template std::error_code DynamicFile::doParse() { typedef llvm::object::ELFFile ELFO; + typedef typename ELFO::Elf_Shdr Elf_Shdr; + typedef typename ELFO::Elf_Dyn Elf_Dyn; std::error_code ec; _objFile.reset(new ELFO(_mb->getBuffer(), ec)); @@ -63,16 +65,39 @@ template std::error_code DynamicFile::doParse() { ELFO &obj = *_objFile; - _soname = obj.getLoadName(); - if (_soname.empty()) - _soname = llvm::sys::path::filename(path()); + const char *base = _mb->getBuffer().data(); + const Elf_Dyn *dynStart = nullptr; + const Elf_Dyn *dynEnd = nullptr; + for (const Elf_Shdr &sec : obj.sections()) { + if (sec.sh_type == llvm::ELF::SHT_DYNAMIC) { + dynStart = reinterpret_cast(base + sec.sh_offset); + uint64_t size = sec.sh_size; + if (size % sizeof(Elf_Dyn)) + return llvm::object::object_error::parse_failed; + dynEnd = dynStart + size / sizeof(Elf_Dyn); + break; + } + } - const typename ELFO::Elf_Shdr *dynSymSec = obj.getDotDynSymSec(); + const Elf_Shdr *dynSymSec = obj.getDotDynSymSec(); ErrorOr strTableOrErr = obj.getStringTableForSymtab(*dynSymSec); if (std::error_code ec = strTableOrErr.getError()) return ec; StringRef stringTable = *strTableOrErr; + for (const Elf_Dyn &dyn : llvm::make_range(dynStart, dynEnd)) { + if (dyn.d_tag == llvm::ELF::DT_SONAME) { + uint64_t offset = dyn.getVal(); + if (offset >= stringTable.size()) + return llvm::object::object_error::parse_failed; + _soname = StringRef(stringTable.data() + offset); + break; + } + } + + if (_soname.empty()) + _soname = llvm::sys::path::filename(path()); + // Create a map from names to dynamic symbol table entries. // TODO: This should use the object file's build in hash table instead if // it exists. -- 2.7.4