diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-07-21 20:46:21 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-07-21 20:46:21 +0000 |
commit | 1cb8a19bcb32a8319bdb34a18c29b9f44b02af17 (patch) | |
tree | 84ee142540d316538e4b6356f292fce4061edb00 | |
parent | af346433b1c6417aa27fcc8b9b2b654a5aa0edc8 (diff) | |
download | bcm5719-llvm-1cb8a19bcb32a8319bdb34a18c29b9f44b02af17.tar.gz bcm5719-llvm-1cb8a19bcb32a8319bdb34a18c29b9f44b02af17.zip |
Don't assume ELFFile iterates over the program headers.
It will stop doing so shortly.
llvm-svn: 242832
-rw-r--r-- | lld/lib/ReaderWriter/ELF/DynamicFile.cpp | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/lld/lib/ReaderWriter/ELF/DynamicFile.cpp b/lld/lib/ReaderWriter/ELF/DynamicFile.cpp index a8209dedef2..33044a23c29 100644 --- a/lld/lib/ReaderWriter/ELF/DynamicFile.cpp +++ b/lld/lib/ReaderWriter/ELF/DynamicFile.cpp @@ -55,6 +55,8 @@ template <class ELFT> bool DynamicFile<ELFT>::canParse(file_magic magic) { template <class ELFT> std::error_code DynamicFile<ELFT>::doParse() { typedef llvm::object::ELFFile<ELFT> 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 <class ELFT> std::error_code DynamicFile<ELFT>::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<const Elf_Dyn *>(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<StringRef> 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. |