summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-09-16 12:54:20 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-09-16 12:54:20 +0200
commitabd5cfdd4a6c8e9979b2deb3c48304fb3d63a44c (patch)
tree582bddd69e1c4c7a68642798b7702f4bf1ca9b4d
parent563336ff1a4ed88401bf754ef7762542a4986d12 (diff)
downloadopenwar-abd5cfdd4a6c8e9979b2deb3c48304fb3d63a44c.tar.gz
openwar-abd5cfdd4a6c8e9979b2deb3c48304fb3d63a44c.tar.bz2
openwar-abd5cfdd4a6c8e9979b2deb3c48304fb3d63a44c.zip
Added relocation to disasm.
-rw-r--r--disasm/extractfunction.cpp24
-rw-r--r--disasm/leparseutil.cpp66
-rw-r--r--disasm/leparseutil.hpp5
-rw-r--r--le/le_fixup_record_table.cpp2
4 files changed, 78 insertions, 19 deletions
diff --git a/disasm/extractfunction.cpp b/disasm/extractfunction.cpp
index 3fc12e1..f2da04c 100644
--- a/disasm/extractfunction.cpp
+++ b/disasm/extractfunction.cpp
@@ -30,15 +30,12 @@ void extract_function(std::string file_path, binparse::Value32 object_id, binpar
_DecodeType dt = Decode32Bits;
unsigned int decodedInstructionsCount = 0;
- std::vector<uint8_t> code_buf = read_object(ifs, file, object_id);
-
- binparse::Offset32 base_reloc_offset = file.object_table.entries[object_id].reloc_base_address;
- binparse::Offset32 buffer_offset = binparse::Offset32(function_offset - base_reloc_offset);
+ std::vector<uint8_t> code_buf = load_binary(file);
_CodeInfo ci;
- ci.code = code_buf.data() + buffer_offset;
- ci.codeLen = code_buf.size() - buffer_offset;
- ci.codeOffset = base_reloc_offset + buffer_offset;
+ ci.code = code_buf.data() + function_offset;
+ ci.codeLen = code_buf.size() - function_offset;
+ ci.codeOffset = function_offset;
ci.dt = dt;
ci.features = DF_RETURN_FC_ONLY | DF_STOP_ON_FLOW_CONTROL;
@@ -55,7 +52,6 @@ void extract_function(std::string file_path, binparse::Value32 object_id, binpar
switch(META_GET_FC(decinst.meta)) {
case FC_CALL: {
binparse::Offset32 target = binparse::Offset32(INSTRUCTION_GET_TARGET(&decinst));
- std::cout << binparse::Offset32(ci.codeOffset) << " " << target << std::endl;
extract_function(file_path, object_id, target);
break;
}
@@ -99,12 +95,6 @@ void extract_function(std::string file_path, binparse::Value32 object_id, binpar
throw std::runtime_error("This should never happen.");
}
}
- /*
- _DecodedInst inst;
- distorm_format64(&ci, &decinst, &inst);
-
- std::cout << std::hex << std::setw(8) << std::setfill('0') << inst.offset << ":\t" << inst.mnemonic.p << " " << inst.operands.p << std::endl;
- */
if(!done) {
auto distance = ci.nextOffset - ci.codeOffset;
@@ -119,10 +109,10 @@ void extract_function(std::string file_path, binparse::Value32 object_id, binpar
auto end = ci.nextOffset;
- ci.code = code_buf.data() + buffer_offset;
+ ci.code = code_buf.data() + function_offset;
ci.nextOffset = 0;
- ci.codeLen = code_buf.size() - buffer_offset;
- ci.codeOffset = base_reloc_offset + buffer_offset;
+ ci.codeLen = code_buf.size() - function_offset;
+ ci.codeOffset = function_offset;
ci.dt = dt;
ci.features = DF_NONE;
diff --git a/disasm/leparseutil.cpp b/disasm/leparseutil.cpp
index 9c4e790..f2af13c 100644
--- a/disasm/leparseutil.cpp
+++ b/disasm/leparseutil.cpp
@@ -1,5 +1,7 @@
#include "leparseutil.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);
@@ -29,3 +31,67 @@ le::File parse_file(std::istream& 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&& object : file.object_table.entries) {
+ auto index = object.second.page_table_index;
+ for(binparse::Value32 i = index ; i < index + object.second.nr_page_table_entries; ++i) {
+ auto page = file.pages.map[i];
+
+ binparse::Offset32 dest_offset = binparse::Offset32(object.second.reloc_base_address + ((i-1)-index) * file.le_header.page_size);
+
+ std::copy(page.begin(), page.end(), binary.data() + dest_offset);
+ }
+ }
+
+ for(auto&& relocation : file.fixup_record_table.entries) {
+ relocate(relocation.second, binary, relocation.first, file);
+ }
+
+ return binary;
+}
diff --git a/disasm/leparseutil.hpp b/disasm/leparseutil.hpp
index d44bc18..77bcaf1 100644
--- a/disasm/leparseutil.hpp
+++ b/disasm/leparseutil.hpp
@@ -8,4 +8,7 @@ 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); \ No newline at end of file
+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
diff --git a/le/le_fixup_record_table.cpp b/le/le_fixup_record_table.cpp
index 8b52b82..e909203 100644
--- a/le/le_fixup_record_table.cpp
+++ b/le/le_fixup_record_table.cpp
@@ -66,7 +66,7 @@ FixupRecordTable::Entry::Internal parse_internal(std::istream& is, Value8 target
FixupRecordTable::Entry::Internal internal;
- if(bit(6, target_flags)) {
+ if(bit(7, target_flags)) {
internal.object_number = parse<Value16>(is, "segment_number");
} else {
internal.object_number = parse<Value8>(is, "segment_number");