summaryrefslogtreecommitdiff
path: root/le
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-09-19 17:38:23 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-10-04 22:18:23 +0200
commitc29ae7a65c636b8d1fa37c6589278dcdee97658f (patch)
treea0ad6583a1f954a179349e0b27d58d7c945c59b5 /le
parentabd5cfdd4a6c8e9979b2deb3c48304fb3d63a44c (diff)
downloadopenwar-c29ae7a65c636b8d1fa37c6589278dcdee97658f.tar.gz
openwar-c29ae7a65c636b8d1fa37c6589278dcdee97658f.tar.bz2
openwar-c29ae7a65c636b8d1fa37c6589278dcdee97658f.zip
Started working on a x86 emulator.
Diffstat (limited to 'le')
-rw-r--r--le/CMakeLists.txt1
-rw-r--r--le/le_parse_util.cpp99
-rw-r--r--le/le_parse_util.hpp14
3 files changed, 114 insertions, 0 deletions
diff --git a/le/CMakeLists.txt b/le/CMakeLists.txt
index d01ae7f..7f738fc 100644
--- a/le/CMakeLists.txt
+++ b/le/CMakeLists.txt
@@ -11,6 +11,7 @@ add_library(le STATIC
le_fixup_page_table.hpp le_fixup_page_table.cpp
le_fixup_record_table.hpp le_fixup_record_table.cpp
le_pages.hpp le_pages.cpp
+ le_parse_util.hpp le_parse_util.cpp
)
target_include_directories(le
diff --git a/le/le_parse_util.cpp b/le/le_parse_util.cpp
new file mode 100644
index 0000000..ab2d70d
--- /dev/null
+++ b/le/le_parse_util.cpp
@@ -0,0 +1,99 @@
+#include "le_parse_util.hpp"
+
+#include "parse.hpp"
+
+std::vector<uint8_t> 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<uint8_t> vec;
+ vec.reserve(length);
+
+ std::copy_n(std::istream_iterator<uint8_t>(is), length, std::back_inserter(vec));
+ return vec;
+}
+
+std::vector<uint8_t> 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<le::FixupRecordTable::Entry> fixups, std::vector<uint8_t>& 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<le::FixupRecordTable::Entry::Internal>(fixup.data);
+
+ auto source_offset = boost::get<binparse::Offset16>(fixup.source_offset_or_source_list_count);
+
+ auto target_object = boost::get<binparse::Value8>(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<binparse::Offset32>(internal.target_offset);
+ } else {
+ dest_offset = binparse::Offset32(boost::get<binparse::Offset16>(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<uint8_t> 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<uint8_t> 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;
+}
diff --git a/le/le_parse_util.hpp b/le/le_parse_util.hpp
new file mode 100644
index 0000000..77bcaf1
--- /dev/null
+++ b/le/le_parse_util.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "le_file.hpp"
+
+#include <istream>
+
+le::File parse_file(std::istream& is);
+
+std::vector<uint8_t> read_file_part(std::istream& is, std::streamsize offset, size_t length);
+
+std::vector<uint8_t> read_object(std::istream& is, le::File file, binparse::Value32 object_id);
+
+std::vector<uint8_t> relocate(le::File& file, std::vector<uint8_t> page, size_t index);
+std::vector<uint8_t> load_binary(le::File file); \ No newline at end of file