mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-05-12 19:39:32 +00:00
Add support for endianness
This commit is contained in:
parent
9e3b5b45f7
commit
e794ac1502
@ -77,6 +77,7 @@ set(LIBLIEF_SOURCE_FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/Visitor.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/BinaryStream/BinaryStream.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/BinaryStream/VectorStream.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/BinaryStream/Convert.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/visitors/hash.cpp")
|
||||
|
||||
|
||||
@ -102,6 +103,7 @@ set(LIEF_INC_FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/visitor_macros.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/BinaryStream.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/VectorStream.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/Convert.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/frozen.hpp"
|
||||
)
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include <vector>
|
||||
#include <istream>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include "LIEF/BinaryStream/Convert.hpp"
|
||||
|
||||
class BinaryStream {
|
||||
public:
|
||||
@ -79,9 +82,26 @@ class BinaryStream {
|
||||
|
||||
size_t align(size_t align_on) const;
|
||||
|
||||
/* Read an integer value and adjust endianness as needed */
|
||||
template<typename T>
|
||||
T read_conv() const;
|
||||
|
||||
/* Read an array of values and adjust endianness as needed */
|
||||
template<typename T>
|
||||
std::unique_ptr<T[]> read_conv_array(size_t size, bool check = true) const;
|
||||
|
||||
template<typename T>
|
||||
T peek_conv(size_t offset) const;
|
||||
|
||||
template<typename T>
|
||||
std::unique_ptr<T[]> peek_conv_array(size_t offset, size_t size, bool check = true) const;
|
||||
|
||||
void set_endian_swap(bool swap);
|
||||
|
||||
protected:
|
||||
virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const = 0;
|
||||
mutable size_t pos_{0};
|
||||
bool endian_swap_{false};
|
||||
};
|
||||
|
||||
|
||||
@ -167,5 +187,62 @@ const T* BinaryStream::read_array(size_t size, bool check) const {
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T BinaryStream::read_conv(void) const {
|
||||
T t = this->read<T>();
|
||||
if (this->endian_swap_) {
|
||||
LIEF::Convert::swap_endian<T>(& t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::unique_ptr<T[]> BinaryStream::read_conv_array(size_t size, bool check) const {
|
||||
const T *t = this->read_array<T>(size, check);
|
||||
|
||||
if (t == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<T[]> uptr(new T[size]);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
uptr[i] = t[i];
|
||||
if (this->endian_swap_) {
|
||||
LIEF::Convert::swap_endian<T>(& uptr[i]);
|
||||
} /* else no conversion, just provide the copied data */
|
||||
}
|
||||
return uptr;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T BinaryStream::peek_conv(size_t offset) const {
|
||||
T t = this->peek<T>(offset);
|
||||
|
||||
if (this->endian_swap_) {
|
||||
LIEF::Convert::swap_endian(&t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::unique_ptr<T[]> BinaryStream::peek_conv_array(size_t offset, size_t size, bool check) const {
|
||||
const T *t = this->peek_array<T>(offset, size, check);
|
||||
|
||||
if (t == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<T[]> uptr(new T[size]);
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
uptr[i] = t[i];
|
||||
if (this->endian_swap_) {
|
||||
LIEF::Convert::swap_endian<T>(& uptr[i]);
|
||||
} /* else no conversion, just provide the copied data */
|
||||
}
|
||||
return uptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
12
include/LIEF/BinaryStream/Convert.hpp
Normal file
12
include/LIEF/BinaryStream/Convert.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef LIEF_CONVERT_H_
|
||||
#define LIEF_CONVERT_H_
|
||||
|
||||
namespace LIEF {
|
||||
namespace Convert {
|
||||
|
||||
template<typename X>
|
||||
void swap_endian(X* x);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LIEF_CONVERT_H_
|
@ -96,6 +96,8 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
|
||||
void init(const std::string& name = "");
|
||||
|
||||
bool should_swap(void) const;
|
||||
|
||||
// map, dynamic_symbol.version <----> symbol_version
|
||||
// symbol_version comes from symbol_version table
|
||||
void link_symbol_version(void);
|
||||
|
@ -218,3 +218,7 @@ std::string BinaryStream::read_mutf8(size_t maxsize) const {
|
||||
return u8str_clean;
|
||||
}
|
||||
|
||||
void BinaryStream::set_endian_swap(bool swap) {
|
||||
this->endian_swap_ = swap;
|
||||
}
|
||||
|
||||
|
23
src/BinaryStream/Convert.cpp
Normal file
23
src/BinaryStream/Convert.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "LIEF/BinaryStream/Convert.hpp"
|
||||
#include "LIEF/BinaryStream/BinaryStream.hpp"
|
||||
|
||||
/* In place conversions for BinaryStream/VectorStream data */
|
||||
|
||||
namespace LIEF {
|
||||
namespace Convert {
|
||||
|
||||
template<typename T>
|
||||
void swap_endian(T *v) {
|
||||
static_assert(std::is_integral<T>::value, "Only integer types can use generic endian swap");
|
||||
*v = BinaryStream::swap_endian(*v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Force instantiation of template for types used
|
||||
*/
|
||||
template void swap_endian<uint16_t>(uint16_t *v);
|
||||
template void swap_endian<uint32_t>(uint32_t *v);
|
||||
template void swap_endian<uint64_t>(uint64_t *v);
|
||||
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ configure_file(
|
||||
)
|
||||
|
||||
set(LIEF_ELF_SRC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Convert.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/DynamicEntryArray.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/utils.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/SymbolVersionRequirement.cpp"
|
||||
|
248
src/ELF/Convert.cpp
Normal file
248
src/ELF/Convert.cpp
Normal file
@ -0,0 +1,248 @@
|
||||
#include "LIEF/BinaryStream/Convert.hpp"
|
||||
#include "LIEF/BinaryStream/BinaryStream.hpp"
|
||||
#include "LIEF/ELF/Structures.hpp"
|
||||
|
||||
/* In place conversions for BinaryStream/VectorStream data */
|
||||
|
||||
namespace LIEF {
|
||||
namespace Convert {
|
||||
|
||||
/*
|
||||
* ELF conversions
|
||||
*/
|
||||
|
||||
/** ELF header */
|
||||
template <typename Elf_Ehdr>
|
||||
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::Elf32_Ehdr>(LIEF::ELF::Elf32_Ehdr *hdr) {
|
||||
swap_endian_ehdr(hdr);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Ehdr>(LIEF::ELF::Elf64_Ehdr *hdr) {
|
||||
swap_endian_ehdr(hdr);
|
||||
}
|
||||
|
||||
|
||||
/** ELF Section Header */
|
||||
template <typename Elf_Shdr>
|
||||
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::Elf32_Shdr>(LIEF::ELF::Elf32_Shdr *shdr) {
|
||||
swap_endian_shdr(shdr);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Shdr>(LIEF::ELF::Elf64_Shdr *shdr) {
|
||||
swap_endian_shdr(shdr);
|
||||
}
|
||||
|
||||
|
||||
/** ELF Program Header */
|
||||
template <typename Elf_Phdr>
|
||||
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::Elf32_Phdr>(LIEF::ELF::Elf32_Phdr *phdr) {
|
||||
swap_endian_phdr(phdr);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Phdr>(LIEF::ELF::Elf64_Phdr *phdr) {
|
||||
swap_endian_phdr(phdr);
|
||||
}
|
||||
|
||||
|
||||
/** ELF Symbols */
|
||||
template <typename Elf_Sym>
|
||||
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::Elf32_Sym>(LIEF::ELF::Elf32_Sym *sym) {
|
||||
swap_endian_sym(sym);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Sym>(LIEF::ELF::Elf64_Sym *sym) {
|
||||
swap_endian_sym(sym);
|
||||
}
|
||||
|
||||
/** ELF Relocations */
|
||||
template <typename REL_T>
|
||||
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 <typename RELA_T>
|
||||
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::Elf32_Rel>(LIEF::ELF::Elf32_Rel *rel) {
|
||||
swap_endian_rel(rel);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Rel>(LIEF::ELF::Elf64_Rel *rel) {
|
||||
swap_endian_rel(rel);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf32_Rela>(LIEF::ELF::Elf32_Rela *rel) {
|
||||
swap_endian_rela(rel);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Rela>(LIEF::ELF::Elf64_Rela *rel) {
|
||||
swap_endian_rela(rel);
|
||||
}
|
||||
|
||||
|
||||
/** ELF Dynamic Symbol */
|
||||
template <typename Elf_Dyn>
|
||||
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::Elf32_Dyn>(LIEF::ELF::Elf32_Dyn *dyn) {
|
||||
swap_endian_dyn(dyn);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Dyn>(LIEF::ELF::Elf64_Dyn *dyn) {
|
||||
swap_endian_dyn(dyn);
|
||||
}
|
||||
|
||||
|
||||
/** ELF Verneed */
|
||||
template <typename Elf_Verneed>
|
||||
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::Elf32_Verneed>(LIEF::ELF::Elf32_Verneed *ver) {
|
||||
swap_endian_verneed(ver);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Verneed>(LIEF::ELF::Elf64_Verneed *ver) {
|
||||
swap_endian_verneed(ver);
|
||||
}
|
||||
|
||||
|
||||
/** ELF Vernaux */
|
||||
template <typename Elf_Vernaux>
|
||||
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::Elf32_Vernaux>(LIEF::ELF::Elf32_Vernaux *ver) {
|
||||
swap_endian_vernaux(ver);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Vernaux>(LIEF::ELF::Elf64_Vernaux *ver) {
|
||||
swap_endian_vernaux(ver);
|
||||
}
|
||||
|
||||
/** ELF Symbol Version Definition */
|
||||
template <typename Elf_Verdef>
|
||||
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::Elf32_Verdef>(LIEF::ELF::Elf32_Verdef *ver) {
|
||||
swap_endian_verdef(ver);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Verdef>(LIEF::ELF::Elf64_Verdef *ver) {
|
||||
swap_endian_verdef(ver);
|
||||
}
|
||||
|
||||
|
||||
template <typename Elf_Verdaux>
|
||||
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::Elf32_Verdaux>(LIEF::ELF::Elf32_Verdaux *ver) {
|
||||
swap_endian_verdaux(ver);
|
||||
}
|
||||
|
||||
template<>
|
||||
void swap_endian<LIEF::ELF::Elf64_Verdaux>(LIEF::ELF::Elf64_Verdaux *ver) {
|
||||
swap_endian_verdaux(ver);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@
|
||||
#include "LIEF/ELF/AndroidNote.hpp"
|
||||
|
||||
|
||||
|
||||
#include "Parser.tcc"
|
||||
|
||||
|
||||
@ -84,6 +85,29 @@ Parser::Parser(const std::string& file, DYNSYM_COUNT_METHODS count_mtd, Binary*
|
||||
this->init(filesystem::path(file).filename());
|
||||
}
|
||||
|
||||
bool Parser::should_swap(void) const {
|
||||
if (not this->stream_->can_read<Elf32_Ehdr>(0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Elf32_Ehdr& elf_hdr = this->stream_->peek<Elf32_Ehdr>(0);
|
||||
ELF_DATA endian = static_cast<ELF_DATA>(elf_hdr.e_ident[static_cast<uint8_t>(IDENTITY::EI_DATA)]);
|
||||
|
||||
switch (endian) {
|
||||
#ifdef __BYTE_ORDER__
|
||||
#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
case ELF_DATA::ELFDATA2MSB:
|
||||
#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
case ELF_DATA::ELFDATA2LSB:
|
||||
#endif
|
||||
return true;
|
||||
#endif // __BYTE_ORDER__
|
||||
default:
|
||||
// we're good (or don't know what to do), consider bytes are in the expected order
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::init(const std::string& name) {
|
||||
VLOG(VDEBUG) << "Parsing binary: " << name << std::endl;
|
||||
|
||||
@ -92,7 +116,9 @@ void Parser::init(const std::string& name) {
|
||||
this->binary_->name(name);
|
||||
this->binary_->datahandler_ = new DataHandler::Handler{this->stream_->content()};
|
||||
|
||||
uint32_t type = this->stream_->peek<Elf32_Ehdr>(0).e_ident[static_cast<size_t>(IDENTITY::EI_CLASS)];
|
||||
const Elf32_Ehdr& elf_hdr = this->stream_->peek<Elf32_Ehdr>(0);
|
||||
this->stream_->set_endian_swap(this->should_swap());
|
||||
uint32_t type = elf_hdr.e_ident[static_cast<size_t>(IDENTITY::EI_CLASS)];
|
||||
|
||||
this->binary_->type_ = static_cast<ELF_CLASS>(type);
|
||||
this->type_ = static_cast<ELF_CLASS>(type);
|
||||
@ -157,7 +183,7 @@ void Parser::parse_symbol_version(uint64_t symbol_version_offset) {
|
||||
if (not this->stream_->can_read<uint16_t>()) {
|
||||
break;
|
||||
}
|
||||
this->binary_->symbol_version_table_.push_back(new SymbolVersion{this->stream_->read<uint16_t>()});
|
||||
this->binary_->symbol_version_table_.push_back(new SymbolVersion{this->stream_->read_conv<uint16_t>()});
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,7 +215,7 @@ uint64_t Parser::get_dynamic_string_table_from_segments(void) const {
|
||||
if (not this->stream_->can_read<Elf32_Dyn>()) {
|
||||
return 0;
|
||||
}
|
||||
const Elf32_Dyn& e = this->stream_->read<Elf32_Dyn>();
|
||||
const Elf32_Dyn e = this->stream_->read_conv<Elf32_Dyn>();
|
||||
|
||||
if (static_cast<DYNAMIC_TAGS>(e.d_tag) == DYNAMIC_TAGS::DT_STRTAB) {
|
||||
return this->binary_->virtual_address_to_offset(e.d_un.d_val);
|
||||
@ -203,7 +229,7 @@ uint64_t Parser::get_dynamic_string_table_from_segments(void) const {
|
||||
if (not this->stream_->can_read<Elf64_Dyn>()) {
|
||||
return 0;
|
||||
}
|
||||
const Elf64_Dyn& e = this->stream_->read<Elf64_Dyn>();
|
||||
const Elf64_Dyn e = this->stream_->read_conv<Elf64_Dyn>();
|
||||
|
||||
if (static_cast<DYNAMIC_TAGS>(e.d_tag) == DYNAMIC_TAGS::DT_STRTAB) {
|
||||
return this->binary_->virtual_address_to_offset(e.d_un.d_val);
|
||||
@ -258,7 +284,7 @@ void Parser::parse_symbol_sysv_hash(uint64_t offset) {
|
||||
SysvHash sysvhash;
|
||||
|
||||
this->stream_->setpos(offset);
|
||||
const uint32_t* header = this->stream_->read_array<uint32_t>(2, /* check */false);
|
||||
std::unique_ptr<uint32_t[]> header = this->stream_->read_conv_array<uint32_t>(2, /* check */false);
|
||||
|
||||
if (header == nullptr) {
|
||||
LOG(ERROR) << "Can't read SYSV Hash header";
|
||||
@ -274,7 +300,7 @@ void Parser::parse_symbol_sysv_hash(uint64_t offset) {
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
buckets[i] = this->stream_->read<uint32_t>();
|
||||
buckets[i] = this->stream_->read_conv<uint32_t>();
|
||||
}
|
||||
|
||||
sysvhash.buckets_ = std::move(buckets);
|
||||
@ -285,7 +311,7 @@ void Parser::parse_symbol_sysv_hash(uint64_t offset) {
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
chains[i] = this->stream_->read<uint32_t>();
|
||||
chains[i] = this->stream_->read_conv<uint32_t>();
|
||||
}
|
||||
|
||||
sysvhash.chains_ = std::move(chains);
|
||||
@ -304,21 +330,21 @@ void Parser::parse_notes(uint64_t offset, uint64_t size) {
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
uint32_t namesz = this->stream_->read<uint32_t>();
|
||||
uint32_t namesz = this->stream_->read_conv<uint32_t>();
|
||||
VLOG(VDEBUG) << "Name size: " << std::hex << namesz;
|
||||
|
||||
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
uint32_t descsz = std::min(this->stream_->read<uint32_t>(), Parser::MAX_NOTE_DESCRIPTION);
|
||||
uint32_t descsz = std::min(this->stream_->read_conv<uint32_t>(), Parser::MAX_NOTE_DESCRIPTION);
|
||||
|
||||
VLOG(VDEBUG) << "Description size: " << std::hex << descsz;
|
||||
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
NOTE_TYPES type = static_cast<NOTE_TYPES>(this->stream_->read<uint32_t>());
|
||||
NOTE_TYPES type = static_cast<NOTE_TYPES>(this->stream_->read_conv<uint32_t>());
|
||||
VLOG(VDEBUG) << "Type: " << std::hex << static_cast<size_t>(type);
|
||||
|
||||
if (namesz == 0) { // System reserves
|
||||
@ -331,9 +357,12 @@ void Parser::parse_notes(uint64_t offset, uint64_t size) {
|
||||
|
||||
std::vector<uint8_t> description;
|
||||
if (descsz > 0) {
|
||||
const uint8_t* desc_ptr = this->stream_->read_array<uint8_t>(descsz, /* check */false);
|
||||
const size_t nb_chunks = (descsz - 1) / sizeof(uint32_t) + 1;
|
||||
std::unique_ptr<uint32_t[]> desc_ptr = this->stream_->read_conv_array<uint32_t>(nb_chunks, /* check */ false);
|
||||
if (desc_ptr != nullptr) {
|
||||
description = {desc_ptr, desc_ptr + descsz};
|
||||
description = {
|
||||
reinterpret_cast<uint8_t *>(desc_ptr.get()),
|
||||
reinterpret_cast<uint8_t *>(desc_ptr.get()) + descsz};
|
||||
}
|
||||
this->stream_->align(sizeof(uint32_t));
|
||||
}
|
||||
|
@ -454,7 +454,8 @@ bool Parser::parse_header(void) {
|
||||
VLOG(VDEBUG) << "[+] Parsing Header";
|
||||
this->stream_->setpos(0);
|
||||
if (this->stream_->can_read<Elf_Ehdr>()) {
|
||||
this->binary_->header_ = &this->stream_->read<Elf_Ehdr>();
|
||||
Elf_Ehdr hdr = this->stream_->read_conv<Elf_Ehdr>();
|
||||
this->binary_->header_ = &hdr;
|
||||
return true;
|
||||
} else {
|
||||
LOG(FATAL) << "Can't read header!";
|
||||
@ -648,7 +649,7 @@ uint32_t Parser::max_relocation_index(uint64_t relocations_offset, uint64_t size
|
||||
if (not this->stream_->can_read<REL_T>()) {
|
||||
break;
|
||||
}
|
||||
const REL_T& reloc_entry = this->stream_->read<REL_T>();
|
||||
const REL_T reloc_entry = this->stream_->read_conv<REL_T>();
|
||||
idx = std::max(idx, static_cast<uint32_t>(reloc_entry.r_info >> shift));
|
||||
}
|
||||
return (idx + 1);
|
||||
@ -704,7 +705,7 @@ uint32_t Parser::nb_dynsym_sysv_hash(void) const {
|
||||
|
||||
this->stream_->setpos(sysv_hash_offset + sizeof(uint32_t));
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
return this->stream_->read<uint32_t>();
|
||||
return this->stream_->read_conv<uint32_t>();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -724,25 +725,25 @@ uint32_t Parser::nb_dynsym_gnu_hash(void) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t nbuckets = std::min(this->stream_->read<uint32_t>(), Parser::NB_MAX_BUCKETS);
|
||||
const uint32_t nbuckets = std::min(this->stream_->read_conv<uint32_t>(), Parser::NB_MAX_BUCKETS);
|
||||
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t symndx = this->stream_->read<uint32_t>();
|
||||
const uint32_t symndx = this->stream_->read_conv<uint32_t>();
|
||||
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t maskwords = std::min(this->stream_->read<uint32_t>(), Parser::NB_MAX_MASKWORD);
|
||||
const uint32_t maskwords = std::min(this->stream_->read_conv<uint32_t>(), Parser::NB_MAX_MASKWORD);
|
||||
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t shift2 = this->stream_->read<uint32_t>();
|
||||
const uint32_t shift2 = this->stream_->read_conv<uint32_t>();
|
||||
|
||||
if (maskwords & (maskwords - 1)) {
|
||||
LOG(WARNING) << "maskwords is not a power of 2";
|
||||
@ -762,7 +763,7 @@ uint32_t Parser::nb_dynsym_gnu_hash(void) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bloom_filters[i] = this->stream_->read<uint__>();
|
||||
bloom_filters[i] = this->stream_->read_conv<uint__>();
|
||||
}
|
||||
|
||||
std::vector<uint32_t> buckets;
|
||||
@ -777,7 +778,7 @@ uint32_t Parser::nb_dynsym_gnu_hash(void) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
buckets.push_back(this->stream_->read<uint32_t>());
|
||||
buckets.push_back(this->stream_->read_conv<uint32_t>());
|
||||
}
|
||||
|
||||
if (buckets.size() == 0) {
|
||||
@ -806,7 +807,7 @@ uint32_t Parser::nb_dynsym_gnu_hash(void) const {
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
return 0;
|
||||
}
|
||||
hash_value = this->stream_->read<uint32_t>();
|
||||
hash_value = this->stream_->read_conv<uint32_t>();
|
||||
|
||||
nsyms++;
|
||||
} while ((hash_value & 1) == 0); // "It is set to 1 when a symbol is the last symbol in a given hash bucket"
|
||||
@ -837,7 +838,7 @@ void Parser::parse_sections(void) {
|
||||
break;
|
||||
}
|
||||
|
||||
const Elf_Shdr& shdr = this->stream_->read<Elf_Shdr>();
|
||||
const Elf_Shdr shdr = this->stream_->read_conv<Elf_Shdr>();
|
||||
|
||||
std::unique_ptr<Section> section{new Section{&shdr}};
|
||||
section->datahandler_ = this->binary_->datahandler_;
|
||||
@ -899,7 +900,7 @@ void Parser::parse_segments(void) {
|
||||
LOG(ERROR) << "Can't parse segment #" << std::dec << i;
|
||||
break;
|
||||
}
|
||||
const Elf_Phdr& segment_headers = this->stream_->read<Elf_Phdr>();
|
||||
const Elf_Phdr segment_headers = this->stream_->read_conv<Elf_Phdr>();
|
||||
|
||||
std::unique_ptr<Segment> segment{new Segment{&segment_headers}};
|
||||
segment->datahandler_ = this->binary_->datahandler_;
|
||||
@ -957,7 +958,7 @@ void Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64_t siz
|
||||
if (not this->stream_->can_read<REL_T>()) {
|
||||
break;
|
||||
}
|
||||
const REL_T& raw_reloc = this->stream_->read<REL_T>();
|
||||
const REL_T raw_reloc = this->stream_->read_conv<REL_T>();
|
||||
std::unique_ptr<Relocation> reloc{new Relocation{&raw_reloc}};
|
||||
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC);
|
||||
reloc->architecture_ = this->binary_->header().machine_type();
|
||||
@ -989,7 +990,7 @@ void Parser::parse_static_symbols(uint64_t offset, uint32_t nbSymbols, const Sec
|
||||
if (not this->stream_->can_read<Elf_Sym>()) {
|
||||
break;
|
||||
}
|
||||
const Elf_Sym& raw_sym = this->stream_->read<Elf_Sym>();
|
||||
const Elf_Sym raw_sym = this->stream_->read_conv<Elf_Sym>();
|
||||
|
||||
std::unique_ptr<Symbol> symbol{new Symbol{&raw_sym}};
|
||||
std::string symbol_name = this->stream_->peek_string_at(string_section->file_offset() + raw_sym.st_name);
|
||||
@ -1026,7 +1027,7 @@ void Parser::parse_dynamic_symbols(uint64_t offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Elf_Sym& symbol_header = this->stream_->read<Elf_Sym>();
|
||||
const Elf_Sym symbol_header = this->stream_->read_conv<Elf_Sym>();
|
||||
std::unique_ptr<Symbol> symbol{new Symbol{&symbol_header}};
|
||||
|
||||
if (symbol_header.st_name > 0) {
|
||||
@ -1073,7 +1074,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
if (not this->stream_->can_read<Elf_Dyn>()) {
|
||||
break;
|
||||
}
|
||||
const Elf_Dyn& entry = this->stream_->read<Elf_Dyn>();
|
||||
const Elf_Dyn entry = this->stream_->read_conv<Elf_Dyn>();
|
||||
|
||||
std::unique_ptr<DynamicEntry> dynamic_entry;
|
||||
|
||||
@ -1193,7 +1194,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
if (not this->stream_->can_read<Elf_Addr>()) {
|
||||
break;
|
||||
}
|
||||
array.push_back(this->stream_->read<Elf_Addr>());
|
||||
array.push_back(this->stream_->read_conv<Elf_Addr>());
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1235,7 +1236,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
if (not this->stream_->can_read<Elf_Addr>()) {
|
||||
break;
|
||||
}
|
||||
array.push_back(this->stream_->read<Elf_Addr>());
|
||||
array.push_back(this->stream_->read_conv<Elf_Addr>());
|
||||
}
|
||||
} else {
|
||||
//TODO
|
||||
@ -1278,7 +1279,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
break;
|
||||
}
|
||||
|
||||
array.push_back(this->stream_->read<Elf_Addr>());
|
||||
array.push_back(this->stream_->read_conv<Elf_Addr>());
|
||||
}
|
||||
} else {
|
||||
//TODO: has DT_FINI but not DT_FINISZ
|
||||
@ -1310,7 +1311,7 @@ void Parser::parse_pltgot_relocations(uint64_t offset, uint64_t size) {
|
||||
if (not this->stream_->can_read<REL_T>()) {
|
||||
break;
|
||||
}
|
||||
const REL_T& rel_hdr = this->stream_->read<REL_T>();
|
||||
const REL_T rel_hdr = this->stream_->read_conv<REL_T>();
|
||||
std::unique_ptr<Relocation> reloc{new Relocation{&rel_hdr}};
|
||||
reloc->architecture_ = this->binary_->header_.machine_type();
|
||||
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT);
|
||||
@ -1343,7 +1344,7 @@ void Parser::parse_section_relocations(uint64_t offset, uint64_t size, Section *
|
||||
if (not this->stream_->can_read<REL_T>()) {
|
||||
break;
|
||||
}
|
||||
const REL_T& rel_hdr = this->stream_->read<REL_T>();
|
||||
const REL_T rel_hdr = this->stream_->read_conv<REL_T>();
|
||||
|
||||
std::unique_ptr<Relocation> reloc{new Relocation{&rel_hdr}};
|
||||
reloc->architecture_ = this->binary_->header_.machine_type();
|
||||
@ -1394,7 +1395,7 @@ void Parser::parse_symbol_version_requirement(uint64_t offset, uint32_t nb_entri
|
||||
if (not this->stream_->can_read<Elf_Verneed>(svr_offset + next_symbol_offset)) {
|
||||
break;
|
||||
}
|
||||
const Elf_Verneed& header = this->stream_->peek<Elf_Verneed>(svr_offset + next_symbol_offset);
|
||||
const Elf_Verneed header = this->stream_->peek_conv<Elf_Verneed>(svr_offset + next_symbol_offset);
|
||||
|
||||
std::unique_ptr<SymbolVersionRequirement> symbol_version_requirement{new SymbolVersionRequirement{&header}};
|
||||
if (string_offset != 0) {
|
||||
@ -1410,7 +1411,7 @@ void Parser::parse_symbol_version_requirement(uint64_t offset, uint32_t nb_entri
|
||||
if (not this->stream_->can_read<Elf_Vernaux>(svr_offset + next_symbol_offset + header.vn_aux + next_aux_offset)) {
|
||||
break;
|
||||
}
|
||||
const Elf_Vernaux& aux_header = this->stream_->peek<Elf_Vernaux>(svr_offset + next_symbol_offset + header.vn_aux + next_aux_offset);
|
||||
const Elf_Vernaux aux_header = this->stream_->peek_conv<Elf_Vernaux>(svr_offset + next_symbol_offset + header.vn_aux + next_aux_offset);
|
||||
|
||||
std::unique_ptr<SymbolVersionAuxRequirement> svar{new SymbolVersionAuxRequirement{&aux_header}};
|
||||
if (string_offset != 0) {
|
||||
@ -1465,7 +1466,7 @@ void Parser::parse_symbol_version_definition(uint64_t offset, uint32_t nb_entrie
|
||||
if (not this->stream_->can_read<Elf_Verdef>(offset + next_symbol_offset)) {
|
||||
break;
|
||||
}
|
||||
const Elf_Verdef& svd_header = this->stream_->peek<Elf_Verdef>(offset + next_symbol_offset);
|
||||
const Elf_Verdef svd_header = this->stream_->peek_conv<Elf_Verdef>(offset + next_symbol_offset);
|
||||
|
||||
std::unique_ptr<SymbolVersionDefinition> symbol_version_definition{new SymbolVersionDefinition{&svd_header}};
|
||||
uint32_t nb_aux_symbols = svd_header.vd_cnt;
|
||||
@ -1475,7 +1476,7 @@ void Parser::parse_symbol_version_definition(uint64_t offset, uint32_t nb_entrie
|
||||
break;
|
||||
}
|
||||
|
||||
const Elf_Verdaux& svda_header = this->stream_->peek<Elf_Verdaux>(offset + next_symbol_offset + svd_header.vd_aux + next_aux_offset);
|
||||
const Elf_Verdaux svda_header = this->stream_->peek_conv<Elf_Verdaux>(offset + next_symbol_offset + svd_header.vd_aux + next_aux_offset);
|
||||
|
||||
if (string_offset != 0) {
|
||||
std::string name = this->stream_->peek_string_at(string_offset + svda_header.vda_name);
|
||||
@ -1531,7 +1532,7 @@ void Parser::parse_symbol_gnu_hash(uint64_t offset) {
|
||||
|
||||
this->stream_->setpos(offset);
|
||||
|
||||
const uint32_t* header = this->stream_->read_array<uint32_t>(4, /* check */false);
|
||||
std::unique_ptr<uint32_t[]> header = this->stream_->read_conv_array<uint32_t>(4, /* check */false);
|
||||
|
||||
if (header == nullptr) {
|
||||
LOG(ERROR) << "Can't read GNU Hash header";
|
||||
@ -1558,7 +1559,7 @@ void Parser::parse_symbol_gnu_hash(uint64_t offset) {
|
||||
LOG(ERROR) << "Can't read maskwords #" << std::dec << i;
|
||||
break;
|
||||
}
|
||||
bloom_filters[i] = this->stream_->read<uint__>();
|
||||
bloom_filters[i] = this->stream_->read_conv<uint__>();
|
||||
}
|
||||
gnuhash.bloom_filters_ = std::move(bloom_filters);
|
||||
|
||||
@ -1574,10 +1575,10 @@ void Parser::parse_symbol_gnu_hash(uint64_t offset) {
|
||||
std::vector<uint32_t> buckets;
|
||||
buckets.reserve(nbuckets);
|
||||
|
||||
const uint32_t* hash_buckets = this->stream_->read_array<uint32_t>(nbuckets, /* check */false);
|
||||
std::unique_ptr<uint32_t[]> hash_buckets = this->stream_->read_conv_array<uint32_t>(nbuckets, false);
|
||||
|
||||
if (hash_buckets != nullptr) {
|
||||
buckets = {hash_buckets, hash_buckets + nbuckets};
|
||||
buckets = {hash_buckets.get(), hash_buckets.get() + nbuckets};
|
||||
} else {
|
||||
LOG(ERROR) << "GNU Hash, hash_buckets corrupted";
|
||||
}
|
||||
@ -1593,11 +1594,11 @@ void Parser::parse_symbol_gnu_hash(uint64_t offset) {
|
||||
if (nb_hash < MAX_NB_HASH) {
|
||||
std::vector<uint32_t> hashvalues;
|
||||
hashvalues.reserve(nb_hash);
|
||||
const uint32_t* hash_values = this->stream_->read_array<uint32_t>(nb_hash, /* check */false);
|
||||
std::unique_ptr<uint32_t[]> hash_values = this->stream_->read_conv_array<uint32_t>(nb_hash, /* check */ false);
|
||||
if (hash_values == nullptr) {
|
||||
LOG(ERROR) << "Can't read hash table";
|
||||
} else {
|
||||
hashvalues = {hash_values, hash_values + nb_hash};
|
||||
hashvalues = {hash_values.get(), hash_values.get() + nb_hash};
|
||||
gnuhash.hash_values_ = std::move(hashvalues);
|
||||
}
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user