From 9697525aaa6bfe889b576993851bc37db669e8b9 Mon Sep 17 00:00:00 2001 From: mefistotelis Date: Tue, 9 Jan 2024 03:05:24 +0100 Subject: [PATCH] disasm: Separated Analyser --- src/Makefile.am | 2 + src/analyser.cpp | 587 ++++++++++++++++++++++++++++++++++++++++ src/analyser.hpp | 119 +++++++++ src/disassembler.hpp | 6 +- src/image.hpp | 6 +- src/instruction.hpp | 2 +- src/le.hpp | 10 +- src/le_disasm.cpp | 624 +------------------------------------------ src/le_disasm_ver.h | 6 +- src/le_image.cpp | 2 + src/le_image.hpp | 10 +- src/regions.hpp | 4 + src/util.hpp | 6 +- 13 files changed, 746 insertions(+), 638 deletions(-) create mode 100644 src/analyser.cpp create mode 100644 src/analyser.hpp diff --git a/src/Makefile.am b/src/Makefile.am index 9ce00e6..c861b61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,8 @@ bin_PROGRAMS = swdisasm bindir = $(prefix)/usr/$(PACKAGE) swdisasm_SOURCES = \ + analyser.hpp \ + analyser.cpp \ disassembler.hpp \ disassembler.cpp \ instruction.hpp \ diff --git a/src/analyser.cpp b/src/analyser.cpp new file mode 100644 index 0000000..747d9c9 --- /dev/null +++ b/src/analyser.cpp @@ -0,0 +1,587 @@ +/* + * swdisasm - LE disassembler for Syndicate Wars + * + * Copyright (C) 2010 Unavowed + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "analyser.hpp" +#include "instruction.hpp" +#include "image.hpp" +#include "le.hpp" +#include "regions.hpp" +#include "util.hpp" + +using std::ios; + +Label::Label (uint32_t address, Label::Type type, + const std::string &name) +{ + this->address = address; + this->name = name; + this->type = type; +} + +Label::Label (void) +{ + this->address = 0; + this->name = ""; + this->type = UNKNOWN; +} + +Label::Label (const Label &other) +{ + *this = other; +} + +uint32_t +Label::get_address (void) const +{ + return this->address; +} + +Label::Type +Label::get_type (void) const +{ + return this->type; +} + +std::string +Label::get_name (void) const +{ + return this->name; +} + +std::ostream & +operator<< (std::ostream &os, const Label &label) +{ + PUSH_IOS_FLAGS (&os); + + if (label.get_name ().empty ()) + { + std::string prefix; + + switch (label.get_type ()) + { + case Label::FUNCTION: prefix = "func"; break; + case Label::JUMP: prefix = "jump"; break; + case Label::DATA: prefix = "data"; break; + case Label::VTABLE: prefix = "vtable"; break; + default: prefix = "unknown"; break; + } + + os << prefix << "_" << std::hex << std::noshowbase + << label.get_address (); + } + else + os << label.get_name (); + + return os; +} + + +void +Analyser::add_region (const Region ®) +{ + this->regions[reg.get_address ()] = reg; +} + +void +Analyser::add_initial_regions (void) +{ + const LEOH *ohdr; + size_t n; + Region::Type type; + + for (n = 0; n < this->le->get_object_count (); n++) + { + ohdr = this->le->get_object_header (n); + + if ((ohdr->flags & LEOH::EXECUTABLE) == 0) + { + type = Region::DATA; + this->set_label (Label (ohdr->base_address, Label::DATA)); + } + else + type = Region::UNKNOWN; + + this->add_region (Region (ohdr->base_address, + ohdr->virtual_size, type)); + } +} + +void +Analyser::add_eip_to_trace_queue (void) +{ + const LEOH *ohdr; + const LEH *hdr; + uint32_t eip; + + hdr = this->le->get_header (); + ohdr = this->le->get_object_header (hdr->eip_object_index); + eip = ohdr->base_address + hdr->eip_offset; + this->add_code_trace_address (eip); + this->set_label (Label (eip, Label::FUNCTION, "_start")); +} + +void +Analyser::add_code_trace_address (uint32_t addr) +{ + this->code_trace_queue.push_back (addr); +} + +void +Analyser::trace_code (void) +{ + uint32_t address; + + while (!this->code_trace_queue.empty ()) + { + address = this->code_trace_queue.front (); + this->code_trace_queue.pop_front (); + this->trace_code_at_address (address); + } +} + +void +Analyser::trace_code_at_address (uint32_t start_addr) +{ + Region *reg; + size_t end_addr; + size_t addr; + const Image::Object *obj; + const Image::DataVector *data; + Instruction inst; + const void *data_ptr; + + reg = this->get_region_at_address (start_addr); + if (reg == NULL) + { + std::cerr << "Warning: Tried to trace code at an unmapped address: " + << start_addr << ".\n"; + return; + } + + if (reg->get_type () == Region::CODE) /* already traced */ + return; + + end_addr = reg->get_end_address (); + obj = this->image->get_object_at_address (start_addr); + data = obj->get_data (); + + addr = start_addr; + + while (addr < end_addr) + { + data_ptr = &data->front () + addr - obj->get_base_address (); + this->disasm.disassemble (addr, data_ptr, end_addr - addr, &inst); + + if (inst.get_target () != 0) + { + switch (inst.get_type ()) + { + case Instruction::CALL: + this->set_label (Label (inst.get_target (), Label::FUNCTION)); + this->add_code_trace_address (inst.get_target ()); + break; + + case Instruction::COND_JUMP: + case Instruction::JUMP: + this->set_label (Label (inst.get_target (), Label::JUMP)); + this->add_code_trace_address (inst.get_target ()); + break; + + default: + break; + } + } + + addr += inst.get_size(); + + switch (inst.get_type ()) + { + case Instruction::JUMP: + case Instruction::RET: + goto end; + + default: + break; + } + } + +end: + this->insert_region + (reg, Region (start_addr, addr - start_addr, Region::CODE)); +} + +Region * +Analyser::get_previous_region (const Region *reg) +{ + return get_previous_value (&this->regions, reg->get_address ()); +} + +Region * +Analyser::get_region_at_address (uint32_t address) +{ + Analyser::RegionMap::iterator itr; + + if (this->regions.empty ()) + return NULL; + + itr = this->regions.lower_bound (address); + + if (itr == this->regions.end ()) + { + --itr; + + if (itr->second.contains_address (address)) + return &itr->second; + else + return NULL; + } + + if (itr->first == address) + return &itr->second; + + if (itr == this->regions.begin ()) + return NULL; + + --itr; + + if (!itr->second.contains_address (address)) + return NULL; + + return &itr->second; +} + +Region * +Analyser::get_region (uint32_t address) +{ + Analyser::RegionMap::iterator itr; + + itr = this->regions.find (address); + if (itr == this->regions.end ()) + return NULL; + + return &itr->second; +} + +void +Analyser::insert_region (Region *parent, const Region ®) +{ + assert (parent->contains_address (reg.get_address ())); + assert (parent->contains_address (reg.get_end_address () - 1)); + + if (reg.get_end_address () != parent->get_end_address ()) + { + this->add_region + (Region (reg.get_end_address (), + parent->get_end_address () - reg.get_end_address (), + parent->get_type ())); + } + + if (reg.get_address () != parent->get_address ()) + { + this->add_region (reg); + + parent->size = reg.get_address () - parent->get_address (); + } + else + *parent = reg; + + this->check_merge_regions (reg.address); +} + +void +Analyser::check_merge_regions (uint32_t addr) +{ + Region *reg; + Region *prev; + Region *next; + + reg = this->get_region (addr); + prev = this->get_previous_region (reg); + next = this->get_next_region (reg); + + if (prev != NULL and prev->get_type () == reg->get_type () + and prev->get_end_address () == reg->get_address ()) + { + prev->size += reg->size; + this->regions.erase (addr); + reg = prev; + } + + if (next != NULL and reg->get_type () == next->get_type () + and reg->get_end_address () == next->get_address ()) + { + reg->size += next->size; + this->regions.erase (next->get_address ()); + } +} + +void +Analyser::trace_vtables (void) +{ + const LEFM *fixups; + LEFM::const_iterator itr; + const Image::Object *obj; + const uint8_t *data_ptr; + Region *reg; + size_t off; + size_t size; + size_t count; + size_t n; + uint32_t addr; + const uint32_t *aptr; + + PUSH_IOS_FLAGS (&std::cerr); + std::cerr.setf (ios::hex, ios::basefield); + std::cerr.setf (ios::showbase); + + for (n = 0; n < this->le->get_object_count (); n++) + { + fixups = this->le->get_fixups_for_object (n); + + for (itr = fixups->begin (); itr != fixups->end (); ++itr) + { + reg = this->get_region_at_address (itr->second.address); + if (reg == NULL) + { + std::cerr << "Warning: Reloc pointing to unmapped memory at " + << itr->second.address << ".\n"; + continue; + } + + if (reg->get_type () != Region::UNKNOWN) + continue; + + obj = this->image->get_object_at_address (reg->get_address ()); + if (!obj->is_executable ()) + continue; + size = reg->get_end_address () - itr->second.address; + aptr = get_next_value (this->le->get_fixup_addresses (), + itr->second.address); + if (aptr != NULL) + size = std::min (size, *aptr - itr->second.address); + + data_ptr = obj->get_data_at (itr->second.address); + count = 0; + off = 0; + + while (off + 4 <= size) + { + addr = read_le (data_ptr + off); + + if (addr == 0 + or fixups->find (itr->second.address + off + - obj->get_base_address ()) + != fixups->end ()) + { + count++; + + if (addr != 0) + { + this->set_label (Label (addr, Label::FUNCTION)); + this->add_code_trace_address (addr); + } + } + else + break; + + off += 4; + } + + if (count > 0) + { + this->insert_region (reg, Region (itr->second.address, + 4 * count, Region::VTABLE)); + this->set_label (Label (itr->second.address, Label::VTABLE)); + this->trace_code (); + } + } + } +} + +void +Analyser::trace_remaining_relocs (void) +{ + const LEFM *fixups; + LEFM::const_iterator itr; + Region *reg; + size_t n; + size_t guess_count = 0; + const Label *label; + + PUSH_IOS_FLAGS (&std::cerr); + std::cerr.setf (ios::hex, ios::basefield); + std::cerr.setf (ios::showbase); + + for (n = 0; n < this->image->get_object_count (); n++) + { + fixups = this->le->get_fixups_for_object (n); + + for (itr = fixups->begin (); itr != fixups->end (); ++itr) + { + reg = this->get_region_at_address (itr->second.address); + if (reg == NULL + or (reg->get_type () != Region::UNKNOWN + and reg->get_type () != Region::DATA)) + continue; + + if (reg->get_type () == Region::UNKNOWN) + { + label = this->get_label (itr->second.address); + + if (label == NULL + or (label->get_type () != Label::FUNCTION + and label->get_type () != Label::JUMP)) + { + std::cerr << "Guessing that " << itr->second.address + << " is a function.\n"; + guess_count++; + this->set_label (Label (itr->second.address, + Label::FUNCTION)); + } + + this->add_code_trace_address (itr->second.address); + this->trace_code (); + } + else + { + this->set_label (Label (itr->second.address, + Label::DATA)); + } + } + } + + std::cerr.setf (ios::dec, ios::basefield); + std::cerr.unsetf (ios::showbase); + std::cerr << guess_count << " guess(es) to investigate.\n"; +} + +Analyser::Analyser (void) +{ + this->le = NULL; + this->image = NULL; +} + +Analyser::Analyser (const Analyser &other) +{ + *this = other; +} + +Analyser::Analyser (LinearExecutable *le, Image *img) +{ + this->le = le; + this->image = img; + this->add_initial_regions (); +} + +Analyser & +Analyser::operator= (const Analyser &other) +{ + this->le = other.le; + this->image = other.image; + this->disasm = other.disasm; + this->add_initial_regions (); + return *this; +} + +Label * +Analyser::get_next_label (const Label *lab) +{ + return get_next_value (&this->labels, lab->get_address ()); +} + +Label * +Analyser::get_next_label (uint32_t addr) +{ + return get_next_value (&this->labels, addr); +} + +Region * +Analyser::get_next_region (const Region *reg) +{ + return get_next_value (&this->regions, reg->get_address ()); +} + +void +Analyser::insert_region (const Region ®) +{ + Region *parent; + parent = this->get_region_at_address (reg.get_address ()); + this->insert_region (parent, reg); +} + +void +Analyser::set_label (const Label &lab) +{ + const Label *label; + + label = this->get_label (lab.get_address ()); + if (label != NULL) + { + if (label->get_type () == Label::FUNCTION + or !label->get_name ().empty ()) + return; + } + + this->labels[lab.get_address ()] = lab; +} + +void +Analyser::remove_label (uint32_t addr) +{ + this->labels.erase (addr); +} + +void +Analyser::run (void) +{ + this->add_eip_to_trace_queue (); + std::cerr << "Tracing code directly accessible from the entry point...\n"; + this->trace_code (); + std::cerr << "Tracing text relocs for vtables...\n"; + this->trace_vtables (); + std::cerr << "Tracing remaining relocs for functions and data...\n"; + this->trace_remaining_relocs (); +} + +const Analyser::RegionMap * +Analyser::get_regions (void) const +{ + return &this->regions; +} + +const Analyser::LabelMap * +Analyser::get_labels (void) const +{ + return &this->labels; +} + +const Label * +Analyser::get_label (uint32_t addr) const +{ + Analyser::LabelMap::const_iterator itr; + + itr = this->labels.find (addr); + if (itr == this->labels.end ()) + return NULL; + + return &itr->second; +} diff --git a/src/analyser.hpp b/src/analyser.hpp new file mode 100644 index 0000000..984dcf5 --- /dev/null +++ b/src/analyser.hpp @@ -0,0 +1,119 @@ +/* + * swdisasm - LE disassembler for Syndicate Wars + * + * Copyright (C) 2010 Unavowed + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef LEDISASM_ANALYSER_H +#define LEDISASM_ANALYSER_H + +#include +#include +#include +#include + +#include "disassembler.hpp" + +class LinearExecutable; +class Image; +class Region; + +class Label +{ +public: + enum Type + { + UNKNOWN, + JUMP, + FUNCTION, + VTABLE, + DATA + }; + +protected: + uint32_t address; + std::string name; + Label::Type type; + +public: + Label (uint32_t address, Label::Type type = UNKNOWN, + const std::string &name = ""); + Label (void); + Label (const Label &other); + + uint32_t get_address (void) const; + Label::Type get_type (void) const; + std::string get_name (void) const; +}; + +std::ostream &operator<< (std::ostream &os, const Label &label); + +class Analyser +{ +public: + typedef std::map RegionMap; + typedef std::map LabelMap; + +protected: + RegionMap regions; + LabelMap labels; + std::deque code_trace_queue; + LinearExecutable *le; + Image *image; + Disassembler disasm; + +protected: + void add_region (const Region ®); + + void add_initial_regions (void); + void add_eip_to_trace_queue (void); + void add_code_trace_address (uint32_t addr); + + void trace_code (void); + void trace_code_at_address (uint32_t start_addr); + + Region * get_previous_region (const Region *reg); + Region * get_region_at_address (uint32_t address); + Region * get_region (uint32_t address); + + void insert_region (Region *parent, const Region ®); + void check_merge_regions (uint32_t addr); + + void trace_vtables (void); + void trace_remaining_relocs (void); + +public: + Analyser (void); + Analyser (const Analyser &other); + Analyser (LinearExecutable *le, Image *img); + + Analyser &operator= (const Analyser &other); + + Label * get_next_label (const Label *lab); + Label * get_next_label (uint32_t addr); + Region *get_next_region (const Region *reg); + + void insert_region (const Region ®); + void set_label (const Label &lab); + void remove_label (uint32_t addr); + void run (void); + + const RegionMap * get_regions (void) const; + const LabelMap * get_labels (void) const; + const Label * get_label (uint32_t addr) const; +}; + +#endif // LEDISASM_ANALYSER_H diff --git a/src/disassembler.hpp b/src/disassembler.hpp index 891f3c1..778c0b1 100644 --- a/src/disassembler.hpp +++ b/src/disassembler.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SWDISASM_DISASSEMBLER_H -#define SWDISASM_DISASSEMBLER_H +#ifndef LEDISASM_DISASSEMBLER_H +#define LEDISASM_DISASSEMBLER_H #include #include @@ -53,4 +53,4 @@ class Disassembler Instruction *ret); }; -#endif +#endif // LEDISASM_DISASSEMBLER_H diff --git a/src/image.hpp b/src/image.hpp index 8f3ba3b..948fe58 100644 --- a/src/image.hpp +++ b/src/image.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SWDISASM_IMAGE_H -#define SWDISASM_IMAGE_H +#ifndef LEDISASM_IMAGE_H +#define LEDISASM_IMAGE_H #include #include @@ -61,4 +61,4 @@ class Image size_t get_object_count (void) const; }; -#endif +#endif // LEDISASM_IMAGE_H diff --git a/src/instruction.hpp b/src/instruction.hpp index 3e0947f..252aad7 100644 --- a/src/instruction.hpp +++ b/src/instruction.hpp @@ -50,4 +50,4 @@ struct Instruction size_t get_size (void); }; -#endif +#endif // LEDISASM_INSTRUCTION_H diff --git a/src/le.hpp b/src/le.hpp index 82533e6..a8dd952 100644 --- a/src/le.hpp +++ b/src/le.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SWDISASM_LE_H -#define SWDISASM_LE_H +#ifndef LEDISASM_LE_H +#define LEDISASM_LE_H #include #include @@ -155,6 +155,10 @@ class LinearExecutable const std::string &name = "stream"); }; +typedef LinearExecutable::FixupMap LEFM; +typedef LinearExecutable::Header LEH; +typedef LinearExecutable::ObjectHeader LEOH; + std::ostream &operator<< (std::ostream &os, const LinearExecutable::Header &hdr); @@ -167,4 +171,4 @@ std::ostream &operator<< (std::ostream &os, std::ostream &operator<< (std::ostream &os, const LinearExecutable::ObjectPageType &type); -#endif +#endif // LEDISASM_LE_H diff --git a/src/le_disasm.cpp b/src/le_disasm.cpp index 2c6f858..cc3926f 100644 --- a/src/le_disasm.cpp +++ b/src/le_disasm.cpp @@ -17,16 +17,12 @@ * along with this program. If not, see . */ #include -#include -#include -#include #include -#include #include -#include #include -#include "disassembler.hpp" +#include "analyser.hpp" +#include "image.hpp" #include "instruction.hpp" #include "le.hpp" #include "le_image.hpp" @@ -35,612 +31,6 @@ using std::ios; - -typedef Image::DataVector IDV; -typedef Image::Object Object; -typedef LinearExecutable::FixupMap LEFM; -typedef LinearExecutable::Header LEH; -typedef LinearExecutable::ObjectHeader LEOH; - - -class Analyser; - - -class Label -{ -public: - enum Type - { - UNKNOWN, - JUMP, - FUNCTION, - VTABLE, - DATA - }; - -protected: - uint32_t address; - std::string name; - Type type; - -public: - Label (uint32_t address, Type type = UNKNOWN, - const std::string &name = "") - { - this->address = address; - this->name = name; - this->type = type; - } - - Label (void) - { - this->address = 0; - this->name = ""; - this->type = UNKNOWN; - } - - Label (const Label &other) - { - *this = other; - } - - uint32_t - get_address (void) const - { - return this->address; - } - - Type - get_type (void) const - { - return this->type; - } - - std::string - get_name (void) const - { - return this->name; - } -}; - -std::ostream & -operator<< (std::ostream &os, const Label &label) -{ - PUSH_IOS_FLAGS (&os); - - if (label.get_name ().empty ()) - { - std::string prefix; - - switch (label.get_type ()) - { - case Label::FUNCTION: prefix = "func"; break; - case Label::JUMP: prefix = "jump"; break; - case Label::DATA: prefix = "data"; break; - case Label::VTABLE: prefix = "vtable"; break; - default: prefix = "unknown"; break; - } - - os << prefix << "_" << std::hex << std::noshowbase - << label.get_address (); - } - else - os << label.get_name (); - - return os; -} - - -class Analyser -{ -public: - typedef std::map RegionMap; - typedef std::map LabelMap; - -protected: - RegionMap regions; - LabelMap labels; - std::deque code_trace_queue; - LinearExecutable *le; - Image *image; - Disassembler disasm; - -protected: - void - add_region (const Region ®) - { - this->regions[reg.get_address ()] = reg; - } - - void - add_initial_regions (void) - { - const LEOH *ohdr; - size_t n; - Region::Type type; - - for (n = 0; n < this->le->get_object_count (); n++) - { - ohdr = this->le->get_object_header (n); - - if ((ohdr->flags & LEOH::EXECUTABLE) == 0) - { - type = Region::DATA; - this->set_label (Label (ohdr->base_address, Label::DATA)); - } - else - type = Region::UNKNOWN; - - this->add_region (Region (ohdr->base_address, - ohdr->virtual_size, type)); - } - } - - void - add_eip_to_trace_queue (void) - { - const LEOH *ohdr; - const LEH *hdr; - uint32_t eip; - - hdr = this->le->get_header (); - ohdr = this->le->get_object_header (hdr->eip_object_index); - eip = ohdr->base_address + hdr->eip_offset; - this->add_code_trace_address (eip); - this->set_label (Label (eip, Label::FUNCTION, "_start")); - } - - void - add_code_trace_address (uint32_t addr) - { - this->code_trace_queue.push_back (addr); - } - - void - trace_code (void) - { - uint32_t address; - - while (!this->code_trace_queue.empty ()) - { - address = this->code_trace_queue.front (); - this->code_trace_queue.pop_front (); - this->trace_code_at_address (address); - } - } - - void - trace_code_at_address (uint32_t start_addr) - { - Region *reg; - size_t end_addr; - size_t addr; - const Object *obj; - const IDV *data; - Instruction inst; - const void *data_ptr; - - reg = this->get_region_at_address (start_addr); - if (reg == NULL) - { - std::cerr << "Warning: Tried to trace code at an unmapped address: " - << start_addr << ".\n"; - return; - } - - if (reg->get_type () == Region::CODE) /* already traced */ - return; - - end_addr = reg->get_end_address (); - obj = this->image->get_object_at_address (start_addr); - data = obj->get_data (); - - addr = start_addr; - - while (addr < end_addr) - { - data_ptr = &data->front () + addr - obj->get_base_address (); - this->disasm.disassemble (addr, data_ptr, end_addr - addr, &inst); - - if (inst.get_target () != 0) - { - switch (inst.get_type ()) - { - case Instruction::CALL: - this->set_label (Label (inst.get_target (), Label::FUNCTION)); - this->add_code_trace_address (inst.get_target ()); - break; - - case Instruction::COND_JUMP: - case Instruction::JUMP: - this->set_label (Label (inst.get_target (), Label::JUMP)); - this->add_code_trace_address (inst.get_target ()); - break; - - default: - break; - } - } - - addr += inst.get_size(); - - switch (inst.get_type ()) - { - case Instruction::JUMP: - case Instruction::RET: - goto end; - - default: - break; - } - } - - end: - this->insert_region - (reg, Region (start_addr, addr - start_addr, Region::CODE)); - } - - Region * - get_previous_region (const Region *reg) - { - return get_previous_value (&this->regions, reg->get_address ()); - } - - Region * - get_region_at_address (uint32_t address) - { - RegionMap::iterator itr; - - if (this->regions.empty ()) - return NULL; - - itr = this->regions.lower_bound (address); - - if (itr == this->regions.end ()) - { - --itr; - - if (itr->second.contains_address (address)) - return &itr->second; - else - return NULL; - } - - if (itr->first == address) - return &itr->second; - - if (itr == this->regions.begin ()) - return NULL; - - --itr; - - if (!itr->second.contains_address (address)) - return NULL; - - return &itr->second; - } - - Region * - get_region (uint32_t address) - { - RegionMap::iterator itr; - - itr = this->regions.find (address); - if (itr == this->regions.end ()) - return NULL; - - return &itr->second; - } - - void - insert_region (Region *parent, const Region ®) - { - assert (parent->contains_address (reg.get_address ())); - assert (parent->contains_address (reg.get_end_address () - 1)); - - if (reg.get_end_address () != parent->get_end_address ()) - { - this->add_region - (Region (reg.get_end_address (), - parent->get_end_address () - reg.get_end_address (), - parent->get_type ())); - } - - if (reg.get_address () != parent->get_address ()) - { - this->add_region (reg); - - parent->size = reg.get_address () - parent->get_address (); - } - else - *parent = reg; - - this->check_merge_regions (reg.address); - } - - void - check_merge_regions (uint32_t addr) - { - Region *reg; - Region *prev; - Region *next; - - reg = this->get_region (addr); - prev = this->get_previous_region (reg); - next = this->get_next_region (reg); - - if (prev != NULL and prev->get_type () == reg->get_type () - and prev->get_end_address () == reg->get_address ()) - { - prev->size += reg->size; - this->regions.erase (addr); - reg = prev; - } - - if (next != NULL and reg->get_type () == next->get_type () - and reg->get_end_address () == next->get_address ()) - { - reg->size += next->size; - this->regions.erase (next->get_address ()); - } - } - - void - trace_vtables (void) - { - const LEFM *fixups; - LEFM::const_iterator itr; - const Image::Object *obj; - const uint8_t *data_ptr; - Region *reg; - size_t off; - size_t size; - size_t count; - size_t n; - uint32_t addr; - const uint32_t *aptr; - - PUSH_IOS_FLAGS (&std::cerr); - std::cerr.setf (ios::hex, ios::basefield); - std::cerr.setf (ios::showbase); - - for (n = 0; n < this->le->get_object_count (); n++) - { - fixups = this->le->get_fixups_for_object (n); - - for (itr = fixups->begin (); itr != fixups->end (); ++itr) - { - reg = this->get_region_at_address (itr->second.address); - if (reg == NULL) - { - std::cerr << "Warning: Reloc pointing to unmapped memory at " - << itr->second.address << ".\n"; - continue; - } - - if (reg->get_type () != Region::UNKNOWN) - continue; - - obj = this->image->get_object_at_address (reg->get_address ()); - if (!obj->is_executable ()) - continue; - size = reg->get_end_address () - itr->second.address; - aptr = get_next_value (this->le->get_fixup_addresses (), - itr->second.address); - if (aptr != NULL) - size = std::min (size, *aptr - itr->second.address); - - - data_ptr = obj->get_data_at (itr->second.address); - count = 0; - off = 0; - - while (off + 4 <= size) - { - addr = read_le (data_ptr + off); - - if (addr == 0 - or fixups->find (itr->second.address + off - - obj->get_base_address ()) - != fixups->end ()) - { - count++; - - if (addr != 0) - { - this->set_label (Label (addr, Label::FUNCTION)); - this->add_code_trace_address (addr); - } - } - else - break; - - off += 4; - } - - if (count > 0) - { - this->insert_region (reg, Region (itr->second.address, - 4 * count, Region::VTABLE)); - this->set_label (Label (itr->second.address, Label::VTABLE)); - this->trace_code (); - } - } - } - } - - void - trace_remaining_relocs (void) - { - const LEFM *fixups; - LEFM::const_iterator itr; - Region *reg; - size_t n; - size_t guess_count = 0; - const Label *label; - - PUSH_IOS_FLAGS (&std::cerr); - std::cerr.setf (ios::hex, ios::basefield); - std::cerr.setf (ios::showbase); - - for (n = 0; n < this->image->get_object_count (); n++) - { - fixups = this->le->get_fixups_for_object (n); - - for (itr = fixups->begin (); itr != fixups->end (); ++itr) - { - reg = this->get_region_at_address (itr->second.address); - if (reg == NULL - or (reg->get_type () != Region::UNKNOWN - and reg->get_type () != Region::DATA)) - continue; - - if (reg->get_type () == Region::UNKNOWN) - { - label = this->get_label (itr->second.address); - - if (label == NULL - or (label->get_type () != Label::FUNCTION - and label->get_type () != Label::JUMP)) - { - std::cerr << "Guessing that " << itr->second.address - << " is a function.\n"; - guess_count++; - this->set_label (Label (itr->second.address, - Label::FUNCTION)); - } - - this->add_code_trace_address (itr->second.address); - this->trace_code (); - } - else - { - this->set_label (Label (itr->second.address, - Label::DATA)); - } - } - } - - std::cerr.setf (ios::dec, ios::basefield); - std::cerr.unsetf (ios::showbase); - std::cerr << guess_count << " guess(es) to investigate.\n"; - } - -public: - Analyser (void) - { - this->le = NULL; - this->image = NULL; - } - - Analyser (const Analyser &other) - { - *this = other; - } - - Analyser (LinearExecutable *le, Image *img) - { - this->le = le; - this->image = img; - this->add_initial_regions (); - } - - Analyser & - operator= (const Analyser &other) - { - this->le = other.le; - this->image = other.image; - this->disasm = other.disasm; - this->add_initial_regions (); - return *this; - } - - Label * - get_next_label (const Label *lab) - { - return get_next_value (&this->labels, lab->get_address ()); - } - - Label * - get_next_label (uint32_t addr) - { - return get_next_value (&this->labels, addr); - } - - Region * - get_next_region (const Region *reg) - { - return get_next_value (&this->regions, reg->get_address ()); - } - - void - insert_region (const Region ®) - { - Region *parent; - parent = this->get_region_at_address (reg.get_address ()); - this->insert_region (parent, reg); - } - - void - set_label (const Label &lab) - { - const Label *label; - - label = this->get_label (lab.get_address ()); - if (label != NULL) - { - if (label->get_type () == Label::FUNCTION - or !label->get_name ().empty ()) - return; - } - - this->labels[lab.get_address ()] = lab; - } - - void - remove_label (uint32_t addr) - { - this->labels.erase (addr); - } - - void - run (void) - { - this->add_eip_to_trace_queue (); - std::cerr << "Tracing code directly accessible from the entry point...\n"; - this->trace_code (); - std::cerr << "Tracing text relocs for vtables...\n"; - this->trace_vtables (); - std::cerr << "Tracing remaining relocs for functions and data...\n"; - this->trace_remaining_relocs (); - } - - const RegionMap * - get_regions (void) const - { - return &this->regions; - } - - const LabelMap * - get_labels (void) const - { - return &this->labels; - } - - const Label * - get_label (uint32_t addr) const - { - LabelMap::const_iterator itr; - - itr = this->labels.find (addr); - if (itr == this->labels.end ()) - return NULL; - - return &itr->second; - } -}; - - static void print_separator (void) { @@ -805,7 +195,7 @@ print_instruction (Instruction *inst, Image *img, LinearExecutable *le, } static bool -data_is_address (const Object *obj, uint32_t addr, size_t len, +data_is_address (const Image::Object *obj, uint32_t addr, size_t len, LinearExecutable *le) { uint32_t offset; @@ -824,7 +214,7 @@ data_is_address (const Object *obj, uint32_t addr, size_t len, } static bool -data_is_zeros (const Object *obj, uint32_t addr, size_t len, size_t *rlen) +data_is_zeros (const Image::Object *obj, uint32_t addr, size_t len, size_t *rlen) { size_t x; const uint8_t *data; @@ -845,7 +235,7 @@ data_is_zeros (const Object *obj, uint32_t addr, size_t len, size_t *rlen) } static bool -data_is_string (const Object *obj, uint32_t addr, size_t len, size_t *rlen, +data_is_string (const Image::Object *obj, uint32_t addr, size_t len, size_t *rlen, bool *zero_terminated) { size_t x; @@ -898,7 +288,7 @@ print_escaped_string (const uint8_t *data, size_t len) } static void -print_region (const Region *reg, const Object *obj, LinearExecutable *le, +print_region (const Region *reg, const Image::Object *obj, LinearExecutable *le, Image *img, Analyser *anal) { const Label *label; @@ -1112,7 +502,7 @@ print_code (LinearExecutable *le, Image *img, Analyser *anal) const Region *prev = NULL; const Region *next; const Region *reg; - const Object *obj; + const Image::Object *obj; Section sec = NONE; regions = anal->get_regions (); diff --git a/src/le_disasm_ver.h b/src/le_disasm_ver.h index 9e623c0..f941765 100644 --- a/src/le_disasm_ver.h +++ b/src/le_disasm_ver.h @@ -16,8 +16,8 @@ * (at your option) any later version. */ /******************************************************************************/ -#ifndef SWDISASM_VER_H -#define SWDISASM_VER_H +#ifndef LEDISASM_VER_H +#define LEDISASM_VER_H /* Version definitions */ #include "config.h" @@ -42,5 +42,5 @@ #define PRODUCT_VERSION VERSION #define DEFAULT_LOG_FILENAME INTERNAL_NAME".log" -#endif // SWDISASM_VER_H +#endif // LEDISASM_VER_H /******************************************************************************/ diff --git a/src/le_image.cpp b/src/le_image.cpp index 45da86c..fe7c6f1 100644 --- a/src/le_image.cpp +++ b/src/le_image.cpp @@ -20,6 +20,8 @@ #include #include "le_image.hpp" +#include "le.hpp" +#include "image.hpp" using std::cerr; using std::min; diff --git a/src/le_image.hpp b/src/le_image.hpp index b1535ff..6e8262b 100644 --- a/src/le_image.hpp +++ b/src/le_image.hpp @@ -16,14 +16,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SWDISASM_LE_IMAGE_H -#define SWDISASM_LE_IMAGE_H +#ifndef LEDISASM_LE_IMAGE_H +#define LEDISASM_LE_IMAGE_H #include -#include "le.hpp" -#include "image.hpp" +class Image; +class LinearExecutable; Image *create_image (std::istream *is, const LinearExecutable *lx); -#endif +#endif // LEDISASM_LE_IMAGE_H diff --git a/src/regions.hpp b/src/regions.hpp index 44e0f2a..d28ed4e 100644 --- a/src/regions.hpp +++ b/src/regions.hpp @@ -16,6 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#ifndef LEDISASM_REGIONS_H +#define LEDISASM_REGIONS_H #include #include @@ -56,3 +58,5 @@ class Region std::ostream &operator<< (std::ostream &os, Region::Type type); std::ostream &operator<< (std::ostream &os, const Region ®); + +#endif // LEDISASM_REGIONS_H diff --git a/src/util.hpp b/src/util.hpp index b1800c3..9df89b6 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SWDISASM_UTIL_H -#define SWDISASM_UTIL_H +#ifndef LEDISASM_UTIL_H +#define LEDISASM_UTIL_H #include #include @@ -188,4 +188,4 @@ print_variable (std::ostream *os, size_t value_column, os->flags (flags); } -#endif +#endif // LEDISASM_UTIL_H