summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-06-27 01:33:02 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-06-27 15:23:06 +0200
commitb80a82fcc9edc73057796005cede4eea8380e193 (patch)
tree2da5e7cddef0bc39b449410c9826680a3dd6ca9d
parenta7bcede17b4c10e172c7877fc2ce89862dc454af (diff)
downloadopenwar-b80a82fcc9edc73057796005cede4eea8380e193.tar.gz
openwar-b80a82fcc9edc73057796005cede4eea8380e193.tar.bz2
openwar-b80a82fcc9edc73057796005cede4eea8380e193.zip
Parses the fixup page and fixup record table.
-rw-r--r--binparse/CMakeLists.txt1
-rw-r--r--binparse/output.hpp4
-rw-r--r--binparse/parse.hpp6
-rw-r--r--binparse/variant_output_helper.hpp18
-rw-r--r--le/CMakeLists.txt4
-rw-r--r--le/le_file.cpp17
-rw-r--r--le/le_file.hpp8
-rw-r--r--le/le_fixup_page_table.cpp33
-rw-r--r--le/le_fixup_page_table.hpp19
-rw-r--r--le/le_fixup_record_table.cpp237
-rw-r--r--le/le_fixup_record_table.hpp56
-rw-r--r--le/le_object_iterate_data_map_table.cpp18
-rw-r--r--le/le_object_iterate_data_map_table.hpp13
-rw-r--r--le/le_resource_table.cpp52
-rw-r--r--le/le_resource_table.hpp27
15 files changed, 508 insertions, 5 deletions
diff --git a/binparse/CMakeLists.txt b/binparse/CMakeLists.txt
index c41a2b5..e436331 100644
--- a/binparse/CMakeLists.txt
+++ b/binparse/CMakeLists.txt
@@ -1,6 +1,7 @@
add_library(binparse STATIC
types.hpp
+ variant_output_helper.hpp
parse.hpp parse.cpp
output.hpp output.cpp
otreestream.hpp otreestream.cpp
diff --git a/binparse/output.hpp b/binparse/output.hpp
index c5db2da..3919bef 100644
--- a/binparse/output.hpp
+++ b/binparse/output.hpp
@@ -42,6 +42,10 @@ std::ostream& operator<<(std::ostream& os, std::vector<uint8_t> vec);
template <typename T, typename std::enable_if<boost::fusion::traits::is_sequence<T>::value>::type* = nullptr>
std::ostream& operator<<(std::ostream&, T const&);
+
+template <typename ValueType>
+std::ostream& operator<<(std::ostream& os, std::vector<ValueType> const& vec);
+
template <typename Key, typename Value>
std::ostream& operator<<(std::ostream& os, std::map<Key, Value> const& map) {
try {
diff --git a/binparse/parse.hpp b/binparse/parse.hpp
index 2103177..e02b230 100644
--- a/binparse/parse.hpp
+++ b/binparse/parse.hpp
@@ -12,9 +12,15 @@
#include <array>
#include <vector>
#include <string>
+#include <cmath>
namespace binparse {
+template<typename T>
+constexpr bool bit(unsigned char bit, T const& t) {
+ return t & T(std::pow(2, bit));
+}
+
struct UnexpectedEOS : public std::runtime_error {
UnexpectedEOS();
diff --git a/binparse/variant_output_helper.hpp b/binparse/variant_output_helper.hpp
new file mode 100644
index 0000000..7207a36
--- /dev/null
+++ b/binparse/variant_output_helper.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "output.hpp"
+
+#include <boost/fusion/support/is_sequence.hpp>
+
+#include <ostream>
+
+namespace boost { namespace detail { namespace variant {
+
+template <typename T, typename std::enable_if<boost::fusion::traits::is_sequence<T>::value>::type* = nullptr>
+std::ostream& operator<<(std::ostream& os, T const& t) {
+ return binparse::operator<<(os, t);
+}
+
+}
+}
+} \ No newline at end of file
diff --git a/le/CMakeLists.txt b/le/CMakeLists.txt
index a135f8b..a453669 100644
--- a/le/CMakeLists.txt
+++ b/le/CMakeLists.txt
@@ -6,10 +6,14 @@ add_library(le STATIC
le_object_table_entry.hpp le_object_table_entry.cpp
le_object_page_table.hpp le_object_page_table.cpp
le_object_page_table_entry.hpp le_object_page_table_entry.cpp
+ le_object_iterate_data_map_table.hpp le_object_iterate_data_map_table.cpp
+ le_resource_table.hpp le_resource_table.cpp
le_resident_name_table.hpp le_resident_name_table.cpp
le_resident_name_table_entry.hpp le_resident_name_table_entry.cpp
le_entry_table.hpp le_entry_table.cpp
le_entry_table_entry.hpp le_entry_table_entry.cpp
+ le_fixup_page_table.hpp le_fixup_page_table.cpp
+ le_fixup_record_table.hpp le_fixup_record_table.cpp
)
target_include_directories(le
diff --git a/le/le_file.cpp b/le/le_file.cpp
index b6aa54f..55478c8 100644
--- a/le/le_file.cpp
+++ b/le/le_file.cpp
@@ -19,8 +19,12 @@ BOOST_FUSION_ADAPT_STRUCT(
(le::Header, le_header)
(le::ObjectTable, object_table)
(le::ObjectPageTable, object_page_table)
+ (le::ObjectIterateDataMapTable, object_iterate_data_map_table)
+ (le::ResourceTable, resource_table)
(le::ResidentNameTable, resident_name_table)
(le::EntryTable, entry_table)
+ (le::FixupPageTable, fixup_page_table)
+ (le::FixupRecordTable, fixup_record_table)
)
namespace le {
@@ -39,14 +43,13 @@ File parse_file(std::istream& is) {
binparse::dump_bytes(is, dos_exe, "dos_exe");
auto le_h = le::parse_header(is);
-
auto object_table = parse_object_table(is, le_offset + le_h.object_table_offset, le_h.nr_objects_in_module);
-
auto object_page_table = parse_object_page_table(is, le_offset + le_h.object_page_table_offset, le_h.module_nr_of_pages);
-
auto resident_name_table = parse_resident_name_table(is, le_offset + le_h.resident_name_table_offset);
-
auto entry_table = parse_entry_table(is, le_offset + le_h.entry_table_offset);
+ auto resource_table = parse_resource_table(is, le_offset + le_h.resource_table_offset, le_h.nr_resource_table_entries);
+ auto fixup_page_table = parse_fixup_page_table(is, le_offset + le_h.fixup_page_table_offset, le_h.module_nr_of_pages + binparse::Value32(1));
+ auto fixup_record_table = parse_fixup_record_table(is, le_offset + le_h.fixup_record_table_offset, fixup_page_table);
return {
mz_h,
@@ -58,8 +61,12 @@ File parse_file(std::istream& is) {
le_h,
object_table,
object_page_table,
+ {},
+ resource_table,
resident_name_table,
- entry_table
+ entry_table,
+ fixup_page_table,
+ fixup_record_table
};
}
diff --git a/le/le_file.hpp b/le/le_file.hpp
index f66bd36..09fc42d 100644
--- a/le/le_file.hpp
+++ b/le/le_file.hpp
@@ -6,8 +6,12 @@
#include "le_header.hpp"
#include "le_object_table.hpp"
#include "le_object_page_table.hpp"
+#include "le_object_iterate_data_map_table.hpp"
+#include "le_resource_table.hpp"
#include "le_resident_name_table.hpp"
#include "le_entry_table.hpp"
+#include "le_fixup_page_table.hpp"
+#include "le_fixup_record_table.hpp"
#include <cstdint>
#include <cstddef>
@@ -31,8 +35,12 @@ struct File
Header le_header;
ObjectTable object_table;
ObjectPageTable object_page_table;
+ ObjectIterateDataMapTable object_iterate_data_map_table;
+ ResourceTable resource_table;
ResidentNameTable resident_name_table;
EntryTable entry_table;
+ FixupPageTable fixup_page_table;
+ FixupRecordTable fixup_record_table;
};
File parse_file(std::istream& is);
diff --git a/le/le_fixup_page_table.cpp b/le/le_fixup_page_table.cpp
new file mode 100644
index 0000000..c148fa6
--- /dev/null
+++ b/le/le_fixup_page_table.cpp
@@ -0,0 +1,33 @@
+#include "le_fixup_page_table.hpp"
+
+#include "parse.hpp"
+#include "output.hpp"
+
+#include <boost/fusion/adapted/struct.hpp>
+
+BOOST_FUSION_ADAPT_STRUCT(
+ le::FixupPageTable,
+ (std::vector<binparse::Value32>, entries)
+)
+
+namespace le {
+
+FixupPageTable parse_fixup_page_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries)
+{
+ is.seekg(offset, std::ios::beg);
+
+ FixupPageTable table;
+
+ for(binparse::Value32 i = binparse::Value32(0); i < nr_entries; i++) {
+ table.entries.push_back(binparse::parse<binparse::Value32>(is, "offset"));
+ }
+
+ return table;
+}
+
+std::ostream&operator<<(std::ostream& os, const FixupPageTable& table)
+{
+ return binparse::operator<<(os, table);
+}
+
+}
diff --git a/le/le_fixup_page_table.hpp b/le/le_fixup_page_table.hpp
new file mode 100644
index 0000000..be44895
--- /dev/null
+++ b/le/le_fixup_page_table.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "types.hpp"
+
+#include <iostream>
+#include <vector>
+
+namespace le {
+
+struct FixupPageTable
+{
+ std::vector<binparse::Value32> entries;
+};
+
+FixupPageTable parse_fixup_page_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries);
+
+std::ostream& operator<<(std::ostream& os, FixupPageTable const& table);
+
+} \ No newline at end of file
diff --git a/le/le_fixup_record_table.cpp b/le/le_fixup_record_table.cpp
new file mode 100644
index 0000000..9331626
--- /dev/null
+++ b/le/le_fixup_record_table.cpp
@@ -0,0 +1,237 @@
+#include "le_fixup_record_table.hpp"
+
+#include "parse.hpp"
+#include "output.hpp"
+
+#include <boost/fusion/adapted/struct.hpp>
+#include <bitset>
+
+typedef le::FixupRecordTable::Entry Entry;
+typedef Entry::Internal Internal;
+typedef Entry::ImportedOrdinal ImportedOrdinal;
+typedef Entry::ImportedName ImportedName;
+typedef Entry::InternalEntry InternalEntry;
+
+typedef binparse::Offset16 Offset16;
+typedef binparse::Offset32 Offset32;
+typedef binparse::Value8 Value8;
+typedef binparse::Value16 Value16;
+
+typedef boost::variant<Offset16, Value8> ListOrOffsetT;
+typedef boost::variant<Internal, ImportedOrdinal, ImportedName, InternalEntry> DataT;
+typedef boost::optional<boost::variant<boost::variant<Offset16, Offset32>, std::vector<boost::variant<Offset16, Offset32>>>> AdditiveT;
+typedef boost::optional<std::vector<Value16>> SourcesT;
+
+typedef boost::variant<Value8,Value16> V8orV16T;
+typedef boost::variant<Offset16, Offset32> O16orO32T;
+
+BOOST_FUSION_ADAPT_STRUCT(
+ Internal,
+ (V8orV16T, object_number)
+ (O16orO32T, target_offset)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ ImportedOrdinal,
+ (V8orV16T, ordinal_number)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ ImportedName,
+ (V8orV16T, ordinal_number)
+ (O16orO32T, procedure_name_offset)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ InternalEntry,
+ (V8orV16T, entry_number)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ Entry,
+ (Value8, source_flags)
+ (Value8, target_flags)
+ (ListOrOffsetT, source_offset_or_source_list_count)
+ (DataT, data)
+ (AdditiveT, additive)
+ (SourcesT, sources)
+)
+
+namespace le {
+
+using namespace binparse;
+
+FixupRecordTable::Entry::Internal parse_internal(std::istream& is, Value8 target_flags) {
+ using binparse::parse;
+
+ FixupRecordTable::Entry::Internal internal;
+
+ if(bit(6, target_flags)) {
+ internal.object_number = parse<Value16>(is, "segment_number");
+ } else {
+ internal.object_number = parse<Value8>(is, "segment_number");
+ }
+
+ if(bit(4, target_flags)) {
+ internal.target_offset = parse<Offset32>(is, "target_offset");
+ } else {
+ internal.target_offset = parse<Offset16>(is, "target_offset");
+ }
+
+ return internal;
+}
+
+FixupRecordTable::Entry::ImportedOrdinal parse_imported_ordinal(std::istream& is, Value8 target_flags) {
+ using binparse::parse;
+
+ FixupRecordTable::Entry::ImportedOrdinal ordinal;
+
+ if(bit(6, target_flags)) {
+ ordinal.ordinal_number = parse<Value16>(is, "ordinal_value");
+ } else {
+ ordinal.ordinal_number = parse<Value8>(is, "ordinal_value");
+ }
+
+ return ordinal;
+}
+
+FixupRecordTable::Entry::ImportedName parse_imported_name(std::istream& is, Value8 target_flags) {
+ using binparse::parse;
+
+ FixupRecordTable::Entry::ImportedName name;
+
+ if(bit(6, target_flags)) {
+ name.ordinal_number = parse<Value16>(is, "ordinal_number");
+ } else {
+ name.ordinal_number = parse<Value8>(is, "ordinal_number");
+ }
+
+ if(bit(4, target_flags)) {
+ name.procedure_name_offset = parse<Offset32>(is, "procedure_name_offset");
+ } else {
+ name.procedure_name_offset = parse<Offset16>(is, "procedure_name_offset");
+ }
+
+ return name;
+}
+
+FixupRecordTable::Entry::InternalEntry parse_internal_entry(std::istream& is, Value8 target_flags) {
+ using binparse::parse;
+
+ FixupRecordTable::Entry::InternalEntry entry;
+
+ if(bit(6, target_flags)) {
+ entry.entry_number = parse<Value16>(is, "entry_number");
+ } else {
+ entry.entry_number = parse<Value8>(is, "entry_number");
+ }
+
+ return entry;
+}
+
+FixupRecordTable::Entry parse(std::istream& is)
+{
+ using binparse::parse;
+
+ FixupRecordTable::Entry entry;
+
+ entry.source_flags = parse<Value8>(is, "source_flags");
+ entry.target_flags = parse<Value8>(is, "target_flags");
+
+ bool has_lists = bit(6, entry.source_flags);
+ if(has_lists) {
+ entry.source_offset_or_source_list_count = parse<Value8>(is, "source_list_count");
+ } else {
+ entry.source_offset_or_source_list_count = parse<Offset16>(is, "source_offset");
+ }
+
+ auto relevant_flags = entry.target_flags & 3;
+
+ switch(relevant_flags) {
+ case 0: {
+ entry.data = parse_internal(is, entry.target_flags);
+ break;
+ }
+ case 1: {
+ entry.data = parse_imported_ordinal(is, entry.target_flags);
+ break;
+ }
+ case 2: {
+ entry.data = parse_imported_name(is, entry.target_flags);
+ break;
+ }
+ case 3: {
+ entry.data = parse_internal_entry(is, entry.target_flags);
+ break;
+ }
+ default: {
+ throw std::runtime_error("This cannot happen, value of relevant flags should be [0-3]");
+ }
+ }
+
+ if(relevant_flags == 0 or relevant_flags == 3) {
+ entry.additive.reset();
+ } else {
+ if(bit(2, entry.target_flags)) {
+ std::vector<boost::variant<Offset16, Offset32>> vec;
+ for(int i = 0; i < int(boost::get<Value8>(entry.source_offset_or_source_list_count)); i++) {
+ if(bit(5, entry.target_flags)) {
+ vec.push_back(parse<Offset32>(is, ""));
+ }
+ else {
+ vec.push_back(parse<Offset16>(is, ""));
+ }
+ }
+ entry.additive = vec;
+ } else {
+ if(bit(5, entry.target_flags)) {
+ entry.additive = parse<Offset32>(is, "");
+ }
+ else {
+ entry.additive = parse<Offset16>(is, "");
+ }
+ }
+ }
+
+ if(has_lists) {
+ std::vector<Value16> vec;
+ for(int i = 0; i < int(boost::get<Value8>(entry.source_offset_or_source_list_count)); i++) {
+ vec.push_back(parse<Value16>(is, ""));
+ }
+ entry.sources = vec;
+ } else {
+ entry.sources.reset();
+ }
+
+ return entry;
+}
+
+FixupRecordTable parse_fixup_record_table(std::istream& is, Offset32 offset, FixupPageTable fixups)
+{
+ is.seekg(offset, std::ios::beg);
+
+ FixupRecordTable table;
+
+ binparse::otreestream otree(std::cout);
+
+ for(int i = 1; i < fixups.entries.size(); i++) {
+ unsigned int current_pos = is.tellg();
+ unsigned int endpos = current_pos + (fixups.entries[i] - fixups.entries[i-1]);
+
+ while(current_pos = is.tellg(), current_pos < endpos) {
+ auto x = parse(is);
+ table.entries[Value32(i)].push_back(x);
+ }
+
+
+ }
+
+ return table;
+}
+
+std::ostream&operator<<(std::ostream& os, const FixupRecordTable& table)
+{
+ return binparse::operator<<(os, table.entries);
+}
+
+}
diff --git a/le/le_fixup_record_table.hpp b/le/le_fixup_record_table.hpp
new file mode 100644
index 0000000..6a07da5
--- /dev/null
+++ b/le/le_fixup_record_table.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "le_fixup_page_table.hpp"
+#include "types.hpp"
+#include "variant_output_helper.hpp" //include this before <boost/variant>
+
+#include <boost/variant.hpp>
+#include <boost/optional.hpp>
+#include <boost/optional/optional_io.hpp>
+
+#include <vector>
+#include <map>
+
+namespace le {
+
+using namespace binparse;
+
+struct FixupRecordTable
+{
+ struct Entry {
+ struct Internal {
+ boost::variant<Value8,Value16> object_number;
+ boost::variant<Offset16, Offset32> target_offset;
+ };
+
+ struct ImportedOrdinal {
+ boost::variant<Value8, Value16> ordinal_number;
+ };
+
+ struct ImportedName {
+ boost::variant<Value8, Value16> ordinal_number;
+ boost::variant<Offset16, Offset32> procedure_name_offset;
+ };
+
+ struct InternalEntry {
+ boost::variant<Value8, Value16> entry_number;
+ };
+
+ Value8 source_flags;
+ Value8 target_flags;
+ boost::variant<Offset16, Value8> source_offset_or_source_list_count;
+ boost::variant<Internal, ImportedOrdinal, ImportedName, InternalEntry> data;
+ boost::optional<boost::variant<boost::variant<Offset16, Offset32>, std::vector<boost::variant<Offset16, Offset32>>>> additive;
+ boost::optional<std::vector<Value16>> sources;
+ };
+
+ std::map<Value32, std::vector<Entry>> entries;
+
+};
+
+FixupRecordTable::Entry parse(std::istream& is);
+FixupRecordTable parse_fixup_record_table(std::istream& is, Offset32 offset, FixupPageTable fixups);
+
+std::ostream& operator<<(std::ostream& os, FixupRecordTable const& table);
+
+} \ No newline at end of file
diff --git a/le/le_object_iterate_data_map_table.cpp b/le/le_object_iterate_data_map_table.cpp
new file mode 100644
index 0000000..bc1b456
--- /dev/null
+++ b/le/le_object_iterate_data_map_table.cpp
@@ -0,0 +1,18 @@
+#include "le_object_iterate_data_map_table.hpp"
+
+#include "output.hpp"
+
+#include <boost/fusion/adapted/struct.hpp>
+
+BOOST_FUSION_ADAPT_STRUCT(
+ le::ObjectIterateDataMapTable,
+)
+
+namespace le {
+
+std::ostream& operator<<(std::ostream& os, ObjectIterateDataMapTable const& table)
+{
+ return binparse::operator<<(os, table);
+}
+
+} \ No newline at end of file
diff --git a/le/le_object_iterate_data_map_table.hpp b/le/le_object_iterate_data_map_table.hpp
new file mode 100644
index 0000000..ef1a24d
--- /dev/null
+++ b/le/le_object_iterate_data_map_table.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <ostream>
+
+namespace le {
+
+struct ObjectIterateDataMapTable
+{
+};
+
+std::ostream& operator<<(std::ostream& os, ObjectIterateDataMapTable const& table);
+
+}
diff --git a/le/le_resource_table.cpp b/le/le_resource_table.cpp
new file mode 100644
index 0000000..8b69733
--- /dev/null
+++ b/le/le_resource_table.cpp
@@ -0,0 +1,52 @@
+#include "le_resource_table.hpp"
+
+#include "parse.hpp"
+#include "output.hpp"
+
+#include <boost/fusion/adapted/struct.hpp>
+
+BOOST_FUSION_ADAPT_STRUCT(
+ le::ResourceTable::Entry,
+ (binparse::Value16, type_id)
+ (binparse::Value16, name_id)
+ (binparse::Value32, resource_size)
+ (binparse::Value16, object_index)
+ (binparse::Offset32, offset)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ le::ResourceTable,
+ (std::vector<le::ResourceTable::Entry>, entries)
+)
+
+namespace le {
+
+ResourceTable::Entry parse_resource_table_entry(std::istream& is)
+{
+ return binparse::parse<ResourceTable::Entry>(is);
+}
+
+ResourceTable parse_resource_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries)
+{
+ is.seekg(offset, std::ios::beg);
+
+ ResourceTable table;
+
+ for(binparse::Value32 i = binparse::Value32(0); i < nr_entries; i++) {
+ table.entries.push_back(parse_resource_table_entry(is));
+ }
+
+ return table;
+}
+
+std::ostream&operator<<(std::ostream& os, const ResourceTable::Entry& entry)
+{
+ return binparse::operator<<(os, entry);
+}
+
+std::ostream&operator<<(std::ostream& os, const ResourceTable& table)
+{
+ return binparse::operator<<(os, table.entries);
+}
+
+} \ No newline at end of file
diff --git a/le/le_resource_table.hpp b/le/le_resource_table.hpp
new file mode 100644
index 0000000..7590c6a
--- /dev/null
+++ b/le/le_resource_table.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "types.hpp"
+
+#include <vector>
+
+namespace le {
+
+struct ResourceTable
+{
+ struct Entry {
+ binparse::Value16 type_id;
+ binparse::Value16 name_id;
+ binparse::Value32 resource_size;
+ binparse::Value16 object_index;
+ binparse::Offset32 offset;
+ };
+ std::vector<Entry> entries;
+};
+
+ResourceTable::Entry parse_resource_table_entry(std::istream& is);
+ResourceTable parse_resource_table(std::istream& is, binparse::Offset32 offset, binparse::Value32 nr_entries);
+
+std::ostream& operator<<(std::ostream& os, ResourceTable::Entry const& entry);
+std::ostream& operator<<(std::ostream& os, ResourceTable const& table);
+
+} \ No newline at end of file