diff --git a/include/LIEF/ELF/Symbol.hpp b/include/LIEF/ELF/Symbol.hpp index b4608f4951..c81d5d0e61 100644 --- a/include/LIEF/ELF/Symbol.hpp +++ b/include/LIEF/ELF/Symbol.hpp @@ -43,8 +43,8 @@ class LIEF_API Symbol : public LIEF::Symbol { friend class Binary; public: - Symbol(const details::Elf32_Sym& header); - Symbol(const details::Elf64_Sym& header); + Symbol(const details::Elf32_Sym& header, ARCH arch); + Symbol(const details::Elf64_Sym& header, ARCH arch); Symbol(std::string name, ELF_SYMBOL_TYPES type = ELF_SYMBOL_TYPES::STT_NOTYPE, SYMBOL_BINDINGS binding = SYMBOL_BINDINGS::STB_WEAK, @@ -173,6 +173,7 @@ class LIEF_API Symbol : public LIEF::Symbol { uint16_t shndx_ = 0; Section* section_ = nullptr; SymbolVersion* symbol_version_ = nullptr; + ARCH arch_ = ARCH::EM_NONE; }; } } diff --git a/src/ELF/Parser.tcc b/src/ELF/Parser.tcc index 0159a301a5..fb05e17203 100644 --- a/src/ELF/Parser.tcc +++ b/src/ELF/Parser.tcc @@ -992,8 +992,11 @@ ok_error_t Parser::parse_static_symbols(uint64_t offset, uint32_t nb_symbols, if (!raw_sym) { break; } - auto symbol = std::make_unique(std::move(*raw_sym)); - auto symbol_name = stream_->peek_string_at(string_section.file_offset() + raw_sym->st_name); + auto symbol = std::make_unique(std::move(*raw_sym), + binary_->header().machine_type()); + + const auto name_offset = string_section.file_offset() + raw_sym->st_name; + auto symbol_name = stream_->peek_string_at(name_offset); if (symbol_name) { symbol->name(std::move(*symbol_name)); } else { @@ -1044,7 +1047,8 @@ ok_error_t Parser::parse_dynamic_symbols(uint64_t offset) { LIEF_DEBUG("Break on symbol #{:d}", i); break; } - auto symbol = std::make_unique(std::move(*symbol_header)); + auto symbol = std::make_unique(std::move(*symbol_header), + binary_->header().machine_type()); if (symbol_header->st_name > 0) { auto name = stream_->peek_string_at(string_offset + symbol_header->st_name); diff --git a/src/ELF/Symbol.cpp b/src/ELF/Symbol.cpp index db468610af..70e463263a 100644 --- a/src/ELF/Symbol.cpp +++ b/src/ELF/Symbol.cpp @@ -45,7 +45,8 @@ Symbol::Symbol(const Symbol& other) : LIEF::Symbol{other}, type_{other.type_}, binding_{other.binding_}, other_{other.other_}, - shndx_{other.shndx_} + shndx_{other.shndx_}, + arch_{other.arch_} {} @@ -57,23 +58,26 @@ void Symbol::swap(Symbol& other) { std::swap(shndx_, other.shndx_); std::swap(section_, other.section_); std::swap(symbol_version_, other.symbol_version_); + std::swap(arch_, other.arch_); } -Symbol::Symbol(const details::Elf32_Sym& header) : +Symbol::Symbol(const details::Elf32_Sym& header, ARCH arch) : type_{static_cast(header.st_info & 0x0f)}, binding_{static_cast(header.st_info >> 4)}, other_{header.st_other}, - shndx_{header.st_shndx} + shndx_{header.st_shndx}, + arch_{arch} { value_ = header.st_value; size_ = header.st_size; } -Symbol::Symbol(const details::Elf64_Sym& header) : +Symbol::Symbol(const details::Elf64_Sym& header, ARCH arch) : type_{static_cast(header.st_info & 0x0f)}, binding_{static_cast(header.st_info >> 4)}, other_{header.st_other}, - shndx_{header.st_shndx} + shndx_{header.st_shndx}, + arch_{arch} { value_ = header.st_value; size_ = header.st_size; @@ -214,8 +218,14 @@ bool Symbol::is_imported() const { // An import must not be defined in a section bool is_imported = shndx() == static_cast(SYMBOL_SECTION_INDEX::SHN_UNDEF); - // An import must not have an address - is_imported = is_imported && value() == 0; + const bool is_mips = arch_ == ARCH::EM_MIPS || arch_ == ARCH::EM_MIPS_X || + arch_ == ARCH::EM_MIPS_RS3_LE; + const bool is_ppc = arch_ == ARCH::EM_PPC || arch_ == ARCH::EM_PPC64; + + // An import must not have an address (except for some architectures like Mips/PPC) + if (!is_mips && !is_ppc) { + is_imported = is_imported && value() == 0; + } // its name must not be empty is_imported = is_imported && !name().empty(); @@ -239,16 +249,10 @@ void Symbol::set_imported(bool flag) { } } - - void Symbol::accept(Visitor& visitor) const { visitor.visit(*this); } - - - - std::ostream& operator<<(std::ostream& os, const Symbol& entry) { std::string name = entry.demangled_name(); diff --git a/tests/elf/test_issues.py b/tests/elf/test_issues.py index 72e1b30057..da1eeed2dd 100755 --- a/tests/elf/test_issues.py +++ b/tests/elf/test_issues.py @@ -19,3 +19,7 @@ def test_issue_863(tmp_path: Path): new = lief.parse(out.as_posix()) assert new.sysv_hash.nchain == 6 +def test_pr_968(): + elf = lief.ELF.parse(get_sample('ELF/echo.mips_r3000.bin')) + sym: lief.ELF.Symbol = elf.get_symbol("strstr") + assert sym.imported