diff --git a/doc/sphinx/changelog.rst b/doc/sphinx/changelog.rst index 237c2a4abc..8f367be562 100644 --- a/doc/sphinx/changelog.rst +++ b/doc/sphinx/changelog.rst @@ -37,6 +37,7 @@ Changelog :MachO: + * Fix endianness support (:issue:`1110`) * Add helpers to determine the platform targeted by a Mach-O binary: - :attr:`lief.MachO.Binary.is_ios` diff --git a/include/LIEF/BinaryStream/BinaryStream.hpp b/include/LIEF/BinaryStream/BinaryStream.hpp index 10cdeb1442..2120d8e3f2 100644 --- a/include/LIEF/BinaryStream/BinaryStream.hpp +++ b/include/LIEF/BinaryStream/BinaryStream.hpp @@ -24,7 +24,7 @@ #include #include -#include "LIEF/BinaryStream/Convert.hpp" +#include "LIEF/endianness_support.hpp" #include "LIEF/errors.hpp" namespace LIEF { @@ -201,31 +201,6 @@ class BinaryStream { size_t align(size_t align_on) const; - /* Functions that are endianness aware */ - template - typename std::enable_if::value, result>::type - peek_conv() const; - - template - typename std::enable_if::value, result>::type - peek_conv() const; - - template - result peek_conv(size_t offset) const; - - template - result read_conv() const; - - /* Read an array of values and adjust endianness as needed */ - template - std::unique_ptr read_conv_array(size_t size) const; - - template - std::unique_ptr peek_conv_array(size_t offset, size_t size) const; - - template - static T swap_endian(T u); - void set_endian_swap(bool swap) { endian_swap_ = swap; } @@ -333,6 +308,50 @@ class ScopedStream { BinaryStream& stream_; }; +class ToggleEndianness { + public: + ToggleEndianness(const ToggleEndianness&) = delete; + ToggleEndianness& operator=(const ToggleEndianness&) = delete; + + ToggleEndianness(ToggleEndianness&&) = delete; + ToggleEndianness& operator=(ToggleEndianness&&) = delete; + + explicit ToggleEndianness(BinaryStream& stream, bool value) : + endian_swap_(stream.should_swap()), + stream_{stream} + { + stream.set_endian_swap(value); + } + + explicit ToggleEndianness(BinaryStream& stream) : + endian_swap_(stream.should_swap()), + stream_{stream} + { + stream.set_endian_swap(!stream_.should_swap()); + } + + ~ToggleEndianness() { + stream_.set_endian_swap(endian_swap_); + } + + BinaryStream* operator->() { + return &stream_; + } + + BinaryStream& operator*() { + return stream_; + } + + const BinaryStream& operator*() const { + return stream_; + } + + private: + bool endian_swap_ = false; + BinaryStream& stream_; +}; + + template result BinaryStream::read() const { @@ -350,6 +369,9 @@ result BinaryStream::peek() const { T ret{}; if (auto res = peek_in(&ret, pos(), sizeof(T))) { setpos(current_p); + if (endian_swap_) { + swap_endian(&ret); + } return ret; } @@ -409,88 +431,5 @@ const T* BinaryStream::read_array(size_t size) const { return tmp; } - -template -result BinaryStream::read_conv() const { - result tmp = this->peek_conv(); - if (!tmp) { - return tmp; - } - this->increment_pos(sizeof(T)); - return tmp; -} - -template -typename std::enable_if::value, result>::type -BinaryStream::peek_conv() const { - T ret; - if (auto res = peek_in(&ret, pos(), sizeof(T))) { - return endian_swap_ ? swap_endian(ret) : ret; - } - return make_error_code(lief_errors::read_error); -} - -template -typename std::enable_if::value, result>::type -BinaryStream::peek_conv() const { - T ret; - if (auto res = peek_in(&ret, pos(), sizeof(T))) { - if (endian_swap_) { - LIEF::Convert::swap_endian(&ret); - } - return ret; - } - return make_error_code(lief_errors::read_error); -} - - -template -result BinaryStream::peek_conv(size_t offset) const { - const size_t saved_offset = this->pos(); - this->setpos(offset); - result r = this->peek_conv(); - this->setpos(saved_offset); - return r; -} - - -template -std::unique_ptr BinaryStream::read_conv_array(size_t size) const { - const T *t = this->read_array(size); - - if (t == nullptr) { - return nullptr; - } - - std::unique_ptr uptr(new T[size]); - - for (size_t i = 0; i < size; i++) { - uptr[i] = t[i]; - if (this->endian_swap_) { - LIEF::Convert::swap_endian(& uptr[i]); - } /* else no conversion, just provide the copied data */ - } - return uptr; -} - - -template -std::unique_ptr BinaryStream::peek_conv_array(size_t offset, size_t size) const { - const T *t = this->peek_array(offset, size); - - if (t == nullptr) { - return nullptr; - } - - std::unique_ptr uptr(new T[size]); - - for (size_t i = 0; i < size; i++) { - uptr[i] = t[i]; - if (this->endian_swap_) { - LIEF::Convert::swap_endian(& uptr[i]); - } /* else no conversion, just provide the copied data */ - } - return uptr; -} } #endif diff --git a/include/LIEF/endianness_support.hpp b/include/LIEF/endianness_support.hpp new file mode 100644 index 0000000000..73fccfc1a1 --- /dev/null +++ b/include/LIEF/endianness_support.hpp @@ -0,0 +1,221 @@ +/* Copyright 2021 - 2024 R. Thomas + * Copyright 2021 - 2024 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LIEF_ENDIANNESS_SUPPORT_H +#define LIEF_ENDIANNESS_SUPPORT_H +#include +#include "LIEF/config.h" + +#define LIEF_ENDIAN_SUPPORT(X) \ + template<> \ + void swap_endian(X* hdr) + +namespace LIEF { + +namespace ELF { +namespace details { +struct Elf32_Auxv; +struct Elf32_Dyn; +struct Elf32_Ehdr; +struct Elf32_FileEntry; +struct Elf32_Phdr; +struct Elf32_Rel; +struct Elf32_Rela; +struct Elf32_Shdr; +struct Elf32_Sym; +struct Elf32_Verdaux; +struct Elf32_Verdef; +struct Elf32_Vernaux; +struct Elf32_Verneed; +struct Elf64_Auxv; +struct Elf64_Dyn; +struct Elf64_Ehdr; +struct Elf64_FileEntry; +struct Elf64_Phdr; +struct Elf64_Rel; +struct Elf64_Rela; +struct Elf64_Shdr; +struct Elf64_Sym; +struct Elf64_Verdaux; +struct Elf64_Verdef; +struct Elf64_Vernaux; +struct Elf64_Verneed; +} +} + +namespace MachO { +namespace details { +struct arm_thread_state64_t; +struct arm_thread_state_t; +struct build_tool_version; +struct build_version_command; +struct data_in_code_entry; +struct dyld_info_command; +struct dylib_command; +struct dylib_module_32; +struct dylib_module_64; +struct dylib_reference; +struct dylib_table_of_contents; +struct dylinker_command; +struct dysymtab_command; +struct encryption_info_command; +struct entry_point_command; +struct fileset_entry_command; +struct fvmfile_command; +struct ident_command; +struct linkedit_data_command; +struct linker_option_command; +struct load_command; +struct mach_header; +struct mach_header_64; +struct nlist_32; +struct nlist_64; +struct prebind_cksum_command; +struct prebound_dylib_command; +struct relocation_info; +struct routines_command_32; +struct routines_command_64; +struct rpath_command; +struct scattered_relocation_info; +struct section_32; +struct section_64; +struct segment_command_32; +struct segment_command_64; +struct source_version_command; +struct sub_client_command; +struct sub_framework_command; +struct sub_library_command; +struct sub_umbrella_command; +struct symseg_command; +struct symtab_command; +struct thread_command; +struct twolevel_hint; +struct twolevel_hints_command; +struct uuid_command; +struct version_min_command; +struct x86_thread_state64_t; +struct x86_thread_state_t; +} +} + +template +void swap_endian(T*) { +} + +template +T get_swapped_endian(const T& other) { + T tmp = other; + swap_endian(&tmp); + return tmp; +} + +LIEF_ENDIAN_SUPPORT(char); +LIEF_ENDIAN_SUPPORT(char16_t); + +LIEF_ENDIAN_SUPPORT(uint8_t); +LIEF_ENDIAN_SUPPORT(uint16_t); +LIEF_ENDIAN_SUPPORT(uint32_t); +LIEF_ENDIAN_SUPPORT(uint64_t); + +LIEF_ENDIAN_SUPPORT(int8_t); +LIEF_ENDIAN_SUPPORT(int16_t); +LIEF_ENDIAN_SUPPORT(int32_t); +LIEF_ENDIAN_SUPPORT(int64_t); + +#if defined (LIEF_ELF_SUPPORT) +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Auxv); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Dyn); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Ehdr); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_FileEntry); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Phdr); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Rel); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Rela); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Shdr); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Sym); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Verdaux); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Verdef); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Vernaux); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf32_Verneed); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Auxv); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Dyn); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Ehdr); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_FileEntry); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Phdr); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Rel); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Rela); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Shdr); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Sym); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Verdaux); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Verdef); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Vernaux); +LIEF_ENDIAN_SUPPORT(ELF::details::Elf64_Verneed); +#endif + +#if defined (LIEF_MACHO_SUPPORT) +LIEF_ENDIAN_SUPPORT(MachO::details::arm_thread_state64_t); +LIEF_ENDIAN_SUPPORT(MachO::details::arm_thread_state_t); +LIEF_ENDIAN_SUPPORT(MachO::details::build_tool_version); +LIEF_ENDIAN_SUPPORT(MachO::details::build_version_command); +LIEF_ENDIAN_SUPPORT(MachO::details::data_in_code_entry); +LIEF_ENDIAN_SUPPORT(MachO::details::dyld_info_command); +LIEF_ENDIAN_SUPPORT(MachO::details::dylib_command); +LIEF_ENDIAN_SUPPORT(MachO::details::dylib_module_32); +LIEF_ENDIAN_SUPPORT(MachO::details::dylib_module_64); +LIEF_ENDIAN_SUPPORT(MachO::details::dylib_reference); +LIEF_ENDIAN_SUPPORT(MachO::details::dylib_table_of_contents); +LIEF_ENDIAN_SUPPORT(MachO::details::dylinker_command); +LIEF_ENDIAN_SUPPORT(MachO::details::dysymtab_command); +LIEF_ENDIAN_SUPPORT(MachO::details::encryption_info_command); +LIEF_ENDIAN_SUPPORT(MachO::details::entry_point_command); +LIEF_ENDIAN_SUPPORT(MachO::details::fileset_entry_command); +LIEF_ENDIAN_SUPPORT(MachO::details::fvmfile_command); +LIEF_ENDIAN_SUPPORT(MachO::details::ident_command); +LIEF_ENDIAN_SUPPORT(MachO::details::linkedit_data_command); +LIEF_ENDIAN_SUPPORT(MachO::details::linker_option_command); +LIEF_ENDIAN_SUPPORT(MachO::details::load_command); +LIEF_ENDIAN_SUPPORT(MachO::details::mach_header); +LIEF_ENDIAN_SUPPORT(MachO::details::mach_header_64); +LIEF_ENDIAN_SUPPORT(MachO::details::nlist_32); +LIEF_ENDIAN_SUPPORT(MachO::details::nlist_64); +LIEF_ENDIAN_SUPPORT(MachO::details::prebind_cksum_command); +LIEF_ENDIAN_SUPPORT(MachO::details::prebound_dylib_command); +LIEF_ENDIAN_SUPPORT(MachO::details::relocation_info); +LIEF_ENDIAN_SUPPORT(MachO::details::routines_command_32); +LIEF_ENDIAN_SUPPORT(MachO::details::routines_command_64); +LIEF_ENDIAN_SUPPORT(MachO::details::rpath_command); +LIEF_ENDIAN_SUPPORT(MachO::details::scattered_relocation_info); +LIEF_ENDIAN_SUPPORT(MachO::details::section_32); +LIEF_ENDIAN_SUPPORT(MachO::details::section_64); +LIEF_ENDIAN_SUPPORT(MachO::details::segment_command_32); +LIEF_ENDIAN_SUPPORT(MachO::details::segment_command_64); +LIEF_ENDIAN_SUPPORT(MachO::details::source_version_command); +LIEF_ENDIAN_SUPPORT(MachO::details::sub_client_command); +LIEF_ENDIAN_SUPPORT(MachO::details::sub_framework_command); +LIEF_ENDIAN_SUPPORT(MachO::details::sub_library_command); +LIEF_ENDIAN_SUPPORT(MachO::details::sub_umbrella_command); +LIEF_ENDIAN_SUPPORT(MachO::details::symseg_command); +LIEF_ENDIAN_SUPPORT(MachO::details::symtab_command); +LIEF_ENDIAN_SUPPORT(MachO::details::thread_command); +LIEF_ENDIAN_SUPPORT(MachO::details::twolevel_hint); +LIEF_ENDIAN_SUPPORT(MachO::details::twolevel_hints_command); +LIEF_ENDIAN_SUPPORT(MachO::details::uuid_command); +LIEF_ENDIAN_SUPPORT(MachO::details::version_min_command); +LIEF_ENDIAN_SUPPORT(MachO::details::x86_thread_state64_t); +LIEF_ENDIAN_SUPPORT(MachO::details::x86_thread_state_t); +#endif + +} + +#endif // LIEF_CONVERT_H diff --git a/include/LIEF/iostream.hpp b/include/LIEF/iostream.hpp index 80452b626d..3467c7aeef 100644 --- a/include/LIEF/iostream.hpp +++ b/include/LIEF/iostream.hpp @@ -23,7 +23,7 @@ #include #include "LIEF/span.hpp" -#include "LIEF/BinaryStream/Convert.hpp" +#include "LIEF/endianness_support.hpp" namespace LIEF { class vector_iostream { @@ -67,17 +67,17 @@ class vector_iostream { if (raw_.size() < (pos + sizeof(T))) { raw_.resize(pos + sizeof(T)); } - memcpy(raw_.data() + pos, &t, sizeof(T)); + if (endian_swap_) { + T tmp = t; + swap_endian(&tmp); + memcpy(raw_.data() + pos, &tmp, sizeof(T)); + } else { + memcpy(raw_.data() + pos, &t, sizeof(T)); + } current_pos_ += sizeof(T); return *this; } - template - vector_iostream& write_conv(const T& t); - - template - vector_iostream& write_conv_array(const std::vector& v); - vector_iostream& align(size_t alignment, uint8_t fill = 0); template @@ -149,36 +149,5 @@ class vector_iostream { }; -template -vector_iostream& vector_iostream::write_conv(const T& t) { - const uint8_t *ptr = nullptr; - T tmp = t; - if (endian_swap_) { - LIEF::Convert::swap_endian(&tmp); - ptr = reinterpret_cast(&tmp); - } else { - ptr = reinterpret_cast(&t); - } - write(ptr, sizeof(T)); - return *this; -} - -template -vector_iostream& vector_iostream::write_conv_array(const std::vector& v) { - for (const T& i: v) { - const uint8_t* ptr = nullptr; - T tmp = i; - if (endian_swap_) { - LIEF::Convert::swap_endian(&tmp); - ptr = reinterpret_cast(&tmp); - } else { - ptr = reinterpret_cast(&i); - } - write(ptr, sizeof(T)); - } - return *this; -} - - } #endif diff --git a/src/BinaryStream/BinaryStream.cpp b/src/BinaryStream/BinaryStream.cpp index f38a3d4310..83e618c6da 100644 --- a/src/BinaryStream/BinaryStream.cpp +++ b/src/BinaryStream/BinaryStream.cpp @@ -20,39 +20,10 @@ #include #include -#include "intmem.h" - #include -#define TMPL_DECL(T) template T BinaryStream::swap_endian(T u) - namespace LIEF { -template -T BinaryStream::swap_endian(T u) { - return intmem::bswap(u); -} - -template<> -char16_t BinaryStream::swap_endian(char16_t u) { - return intmem::bswap(static_cast(u)); -} - -template<> -char BinaryStream::swap_endian(char u) { - return intmem::bswap(static_cast(u)); -} - -TMPL_DECL(uint8_t); -TMPL_DECL(uint16_t); -TMPL_DECL(uint32_t); -TMPL_DECL(uint64_t); - -TMPL_DECL(int8_t); -TMPL_DECL(int16_t); -TMPL_DECL(int32_t); -TMPL_DECL(int64_t); - result BinaryStream::read_dwarf_encoded(uint8_t encoding) const { const auto encodevalue = static_cast(encoding & 0x0F); @@ -222,7 +193,7 @@ result BinaryStream::peek_u16string(size_t length) const { if (peek_in(raw_u16str.data(), pos(), length * sizeof(char16_t))) { if (endian_swap_) { for (char16_t& x : raw_u16str) { - LIEF::Convert::swap_endian(&x); + LIEF::swap_endian(&x); } } return std::u16string{std::begin(raw_u16str), std::end(raw_u16str)}; diff --git a/src/BinaryStream/CMakeLists.txt b/src/BinaryStream/CMakeLists.txt index f4b855e161..8765c36512 100644 --- a/src/BinaryStream/CMakeLists.txt +++ b/src/BinaryStream/CMakeLists.txt @@ -1,7 +1,6 @@ target_sources(LIB_LIEF PRIVATE ASN1Reader.cpp BinaryStream.cpp - Convert.cpp FileStream.cpp MemoryStream.cpp SpanStream.cpp diff --git a/src/BinaryStream/Convert.cpp b/src/BinaryStream/Convert.cpp deleted file mode 100644 index 0bf43f232f..0000000000 --- a/src/BinaryStream/Convert.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2021 - 2024 R. Thomas - * Copyright 2021 - 2024 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "LIEF/BinaryStream/Convert.hpp" -#include "LIEF/BinaryStream/BinaryStream.hpp" - -#define TMPL_DECL(T) template<> void swap_endian(T* u) { *u = BinaryStream::swap_endian(*u); } - -/* In place conversions for BinaryStream/VectorStream data */ -namespace LIEF { -namespace Convert { - -TMPL_DECL(char) -TMPL_DECL(char16_t) - -TMPL_DECL(uint8_t) -TMPL_DECL(uint16_t) -TMPL_DECL(uint32_t) -TMPL_DECL(uint64_t) - -TMPL_DECL(int8_t) -TMPL_DECL(int16_t) -TMPL_DECL(int32_t) -TMPL_DECL(int64_t) - - -} -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fd17c8c4fa..a8bbff8ff8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(LIB_LIEF PRIVATE + endianness_support.cpp Object.tcc Visitor.cpp errors.cpp diff --git a/src/ELF/Builder.cpp b/src/ELF/Builder.cpp index d517bed4c8..ada991e273 100644 --- a/src/ELF/Builder.cpp +++ b/src/ELF/Builder.cpp @@ -162,16 +162,16 @@ ok_error_t Builder::build_empty_symbol_gnuhash() { const uint32_t symndx = 1; // 0 is reserved // nb_buckets - content.write_conv(nb_buckets); + content.write(nb_buckets); // symndx - content.write_conv(symndx); + content.write(symndx); // maskwords - content.write_conv(maskwords); + content.write(maskwords); // shift2 - content.write_conv(shift2); + content.write(shift2); // fill with 0 content.align(gnu_hash_section->size(), 0); diff --git a/src/ELF/Builder.tcc b/src/ELF/Builder.tcc index 0aafcf2f45..143c44a707 100644 --- a/src/ELF/Builder.tcc +++ b/src/ELF/Builder.tcc @@ -653,7 +653,7 @@ ok_error_t Builder::build(const Header& header) {; std::begin(ehdr.e_ident)); ios_.seekp(0); - ios_.write_conv(ehdr); + ios_.write(ehdr); return ok(); } @@ -731,7 +731,7 @@ ok_error_t Builder::build_sections() { section->name(), offset, offset + sizeof(Elf_Shdr)); ios_.seekp(offset); - ios_.write_conv(shdr); + ios_.write(shdr); } } return ok(); @@ -763,7 +763,7 @@ ok_error_t Builder::build_segments() { phdr.p_memsz = static_cast(segment->virtual_size()); phdr.p_align = static_cast(segment->alignment()); - pheaders.write_conv(phdr); + pheaders.write(phdr); } Segment* phdr_segment = binary_->get(Segment::TYPE::PHDR); @@ -870,7 +870,7 @@ ok_error_t Builder::build_symtab_symbols() { sym_hdr.st_value = static_cast(symbol->value()); sym_hdr.st_size = static_cast(symbol->size()); - content.write_conv(sym_hdr); + content.write(sym_hdr); } symbol_section->content(std::move(content.raw())); return ok(); @@ -1017,7 +1017,7 @@ ok_error_t Builder::build_dynamic_section() { dynhdr.d_tag = static_cast(DynamicEntry::to_value(entry->tag())); dynhdr.d_un.d_val = static_cast(entry->value()); - dynamic_table_raw.write_conv(dynhdr); + dynamic_table_raw.write(dynhdr); } std::vector raw = dynamic_table_raw.raw(); @@ -1106,7 +1106,7 @@ ok_error_t Builder::build_symbol_hash() { // to be improved...? if (should_swap()) { for (size_t i = 0; i < buckets_limits; i++) { - Convert::swap_endian(&new_hash_table_ptr[i]); + swap_endian(&new_hash_table_ptr[i]); } } binary_->patch_address(dt_hash->value(), new_hash_table); @@ -1184,7 +1184,7 @@ ok_error_t Builder::build_obj_symbols() { sym_header.st_value = static_cast(symbol->value()); sym_header.st_size = static_cast(symbol->size()); - symbol_table_raw.write_conv(sym_header); + symbol_table_raw.write(sym_header); } symbol_table_section->content(std::move(symbol_table_raw.raw())); return ok(); @@ -1237,7 +1237,7 @@ ok_error_t Builder::build_dynamic_symbols() { sym_header.st_value = static_cast(symbol->value()); sym_header.st_size = static_cast(symbol->size()); - symbol_table_raw.write_conv(sym_header); + symbol_table_raw.write(sym_header); } binary_->patch_address(symbol_table_va, symbol_table_raw.raw()); return ok(); @@ -1489,13 +1489,13 @@ ok_error_t Builder::build_dynamic_relocations() { relahdr.r_info = static_cast(r_info); relahdr.r_addend = static_cast(relocation.addend()); - content.write_conv(relahdr); + content.write(relahdr); } else { Elf_Rel relhdr; relhdr.r_offset = static_cast(relocation.address()); relhdr.r_info = static_cast(r_info); - content.write_conv(relhdr); + content.write(relhdr); } } binary_->patch_address(dt_reloc->value(), content.raw()); @@ -1571,13 +1571,13 @@ ok_error_t Builder::build_pltgot_relocations() { relahdr.r_info = static_cast(r_info); relahdr.r_addend = static_cast(relocation.addend()); - content.write_conv(relahdr); + content.write(relahdr); } else { Elf_Rel relhdr; relhdr.r_offset = static_cast(relocation.address()); relhdr.r_info = static_cast(r_info); - content.write_conv(relhdr); + content.write(relhdr); } } binary_->patch_address(dt_jmprel->value(), content.raw()); @@ -1645,7 +1645,7 @@ ok_error_t Builder::build_symbol_requirement() { header.vn_aux = static_cast(!svars.empty() ? sizeof(Elf_Verneed) : 0); header.vn_next = static_cast(next_symbol_offset); - svr_raw.write_conv(header); + svr_raw.write(header); uint32_t svar_idx = 0; @@ -1679,7 +1679,7 @@ ok_error_t Builder::build_symbol_requirement() { aux_header.vna_name = static_cast(svar_name_offset); aux_header.vna_next = static_cast(svar_idx < (svars.size() - 1) ? sizeof(Elf_Vernaux) : 0); - svr_raw.write_conv(aux_header); + svr_raw.write(aux_header); ++svar_idx; } @@ -1748,7 +1748,7 @@ ok_error_t Builder::build_symbol_definition() { aux_header.vda_name = static_cast(dynstr_offset); aux_header.vda_next = static_cast(next_offset); - svd_aux_raw.write_conv(aux_header); + svd_aux_raw.write(aux_header); } } } @@ -1786,7 +1786,7 @@ ok_error_t Builder::build_symbol_definition() { header.vd_hash = static_cast(svd.hash()); header.vd_aux = static_cast(aux_offset); header.vd_next = static_cast(next_offset); - svd_raw.write_conv(header); + svd_raw.write(header); } } @@ -1868,7 +1868,7 @@ ok_error_t Builder::build_symbol_version() { return make_error_code(lief_errors::not_found); } const uint16_t value = sv->value(); - sv_raw.write_conv(value); + sv_raw.write(value); } binary_->patch_address(sv_address, sv_raw.raw()); return ok(); diff --git a/src/ELF/CMakeLists.txt b/src/ELF/CMakeLists.txt index e9f95e1f9b..0149b38e78 100644 --- a/src/ELF/CMakeLists.txt +++ b/src/ELF/CMakeLists.txt @@ -3,7 +3,7 @@ target_sources(LIB_LIEF PRIVATE Binary.tcc Builder.cpp Builder.tcc - Convert.cpp + endianness_support.cpp DataHandler/Handler.cpp DataHandler/Node.cpp DynamicEntry.cpp diff --git a/src/ELF/Convert.cpp b/src/ELF/Convert.cpp deleted file mode 100644 index 69a58305aa..0000000000 --- a/src/ELF/Convert.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright 2021 - 2024 R. Thomas - * Copyright 2021 - 2024 Quarkslab - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "LIEF/BinaryStream/Convert.hpp" -#include "LIEF/BinaryStream/BinaryStream.hpp" -#include "ELF/Structures.hpp" - -/* In place conversions for BinaryStream/VectorStream data */ - -namespace LIEF { -namespace Convert { - -/* - * ELF conversions - */ - -/** ELF header */ -template -void swap_endian_ehdr(Elf_Ehdr *hdr) { - hdr->e_type = BinaryStream::swap_endian(hdr->e_type); - hdr->e_machine = BinaryStream::swap_endian(hdr->e_machine); - hdr->e_version = BinaryStream::swap_endian(hdr->e_version); - hdr->e_entry = BinaryStream::swap_endian(hdr->e_entry); - hdr->e_phoff = BinaryStream::swap_endian(hdr->e_phoff); - hdr->e_shoff = BinaryStream::swap_endian(hdr->e_shoff); - hdr->e_flags = BinaryStream::swap_endian(hdr->e_flags); - hdr->e_ehsize = BinaryStream::swap_endian(hdr->e_ehsize); - hdr->e_phentsize = BinaryStream::swap_endian(hdr->e_phentsize); - hdr->e_phnum = BinaryStream::swap_endian(hdr->e_phnum); - hdr->e_shentsize = BinaryStream::swap_endian(hdr->e_shentsize); - hdr->e_shnum = BinaryStream::swap_endian(hdr->e_shnum); - hdr->e_shstrndx = BinaryStream::swap_endian(hdr->e_shstrndx); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Ehdr *hdr) { - swap_endian_ehdr(hdr); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Ehdr *hdr) { - swap_endian_ehdr(hdr); -} - - -/** ELF Section Header */ -template -void swap_endian_shdr(Elf_Shdr *shdr) { - shdr->sh_name = BinaryStream::swap_endian(shdr->sh_name); - shdr->sh_type = BinaryStream::swap_endian(shdr->sh_type); - shdr->sh_flags = BinaryStream::swap_endian(shdr->sh_flags); - shdr->sh_addr = BinaryStream::swap_endian(shdr->sh_addr); - shdr->sh_offset = BinaryStream::swap_endian(shdr->sh_offset); - shdr->sh_size = BinaryStream::swap_endian(shdr->sh_size); - shdr->sh_link = BinaryStream::swap_endian(shdr->sh_link); - shdr->sh_info = BinaryStream::swap_endian(shdr->sh_info); - shdr->sh_addralign = BinaryStream::swap_endian(shdr->sh_addralign); - shdr->sh_entsize = BinaryStream::swap_endian(shdr->sh_entsize); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Shdr *shdr) { - swap_endian_shdr(shdr); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Shdr *shdr) { - swap_endian_shdr(shdr); -} - - -/** ELF Program Header */ -template -void swap_endian_phdr(Elf_Phdr *phdr) { - phdr->p_type = BinaryStream::swap_endian(phdr->p_type); - phdr->p_offset = BinaryStream::swap_endian(phdr->p_offset); - phdr->p_vaddr = BinaryStream::swap_endian(phdr->p_vaddr); - phdr->p_paddr = BinaryStream::swap_endian(phdr->p_paddr); - phdr->p_filesz = BinaryStream::swap_endian(phdr->p_filesz); - phdr->p_memsz = BinaryStream::swap_endian(phdr->p_memsz); - phdr->p_flags = BinaryStream::swap_endian(phdr->p_flags); - phdr->p_align = BinaryStream::swap_endian(phdr->p_align); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Phdr *phdr) { - swap_endian_phdr(phdr); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Phdr *phdr) { - swap_endian_phdr(phdr); -} - - -/** ELF Symbols */ -template -void swap_endian_sym(Elf_Sym *sym) { - sym->st_name = BinaryStream::swap_endian(sym->st_name); - sym->st_value = BinaryStream::swap_endian(sym->st_value); - sym->st_size = BinaryStream::swap_endian(sym->st_size); - sym->st_info = BinaryStream::swap_endian(sym->st_info); - sym->st_other = BinaryStream::swap_endian(sym->st_other); - sym->st_shndx = BinaryStream::swap_endian(sym->st_shndx); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Sym *sym) { - swap_endian_sym(sym); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Sym *sym) { - swap_endian_sym(sym); -} - -/** ELF Relocations */ -template -void swap_endian_rel(REL_T *rel) { - rel->r_offset = BinaryStream::swap_endian(rel->r_offset); - rel->r_info = BinaryStream::swap_endian(rel->r_info); -} - -template -void swap_endian_rela(RELA_T *rel) { - rel->r_offset = BinaryStream::swap_endian(rel->r_offset); - rel->r_info = BinaryStream::swap_endian(rel->r_info); - rel->r_addend = BinaryStream::swap_endian(rel->r_addend); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Rel *rel) { - swap_endian_rel(rel); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Rel *rel) { - swap_endian_rel(rel); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Rela *rel) { - swap_endian_rela(rel); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Rela *rel) { - swap_endian_rela(rel); -} - - -/** ELF Dynamic Symbol */ -template -void swap_endian_dyn(Elf_Dyn *dyn) { - dyn->d_tag = BinaryStream::swap_endian(dyn->d_tag); - dyn->d_un.d_val = BinaryStream::swap_endian(dyn->d_un.d_val); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Dyn *dyn) { - swap_endian_dyn(dyn); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Dyn *dyn) { - swap_endian_dyn(dyn); -} - - -/** ELF Verneed */ -template -void swap_endian_verneed(Elf_Verneed *ver) { - ver->vn_version = BinaryStream::swap_endian(ver->vn_version); - ver->vn_cnt = BinaryStream::swap_endian(ver->vn_cnt); - ver->vn_file = BinaryStream::swap_endian(ver->vn_file); - ver->vn_aux = BinaryStream::swap_endian(ver->vn_aux); - ver->vn_next = BinaryStream::swap_endian(ver->vn_next); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Verneed *ver) { - swap_endian_verneed(ver); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Verneed *ver) { - swap_endian_verneed(ver); -} - - -/** ELF Vernaux */ -template -void swap_endian_vernaux(Elf_Vernaux *ver) { - ver->vna_hash = BinaryStream::swap_endian(ver->vna_hash); - ver->vna_flags = BinaryStream::swap_endian(ver->vna_flags); - ver->vna_other = BinaryStream::swap_endian(ver->vna_other); - ver->vna_name = BinaryStream::swap_endian(ver->vna_name); - ver->vna_next = BinaryStream::swap_endian(ver->vna_next); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Vernaux *ver) { - swap_endian_vernaux(ver); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Vernaux *ver) { - swap_endian_vernaux(ver); -} - -/** ELF Symbol Version Definition */ -template -void swap_endian_verdef(Elf_Verdef *ver) { - ver->vd_version = BinaryStream::swap_endian(ver->vd_version); - ver->vd_flags = BinaryStream::swap_endian(ver->vd_flags); - ver->vd_ndx = BinaryStream::swap_endian(ver->vd_ndx); - ver->vd_cnt = BinaryStream::swap_endian(ver->vd_cnt); - ver->vd_hash = BinaryStream::swap_endian(ver->vd_hash); - ver->vd_aux = BinaryStream::swap_endian(ver->vd_aux); - ver->vd_next = BinaryStream::swap_endian(ver->vd_next); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Verdef *ver) { - swap_endian_verdef(ver); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Verdef *ver) { - swap_endian_verdef(ver); -} - - -template -void swap_endian_verdaux(Elf_Verdaux *ver) { - ver->vda_name = BinaryStream::swap_endian(ver->vda_name); - ver->vda_next = BinaryStream::swap_endian(ver->vda_next); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Verdaux *ver) { - swap_endian_verdaux(ver); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Verdaux *ver) { - swap_endian_verdaux(ver); -} - -template -void swap_endian_auxv(Elf_Auxv *auxv) { - auxv->a_type = BinaryStream::swap_endian(auxv->a_type); - auxv->a_un.a_val = BinaryStream::swap_endian(auxv->a_un.a_val); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_Auxv *auxv) { - swap_endian_auxv(auxv); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_Auxv *auxv) { - swap_endian_auxv(auxv); -} - -template -void swap_endian_fileentry(Elf_FileEntry *entry) { - entry->start = BinaryStream::swap_endian(entry->start); - entry->end = BinaryStream::swap_endian(entry->end); - entry->file_ofs = BinaryStream::swap_endian(entry->file_ofs); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf32_FileEntry *entry) { - swap_endian_fileentry(entry); -} - -template<> -void swap_endian(LIEF::ELF::details::Elf64_FileEntry *entry) { - swap_endian_fileentry(entry); -} - -} -} diff --git a/src/ELF/ExeLayout.hpp b/src/ELF/ExeLayout.hpp index 6b4f6c00fd..6f20d9f85e 100644 --- a/src/ELF/ExeLayout.hpp +++ b/src/ELF/ExeLayout.hpp @@ -228,15 +228,15 @@ class LIEF_LOCAL ExeLayout : public Layout { size_t pos = raw_notes.tellp(); // First we have to write the length of the Note's name const auto namesz = static_cast(note.name().size() + 1); - raw_notes.write_conv(namesz); + raw_notes.write(namesz); // Then the length of the Note's description const auto descsz = static_cast(note.description().size()); - raw_notes.write_conv(descsz); + raw_notes.write(descsz); // Then the note's type const uint32_t type = note.original_type(); - raw_notes.write_conv(type); + raw_notes.write(type); // Then we write the note's name const std::string& name = note.name(); @@ -250,13 +250,13 @@ class LIEF_LOCAL ExeLayout : public Layout { const auto* desc_ptr = reinterpret_cast(description.data()); size_t i = 0; for (; i < description.size() / sizeof(uint32_t); i++) { - raw_notes.write_conv(desc_ptr[i]); + raw_notes.write(desc_ptr[i]); } if (description.size() % sizeof(uint32_t) != 0) { uint32_t padded = 0; auto *ptr = reinterpret_cast(&padded); memcpy(ptr, desc_ptr + i, description.size() % sizeof(uint32_t)); - raw_notes.write_conv(padded); + raw_notes.write(padded); } notes_off_map_.emplace(¬e, pos); } @@ -349,10 +349,10 @@ class LIEF_LOCAL ExeLayout : public Layout { // Write header // ================================= raw_gnuhash - .write_conv(nb_buckets) - .write_conv(symndx) - .write_conv(maskwords) - .write_conv(shift2); + .write(nb_buckets) + .write(symndx) + .write(maskwords) + .write(shift2); // Compute Bloom filters // ================================= @@ -370,7 +370,7 @@ class LIEF_LOCAL ExeLayout : public Layout { LIEF_DEBUG("Bloom filter [{:d}]: 0x{:x}", idx, bloom_filters[idx]); } - raw_gnuhash.write_conv_array(bloom_filters); + raw_gnuhash.write(bloom_filters); // Write buckets and hash // ================================= @@ -407,8 +407,8 @@ class LIEF_LOCAL ExeLayout : public Layout { } raw_gnuhash - .write_conv_array(buckets) - .write_conv_array(hash_values); + .write(buckets) + .write(hash_values); raw_gnuhash.move(raw_gnu_hash_); return raw_gnu_hash_.size(); } diff --git a/src/ELF/Note.cpp b/src/ELF/Note.cpp index e7ca9226e9..dee86cc06e 100644 --- a/src/ELF/Note.cpp +++ b/src/ELF/Note.cpp @@ -391,7 +391,7 @@ Note::create(BinaryStream& stream, std::string section_name, { static constexpr uint32_t MAX_NOTE_DESCRIPTION = 1_MB; const size_t pos = stream.pos(); - auto res_namesz = stream.read_conv(); + auto res_namesz = stream.read(); if (!res_namesz) { return nullptr; } @@ -399,7 +399,7 @@ Note::create(BinaryStream& stream, std::string section_name, const auto namesz = *res_namesz; LIEF_DEBUG("[0x{:06x}] Name size: 0x{:x}", pos, namesz); - auto res_descz = stream.read_conv(); + auto res_descz = stream.read(); if (!res_descz) { return nullptr; } @@ -407,7 +407,7 @@ Note::create(BinaryStream& stream, std::string section_name, uint32_t descsz = std::min(*res_descz, MAX_NOTE_DESCRIPTION); LIEF_DEBUG("Description size: 0x{:x}", descsz); - auto res_type = stream.read_conv(); + auto res_type = stream.read(); if (!res_type) { return nullptr; } @@ -434,7 +434,7 @@ Note::create(BinaryStream& stream, std::string section_name, const size_t nb_chunks = (descsz - 1) / sizeof(uint32_t) + 1; description.reserve(nb_chunks); for (size_t i = 0; i < nb_chunks; ++i) { - if (const auto chunk = stream.read_conv()) { + if (const auto chunk = stream.read()) { description.push_back(*chunk); } else { break; diff --git a/src/ELF/Parser.cpp b/src/ELF/Parser.cpp index 0741634078..88449a8c8a 100644 --- a/src/ELF/Parser.cpp +++ b/src/ELF/Parser.cpp @@ -148,19 +148,19 @@ Header::ELF_DATA determine_elf_endianess(BinaryStream& stream) { // Read Machine type with both endianess ARCH machine = ARCH::NONE; // e_machine value without endian swap enabled ARCH machine_swap = ARCH::NONE; // e_machine value with endian swap enabled - const bool is_swap = stream.should_swap(); - stream.set_endian_swap(false); - if (auto res = stream.peek_conv(e_machine_off)) { + if (auto res = stream.peek(e_machine_off)) { machine = static_cast(*res); } - stream.set_endian_swap(true); - if (auto res = stream.peek_conv(e_machine_off)) { - machine_swap = static_cast(*res); + + { + ToggleEndianness swapped(stream); + if (auto res = swapped->peek(e_machine_off)) { + machine_swap = static_cast(*res); + } } - stream.set_endian_swap(is_swap); - LIEF_DEBUG("Machine '{}'", to_string(machine)); - LIEF_DEBUG("Machine Swap'{}'", to_string(machine_swap)); + LIEF_DEBUG("Machine '{}' (0x{:x})", to_string(machine), (int)machine); + LIEF_DEBUG("Machine Swap '{}' (0x{:x})", to_string(machine_swap), (int)machine); const Header::ELF_DATA endian = determine_elf_endianess(machine); const Header::ELF_DATA endian_swap = determine_elf_endianess(machine_swap); @@ -197,8 +197,6 @@ bool Parser::should_swap() const { return false; } - - Header::CLASS determine_elf_class(BinaryStream& stream) { auto from_ei_class = Header::CLASS::NONE; auto from_e_machine = Header::CLASS::NONE; @@ -229,7 +227,7 @@ Header::CLASS determine_elf_class(BinaryStream& stream) { // .... // } ElfN_Ehdr; constexpr size_t e_machine_off = offsetof(details::Elf32_Ehdr, e_machine); - if (auto res = stream.peek_conv(e_machine_off)) { + if (auto res = stream.peek(e_machine_off)) { const auto machine = static_cast(*res); switch (machine) { case ARCH::AARCH64: @@ -361,7 +359,7 @@ ok_error_t Parser::parse_symbol_version(uint64_t symbol_version_offset) { stream_->setpos(symbol_version_offset); for (size_t i = 0; i < nb_entries; ++i) { - auto val = stream_->read_conv(); + auto val = stream_->read(); if (!val) { break; } @@ -388,7 +386,7 @@ result Parser::get_dynamic_string_table_from_segments() const { size_t nb_entries = size / sizeof(details::Elf32_Dyn); for (size_t i = 0; i < nb_entries; ++i) { - auto res = stream_->read_conv(); + auto res = stream_->read(); if (!res) { LIEF_ERR("Can't read dynamic entry #{}", i); return 0; @@ -403,7 +401,7 @@ result Parser::get_dynamic_string_table_from_segments() const { } else { size_t nb_entries = size / sizeof(details::Elf64_Dyn); for (size_t i = 0; i < nb_entries; ++i) { - auto res = stream_->read_conv(); + auto res = stream_->read(); if (!res) { LIEF_ERR("Can't read dynamic entry #{}", i); return 0; @@ -456,13 +454,13 @@ ok_error_t Parser::parse_symbol_sysv_hash(uint64_t offset) { stream_->setpos(offset); - auto res_nbucket = stream_->read_conv(); + auto res_nbucket = stream_->read(); if (!res_nbucket) { LIEF_ERR("Can't read the number of buckets"); return make_error_code(lief_errors::read_error); } - auto res_nchains = stream_->read_conv(); + auto res_nchains = stream_->read(); if (!res_nchains) { LIEF_ERR("Can't read the number of chains"); return make_error_code(lief_errors::read_error); @@ -474,7 +472,7 @@ ok_error_t Parser::parse_symbol_sysv_hash(uint64_t offset) { sysvhash->buckets_.reserve(nbuckets); for (size_t i = 0; i < nbuckets; ++i) { - if (auto bucket = stream_->read_conv()) { + if (auto bucket = stream_->read()) { sysvhash->buckets_.push_back(*bucket); } else { LIEF_ERR("Can't read bucket #{}", i); @@ -484,7 +482,7 @@ ok_error_t Parser::parse_symbol_sysv_hash(uint64_t offset) { sysvhash->chains_.reserve(nchain); for (size_t i = 0; i < nchain; ++i) { - if (auto chain = stream_->read_conv()) { + if (auto chain = stream_->read()) { sysvhash->chains_.push_back(*chain); } else { LIEF_ERR("Can't read chain #{}", i); diff --git a/src/ELF/Parser.tcc b/src/ELF/Parser.tcc index 424dc8e4f8..f6ff4e4310 100644 --- a/src/ELF/Parser.tcc +++ b/src/ELF/Parser.tcc @@ -369,73 +369,73 @@ ok_error_t Parser::parse_header() { return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.file_type_ = Header::FILE_TYPE(*res); } else { LIEF_ERR("Can't parse Elf_Ehdr.e_type"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.machine_type_ = static_cast(*res); } else { LIEF_ERR("Can't parse Elf_Ehdr.e_machine"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.object_file_version_ = Header::VERSION(*res); } else { LIEF_ERR("Can't parse Elf_Ehdr.e_version"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.entrypoint_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_entry"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.program_headers_offset_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_phoff"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.section_headers_offset_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_shoff"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.processor_flags_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_flags"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.header_size_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_ehsize"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.program_header_size_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_phentsize"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.numberof_segments_ = *res; } else { - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.numberof_segments_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_phnum"); @@ -443,21 +443,21 @@ ok_error_t Parser::parse_header() { } } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.section_header_size_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_shentsize"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.numberof_sections_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_shnum"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { binary_->header_.section_string_table_idx_ = *res; } else { LIEF_ERR("Can't parse Elf_Ehdr.e_shstrndx"); @@ -606,7 +606,7 @@ uint32_t Parser::max_relocation_index(uint64_t relocations_offset, uint64_t size uint32_t idx = 0; stream_->setpos(relocations_offset); for (uint32_t i = 0; i < nb_entries; ++i) { - auto reloc_entry = stream_->read_conv(); + auto reloc_entry = stream_->read(); if (!reloc_entry) { break; } @@ -665,7 +665,7 @@ result Parser::nb_dynsym_sysv_hash() const { // From the doc: 'so nchain should equal the number of symbol table entries.' stream_->setpos(sysv_hash_offset + sizeof(uint32_t)); - auto nb_symbols = stream_->read_conv(); + auto nb_symbols = stream_->read(); if (nb_symbols) { return nb_symbols; } @@ -692,17 +692,17 @@ result Parser::nb_dynsym_gnu_hash() const { } stream_->setpos(gnu_hash_offset); - const auto res_nbuckets = stream_->read_conv(); + const auto res_nbuckets = stream_->read(); if (!res_nbuckets) { return 0; } - const auto res_symndx = stream_->read_conv(); + const auto res_symndx = stream_->read(); if (!res_symndx) { return 0; } - const auto res_maskwords = stream_->read_conv(); + const auto res_maskwords = stream_->read(); if (!res_maskwords) { return 0; } @@ -728,7 +728,7 @@ result Parser::nb_dynsym_gnu_hash() const { uint32_t max_bucket = 0; for (size_t i = 0; i < nbuckets; ++i) { - auto bucket = stream_->read_conv(); + auto bucket = stream_->read(); if (!bucket) { break; } @@ -751,7 +751,7 @@ result Parser::nb_dynsym_gnu_hash() const { if (!stream_->can_read()) { return 0; } - hash_value = *stream_->read_conv(); + hash_value = *stream_->read(); nsyms++; } while ((hash_value & 1) == 0); // "It is set to 1 when a symbol is the last symbol in a given hash bucket" @@ -775,7 +775,7 @@ ok_error_t Parser::parse_sections() { const ARCH arch = binary_->header().machine_type(); for (size_t i = 0; i < numberof_sections; ++i) { LIEF_DEBUG(" Elf_Shdr#{:02d}.offset: 0x{:x} ", i, stream_->pos()); - const auto shdr = stream_->read_conv(); + const auto shdr = stream_->read(); if (!shdr) { LIEF_ERR(" Can't parse section #{:02d}", i); break; @@ -885,7 +885,7 @@ ok_error_t Parser::parse_segments() { const ARCH arch = binary_->header().machine_type(); for (size_t i = 0; i < nbof_segments; ++i) { - const auto elf_phdr = stream_->read_conv(); + const auto elf_phdr = stream_->read(); if (!elf_phdr) { LIEF_ERR("Can't parse segement #{:d}", i); break; @@ -1157,7 +1157,7 @@ ok_error_t Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64 Relocation::ENCODING::RELA; for (uint32_t i = 0; i < nb_entries; ++i) { - const auto raw_reloc = stream_->read_conv(); + const auto raw_reloc = stream_->read(); if (!raw_reloc) { break; } @@ -1184,7 +1184,7 @@ ok_error_t Parser::parse_symtab_symbols(uint64_t offset, uint32_t nb_symbols, stream_->setpos(offset); const ARCH arch = binary_->header().machine_type(); for (uint32_t i = 0; i < nb_symbols; ++i) { - const auto raw_sym = stream_->read_conv(); + const auto raw_sym = stream_->read(); if (!raw_sym) { break; } @@ -1235,7 +1235,7 @@ ok_error_t Parser::parse_dynamic_symbols(uint64_t offset) { stream_->setpos(dynamic_symbols_offset); for (size_t i = 0; i < nb_symbols; ++i) { - const auto symbol_header = stream_->read_conv(); + const auto symbol_header = stream_->read(); if (!symbol_header) { LIEF_DEBUG("Break on symbol #{:d}", i); break; @@ -1285,7 +1285,7 @@ ok_error_t Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) { bool end_of_dynamic = false; stream_->setpos(offset); for (size_t dynIdx = 0; dynIdx < nb_entries; ++dynIdx) { - const auto res_entry = stream_->read_conv(); + const auto res_entry = stream_->read(); if (!res_entry) { break; } @@ -1412,7 +1412,7 @@ ok_error_t Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) { if (auto offset = binary_->virtual_address_to_offset(dt_init_array->value())) { stream_->setpos(*offset); for (size_t i = 0; i < nb_functions; ++i) { - if (auto val = stream_->read_conv()) { + if (auto val = stream_->read()) { array.push_back(*val); } else { break; @@ -1437,7 +1437,7 @@ ok_error_t Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) { if (auto offset = binary_->virtual_address_to_offset(dt_fini_array->value())) { stream_->setpos(*offset); for (size_t i = 0; i < nb_functions; ++i) { - if (auto val = stream_->read_conv()) { + if (auto val = stream_->read()) { array.push_back(*val); } else { break; @@ -1461,7 +1461,7 @@ ok_error_t Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) { if (auto offset = binary_->virtual_address_to_offset(dt_preini_array->value())) { stream_->setpos(static_cast(*offset)); for (size_t i = 0; i < nb_functions; ++i) { - if (auto val = stream_->read_conv()) { + if (auto val = stream_->read()) { array.push_back(*val); } else { break; @@ -1499,7 +1499,7 @@ ok_error_t Parser::parse_pltgot_relocations(uint64_t offset, uint64_t size) { Relocation::ENCODING::RELA; stream_->setpos(offset_relocations); for (uint32_t i = 0; i < nb_entries; ++i) { - const auto rel_hdr = stream_->read_conv(); + const auto rel_hdr = stream_->read(); if (!rel_hdr) { break; } @@ -1586,7 +1586,7 @@ ok_error_t Parser::parse_section_relocations(const Section& section) { std::unordered_set reloc_hash; stream_->setpos(offset_relocations); for (uint32_t i = 0; i < nb_entries; ++i) { - const auto rel_hdr = stream_->read_conv(); + const auto rel_hdr = stream_->read(); if (!rel_hdr) { break; } @@ -1639,7 +1639,7 @@ ok_error_t Parser::parse_symbol_version_requirement(uint64_t offset, uint32_t nb uint32_t next_symbol_offset = 0; for (size_t sym_idx = 0; sym_idx < nb_entries; ++sym_idx) { - const auto header = stream_->peek_conv(svr_offset + next_symbol_offset); + const auto header = stream_->peek(svr_offset + next_symbol_offset); if (!header) { break; } @@ -1660,7 +1660,7 @@ ok_error_t Parser::parse_symbol_version_requirement(uint64_t offset, uint32_t nb const uint64_t aux_hdr_off = svr_offset + next_symbol_offset + header->vn_aux + next_aux_offset; - const auto aux_header = stream_->peek_conv(aux_hdr_off); + const auto aux_header = stream_->peek(aux_hdr_off); if (!aux_header) { break; } @@ -1720,7 +1720,7 @@ ok_error_t Parser::parse_symbol_version_definition(uint64_t offset, uint32_t nb_ uint64_t def_size = 0; for (size_t i = 0; i < nb_entries; ++i) { - const auto svd_header = verdef_stream->peek_conv(); + const auto svd_header = verdef_stream->peek(); def_size = std::max(def_size, verdef_stream->pos() - offset + sizeof(Elf_Verdef)); if (!svd_header) { break; @@ -1731,7 +1731,7 @@ ok_error_t Parser::parse_symbol_version_definition(uint64_t offset, uint32_t nb_ { ScopedStream aux_stream(*stream_, verdef_stream->pos() + svd_header->vd_aux); for (size_t j = 0; j < nb_aux_symbols; ++j) { - const auto svda_header = aux_stream->peek_conv(); + const auto svda_header = aux_stream->peek(); def_size = std::max(def_size, aux_stream->pos() - offset + sizeof(Elf_Verdaux)); if (!svda_header) { break; @@ -1797,28 +1797,28 @@ ok_error_t Parser::parse_symbol_gnu_hash(uint64_t offset) { uint32_t nbuckets = 0; uint32_t maskwords = 0; - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { nbuckets = std::min(*res, NB_MAX_BUCKETS); } else { LIEF_ERR("Can't read the number of buckets"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { gnuhash->symbol_index_ = *res; } else { LIEF_ERR("Can't read the symndx"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { maskwords = std::min(*res, NB_MAX_MASKWORD); } else { LIEF_ERR("Can't read the maskwords"); return make_error_code(lief_errors::read_error); } - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { gnuhash->shift2_ = *res; } else { LIEF_ERR("Can't read the shift2"); @@ -1833,7 +1833,7 @@ ok_error_t Parser::parse_symbol_gnu_hash(uint64_t offset) { gnuhash->bloom_filters_.reserve(maskwords); for (size_t i = 0; i < maskwords; ++i) { - if (auto maskword = stream_->read_conv()) { + if (auto maskword = stream_->read()) { gnuhash->bloom_filters_.push_back(*maskword); } else { LIEF_ERR("Can't read maskwords #{:d}", i); @@ -1852,7 +1852,7 @@ ok_error_t Parser::parse_symbol_gnu_hash(uint64_t offset) { gnuhash->buckets_.reserve(nbuckets); for (size_t i = 0; i < nbuckets; ++i) { - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { gnuhash->buckets_.push_back(*res); } else { LIEF_ERR("Can't read bucket #{}", i); @@ -1868,7 +1868,7 @@ ok_error_t Parser::parse_symbol_gnu_hash(uint64_t offset) { if (nb_hash < MAX_NB_HASH) { gnuhash->hash_values_.reserve(nb_hash); for (size_t i = 0; i < nb_hash; ++i) { - if (auto res = stream_->read_conv()) { + if (auto res = stream_->read()) { gnuhash->hash_values_.push_back(*res); } else { LIEF_ERR("Can't read hash #{}", i); diff --git a/src/ELF/endianness_support.cpp b/src/ELF/endianness_support.cpp new file mode 100644 index 0000000000..e78a1cbde3 --- /dev/null +++ b/src/ELF/endianness_support.cpp @@ -0,0 +1,279 @@ +/* Copyright 2021 - 2024 R. Thomas + * Copyright 2021 - 2024 Quarkslab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "LIEF/endianness_support.hpp" +#include "ELF/Structures.hpp" + +namespace LIEF { + +template +void swap_endian_ehdr(Elf_Ehdr* hdr) { + swap_endian(&hdr->e_type); + swap_endian(&hdr->e_machine); + swap_endian(&hdr->e_version); + swap_endian(&hdr->e_entry); + swap_endian(&hdr->e_phoff); + swap_endian(&hdr->e_shoff); + swap_endian(&hdr->e_flags); + swap_endian(&hdr->e_ehsize); + swap_endian(&hdr->e_phentsize); + swap_endian(&hdr->e_phnum); + swap_endian(&hdr->e_shentsize); + swap_endian(&hdr->e_shnum); + swap_endian(&hdr->e_shstrndx); +} + +template<> +void swap_endian(ELF::details::Elf32_Ehdr* hdr) { + swap_endian_ehdr(hdr); +} + +template<> +void swap_endian(ELF::details::Elf64_Ehdr *hdr) { + swap_endian_ehdr(hdr); +} + +template +void swap_endian_shdr(Elf_Shdr *shdr) { + swap_endian(&shdr->sh_name); + swap_endian(&shdr->sh_type); + swap_endian(&shdr->sh_flags); + swap_endian(&shdr->sh_addr); + swap_endian(&shdr->sh_offset); + swap_endian(&shdr->sh_size); + swap_endian(&shdr->sh_link); + swap_endian(&shdr->sh_info); + swap_endian(&shdr->sh_addralign); + swap_endian(&shdr->sh_entsize); +} + +template<> +void swap_endian(ELF::details::Elf32_Shdr *shdr) { + swap_endian_shdr(shdr); +} + +template<> +void swap_endian(ELF::details::Elf64_Shdr *shdr) { + swap_endian_shdr(shdr); +} + +template +void swap_endian_phdr(Elf_Phdr *phdr) { + swap_endian(&phdr->p_type); + swap_endian(&phdr->p_offset); + swap_endian(&phdr->p_vaddr); + swap_endian(&phdr->p_paddr); + swap_endian(&phdr->p_filesz); + swap_endian(&phdr->p_memsz); + swap_endian(&phdr->p_flags); + swap_endian(&phdr->p_align); +} + +template<> +void swap_endian(ELF::details::Elf32_Phdr *phdr) { + swap_endian_phdr(phdr); +} + +template<> +void swap_endian(ELF::details::Elf64_Phdr *phdr) { + swap_endian_phdr(phdr); +} + + +template +void swap_endian_sym(Elf_Sym *sym) { + swap_endian(&sym->st_name); + swap_endian(&sym->st_value); + swap_endian(&sym->st_size); + swap_endian(&sym->st_info); + swap_endian(&sym->st_other); + swap_endian(&sym->st_shndx); +} + +template<> +void swap_endian(ELF::details::Elf32_Sym *sym) { + swap_endian_sym(sym); +} + +template<> +void swap_endian(ELF::details::Elf64_Sym *sym) { + swap_endian_sym(sym); +} + +template +void swap_endian_rel(REL_T *rel) { + swap_endian(&rel->r_offset); + swap_endian(&rel->r_info); +} + +template +void swap_endian_rela(RELA_T *rel) { + swap_endian(&rel->r_offset); + swap_endian(&rel->r_info); + swap_endian(&rel->r_addend); +} + +template<> +void swap_endian(ELF::details::Elf32_Rel *rel) { + swap_endian_rel(rel); +} + +template<> +void swap_endian(ELF::details::Elf64_Rel *rel) { + swap_endian_rel(rel); +} + +template<> +void swap_endian(ELF::details::Elf32_Rela *rel) { + swap_endian_rela(rel); +} + +template<> +void swap_endian(ELF::details::Elf64_Rela *rel) { + swap_endian_rela(rel); +} + + +/** ELF Dynamic Symbol */ +template +void swap_endian_dyn(Elf_Dyn *dyn) { + swap_endian(&dyn->d_tag); + swap_endian(&dyn->d_un.d_val); +} + +template<> +void swap_endian(ELF::details::Elf32_Dyn *dyn) { + swap_endian_dyn(dyn); +} + +template<> +void swap_endian(ELF::details::Elf64_Dyn *dyn) { + swap_endian_dyn(dyn); +} + + +/** ELF Verneed */ +template +void swap_endian_verneed(Elf_Verneed *ver) { + swap_endian(&ver->vn_version); + swap_endian(&ver->vn_cnt); + swap_endian(&ver->vn_file); + swap_endian(&ver->vn_aux); + swap_endian(&ver->vn_next); +} + +template<> +void swap_endian(ELF::details::Elf32_Verneed *ver) { + swap_endian_verneed(ver); +} + +template<> +void swap_endian(ELF::details::Elf64_Verneed *ver) { + swap_endian_verneed(ver); +} + + +/** ELF Vernaux */ +template +void swap_endian_vernaux(Elf_Vernaux *ver) { + swap_endian(&ver->vna_hash); + swap_endian(&ver->vna_flags); + swap_endian(&ver->vna_other); + swap_endian(&ver->vna_name); + swap_endian(&ver->vna_next); +} + +template<> +void swap_endian(ELF::details::Elf32_Vernaux *ver) { + swap_endian_vernaux(ver); +} + +template<> +void swap_endian(ELF::details::Elf64_Vernaux *ver) { + swap_endian_vernaux(ver); +} + +/** ELF Symbol Version Definition */ +template +void swap_endian_verdef(Elf_Verdef *ver) { + swap_endian(&ver->vd_version); + swap_endian(&ver->vd_flags); + swap_endian(&ver->vd_ndx); + swap_endian(&ver->vd_cnt); + swap_endian(&ver->vd_hash); + swap_endian(&ver->vd_aux); + swap_endian(&ver->vd_next); +} + +template<> +void swap_endian(ELF::details::Elf32_Verdef *ver) { + swap_endian_verdef(ver); +} + +template<> +void swap_endian(ELF::details::Elf64_Verdef *ver) { + swap_endian_verdef(ver); +} + +template +void swap_endian_verdaux(Elf_Verdaux *ver) { + swap_endian(&ver->vda_name); + swap_endian(&ver->vda_next); +} + +template<> +void swap_endian(ELF::details::Elf32_Verdaux *ver) { + swap_endian_verdaux(ver); +} + +template<> +void swap_endian(ELF::details::Elf64_Verdaux *ver) { + swap_endian_verdaux(ver); +} + +template +void swap_endian_auxv(Elf_Auxv *auxv) { + swap_endian(&auxv->a_type); + swap_endian(&auxv->a_un.a_val); +} + +template<> +void swap_endian(ELF::details::Elf32_Auxv *auxv) { + swap_endian_auxv(auxv); +} + +template<> +void swap_endian(ELF::details::Elf64_Auxv *auxv) { + swap_endian_auxv(auxv); +} + +template +void swap_endian_fileentry(Elf_FileEntry *entry) { + swap_endian(&entry->start); + swap_endian(&entry->end); + swap_endian(&entry->file_ofs); +} + +template<> +void swap_endian(ELF::details::Elf32_FileEntry *entry) { + swap_endian_fileentry(entry); +} + +template<> +void swap_endian(ELF::details::Elf64_FileEntry *entry) { + swap_endian_fileentry(entry); +} + +} diff --git a/src/MachO/BinaryParser.cpp b/src/MachO/BinaryParser.cpp index 969165cb5a..bf6ea81de5 100644 --- a/src/MachO/BinaryParser.cpp +++ b/src/MachO/BinaryParser.cpp @@ -133,6 +133,11 @@ ok_error_t BinaryParser::init_and_parse() { type_ = type; binary_->original_size_ = stream_->size(); + bool should_swap = type == MACHO_TYPES::MH_CIGAM_64 || + type == MACHO_TYPES::MH_CIGAM; + + stream_->set_endian_swap(should_swap); + return is64_ ? parse() : parse(); } @@ -420,7 +425,6 @@ ok_error_t BinaryParser::parse_indirect_symbols(DynamicSymbolCommand& cmd, std::vector& symtab, BinaryStream& indirect_stream) { - for (size_t i = 0; i < cmd.nb_indirect_symbols(); ++i) { uint32_t index = 0; auto res = indirect_stream.read(); diff --git a/src/MachO/BinaryParser.tcc b/src/MachO/BinaryParser.tcc index 75fd20ff13..17fac1086a 100644 --- a/src/MachO/BinaryParser.tcc +++ b/src/MachO/BinaryParser.tcc @@ -148,6 +148,7 @@ ok_error_t BinaryParser::parse() { if (DyldChainedFixups* fixups = binary_->dyld_chained_fixups()) { LIEF_DEBUG("[+] Parsing LC_DYLD_CHAINED_FIXUPS payload"); SpanStream stream = fixups->content_; + stream.set_endian_swap(stream_->should_swap()); chained_fixups_ = fixups; auto is_ok = parse_chained_payload(stream); if (!is_ok) { @@ -367,7 +368,7 @@ ok_error_t BinaryParser::parse_load_commands() { } load_command = std::make_unique(*cmd); - const uint32_t str_name_offset = cmd->dylib.name; + const uint32_t str_name_offset = cmd->name; auto name = stream_->peek_string_at(loadcommands_offset + str_name_offset); if (!name) { LIEF_ERR("Can't read Dylib string value"); @@ -2406,6 +2407,7 @@ ok_error_t BinaryParser::parse_chained_payload(SpanStream& stream) { } SpanStream symbols_pool = std::move(*res_symbols_pools); + symbols_pool.set_endian_swap(stream_->should_swap()); if (!parse_chained_import(header, stream, symbols_pool)) { LIEF_WARN("Error while parsing the chained imports"); return make_error_code(lief_errors::parsing_error); @@ -2620,6 +2622,7 @@ ok_error_t BinaryParser::parse_fixup_seg(SpanStream& stream, uint32_t seg_info_o return make_error_code(res_seg_stream.error()); } SpanStream seg_stream = std::move(*res_seg_stream); + seg_stream.set_endian_swap(stream_->should_swap()); seg_stream.read(); LIEF_DEBUG("{}size = {}", DPREFIX, seg_info.size); @@ -3366,6 +3369,9 @@ ok_error_t BinaryParser::post_process(SymbolCommand& cmd) { SpanStream nlist_s(nlist_buffer); SpanStream strings_s(strings_buffer); + + nlist_s.set_endian_swap(stream_->should_swap()); + strings_s.set_endian_swap(stream_->should_swap()); return parse_symtab(cmd, nlist_s, strings_s); } @@ -3410,6 +3416,9 @@ ok_error_t BinaryParser::post_process(SymbolCommand& cmd) { SpanStream nlist_stream(cmd.symbol_table_); SpanStream string_stream(cmd.string_table_); + nlist_stream.set_endian_swap(stream_->should_swap()); + string_stream.set_endian_swap(stream_->should_swap()); + return parse_symtab(cmd, nlist_stream, string_stream); } @@ -3443,6 +3452,7 @@ ok_error_t BinaryParser::post_process(FunctionStarts& cmd) { } SpanStream stream(cmd.content_); + stream.set_endian_swap(stream_->should_swap()); uint64_t value = 0; do { @@ -3584,6 +3594,7 @@ ok_error_t BinaryParser::post_process(DynamicSymbolCommand& cmd) { } span indirect_sym_buffer = content.subspan(rel_offset, size); SpanStream indirect_sym_s(indirect_sym_buffer); + indirect_sym_s.set_endian_swap(stream_->should_swap()); return parse_indirect_symbols(cmd, symtab, indirect_sym_s); } diff --git a/src/MachO/Builder.cpp b/src/MachO/Builder.cpp index a20eab4754..140fb050d6 100644 --- a/src/MachO/Builder.cpp +++ b/src/MachO/Builder.cpp @@ -156,11 +156,11 @@ ok_error_t Builder::build_fat() { auto* arch = reinterpret_cast(raw_.raw().data() + fat_header_sz + i * fat_arch_sz); std::vector raw = build_raw(*binaries_[i], config_); - auto alignment = BinaryStream::swap_endian(arch->align); + auto alignment = get_swapped_endian(arch->align); uint32_t offset = align(raw_.size(), 1llu << alignment); - arch->offset = BinaryStream::swap_endian(offset); - arch->size = BinaryStream::swap_endian(raw.size()); + arch->offset = get_swapped_endian(offset); + arch->size = get_swapped_endian(raw.size()); raw_.seekp(offset); raw_.write(std::move(raw)); } @@ -175,7 +175,7 @@ ok_error_t Builder::build_fat_header() { std::memset(&header, 0, sizeof(details::fat_header)); header.magic = static_cast(MACHO_TYPES::FAT_CIGAM); - header.nfat_arch = BinaryStream::swap_endian(binaries_.size()); + header.nfat_arch = get_swapped_endian(binaries_.size()); raw_.seekp(0); raw_.write(reinterpret_cast(&header), sizeof(details::fat_header)); @@ -185,11 +185,11 @@ ok_error_t Builder::build_fat_header() { details::fat_arch arch_header; std::memset(&arch_header, 0, sizeof(details::fat_arch)); - arch_header.cputype = BinaryStream::swap_endian(static_cast(header.cpu_type())); - arch_header.cpusubtype = BinaryStream::swap_endian(static_cast(header.cpu_subtype())); + arch_header.cputype = get_swapped_endian((uint32_t)header.cpu_type()); + arch_header.cpusubtype = get_swapped_endian((uint32_t)header.cpu_subtype()); arch_header.offset = 0; arch_header.size = 0; - arch_header.align = BinaryStream::swap_endian(ALIGNMENT); + arch_header.align = get_swapped_endian(ALIGNMENT); raw_.write(reinterpret_cast(&arch_header), sizeof(details::fat_arch)); } return ok(); diff --git a/src/MachO/Builder.tcc b/src/MachO/Builder.tcc index ce7cbaf39d..23feef8f95 100644 --- a/src/MachO/Builder.tcc +++ b/src/MachO/Builder.tcc @@ -233,12 +233,12 @@ ok_error_t Builder::build(DylibCommand& library) { details::dylib_command raw_cmd; std::memset(&raw_cmd, 0, sizeof(details::dylib_command)); - raw_cmd.cmd = static_cast(library.command()); - raw_cmd.cmdsize = static_cast(size_needed); - raw_cmd.dylib.name = static_cast(sizeof(details::dylib_command)); - raw_cmd.dylib.timestamp = static_cast(library.timestamp()); - raw_cmd.dylib.current_version = static_cast(DylibCommand::version2int(library.current_version())); - raw_cmd.dylib.compatibility_version = static_cast(DylibCommand::version2int(library.compatibility_version())); + raw_cmd.cmd = static_cast(library.command()); + raw_cmd.cmdsize = static_cast(size_needed); + raw_cmd.name = static_cast(sizeof(details::dylib_command)); + raw_cmd.timestamp = static_cast(library.timestamp()); + raw_cmd.current_version = static_cast(DylibCommand::version2int(library.current_version())); + raw_cmd.compatibility_version = static_cast(DylibCommand::version2int(library.compatibility_version())); library.size_ = size_needed; library.original_data_.clear(); diff --git a/src/MachO/CMakeLists.txt b/src/MachO/CMakeLists.txt index 93eb169191..a54a4ff344 100644 --- a/src/MachO/CMakeLists.txt +++ b/src/MachO/CMakeLists.txt @@ -14,7 +14,7 @@ target_sources(LIB_LIEF PRIVATE ChainedFixup.cpp CodeSignature.cpp CodeSignatureDir.cpp - Convert.cpp + endianness_support.cpp DataCodeEntry.cpp DataInCode.cpp DyldBindingInfo.cpp diff --git a/src/MachO/DylibCommand.cpp b/src/MachO/DylibCommand.cpp index 62ee8879ad..f571f84b6d 100644 --- a/src/MachO/DylibCommand.cpp +++ b/src/MachO/DylibCommand.cpp @@ -25,9 +25,9 @@ namespace MachO { DylibCommand::DylibCommand(const details::dylib_command& cmd) : LoadCommand::LoadCommand{static_cast(cmd.cmd), cmd.cmdsize}, - timestamp_{cmd.dylib.timestamp}, - current_version_{cmd.dylib.current_version}, - compatibility_version_{cmd.dylib.compatibility_version} + timestamp_{cmd.timestamp}, + current_version_{cmd.current_version}, + compatibility_version_{cmd.compatibility_version} {} @@ -52,11 +52,11 @@ DylibCommand DylibCommand::create(LoadCommand::TYPE type, uint32_t compat_version) { details::dylib_command raw_cmd; - raw_cmd.cmd = static_cast(type); - raw_cmd.cmdsize = align(sizeof(details::dylib_command) + name.size() + 1, sizeof(uint64_t)); - raw_cmd.dylib.timestamp = timestamp; - raw_cmd.dylib.current_version = current_version; - raw_cmd.dylib.compatibility_version = compat_version; + raw_cmd.cmd = static_cast(type); + raw_cmd.cmdsize = align(sizeof(details::dylib_command) + name.size() + 1, sizeof(uint64_t)); + raw_cmd.timestamp = timestamp; + raw_cmd.current_version = current_version; + raw_cmd.compatibility_version = compat_version; DylibCommand dylib{raw_cmd}; dylib.name(name); diff --git a/src/MachO/Parser.cpp b/src/MachO/Parser.cpp index 7e827434d8..95355159b6 100644 --- a/src/MachO/Parser.cpp +++ b/src/MachO/Parser.cpp @@ -158,8 +158,8 @@ ok_error_t Parser::build_fat() { } const auto arch = *res_arch; - const uint32_t offset = BinaryStream::swap_endian(arch.offset); - const uint32_t size = BinaryStream::swap_endian(arch.size); + const uint32_t offset = get_swapped_endian(arch.offset); + const uint32_t size = get_swapped_endian(arch.size); LIEF_DEBUG("Dealing with arch[{:d}]", i); LIEF_DEBUG(" [{:d}].offset: 0x{:06x}", i, offset); diff --git a/src/MachO/Structures.hpp b/src/MachO/Structures.hpp index 01be66e9d1..84d9f71ce2 100644 --- a/src/MachO/Structures.hpp +++ b/src/MachO/Structures.hpp @@ -136,31 +136,16 @@ struct section_64 { uint32_t reserved3; }; -struct fvmlib { - uint32_t name; - uint32_t minor_version; - uint32_t header_addr; -}; - -struct fvmlib_command { - uint32_t cmd; +struct dylib_command { + uint32_t cmd; uint32_t cmdsize; - struct fvmlib fvmlib; -}; -struct dylib { uint32_t name; uint32_t timestamp; uint32_t current_version; uint32_t compatibility_version; }; -struct dylib_command { - uint32_t cmd; - uint32_t cmdsize; - struct dylib dylib; -}; - struct sub_framework_command { uint32_t cmd; uint32_t cmdsize; diff --git a/src/MachO/endianness_support.cpp b/src/MachO/endianness_support.cpp new file mode 100644 index 0000000000..5481ee4ca1 --- /dev/null +++ b/src/MachO/endianness_support.cpp @@ -0,0 +1,525 @@ +/* Copyright 2021 - 2024 R. Thomas + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LIEF/endianness_support.hpp" +#include "MachO/Structures.hpp" + +namespace LIEF { + +template<> +void swap_endian(MachO::details::mach_header* hdr) { + swap_endian(&hdr->magic); + swap_endian(&hdr->cputype); + swap_endian(&hdr->cpusubtype); + swap_endian(&hdr->filetype); + swap_endian(&hdr->ncmds); + swap_endian(&hdr->sizeofcmds); + swap_endian(&hdr->flags); +} + +template<> +void swap_endian(MachO::details::mach_header_64* hdr) { + swap_endian(&hdr->magic); + swap_endian(&hdr->cputype); + swap_endian(&hdr->cpusubtype); + swap_endian(&hdr->filetype); + swap_endian(&hdr->ncmds); + swap_endian(&hdr->sizeofcmds); + swap_endian(&hdr->flags); + swap_endian(&hdr->reserved); +} + +template<> +void swap_endian(MachO::details::load_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); +} + +template +void swap_endian_seg(segment_command* cmd) { + swap_endian(&cmd->cmd); + swap_endian(&cmd->cmdsize); + swap_endian(&cmd->vmaddr); + swap_endian(&cmd->vmsize); + swap_endian(&cmd->fileoff); + swap_endian(&cmd->filesize); + swap_endian(&cmd->maxprot); + swap_endian(&cmd->initprot); + swap_endian(&cmd->nsects); + swap_endian(&cmd->flags); +} + +template<> +void swap_endian(MachO::details::segment_command_32* hdr) { + swap_endian_seg(hdr); +} + +template<> +void swap_endian(MachO::details::segment_command_64* hdr) { + swap_endian_seg(hdr); +} + +template +void swap_endian_sec(section* hdr) { + swap_endian(&hdr->addr); + swap_endian(&hdr->size); + swap_endian(&hdr->offset); + swap_endian(&hdr->align); + swap_endian(&hdr->reloff); + swap_endian(&hdr->nreloc); + swap_endian(&hdr->flags); + swap_endian(&hdr->reserved1); + swap_endian(&hdr->reserved2); +} + +template<> +void swap_endian(MachO::details::section_32* hdr) { + swap_endian_sec(hdr); +} + +template<> +void swap_endian(MachO::details::section_64* hdr) { + swap_endian_sec(hdr); + swap_endian(&hdr->reserved3); +} + +template<> +void swap_endian(MachO::details::dylib_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->name); + swap_endian(&hdr->timestamp); + swap_endian(&hdr->current_version); + swap_endian(&hdr->compatibility_version); +} + +template<> +void swap_endian(MachO::details::sub_framework_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->umbrella); +} + +template<> +void swap_endian(MachO::details::sub_client_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->client); +} + +template<> +void swap_endian(MachO::details::sub_umbrella_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->sub_umbrella); +} + +template<> +void swap_endian(MachO::details::sub_library_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->sub_library); +} + +template<> +void swap_endian(MachO::details::prebound_dylib_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->name); + swap_endian(&hdr->nmodules); + swap_endian(&hdr->linked_modules); +} + +template<> +void swap_endian(MachO::details::dylinker_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->name); +} + +template<> +void swap_endian(MachO::details::thread_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->flavor); + swap_endian(&hdr->count); +} + +template +void swap_endian_routine(routine* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->init_address); + swap_endian(&hdr->init_module); + swap_endian(&hdr->reserved1); + swap_endian(&hdr->reserved2); + swap_endian(&hdr->reserved3); + swap_endian(&hdr->reserved4); + swap_endian(&hdr->reserved5); + swap_endian(&hdr->reserved6); +} + +template<> +void swap_endian(MachO::details::routines_command_32* hdr) { + return swap_endian_routine(hdr); +} + +template<> +void swap_endian(MachO::details::routines_command_64* hdr) { + return swap_endian_routine(hdr); +} + +template<> +void swap_endian(MachO::details::symtab_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->symoff); + swap_endian(&hdr->nsyms); + swap_endian(&hdr->stroff); + swap_endian(&hdr->strsize); +} + +template<> +void swap_endian(MachO::details::dysymtab_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->ilocalsym); + swap_endian(&hdr->nlocalsym); + swap_endian(&hdr->iextdefsym); + swap_endian(&hdr->nextdefsym); + swap_endian(&hdr->iundefsym); + swap_endian(&hdr->nundefsym); + swap_endian(&hdr->tocoff); + swap_endian(&hdr->ntoc); + swap_endian(&hdr->modtaboff); + swap_endian(&hdr->nmodtab); + swap_endian(&hdr->extrefsymoff); + swap_endian(&hdr->nextrefsyms); + swap_endian(&hdr->indirectsymoff); + swap_endian(&hdr->nindirectsyms); + swap_endian(&hdr->extreloff); + swap_endian(&hdr->nextrel); + swap_endian(&hdr->locreloff); + swap_endian(&hdr->nlocrel); +} + +template<> +void swap_endian(MachO::details::dylib_table_of_contents* hdr) { + swap_endian(&hdr->symbol_index); + swap_endian(&hdr->module_index); +} + +template +void swap_endian_module(dylib_module* hdr) { + swap_endian(&hdr->module_name); + swap_endian(&hdr->iextdefsym); + swap_endian(&hdr->nextdefsym); + swap_endian(&hdr->irefsym); + swap_endian(&hdr->nrefsym); + swap_endian(&hdr->ilocalsym); + swap_endian(&hdr->nlocalsym); + swap_endian(&hdr->iextrel); + swap_endian(&hdr->nextrel); + swap_endian(&hdr->iinit_iterm); + swap_endian(&hdr->ninit_nterm); + swap_endian(&hdr->objc_module_info_addr); + swap_endian(&hdr->objc_module_info_size); +} + +template<> +void swap_endian(MachO::details::dylib_module_64* hdr) { + return swap_endian_module(hdr); +} + +template<> +void swap_endian(MachO::details::dylib_module_32* hdr) { + return swap_endian_module(hdr); +} + +template<> +void swap_endian(MachO::details::dylib_reference* hdr) { + swap_endian((uint32_t*)hdr); +} + +template<> +void swap_endian(MachO::details::twolevel_hints_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->offset); + swap_endian(&hdr->nhints); +} + +template<> +void swap_endian(MachO::details::twolevel_hint* hdr) { + swap_endian((uint32_t*)hdr); +} + + +template<> +void swap_endian(MachO::details::prebind_cksum_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->cksum); +} + +template<> +void swap_endian(MachO::details::uuid_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); +} + +template<> +void swap_endian(MachO::details::rpath_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->path); +} + +template<> +void swap_endian(MachO::details::linkedit_data_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->dataoff); + swap_endian(&hdr->datasize); +} + +template<> +void swap_endian(MachO::details::data_in_code_entry* hdr) { + swap_endian(&hdr->offset); + swap_endian(&hdr->length); + swap_endian(&hdr->kind); +} + +template<> +void swap_endian(MachO::details::source_version_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->version); +} + +template<> +void swap_endian(MachO::details::encryption_info_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->cryptoff); + swap_endian(&hdr->cryptsize); + swap_endian(&hdr->cryptid); +} + +template<> +void swap_endian(MachO::details::version_min_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->version); + swap_endian(&hdr->sdk); +} + +template<> +void swap_endian(MachO::details::build_version_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->platform); + swap_endian(&hdr->minos); + swap_endian(&hdr->sdk); + swap_endian(&hdr->ntools); +} + +template<> +void swap_endian(MachO::details::build_tool_version* hdr) { + swap_endian(&hdr->tool); + swap_endian(&hdr->version); +} + +template<> +void swap_endian(MachO::details::dyld_info_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->rebase_off); + swap_endian(&hdr->rebase_size); + swap_endian(&hdr->bind_off); + swap_endian(&hdr->bind_size); + swap_endian(&hdr->weak_bind_off); + swap_endian(&hdr->weak_bind_size); + swap_endian(&hdr->lazy_bind_off); + swap_endian(&hdr->lazy_bind_size); + swap_endian(&hdr->export_off); + swap_endian(&hdr->export_size); +} + +template<> +void swap_endian(MachO::details::linker_option_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->count); +} + +template<> +void swap_endian(MachO::details::symseg_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->offset); + swap_endian(&hdr->size); +} + +template<> +void swap_endian(MachO::details::ident_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); +} + +template<> +void swap_endian(MachO::details::fvmfile_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->name); + swap_endian(&hdr->header_addr); +} + +template<> +void swap_endian(MachO::details::entry_point_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->entryoff); + swap_endian(&hdr->stacksize); +} + +template<> +void swap_endian(MachO::details::fileset_entry_command* hdr) { + swap_endian(&hdr->cmd); + swap_endian(&hdr->cmdsize); + swap_endian(&hdr->vmaddr); + swap_endian(&hdr->fileoff); + swap_endian(&hdr->entry_id); + swap_endian(&hdr->reserved); +} + +template<> +void swap_endian(MachO::details::relocation_info* hdr) { + struct mirror_t { + int32_t A; + uint32_t B; + }; + auto* mirror = reinterpret_cast(hdr); + swap_endian(&mirror->A); + swap_endian(&mirror->B); +} + +template<> +void swap_endian(MachO::details::scattered_relocation_info* hdr) { + struct mirror_t { + int32_t A; + uint32_t B; + }; + auto* mirror = reinterpret_cast(hdr); + swap_endian(&mirror->A); +} + +template +void swap_endian_nlist(nlist* hdr) { + swap_endian(&hdr->n_strx); + swap_endian(&hdr->n_type); + swap_endian(&hdr->n_sect); + swap_endian(&hdr->n_desc); + swap_endian(&hdr->n_value); +} + +template<> +void swap_endian(MachO::details::nlist_32* hdr) { + return swap_endian_nlist(hdr); +} + +template<> +void swap_endian(MachO::details::nlist_64* hdr) { + return swap_endian_nlist(hdr); +} + +template<> +void swap_endian(MachO::details::x86_thread_state64_t* hdr) { + swap_endian(&hdr->rax); + swap_endian(&hdr->rbx); + swap_endian(&hdr->rcx); + swap_endian(&hdr->rdx); + swap_endian(&hdr->rdi); + swap_endian(&hdr->rsi); + swap_endian(&hdr->rbp); + swap_endian(&hdr->rsp); + swap_endian(&hdr->r8); + swap_endian(&hdr->r9); + swap_endian(&hdr->r10); + swap_endian(&hdr->r11); + swap_endian(&hdr->r12); + swap_endian(&hdr->r13); + swap_endian(&hdr->r14); + swap_endian(&hdr->r15); + swap_endian(&hdr->rip); + swap_endian(&hdr->rflags); + swap_endian(&hdr->cs); + swap_endian(&hdr->fs); + swap_endian(&hdr->gs); +} + +template<> +void swap_endian(MachO::details::x86_thread_state_t* hdr) { + swap_endian(&hdr->eax); + swap_endian(&hdr->ebx); + swap_endian(&hdr->ecx); + swap_endian(&hdr->edx); + swap_endian(&hdr->edi); + swap_endian(&hdr->esi); + swap_endian(&hdr->ebp); + swap_endian(&hdr->esp); + swap_endian(&hdr->ss); + swap_endian(&hdr->eflags); + swap_endian(&hdr->eip); + swap_endian(&hdr->cs); + swap_endian(&hdr->ds); + swap_endian(&hdr->es); + swap_endian(&hdr->fs); + swap_endian(&hdr->gs); +} + +template<> +void swap_endian(MachO::details::arm_thread_state_t* hdr) { + swap_endian(&hdr->r0); + swap_endian(&hdr->r1); + swap_endian(&hdr->r2); + swap_endian(&hdr->r3); + swap_endian(&hdr->r4); + swap_endian(&hdr->r5); + swap_endian(&hdr->r6); + swap_endian(&hdr->r7); + swap_endian(&hdr->r8); + swap_endian(&hdr->r9); + swap_endian(&hdr->r10); + swap_endian(&hdr->r11); + swap_endian(&hdr->r12); + swap_endian(&hdr->r13); + swap_endian(&hdr->r14); + swap_endian(&hdr->r15); + swap_endian(&hdr->r16); +} + +template<> +void swap_endian(MachO::details::arm_thread_state64_t* hdr) { + for (size_t i = 0; i < 29; ++i) { + swap_endian(&hdr->x[i]); + } + swap_endian(&hdr->fp); + swap_endian(&hdr->lr); + swap_endian(&hdr->sp); + swap_endian(&hdr->pc); + swap_endian(&hdr->cpsr); +} +} diff --git a/src/PE/CMakeLists.txt b/src/PE/CMakeLists.txt index e9c6806c25..03dc89d1b6 100644 --- a/src/PE/CMakeLists.txt +++ b/src/PE/CMakeLists.txt @@ -3,7 +3,7 @@ target_sources(LIB_LIEF PRIVATE Builder.cpp Builder.tcc CodeIntegrity.cpp - Convert.cpp + endianness_support.cpp DataDirectory.cpp DelayImport.cpp DelayImportEntry.cpp diff --git a/src/PE/Convert.cpp b/src/PE/Convert.cpp deleted file mode 100644 index 44844985b1..0000000000 --- a/src/PE/Convert.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright 2021 - 2024 R. Thomas - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -namespace LIEF { -namespace Convert { - // TODO: Implement endian convert -} -} diff --git a/src/PE/debug/CodeViewPDB.cpp b/src/PE/debug/CodeViewPDB.cpp index be81701bea..75a4d972d7 100644 --- a/src/PE/debug/CodeViewPDB.cpp +++ b/src/PE/debug/CodeViewPDB.cpp @@ -16,6 +16,7 @@ #include "LIEF/PE/debug/CodeViewPDB.hpp" #include "LIEF/Visitor.hpp" #include "LIEF/BinaryStream/SpanStream.hpp" +#include "LIEF/endianness_support.hpp" #include "spdlog/fmt/fmt.h" #include "spdlog/fmt/ranges.h" @@ -44,14 +45,14 @@ std::string CodeViewPDB::guid() const { return ""; } - stream->set_endian_swap(true); - const auto chunk1 = stream->read().value_or(0); const auto chunk2 = stream->read().value_or(0); const auto chunk3 = stream->read().value_or(0); - const auto chunk4 = stream->read_conv().value_or(0); - const auto chunk5 = stream->read_conv().value_or(0); - const auto chunk6 = stream->read_conv().value_or(0); + + ToggleEndianness endian(*stream); + const auto chunk4 = endian->read().value_or(0); + const auto chunk5 = endian->read().value_or(0); + const auto chunk6 = endian->read().value_or(0); return fmt::format("{:08x}-{:04x}-{:04x}-{:04x}-{:04x}{:08x}", chunk1, chunk2, chunk3, chunk4, chunk5, chunk6 diff --git a/src/MachO/Convert.cpp b/src/PE/endianness_support.cpp similarity index 93% rename from src/MachO/Convert.cpp rename to src/PE/endianness_support.cpp index ffe75bafaf..b2a624493a 100644 --- a/src/MachO/Convert.cpp +++ b/src/PE/endianness_support.cpp @@ -12,7 +12,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -namespace LIEF { -namespace Convert { -} +namespace LIEF::PE { } diff --git a/src/PE/signature/SignatureParser.cpp b/src/PE/signature/SignatureParser.cpp index 90ed2e8c21..8a80aec030 100644 --- a/src/PE/signature/SignatureParser.cpp +++ b/src/PE/signature/SignatureParser.cpp @@ -1277,19 +1277,17 @@ result SignatureParser::parse_spc_string(BinaryStream& stream) { LIEF_INFO("Can't read spc-string.program-name"); return make_error_code(lief_errors::read_error); } - stream.set_endian_swap(true); + ToggleEndianness endian(stream); - auto progname = stream.read_u16string(length / sizeof(char16_t)); + auto progname = endian->read_u16string(length / sizeof(char16_t)); if (!progname) { LIEF_INFO("Can't read spc-string.program-name"); - stream.set_endian_swap(false); return make_error_code(lief_errors::read_error); } - stream.set_endian_swap(false); - return u16tou8(*progname); } + if ((choice = asn1r.read_tag(MBEDTLS_ASN1_CONTEXT_SPECIFIC | 1))) { LIEF_DEBUG("SpcString: ASCII choice"); const size_t length = choice.value(); diff --git a/include/LIEF/BinaryStream/Convert.hpp b/src/endianness_support.cpp similarity index 50% rename from include/LIEF/BinaryStream/Convert.hpp rename to src/endianness_support.cpp index d92e269fc5..dda8f4335b 100644 --- a/include/LIEF/BinaryStream/Convert.hpp +++ b/src/endianness_support.cpp @@ -13,15 +13,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef LIEF_CONVERT_H -#define LIEF_CONVERT_H +#include "LIEF/endianness_support.hpp" + +#include "intmem.h" + +#define TMPL_DECL(T) \ + template<> void \ + swap_endian(T* u) { \ + *u = swap_integer_endian(*u); \ + } + namespace LIEF { -namespace Convert { template -void swap_endian(T*); +T swap_integer_endian(T u) { + return intmem::bswap(u); +} +template<> +char16_t swap_integer_endian(char16_t u) { + return intmem::bswap((uint16_t)u); } + +template<> +char swap_integer_endian(char u) { + return intmem::bswap((uint8_t)u); } -#endif // LIEF_CONVERT_H +TMPL_DECL(char); +TMPL_DECL(char16_t); + +TMPL_DECL(uint8_t); +TMPL_DECL(uint16_t); +TMPL_DECL(uint32_t); +TMPL_DECL(uint64_t); + +TMPL_DECL(int8_t); +TMPL_DECL(int16_t); +TMPL_DECL(int32_t); +TMPL_DECL(int64_t); + +} diff --git a/src/hash_stream.hpp b/src/hash_stream.hpp index 47a98b2414..405f0b9aed 100644 --- a/src/hash_stream.hpp +++ b/src/hash_stream.hpp @@ -53,12 +53,6 @@ class hashstream { return write(reinterpret_cast(&value), size); } - template - hashstream& write_conv(const T& t); - - template - hashstream& write_conv_array(const std::vector& v); - hashstream& align(size_t size, uint8_t val = 0); template diff --git a/src/BinaryStream/intmem.h b/src/intmem.h similarity index 100% rename from src/BinaryStream/intmem.h rename to src/intmem.h diff --git a/tests/macho/test_issues.py b/tests/macho/test_issues.py index 7d45a4beb1..b37454d95d 100755 --- a/tests/macho/test_issues.py +++ b/tests/macho/test_issues.py @@ -26,3 +26,8 @@ def test_993(tmp_path): def test_1087(): target = lief.MachO.parse(get_sample("MachO/fbcb7580db7bc04d695c3fd0308bb344_issue_1087")).at(0) assert target.offset_to_virtual_address(0x42dae) == 0x100042dae + +def test_endianness(): + target = lief.MachO.parse(get_sample("MachO/macho-issue-1110.bin")).at(0) + + assert len(target.segments) == 3