#include "le_parse_util.hpp" #include #include #include #include #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::ranges::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; } //works only for relocation type 7 (internal) (source flags == 7) void relocate(le::File const& file, std::vector& binary, binparse::Offset32 offset) { for(auto&& entry : file.fixup_record_table.entries) { auto&& page_nr = entry.first; auto&& fixups = entry.second; std::cout << "page_nr: " << page_nr << std::endl; 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; //both page_nr and page_table_index are 1-indexed so this subtraction works out. page_offset += (page_nr - object.second.page_table_index) * file.le_header.page_size; break; } } std::cout << "Page_offset: " << page_offset << std::endl; 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 + 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; dest_offset += offset; std::stringstream byte_stream; std::stringstream fixup_stream; for(int i = 3; i >= 0; --i) { uint8_t& byte = *(binary.data() + binary_offset + i); const uint8_t fixup_byte = (dest_offset >> (i * 8)) & 255; byte_stream << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) byte; fixup_stream << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) fixup_byte; byte = fixup_byte; } std::cout << fixup << std::endl; std::cout << "Fixup (" << std::hex << binary_offset << "): " << byte_stream.str() << " => " << fixup_stream.str() << std::endl; } } } size_t determine_binary_size(le::File const& 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; } } return binary_size; } static void load_binary_into(le::File const& file, uint8_t* buffer, size_t buffer_size) { 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.at(i); binparse::Offset32 dest_offset = binparse::Offset32(object.reloc_base_address + (i-index) * file.le_header.page_size); BOOST_ASSERT_MSG(dest_offset < buffer_size, "buffer too small for binary loading"); std::copy(page.begin(), page.end(), buffer + dest_offset); } } } std::vector load_binary(le::File const& file) { size_t binary_size = determine_binary_size(file); std::vector binary(binary_size, 0x90); load_binary_into(file, binary.data(), binary.size()); return binary; } void load_binary(le::File const& file, uint8_t* buffer, size_t buffer_size) { load_binary_into(file, buffer, buffer_size); }