#include "le_parse_util.hpp" #include "parse.hpp" std::vector read_file_part(std::istream& is, std::streamsize offset, size_t length) { is.clear(); is.seekg(0, std::ios::beg); is.ignore(offset); std::vector vec; vec.reserve(length); std::copy_n(std::istream_iterator(is), length, std::back_inserter(vec)); return vec; } std::vector read_object(std::istream& is, le::File file, binparse::Value32 object_id) { auto object = file.object_table.entries[object_id]; auto index = object.page_table_index; return read_file_part(is, file.le_header.data_page_offset, file.le_header.page_size * (object.nr_page_table_entries -(index -1))); } le::File parse_file(std::istream& is) { is.clear(); is.seekg(0, std::ios::beg); auto file = le::parse_file(is); return file; } void relocate(std::vector fixups, std::vector& binary, binparse::Value32 page_nr, le::File const& file) { binparse::Offset32 page_offset; for(auto&& object : file.object_table.entries) { if(page_nr >= object.second.page_table_index && page_nr < object.second.page_table_index + object.second.nr_page_table_entries) { page_offset = object.second.reloc_base_address; page_offset += ((page_nr - 1) - object.second.page_table_index) * file.le_header.page_size; break; } } for(auto&& fixup : fixups) { auto internal = boost::get(fixup.data); auto source_offset = boost::get(fixup.source_offset_or_source_list_count); auto target_object = boost::get(internal.object_number); auto binary_offset = page_offset + (int32_t) source_offset; binparse::Offset32 dest_offset; if(bit(4, fixup.target_flags)) { dest_offset = boost::get(internal.target_offset); } else { dest_offset = binparse::Offset32(boost::get(internal.target_offset)); } dest_offset += file.object_table.entries.at(target_object).reloc_base_address; for(int i = 0; i < 4; ++i) { uint8_t& byte = *(binary.data() + binary_offset + i); byte = ((dest_offset >> (i * 8)) & 255); } } } std::vector load_binary(le::File file) { size_t binary_size = 0; for(auto&& object : file.object_table.entries) { auto furthest_object_point = object.second.reloc_base_address + (object.second.nr_page_table_entries * file.le_header.page_size); if (furthest_object_point > binary_size) { binary_size = furthest_object_point; } } std::vector binary(binary_size, 0x90); for(auto&& entry : file.object_table.entries) { auto&& object = entry.second; auto index = object.page_table_index; for(binparse::Value32 i = index ; i < index + object.nr_page_table_entries; ++i) { auto page = file.pages.map[i]; binparse::Offset32 dest_offset = binparse::Offset32(object.reloc_base_address + (i-index) * file.le_header.page_size); std::copy(page.begin(), page.end(), binary.data() + dest_offset); } } for(auto&& entry : file.fixup_record_table.entries) { auto&& relocation = entry.second; relocate(relocation, binary, entry.first, file); } return binary; }