Support for building foreign-endian ELF binaries

This commit is contained in:
yd0b0N 2018-05-17 16:45:18 +02:00 committed by Romain Thomas
parent 03529285df
commit d26f398296
8 changed files with 244 additions and 158 deletions

View File

@ -109,7 +109,7 @@ template<typename T>
T BinaryStream::swap_endian(T u) {
// From http://stackoverflow.com/a/4956493
static_assert(CHAR_BIT == 8, "CHAR_BIT != 8");
static_assert(std::is_integral<T>::value, "Interger required");
static_assert(std::is_integral<T>::value, "Integer required");
union {
T u;
unsigned char u8[sizeof(T)];

View File

@ -113,6 +113,8 @@ class LIEF_API Builder {
template<typename ELF_T>
void relocate_dynamic_array(DynamicEntryArray& entry_array, DynamicEntry& entry_size);
bool should_swap(void) const;
mutable vector_iostream ios_;
Binary* binary_;

View File

@ -20,6 +20,8 @@
#include <cstdint>
#include <vector>
#include "LIEF/BinaryStream/Convert.hpp"
namespace LIEF {
class vector_iostream {
public:
@ -27,18 +29,29 @@ class vector_iostream {
using pos_type = std::streampos;
using off_type = std::streamoff;
vector_iostream(void);
vector_iostream(bool endian_swap=false);
void reserve(size_t size);
vector_iostream& put(uint8_t c);
vector_iostream& write(const uint8_t* s, std::streamsize n);
vector_iostream& write(const std::vector<uint8_t>& s);
vector_iostream& write(std::vector<uint8_t>&& s);
vector_iostream& write(const std::string& s);
template<typename T>
vector_iostream& write_conv(const T& t);
template<typename T>
vector_iostream& write_conv_array(const std::vector<T>& v);
vector_iostream& align(size_t size, uint8_t val = 0);
vector_iostream& get(std::vector<uint8_t>& c);
vector_iostream& flush();
size_t size(void) const;
// seeks:
pos_type tellp(void);
vector_iostream& seekp(pos_type p);
@ -46,12 +59,45 @@ class vector_iostream {
const std::vector<uint8_t>& raw(void) const;
void set_endian_swap(bool swap);
private:
pos_type current_pos_;
std::vector<uint8_t> raw_;
bool endian_swap_{false};
};
template<typename T>
vector_iostream& vector_iostream::write_conv(const T& t) {
const uint8_t *ptr = nullptr;
if (this->endian_swap_) {
T tmp = t;
LIEF::Convert::swap_endian<T>(&tmp);
ptr = reinterpret_cast<const uint8_t*>(&tmp);
} else {
ptr = reinterpret_cast<const uint8_t*>(&t);
}
this->write(ptr, sizeof(T));
return *this;
}
template<typename T>
vector_iostream& vector_iostream::write_conv_array(const std::vector<T>& v) {
for (const T& i: v) {
const uint8_t* ptr = nullptr;
if (this->endian_swap_) {
T t = i;
LIEF::Convert::swap_endian<T>(&t);
ptr = reinterpret_cast<const uint8_t*>(&t);
} else {
ptr = reinterpret_cast<const uint8_t*>(&i);
}
this->write(ptr, sizeof(T));
}
return *this;
}
// From https://stackoverflow.com/questions/27336335/c-cout-with-prefix
class prefixbuf : public std::streambuf {
public:

View File

@ -1913,6 +1913,20 @@ void Binary::shift_relocations(uint64_t from, uint64_t shift) {
break;
}
case ARCH::EM_PPC:
{
this->patch_relocations<ARCH::EM_PPC>(from, shift);
break;
}
/*
case ARCH::EM_PPC64:
{
this->patch_relocations<ARCH::EM_PPC64>(from, shift);
break;
}
*/
default:
{
LOG(WARNING) << "Relocations for architecture " << to_string(arch) << " is not supported!";

View File

@ -194,6 +194,35 @@ void Binary::patch_relocations<ARCH::EM_X86_64>(uint64_t from, uint64_t shift) {
}
// ==================
// PPC_32 Relocations
// ==================
template<>
void Binary::patch_relocations<ARCH::EM_PPC>(uint64_t from, uint64_t shift) {
for (Relocation& relocation : this->relocations()) {
if (relocation.address() >= from) {
relocation.address(relocation.address() + shift);
}
const RELOC_POWERPC32 type = static_cast<RELOC_POWERPC32>(relocation.type());
switch (type) {
case RELOC_POWERPC32::R_PPC_RELATIVE:
{
VLOG(VDEBUG) << "Patch addend of " << relocation;
this->patch_addend<uint32_t>(relocation, from, shift);
break;
}
default:
{
VLOG(VDEBUG) << "Relocation '" << to_string(type) << "' not patched";
}
}
}
}
template<class T>
void Binary::patch_addend(Relocation& relocation, uint64_t from, uint64_t shift) {

View File

@ -38,8 +38,27 @@ Builder::Builder(Binary *binary) :
binary_{binary}
{
this->ios_.reserve(binary->original_size());
this->ios_.set_endian_swap(this->should_swap());
}
bool Builder::should_swap(void) const {
switch (this->binary_->header().abstract_endianness()) {
#ifdef __BYTE_ORDER__
#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
case ENDIANNESS::ENDIAN_BIG:
#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
case ENDIANNESS::ENDIAN_LITTLE:
#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 Builder::build(void) {
if(this->binary_->type() == ELF_CLASS::ELFCLASS32) {
this->build<ELF32>();
@ -89,38 +108,27 @@ void Builder::build_empty_symbol_gnuhash(void) {
Section* gnu_hash_section = *it_gnuhash;
std::vector<uint8_t> content;
vector_iostream content(this->should_swap());
const uint32_t nb_buckets = 1;
const uint32_t shift2 = 0;
const uint32_t maskwords = 1;
const uint32_t symndx = 1; // 0 is reserved
// nb_buckets
content.insert(std::end(content),
reinterpret_cast<const uint8_t*>(&nb_buckets),
reinterpret_cast<const uint8_t*>(&nb_buckets) + sizeof(uint32_t));
content.write_conv<uint32_t>(nb_buckets);
// symndx
content.insert(std::end(content),
reinterpret_cast<const uint8_t*>(&symndx),
reinterpret_cast<const uint8_t*>(&symndx) + sizeof(uint32_t));
content.write_conv<uint32_t>(symndx);
// maskwords
content.insert(std::end(content),
reinterpret_cast<const uint8_t*>(&maskwords),
reinterpret_cast<const uint8_t*>(&maskwords) + sizeof(uint32_t));
content.write_conv<uint32_t>(maskwords);
// shift2
content.insert(std::end(content),
reinterpret_cast<const uint8_t*>(&shift2),
reinterpret_cast<const uint8_t*>(&shift2) + sizeof(uint32_t));
content.write_conv<uint32_t>(shift2);
// fill with 0
content.insert(
std::end(content),
gnu_hash_section->size() - content.size(),
0);
gnu_hash_section->content(content);
content.align(gnu_hash_section->size(), 0);
gnu_hash_section->content(content.raw());
}

View File

@ -207,7 +207,7 @@ void Builder::build(const Header& header) {;
std::begin(ehdr.e_ident));
this->ios_.seekp(0);
this->ios_.write(reinterpret_cast<const uint8_t*>(&ehdr), sizeof(Elf_Ehdr));
this->ios_.write_conv<Elf_Ehdr>(ehdr);
}
@ -296,7 +296,7 @@ void Builder::build_sections(void) {
// Write Section'header
if (section_headers_offset > 0) {
this->ios_.seekp(section_headers_offset + i * sizeof(Elf_Shdr));
this->ios_.write(reinterpret_cast<const uint8_t*>(&shdr), sizeof(Elf_Shdr));
this->ios_.write_conv<Elf_Shdr>(shdr);
}
}
@ -317,7 +317,7 @@ void Builder::build_segments(void) {
using Elf_Phdr = typename ELF_T::Elf_Phdr;
VLOG(VDEBUG) << "[+] Build segments";
std::vector<uint8_t> pheaders;
vector_iostream pheaders(this->should_swap());
pheaders.reserve(this->binary_->segments_.size() * sizeof(Elf_Phdr));
for (const Segment* segment : this->binary_->segments_) {
@ -331,10 +331,7 @@ void Builder::build_segments(void) {
phdr.p_memsz = static_cast<Elf_Word>(segment->virtual_size());
phdr.p_align = static_cast<Elf_Word>(segment->alignment());
pheaders.insert(
std::end(pheaders),
reinterpret_cast<uint8_t*>(&phdr),
reinterpret_cast<uint8_t*>(&phdr) + sizeof(Elf_Phdr));
pheaders.write_conv<Elf_Phdr>(phdr);
}
@ -347,7 +344,7 @@ void Builder::build_segments(void) {
});
if (it_segment_phdr != std::end(this->binary_->segments_)) {
(*it_segment_phdr)->content(pheaders);
(*it_segment_phdr)->content(pheaders.raw());
}
@ -366,7 +363,7 @@ void Builder::build_segments(void) {
const Elf_Off segment_header_offset = this->binary_->header().program_headers_offset();
this->ios_.seekp(segment_header_offset);
this->ios_.write(std::move(pheaders));
this->ios_.write(std::move(pheaders.raw()));
}
@ -393,7 +390,7 @@ void Builder::build_static_symbols(void) {
}
Section& symbol_str_section = *(this->binary_->sections_[symbol_section.link()]);
std::vector<uint8_t> content;
vector_iostream content(this->should_swap());
content.reserve(this->binary_->static_symbols_.size() * sizeof(Elf_Sym));
std::vector<uint8_t> string_table;
@ -436,14 +433,11 @@ void Builder::build_static_symbols(void) {
sym_hdr.st_value = static_cast<Elf_Addr>(symbol->value());
sym_hdr.st_size = static_cast<Elf_Word>(symbol->size());
content.insert(
std::end(content),
reinterpret_cast<uint8_t*>(&sym_hdr),
reinterpret_cast<uint8_t*>(&sym_hdr) + sizeof(Elf_Sym));
content.write_conv<Elf_Sym>(sym_hdr);
}
symbol_str_section.content(std::move(string_table));
symbol_section.content(std::move(content));
symbol_section.content(std::move(content.raw()));
}
@ -486,7 +480,7 @@ void Builder::build_dynamic_section(void) {
Section& dyn_section = this->binary_->dynamic_section();
std::vector<uint8_t> dynamic_strings_raw;
std::vector<uint8_t> dynamic_table_raw;
vector_iostream dynamic_table_raw(this->should_swap());
dynamic_strings_raw.push_back(0);
for (DynamicEntry* entry : this->binary_->dynamic_entries_) {
@ -607,10 +601,7 @@ void Builder::build_dynamic_section(void) {
dynhdr.d_tag = static_cast<Elf_Sxword>(entry->tag());
dynhdr.d_un.d_val = static_cast<Elf_Xword>(entry->value());
dynamic_table_raw.insert(
std::end(dynamic_table_raw),
reinterpret_cast<uint8_t*>(&dynhdr),
reinterpret_cast<uint8_t*>(&dynhdr) + sizeof(Elf_Dyn));
dynamic_table_raw.write_conv<Elf_Dyn>(dynhdr);
}
@ -622,7 +613,7 @@ void Builder::build_dynamic_section(void) {
Segment dynamic_load;
dynamic_load.type(SEGMENT_TYPES::PT_LOAD);
dynamic_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
dynamic_load.content(dynamic_table_raw);
dynamic_load.content(dynamic_table_raw.raw());
Segment& new_dynamic_load = this->binary_->add(dynamic_load);
auto&& it_dynamic = std::find_if(
@ -678,7 +669,7 @@ void Builder::build_dynamic_section(void) {
VLOG(VDEBUG) << dyn_strtab_section;
dyn_strtab_section.content(std::move(dynamic_strings_raw));
dyn_section.content(std::move(dynamic_table_raw));
dyn_section.content(std::move(dynamic_table_raw.raw()));
}
@ -699,9 +690,10 @@ void Builder::build_symbol_hash(void) {
std::vector<uint8_t> content = (*it_hash_section)->content();
VectorStream hashtable_stream{content};
hashtable_stream.set_endian_swap(this->should_swap());
hashtable_stream.setpos(0);
uint32_t nbucket = hashtable_stream.read<uint32_t>();
uint32_t nchain = hashtable_stream.read<uint32_t>();
uint32_t nbucket = hashtable_stream.read_conv<uint32_t>();
uint32_t nchain = hashtable_stream.read_conv<uint32_t>();
std::vector<uint8_t> new_hash_table((nbucket + nchain + 2) * sizeof(uint32_t), 0);
@ -739,6 +731,13 @@ void Builder::build_symbol_hash(void) {
++idx;
}
// to be improved...?
if (this->should_swap()) {
for (size_t i = 0; i < nbucket + nchain + 2; i++) {
Convert::swap_endian(&new_hash_table_ptr[i]);
}
}
Section& h_section = **it_hash_section;
if (new_hash_table.size() > h_section.size()) {
LOG(INFO) << "Need to relocate the '" << h_section.name() << "' section";
@ -804,7 +803,7 @@ void Builder::build_symbol_gnuhash(void) {
it_symbols dynamic_symbols = this->binary_->dynamic_symbols();
std::vector<uint8_t> raw_gnuhash;
vector_iostream raw_gnuhash(this->should_swap());
raw_gnuhash.reserve(
4 * sizeof(uint32_t) + // header
maskwords * sizeof(uint__) + // bloom filters
@ -816,24 +815,16 @@ void Builder::build_symbol_gnuhash(void) {
// ==============
// nb_buckets
raw_gnuhash.insert(std::end(raw_gnuhash),
reinterpret_cast<const uint8_t*>(&nb_buckets),
reinterpret_cast<const uint8_t*>(&nb_buckets) + sizeof(uint32_t));
raw_gnuhash.write_conv<uint32_t>(nb_buckets);
// symndx
raw_gnuhash.insert(std::end(raw_gnuhash),
reinterpret_cast<const uint8_t*>(&symndx),
reinterpret_cast<const uint8_t*>(&symndx) + sizeof(uint32_t));
raw_gnuhash.write_conv<uint32_t>(symndx);
// maskwords
raw_gnuhash.insert(std::end(raw_gnuhash),
reinterpret_cast<const uint8_t*>(&maskwords),
reinterpret_cast<const uint8_t*>(&maskwords) + sizeof(uint32_t));
raw_gnuhash.write_conv<uint32_t>(maskwords);
// shift2
raw_gnuhash.insert(std::end(raw_gnuhash),
reinterpret_cast<const uint8_t*>(&shift2),
reinterpret_cast<const uint8_t*>(&shift2) + sizeof(uint32_t));
raw_gnuhash.write_conv<uint32_t>(shift2);
@ -853,9 +844,7 @@ void Builder::build_symbol_gnuhash(void) {
VLOG(VDEBUG) << "Bloom filter [" << std::dec << idx << "]: " << std::hex << bloom_filters[idx];
}
raw_gnuhash.insert(std::end(raw_gnuhash),
reinterpret_cast<uint8_t*>(bloom_filters.data()),
reinterpret_cast<uint8_t*>(bloom_filters.data() + bloom_filters.size()));
raw_gnuhash.write_conv_array(bloom_filters);
// Write buckets and hash
@ -891,13 +880,9 @@ void Builder::build_symbol_gnuhash(void) {
hash_values[hash_value_idx - 1] |= 1;
}
raw_gnuhash.insert(std::end(raw_gnuhash),
reinterpret_cast<uint8_t*>(buckets.data()),
reinterpret_cast<uint8_t*>(buckets.data() + buckets.size()));
raw_gnuhash.write_conv_array<uint32_t>(buckets);
raw_gnuhash.insert(std::end(raw_gnuhash),
reinterpret_cast<uint8_t*>(hash_values.data()),
reinterpret_cast<uint8_t*>(hash_values.data() + hash_values.size()));
raw_gnuhash.write_conv_array<uint32_t>(hash_values);
auto&& it_gnuhash = std::find_if(
std::begin(this->binary_->sections_),
@ -920,7 +905,7 @@ void Builder::build_symbol_gnuhash(void) {
Segment gnuhash;
gnuhash.type(SEGMENT_TYPES::PT_LOAD);
gnuhash.flags(ELF_SEGMENT_FLAGS::PF_R);
gnuhash.content(raw_gnuhash);
gnuhash.content(raw_gnuhash.raw());
Segment& new_segment = this->binary_->add(gnuhash);
@ -936,7 +921,7 @@ void Builder::build_symbol_gnuhash(void) {
}
return h_section.content(std::move(raw_gnuhash));
return h_section.content(std::move(raw_gnuhash.raw()));
}
@ -1013,7 +998,7 @@ void Builder::build_dynamic_symbols(void) {
//
// Build symbols
//
std::vector<uint8_t> symbol_table_raw;
vector_iostream symbol_table_raw(this->should_swap());
for (const Symbol* symbol : this->binary_->dynamic_symbols_) {
const std::string& name = symbol->name();
// Check if name is already pressent
@ -1036,10 +1021,7 @@ void Builder::build_dynamic_symbols(void) {
sym_header.st_value = static_cast<Elf_Addr>(symbol->value());
sym_header.st_size = static_cast<Elf_Word>(symbol->size());
symbol_table_raw.insert(
std::end(symbol_table_raw),
reinterpret_cast<uint8_t*>(&sym_header),
reinterpret_cast<uint8_t*>(&sym_header) + sizeof(Elf_Sym));
symbol_table_raw.write_conv(sym_header);
}
VLOG(VDEBUG) << "Set raw string table";
@ -1075,7 +1057,7 @@ void Builder::build_dynamic_symbols(void) {
Segment dynsym_load;
dynsym_load.type(SEGMENT_TYPES::PT_LOAD);
dynsym_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
dynsym_load.content(symbol_table_raw);
dynsym_load.content(symbol_table_raw.raw());
Segment& new_dynsym_load = this->binary_->add(dynsym_load);
symbol_table_section.virtual_address(new_dynsym_load.virtual_address());
@ -1093,7 +1075,7 @@ void Builder::build_dynamic_symbols(void) {
VLOG(VDEBUG) << "Write back symbol table";
string_table_section.content(std::move(string_table_raw));
symbol_table_section.content(std::move(symbol_table_raw));
symbol_table_section.content(std::move(symbol_table_raw.raw()));
}
@ -1176,7 +1158,7 @@ void Builder::build_dynamic_relocations(void) {
dt_reloc_size->value(dynamic_relocations.size() * sizeof(Elf_Rel));
}
std::vector<uint8_t> content;
vector_iostream content(this->should_swap());
for (const Relocation& relocation : this->binary_->dynamic_relocations()) {
// look for symbol index
@ -1217,20 +1199,13 @@ void Builder::build_dynamic_relocations(void) {
relahdr.r_info = static_cast<Elf_Xword>(r_info);
relahdr.r_addend = static_cast<Elf_Sxword>(relocation.addend());
content.insert(
std::end(content),
reinterpret_cast<uint8_t*>(&relahdr),
reinterpret_cast<uint8_t*>(&relahdr) + sizeof(Elf_Rela));
content.write_conv<Elf_Rela>(relahdr);
} else {
Elf_Rel relhdr;
relhdr.r_offset = static_cast<Elf_Addr>(relocation.address());
relhdr.r_info = static_cast<Elf_Xword>(r_info);
content.insert(
std::end(content),
reinterpret_cast<uint8_t*>(&relhdr),
reinterpret_cast<uint8_t*>(&relhdr) + sizeof(Elf_Rel));
content.write_conv<Elf_Rel>(relhdr);
}
}
@ -1243,7 +1218,7 @@ void Builder::build_dynamic_relocations(void) {
Segment relocation_load;
relocation_load.type(SEGMENT_TYPES::PT_LOAD);
relocation_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
relocation_load.content(content);
relocation_load.content(content.raw());
Segment& new_relocation_load = this->binary_->add(relocation_load);
relocation_section.virtual_address(new_relocation_load.virtual_address());
@ -1260,7 +1235,7 @@ void Builder::build_dynamic_relocations(void) {
}
relocation_section.content(std::move(content));
relocation_section.content(std::move(content.raw()));
}
template<typename ELF_T>
@ -1322,7 +1297,7 @@ void Builder::build_pltgot_relocations(void) {
dt_reloc_size->value(pltgot_relocations.size() * sizeof(Elf_Rel));
}
std::vector<uint8_t> content; // Section's content
vector_iostream content(this->should_swap()); // Section's content
for (const Relocation& relocation : this->binary_->pltgot_relocations()) {
@ -1358,20 +1333,13 @@ void Builder::build_pltgot_relocations(void) {
relahdr.r_info = static_cast<Elf_Xword>(info);
relahdr.r_addend = static_cast<Elf_Sxword>(relocation.addend());
content.insert(
std::end(content),
reinterpret_cast<uint8_t*>(&relahdr),
reinterpret_cast<uint8_t*>(&relahdr) + sizeof(Elf_Rela));
content.write_conv<Elf_Rela>(relahdr);
} else {
Elf_Rel relhdr;
relhdr.r_offset = static_cast<Elf_Addr>(relocation.address());
relhdr.r_info = static_cast<Elf_Xword>(info);
content.insert(
std::end(content),
reinterpret_cast<uint8_t*>(&relhdr),
reinterpret_cast<uint8_t*>(&relhdr) + sizeof(Elf_Rel));
content.write_conv<Elf_Rel>(relhdr);
}
}
@ -1381,7 +1349,7 @@ void Builder::build_pltgot_relocations(void) {
Segment relocation_load;
relocation_load.type(SEGMENT_TYPES::PT_LOAD);
relocation_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
relocation_load.content(content);
relocation_load.content(content.raw());
Segment& new_relocation_load = this->binary_->add(relocation_load);
relocation_section.virtual_address(new_relocation_load.virtual_address());
@ -1397,7 +1365,7 @@ void Builder::build_pltgot_relocations(void) {
return this->build<ELF_T>();
}
relocation_section.content(std::move(content));
relocation_section.content(std::move(content.raw()));
}
@ -1425,7 +1393,7 @@ void Builder::build_symbol_requirement(void) {
const Elf_Addr dyn_str_va = this->binary_->get(DYNAMIC_TAGS::DT_STRTAB).value();
Section& dyn_str_section = this->binary_->section_from_virtual_address(dyn_str_va);
std::vector<uint8_t> svr_raw;
vector_iostream svr_raw(this->should_swap());
std::vector<uint8_t> dyn_str_raw = dyn_str_section.content();
uint32_t svr_idx = 0;
@ -1462,10 +1430,7 @@ void Builder::build_symbol_requirement(void) {
header.vn_aux = static_cast<Elf_Word>(svars.size() > 0 ? sizeof(Elf_Verneed) : 0);
header.vn_next = static_cast<Elf_Word>(next_symbol_offset);
svr_raw.insert(
std::end(svr_raw),
reinterpret_cast<uint8_t*>(&header),
reinterpret_cast<uint8_t*>(&header) + sizeof(Elf_Verneed));
svr_raw.write_conv<Elf_Verneed>(header);
uint32_t svar_idx = 0;
@ -1494,10 +1459,7 @@ void Builder::build_symbol_requirement(void) {
aux_header.vna_name = static_cast<Elf_Word>(svar_name_offset);
aux_header.vna_next = static_cast<Elf_Word>(svar_idx < (svars.size() - 1) ? sizeof(Elf_Vernaux) : 0);
svr_raw.insert(
std::end(svr_raw),
reinterpret_cast<uint8_t*>(&aux_header),
reinterpret_cast<uint8_t*>(&aux_header) + sizeof(Elf_Vernaux));
svr_raw.write_conv<Elf_Vernaux>(aux_header);
++svar_idx;
}
@ -1528,7 +1490,7 @@ void Builder::build_symbol_requirement(void) {
return this->build<ELF_T>();
}
this->binary_->section_from_offset(svr_offset).content(std::move(svr_raw));
this->binary_->section_from_offset(svr_offset).content(std::move(svr_raw.raw()));
dyn_str_section.content(std::move(dyn_str_raw));
}
@ -1558,7 +1520,7 @@ void Builder::build_symbol_definition(void) {
const Elf_Addr dyn_str_va = this->binary_->get(DYNAMIC_TAGS::DT_STRTAB).value();
Section& dyn_str_section = this->binary_->section_from_virtual_address(dyn_str_va);
std::vector<uint8_t> svd_raw;
vector_iostream svd_raw(this->should_swap());
std::vector<uint8_t> dyn_str_raw = dyn_str_section.content();
uint32_t svd_idx = 0;
@ -1581,9 +1543,7 @@ void Builder::build_symbol_definition(void) {
header.vd_aux = static_cast<Elf_Word>(svas.size() > 0 ? sizeof(Elf_Verdef) : 0);
header.vd_next = static_cast<Elf_Word>(next_symbol_offset);
svd_raw.insert(std::end(svd_raw),
reinterpret_cast<uint8_t*>(&header),
reinterpret_cast<uint8_t*>(&header) + sizeof(Elf_Verdef));
svd_raw.write_conv<Elf_Verdef>(header);
uint32_t sva_idx = 0;
@ -1610,10 +1570,7 @@ void Builder::build_symbol_definition(void) {
aux_header.vda_name = static_cast<Elf_Word>(sva_name_offset);
aux_header.vda_next = static_cast<Elf_Word>(sva_idx < (svas.size() - 1) ? sizeof(Elf_Verdaux) : 0);
svd_raw.insert(
std::end(svd_raw),
reinterpret_cast<uint8_t*>(&aux_header),
reinterpret_cast<uint8_t*>(&aux_header) + sizeof(Elf_Verdaux));
svd_raw.write_conv<Elf_Verdaux>(aux_header);
++sva_idx;
}
@ -1644,7 +1601,7 @@ void Builder::build_symbol_definition(void) {
return this->build<ELF_T>();
}
this->binary_->section_from_offset(svd_offset).content(std::move(svd_raw));
this->binary_->section_from_offset(svd_offset).content(std::move(svd_raw.raw()));
dyn_str_section.content(std::move(dyn_str_raw));
}
@ -1758,13 +1715,11 @@ void Builder::relocate_dynamic_array(DynamicEntryArray& entry_array, DynamicEntr
break;
}
/*
case ARCH::EM_PPC:
{
relocation = new Relocation(address_relocation, RELOC_POWERPC32::R_PPC_RELATIVE, array[i], is_rela);
break;
}
*/
/*
case ARCH::EM_PPC64:
@ -1858,50 +1813,41 @@ void Builder::build_notes(void) {
}
Segment& segment_note = this->binary_->get(SEGMENT_TYPES::PT_NOTE);
std::vector<uint8_t> raw_notes;
vector_iostream raw_notes(this->should_swap());
for (const Note& note : this->binary_->notes()) {
// First we have to write the length of the Note's name
const uint32_t namesz = static_cast<uint32_t>(note.name().size() + 1);
raw_notes.insert(
std::end(raw_notes),
reinterpret_cast<const uint8_t*>(&namesz),
reinterpret_cast<const uint8_t*>(&namesz) + sizeof(uint32_t));
raw_notes.write_conv<uint32_t>(namesz);
// Then the length of the Note's description
const uint32_t descsz = static_cast<uint32_t>(note.description().size());
//const uint32_t descsz = 20;
raw_notes.insert(
std::end(raw_notes),
reinterpret_cast<const uint8_t*>(&descsz),
reinterpret_cast<const uint8_t*>(&descsz) + sizeof(uint32_t));
raw_notes.write_conv<uint32_t>(descsz);
// Then the note's type
const NOTE_TYPES type = note.type();
raw_notes.insert(
std::end(raw_notes),
reinterpret_cast<const uint8_t*>(&type),
reinterpret_cast<const uint8_t*>(&type) + sizeof(uint32_t));
raw_notes.write_conv<uint32_t>(static_cast<uint32_t>(type));
// Then we write the note's name
const std::string& name = note.name();
raw_notes.insert(
std::end(raw_notes),
reinterpret_cast<const uint8_t*>(name.c_str()),
reinterpret_cast<const uint8_t*>(name.c_str()) + namesz);
raw_notes.write(name);
// Alignment
raw_notes.resize(align(raw_notes.size(), sizeof(uint32_t)), 0);
raw_notes.align(sizeof(uint32_t), 0);
// description content
// description content (manipulated in 4 byte/uint32_t chunks)
const std::vector<uint8_t>& description = note.description();
raw_notes.insert(
std::end(raw_notes),
std::begin(description),
std::end(description));
// Alignment
raw_notes.resize(align(raw_notes.size(), sizeof(uint32_t)), 0);
const uint32_t *desc_ptr = reinterpret_cast<const uint32_t*>(description.data()) ;
size_t i = 0;
for (; i < description.size() / sizeof(uint32_t); i++) {
raw_notes.write_conv<uint32_t>(desc_ptr[i]);
}
if (description.size() % sizeof(uint32_t) != 0) {
uint32_t padded = 0;
uint8_t *ptr = reinterpret_cast<uint8_t*>(&padded);
memcpy(ptr, desc_ptr + i, description.size() % sizeof(uint32_t));
raw_notes.write_conv<uint32_t>(padded);
}
}
if (segment_note.physical_size() < raw_notes.size()) {
@ -1912,12 +1858,12 @@ void Builder::build_notes(void) {
note.physical_address(0);
note.physical_size(0);
note.virtual_size(0);
note.content(raw_notes);
note.content(raw_notes.raw());
this->binary_->replace(note, segment_note);
return this->build<ELF_T>();
}
segment_note.content(raw_notes);
segment_note.content(raw_notes.raw());
// ".note.ABI-tag" // NOTE_TYPES::NT_GNU_ABI_TAG
// ===============
@ -1942,18 +1888,14 @@ void Builder::build_symbol_version(void) {
const uint64_t sv_address = this->binary_->get(DYNAMIC_TAGS::DT_VERSYM).value();
std::vector<uint8_t> sv_raw;
vector_iostream sv_raw(this->should_swap());
sv_raw.reserve(this->binary_->symbol_version_table_.size() * sizeof(uint16_t));
//for (const SymbolVersion* sv : this->binary_->symbol_version_table_) {
for (const Symbol* symbol : this->binary_->dynamic_symbols_) {
const SymbolVersion& sv = symbol->symbol_version();
const uint16_t value = sv.value();
sv_raw.insert(
std::end(sv_raw),
reinterpret_cast<const uint8_t*>(&value),
reinterpret_cast<const uint8_t*>(&value) + sizeof(uint16_t));
sv_raw.write_conv<uint16_t>(value);
}
Section& sv_section = this->binary_->section_from_virtual_address(sv_address);
@ -1964,7 +1906,7 @@ void Builder::build_symbol_version(void) {
Segment sv_load;
sv_load.type(SEGMENT_TYPES::PT_LOAD);
sv_load.flags(ELF_SEGMENT_FLAGS::PF_R);
sv_load.content(sv_raw);
sv_load.content(sv_raw.raw());
Segment& new_sv_load = this->binary_->add(sv_load);
sv_section.virtual_address(new_sv_load.virtual_address());
@ -1977,7 +1919,7 @@ void Builder::build_symbol_version(void) {
this->binary_->get(DYNAMIC_TAGS::DT_VERSYM).value(new_sv_load.virtual_address());
return this->build<ELF_T>();
}
sv_section.content(std::move(sv_raw));
sv_section.content(std::move(sv_raw.raw()));
}

View File

@ -17,7 +17,7 @@
#include "LIEF/iostream.hpp"
namespace LIEF {
vector_iostream::vector_iostream(void) = default;
vector_iostream::vector_iostream(bool endian_swap) : endian_swap_{endian_swap} {}
void vector_iostream::reserve(size_t size) {
this->raw_.reserve(size);
@ -72,6 +72,43 @@ vector_iostream& vector_iostream::write(std::vector<uint8_t>&& s) {
}
vector_iostream& vector_iostream::write(const std::string& s) {
size_t sz = s.size() + 1; // Size to write (+1 for '\0')
// Check that we have enough spaces
if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + sz)) {
this->raw_.resize(static_cast<size_t>(this->tellp()) + sz);
}
auto&& it = std::begin(this->raw_);
std::advance(it, static_cast<size_t>(this->tellp()));
std::move(
std::begin(s),
std::end(s), it);
this->current_pos_ += sz;
this->raw_[static_cast<size_t>(this->tellp()) - 1] = 0;
return *this;
}
vector_iostream& vector_iostream::align(size_t align_on, uint8_t val) {
// Already aligned
if (align_on == 0 or (this->current_pos_ % align_on) == 0) {
return *this;
}
size_t new_pos = ((static_cast<size_t>(this->tellp()) - 1) / align_on + 1) * align_on;
if (this->raw_.size() < new_pos) {
this->raw_.resize(new_pos, val);
} else {
std::fill(this->raw_.begin() + this->current_pos_, this->raw_.begin() + new_pos, val);
}
this->current_pos_ = new_pos;
return *this;
}
vector_iostream& vector_iostream::get(std::vector<uint8_t>& c) {
c = this->raw_;
return *this;
@ -85,6 +122,10 @@ const std::vector<uint8_t>& vector_iostream::raw(void) const {
return this->raw_;
}
size_t vector_iostream::size(void) const {
return this->raw_.size();
}
// seeks:
vector_iostream::pos_type vector_iostream::tellp(void) {
return this->current_pos_;
@ -125,6 +166,10 @@ vector_iostream& vector_iostream::seekp(vector_iostream::off_type p, std::ios_ba
}
void vector_iostream::set_endian_swap(bool swap) {
this->endian_swap_ = swap;
}
// Prefixbuf
prefixbuf::prefixbuf(std::string const& prefix, std::streambuf* sbuf) :