mirror of
https://github.com/mrkite/regs.git
synced 2024-12-28 12:33:02 +00:00
fingerprints
This commit is contained in:
parent
9d903712bf
commit
54b1b4b8ce
12
src/Makefile
12
src/Makefile
@ -1,12 +1,16 @@
|
||||
OBJS = main.o omf.o handle.o map.o
|
||||
OBJS = main.o omf.o handle.o map.o disasm.o api.o
|
||||
CXX = clang++
|
||||
CXXFLAGS = -g -Wall -std=c++11
|
||||
LDFLAGS = -largp
|
||||
CXXFLAGS = -Wall -std=c++11
|
||||
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME), Darwin)
|
||||
LDFLAGS = -largp
|
||||
endif
|
||||
|
||||
all: regs
|
||||
|
||||
regs: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) $(LIBS) -o $@ $^
|
||||
$(CXX) $(CXXFLAGS) $(LIBS) -o $@ $(LDFLAGS) $^
|
||||
|
||||
%.o: %.cc
|
||||
$(CXX) -c $(CXXFLAGS) -o $@ $<
|
||||
|
201
src/api.cc
Normal file
201
src/api.cc
Normal file
@ -0,0 +1,201 @@
|
||||
/** @copyright 2020 Sean Kasun */
|
||||
|
||||
#include <iostream>
|
||||
#include "api.h"
|
||||
|
||||
Fingerprints::Fingerprints() {
|
||||
root = std::make_shared<Fingerprint>();
|
||||
}
|
||||
|
||||
void Fingerprints::add(const std::vector<uint8_t> &keys, std::string name,
|
||||
uint8_t numDB) {
|
||||
auto node = root;
|
||||
for (auto key : keys) {
|
||||
if (node->map.find(key) == node->map.end()) {
|
||||
node->map.insert(std::pair<uint8_t, std::shared_ptr<Fingerprint>>
|
||||
(key, std::make_shared<Fingerprint>()));
|
||||
}
|
||||
node = node->map[key];
|
||||
}
|
||||
node->name = name;
|
||||
node->numDB = numDB;
|
||||
}
|
||||
|
||||
API::API(unsigned char *dat, unsigned int len) {
|
||||
auto h = TheHandle::createFromArray(std::vector<uint8_t>(dat, dat + len));
|
||||
auto numSymbols = h->r32();
|
||||
for (uint32_t i = 0; i < numSymbols; i++) {
|
||||
auto id = h->r32();
|
||||
auto kind = h->r8();
|
||||
auto name = h->rs();
|
||||
ids.insert(std::pair<uint32_t, std::string>(id, name));
|
||||
std::shared_ptr<symbol::Symbol> s = nullptr;
|
||||
switch (kind) {
|
||||
case symbol::isIntrinsic:
|
||||
s = std::make_shared<symbol::Intrinsic>();
|
||||
s->kind = symbol::isIntrinsic;
|
||||
break;
|
||||
case symbol::isEnum:
|
||||
s = std::make_shared<symbol::Enum>();
|
||||
s->kind = symbol::isEnum;
|
||||
break;
|
||||
case symbol::isAlias:
|
||||
s = std::make_shared<symbol::Ref>();
|
||||
s->kind = symbol::isAlias;
|
||||
break;
|
||||
case symbol::isStruct:
|
||||
s = std::make_shared<symbol::Struct>();
|
||||
s->kind = symbol::isStruct;
|
||||
break;
|
||||
case symbol::isUnion:
|
||||
s = std::make_shared<symbol::Struct>();
|
||||
s->kind = symbol::isUnion;
|
||||
break;
|
||||
case symbol::isRef:
|
||||
std::cerr << "isRef on root!" << std::endl;
|
||||
break;
|
||||
case symbol::isFunction:
|
||||
s = std::make_shared<symbol::Function>();
|
||||
s->kind = symbol::isFunction;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unknown type" << std::endl;
|
||||
break;
|
||||
}
|
||||
s->name = name;
|
||||
symbols.insert(std::pair<std::string, symbol::Symbol>(name, s));
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < numSymbols; i++) {
|
||||
auto id = h->r32();
|
||||
auto s = symbols[ids[id]];
|
||||
s->size = h->r32();
|
||||
switch (s->kind) {
|
||||
case symbol::isIntrinsic:
|
||||
setIntrinsic(h, s);
|
||||
break;
|
||||
case symbol::isEnum:
|
||||
setEnum(h, s);
|
||||
break;
|
||||
case symbol::isAlias:
|
||||
setRef(h, s);
|
||||
break;
|
||||
case symbol::isStruct:
|
||||
setStruct(h, s);
|
||||
break;
|
||||
case symbol::isUnion:
|
||||
setStruct(h, s);
|
||||
break;
|
||||
case symbol::isRef:
|
||||
std::cerr << "base level ref" << std::endl;
|
||||
break;
|
||||
case symbol::isFunction:
|
||||
setFunction(h, s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol::Symbol> API::lookup(uint32_t id) {
|
||||
return symbols[ids[id]];
|
||||
}
|
||||
|
||||
void API::setIntrinsic(Handle h, std::shared_ptr<symbol::Symbol> s) {
|
||||
auto i = std::static_pointer_cast<symbol::Intrinsic>(s);
|
||||
auto type = h->r8();
|
||||
switch (type) {
|
||||
case symbol::Intrinsic::U8:
|
||||
i->type = symbol::Intrinsic::U8;
|
||||
break;
|
||||
case symbol::Intrinsic::U16:
|
||||
i->type = symbol::Intrinsic::U16;
|
||||
break;
|
||||
case symbol::Intrinsic::U32:
|
||||
i->type = symbol::Intrinsic::U32;
|
||||
break;
|
||||
case symbol::Intrinsic::S8:
|
||||
i->type = symbol::Intrinsic::S8;
|
||||
break;
|
||||
case symbol::Intrinsic::S16:
|
||||
i->type = symbol::Intrinsic::S16;
|
||||
break;
|
||||
case symbol::Intrinsic::S32:
|
||||
i->type = symbol::Intrinsic::S32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void API::setEnum(Handle h, std::shared_ptr<symbol::Symbol> s) {
|
||||
auto e = std::static_pointer_cast<symbol::Enum>(s);
|
||||
e->type = lookup(h->r32());
|
||||
auto num = h->r32();
|
||||
for (uint32_t i = 0; i < num; i++) {
|
||||
auto value = h->r32();
|
||||
e->entries[h->rs()] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void API::setRef(Handle h, std::shared_ptr<symbol::Symbol> s) {
|
||||
auto r = std::static_pointer_cast<symbol::Ref>(s);
|
||||
auto id = h->r32();
|
||||
if (id == 0) {
|
||||
r->symbol = nullptr;
|
||||
} else {
|
||||
r->symbol = lookup(id);
|
||||
r->pointer = h->r32();
|
||||
r->array = static_cast<int32_t>(h->r32());
|
||||
r->reg = h->rs();
|
||||
}
|
||||
}
|
||||
|
||||
void API::setStruct(Handle h, std::shared_ptr<symbol::Symbol> s) {
|
||||
auto str = std::static_pointer_cast<symbol::Struct>(s);
|
||||
auto numFields = h->r32();
|
||||
for (uint32_t i = 0; i < numFields; i++) {
|
||||
auto key = h->rs();
|
||||
auto kind = h->r8();
|
||||
auto size = h->r32();
|
||||
std::shared_ptr<symbol::Symbol> sym = nullptr;
|
||||
switch (kind) {
|
||||
case symbol::isRef:
|
||||
sym = std::make_shared<symbol::Ref>();
|
||||
sym->kind = symbol::isRef;
|
||||
sym->size = size;
|
||||
setRef(h, sym);
|
||||
break;
|
||||
case symbol::isStruct:
|
||||
sym = std::make_shared<symbol::Struct>();
|
||||
sym->kind = symbol::isStruct;
|
||||
sym->size = size;
|
||||
setStruct(h, sym);
|
||||
break;
|
||||
case symbol::isUnion:
|
||||
sym = std::make_shared<symbol::Struct>();
|
||||
sym->kind = symbol::isUnion;
|
||||
sym->size = size;
|
||||
setStruct(h, sym);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unknown field type" << std::endl;
|
||||
break;
|
||||
}
|
||||
str->fields.push_back({key, sym});
|
||||
}
|
||||
}
|
||||
|
||||
void API::setFunction(Handle h, std::shared_ptr<symbol::Symbol> s) {
|
||||
auto f = std::static_pointer_cast<symbol::Function>(s);
|
||||
auto numArgs = h->r32();
|
||||
for (uint32_t i = 0; i < numArgs; i++) {
|
||||
auto key = h->rs();
|
||||
auto ref = std::make_shared<symbol::Ref>();
|
||||
setRef(h, ref);
|
||||
f->arguments.push_back({key, ref});
|
||||
}
|
||||
f->returnType = std::make_shared<symbol::Ref>();
|
||||
setRef(h, f->returnType);
|
||||
auto numSig = h->r32();
|
||||
for (uint32_t i = 0; i < numSig; i++) {
|
||||
f->signature.push_back(h->r32());
|
||||
}
|
||||
}
|
86
src/api.h
Normal file
86
src/api.h
Normal file
@ -0,0 +1,86 @@
|
||||
/** @copyright 2020 Sean Kasun */
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include "handle.h"
|
||||
|
||||
struct Fingerprint {
|
||||
std::map<uint8_t, std::shared_ptr<Fingerprint>> map;
|
||||
uint8_t numDB;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class Fingerprints {
|
||||
public:
|
||||
Fingerprints();
|
||||
void add(const std::vector<uint8_t> &keys, std::string name,
|
||||
uint8_t numDB = 0);
|
||||
std::shared_ptr<Fingerprint> root;
|
||||
};
|
||||
|
||||
namespace symbol {
|
||||
|
||||
enum Kind {
|
||||
isIntrinsic = 0, isEnum, isAlias, isStruct, isUnion, isRef, isFunction,
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
std::string name;
|
||||
uint32_t size;
|
||||
Kind kind;
|
||||
};
|
||||
|
||||
struct Ref : public Symbol {
|
||||
std::shared_ptr<Symbol> symbol;
|
||||
uint32_t pointer;
|
||||
int32_t array;
|
||||
std::string reg;
|
||||
};
|
||||
|
||||
struct Argument {
|
||||
std::string key;
|
||||
std::shared_ptr<Ref> ref;
|
||||
};
|
||||
|
||||
struct Function : public Symbol {
|
||||
std::vector<Argument> arguments;
|
||||
std::shared_ptr<Ref> returnType;
|
||||
std::vector<uint32_t> signature;
|
||||
};
|
||||
|
||||
struct Field {
|
||||
std::string key;
|
||||
std::shared_ptr<Symbol> value;
|
||||
};
|
||||
|
||||
struct Struct : public Symbol {
|
||||
std::vector<Field> fields;
|
||||
};
|
||||
|
||||
struct Intrinsic : public Symbol {
|
||||
enum uint8_t { U8, U16, U23, S8, S16, S32 } type;
|
||||
};
|
||||
|
||||
struct Enum : public Symbol {
|
||||
std::shared_ptr<Symbol> type;
|
||||
std::map<std::string, uint32_t> entries;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class API {
|
||||
public:
|
||||
API(unsigned char *dat, unsigned int len);
|
||||
std::map<std::string, std::shared_ptr<symbol::Symbol>> symbols;
|
||||
|
||||
private:
|
||||
std::shared_ptr<symbol::Symbol> lookup(uint32_t id);
|
||||
void setIntrinsic(Handle h, std::shared_ptr<symbol::Symbol> s);
|
||||
void setEnum(Handle h, std::shared_ptr<symbol::Symbol> s);
|
||||
void setRef(Handle h, std::shared_ptr<symbol::Symbol> s);
|
||||
void setStruct(Handle h, std::shared_ptr<symbol::Symbol> s);
|
||||
void setFunction(Handle h, std::shared_ptr<symbol::Symbol> s);
|
||||
|
||||
std::map<uint32_t, std::string> ids;
|
||||
};
|
127
src/disasm.cc
Normal file
127
src/disasm.cc
Normal file
@ -0,0 +1,127 @@
|
||||
/** @copyright 2020 Sean Kasun */
|
||||
|
||||
#include "disasm.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
Disassembler::Disassembler(std::shared_ptr<Fingerprints> prints) : fingerprints(prints) { }
|
||||
|
||||
bool Disassembler::disassemble(std::vector<Segment> segments,
|
||||
std::vector<Entry> entries) {
|
||||
this->segments = segments;
|
||||
// trace all entry points
|
||||
for (auto &entry : entries) {
|
||||
if (!trace(entry)) {
|
||||
std::cerr << "Failed to trace execution flow" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// build the basic blocks
|
||||
if (!basicBlocks()) {
|
||||
std::cerr << "Failed to calculate basic blocks" << std::endl;
|
||||
return false;
|
||||
}
|
||||
// disassemble each segment
|
||||
for (auto &segment : segments) {
|
||||
std::string fname = "seg" + std::to_string(segment.segnum);
|
||||
std::ofstream f(fname, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
if (!f.is_open()) {
|
||||
std::cerr << "Failed to open '" << fname << "' for writing" << std::endl;
|
||||
return false;
|
||||
}
|
||||
f << "Section $" << std::ios::hex << segment.segnum << " "
|
||||
<< segment.name << std::endl;
|
||||
if (!decode(segment.mapped, segment.mapped + segment.length)) {
|
||||
std::cerr << "Disassembly failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Disassembler::trace(const Entry &start) {
|
||||
std::stack<Entry> workList;
|
||||
|
||||
workList.push(start);
|
||||
labels.insert(std::pair<uint32_t, uint32_t>(start.org, start.org));
|
||||
while (!workList.empty()) {
|
||||
auto state = workList.top();
|
||||
workList.pop();
|
||||
std::shared_ptr<Inst> inst = nullptr;
|
||||
do {
|
||||
auto ptr = getAddress(state.org);
|
||||
if (ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto addr = state.org;
|
||||
inst = nullptr;
|
||||
int16_t numDB = 0;
|
||||
if (fingerprints) { // scan for fingerprints
|
||||
auto node = fingerprints->root;
|
||||
int8_t len = 0;
|
||||
auto fstart = ptr->tell();
|
||||
do {
|
||||
node = node->map.value(ptr->r8(), nullptr);
|
||||
len++;
|
||||
if (node != nullptr && !node->name.isEmpty()) {
|
||||
if (inst == nullptr) {
|
||||
inst = std::make_shared<Inst>();
|
||||
inst->type = Special;
|
||||
}
|
||||
inst->name = node->name;
|
||||
inst->length = len;
|
||||
numDB = node->numDB;
|
||||
}
|
||||
} while (node != nullptr && !ptr->eof());
|
||||
if (inst) {
|
||||
fstart += inst->length;
|
||||
state.org += inst->length;
|
||||
}
|
||||
ptr->seek(fstart);
|
||||
}
|
||||
if (numDB > 0 && inst) {
|
||||
inst->name += " {";
|
||||
for (int i = 0; i < numDB; i++) {
|
||||
if (i) {
|
||||
inst->name += ", ";
|
||||
}
|
||||
inst->name += hex2(ptr->r8());
|
||||
}
|
||||
inst->name += "}";
|
||||
inst->length += numDB;
|
||||
state.org += numDB;
|
||||
}
|
||||
if (!inst) {
|
||||
inst = decodeInst(ptr, &state);
|
||||
}
|
||||
map[addr] = inst;
|
||||
if (inst->type == Jump || inst->type == Branch || inst->type == Call) {
|
||||
auto target = target(inst, resolver);
|
||||
if (target > 0 && !labels.contains(target)) {
|
||||
workList.push({state.flags, target});
|
||||
labels.insert(target, target);
|
||||
}
|
||||
}
|
||||
if (inst->type == Jump || inst->type == Branch ||
|
||||
inst->type == Return) {
|
||||
branches.insert(state.org, addr);
|
||||
}
|
||||
if (inst->type == Invalid) {
|
||||
branches.insert(addr, addr);
|
||||
}
|
||||
} while (inst->type != Return && inst->type != Jump &&
|
||||
inst->type != Invalid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Handle Disassembler::getAddress(uint32_t address) {
|
||||
for (auto &s : segments) {
|
||||
if (address >= s.mapped && address < s.mapped + s.length) {
|
||||
s.data->seek(address - s.mapped);
|
||||
return s.data;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
34
src/disasm.h
34
src/disasm.h
@ -2,6 +2,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include "omf.h"
|
||||
#include "api.h"
|
||||
|
||||
enum {
|
||||
IsX8 = 0x10,
|
||||
@ -12,3 +15,34 @@ enum {
|
||||
IsM8Changed = 0x400,
|
||||
IsEmuChanged = 0x2000,
|
||||
};
|
||||
|
||||
enum InsType : uint16_t {
|
||||
Normal = 0x00,
|
||||
Call = 0x01,
|
||||
Jump = 0x02,
|
||||
Return = 0x03,
|
||||
Branch = 0x04,
|
||||
Special = 0x05, // fingerprint
|
||||
Invalid = 0xff,
|
||||
};
|
||||
|
||||
struct Inst {
|
||||
std::string name;
|
||||
InsType type;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
class Disassembler {
|
||||
public:
|
||||
Disassembler(std::shared_ptr<Fingerprints> prints);
|
||||
bool disassemble(std::vector<Segment> segments, std::vector<Entry> entries);
|
||||
|
||||
private:
|
||||
bool trace(const Entry &start);
|
||||
Handle getAddress(uint32_t address);
|
||||
|
||||
std::map<uint32_t, uint32_t> labels;
|
||||
std::map<uint32_t, uint32_t> branches;
|
||||
std::vector<Segment> segments;
|
||||
std::shared_ptr<Fingerprints> fingerprints;
|
||||
};
|
||||
|
@ -68,6 +68,15 @@ uint8_t TheHandle::r8() {
|
||||
return *pos++;
|
||||
}
|
||||
|
||||
std::string TheHandle::rs() {
|
||||
std::string r;
|
||||
uint8_t len = *pos++;
|
||||
for (auto i = 0; i < len; i++) {
|
||||
r += static_cast<char>(*pos++);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
std::string TheHandle::read(int32_t len) {
|
||||
std::string r;
|
||||
for (auto i = 0; i < len; i++) {
|
||||
|
@ -19,6 +19,7 @@ class TheHandle {
|
||||
uint32_t r24();
|
||||
uint16_t r16();
|
||||
uint8_t r8();
|
||||
std::string rs();
|
||||
void seek(int64_t pos);
|
||||
void skip(int64_t length);
|
||||
std::string read(int32_t length);
|
||||
|
52
src/main.cc
52
src/main.cc
@ -4,7 +4,8 @@
|
||||
#include <iostream>
|
||||
#include "disasm.h"
|
||||
#include "omf.h"
|
||||
|
||||
#include "api.h"
|
||||
#include "../iigs.c"
|
||||
|
||||
const char *argp_program_version = "regs 0.2";
|
||||
const char *argp_program_bug_address = "sean@seancode.com";
|
||||
@ -109,11 +110,54 @@ int main(int argc, char **argv) {
|
||||
argp_parse(&argp, argc, argv, 0, 0, &arguments);
|
||||
|
||||
// load map if it exists
|
||||
Map map(arguments.filename, arguments.org, arguments.flags);
|
||||
OMF omf(map);
|
||||
if (!omf.load(arguments.filename)) {
|
||||
Map map(arguments.filename);
|
||||
OMF omf;
|
||||
if (!omf.load(arguments.filename, arguments.org)) {
|
||||
std::cerr << "Failed to load " << arguments.filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
auto segments = omf.get();
|
||||
if (map.needsEntry()) {
|
||||
for (auto &s : segments) {
|
||||
if ((s.kind & 0x1f) == 0) { // code
|
||||
map.addEntry(s.mapped + s.entry, arguments.flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
API api(iigs_dat, iigs_dat_len);
|
||||
|
||||
auto prints = std::make_shared<Fingerprints>();
|
||||
for (auto s : api.symbols) {
|
||||
if (s->kind == symbol::isFunction) {
|
||||
auto f = std::static_pointer_cast<symbol::Function>(s);
|
||||
if (f->signature.size() >= 2) {
|
||||
if (f->signature[0] >= 0) { // tool
|
||||
// ldx tool, jsl e1/0000
|
||||
std::vector<uint8_t> sig = { 0xa2, f->signature[0], f->signature[1],
|
||||
0x22, 0x00, 0x00, 0xe1 };
|
||||
prints->add(sig, f->name);
|
||||
} else if (f->signature[0] == -1) { // p16/gsos
|
||||
// jsl e1/00a8
|
||||
std::vector<uint8_t> sig = { 0x22, 0xa8, 0x00, 0xe1,
|
||||
f->signature[2] & 0xff, f->signature[2] >> 8 };
|
||||
prints->add(sig, f->name, f->signature[1] & 0xff);
|
||||
} else if (f->signature[0] == -2) { // p8
|
||||
// jsr bf00
|
||||
std::vector<uint8_t> sig = { 0x20, 0x00, 0xbf, f->signature[2] };
|
||||
prints->add(sig, f->name, f->signature[1] & 0xff);
|
||||
} else if (f->signature[0] == -3) { // smartport
|
||||
// jsr c50d
|
||||
std::vector<uint8_t> sig5 = { 0x20, 0x0d, 0xc5, f->signature[2] };
|
||||
std::vector<uint8_t> sig7 = { 0x20, 0x0d, 0xc7, f->signature[2] };
|
||||
prints->add(sig5, f->name, f->signature[1]);
|
||||
prints->add(sig7, f->name, f->signature[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Disassembler d(prints);
|
||||
d.disassemble(segments, map.getEntries());
|
||||
}
|
||||
|
19
src/map.cc
19
src/map.cc
@ -3,16 +3,11 @@
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
Map::Map(const char *filename, uint32_t org, uint32_t flags) {
|
||||
Map::Map(const char *filename) {
|
||||
std::string mapname = filename;
|
||||
mapname += ".regs";
|
||||
File file(mapname);
|
||||
if (!file.is_open()) {
|
||||
Entry entry;
|
||||
entry.org = org;
|
||||
this->org = org;
|
||||
entry.flags = flags;
|
||||
entryPoints.push_back(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -54,10 +49,18 @@ Map::Map(const char *filename, uint32_t org, uint32_t flags) {
|
||||
}
|
||||
}
|
||||
|
||||
void Map::addEntry(uint32_t entry) {
|
||||
bool Map::needsEntry() {
|
||||
return entryPoints.size() == 0;
|
||||
}
|
||||
|
||||
std::vector<Entry> Map::getEntries() {
|
||||
return entryPoints;
|
||||
}
|
||||
|
||||
void Map::addEntry(uint32_t entry, uint32_t flags) {
|
||||
Entry e;
|
||||
e.org = entry;
|
||||
e.flags = 0;
|
||||
e.flags = flags;
|
||||
entryPoints.push_back(e);
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,10 @@ struct Entry {
|
||||
|
||||
class Map {
|
||||
public:
|
||||
Map(const char *filename, uint32_t org, uint32_t flags);
|
||||
void addEntry(uint32_t entry);
|
||||
Map(const char *filename);
|
||||
bool needsEntry();
|
||||
std::vector<Entry> getEntries();
|
||||
void addEntry(uint32_t entry, uint32_t flags);
|
||||
uint32_t org;
|
||||
|
||||
private:
|
||||
|
14
src/omf.cc
14
src/omf.cc
@ -13,21 +13,22 @@ enum SegOp {
|
||||
SUPER = 0xf7,
|
||||
};
|
||||
|
||||
OMF::OMF(const Map &map) : map(map) {
|
||||
OMF::OMF() {
|
||||
}
|
||||
|
||||
static bool compareSegments(const Segment &a, const Segment &b) {
|
||||
return a.mapped < b.mapped;
|
||||
}
|
||||
|
||||
bool OMF::load(const char *filename) {
|
||||
bool OMF::load(const char *filename, uint32_t org) {
|
||||
handle = TheHandle::createFromFile(filename);
|
||||
|
||||
if (!isOMF()) {
|
||||
Segment seg;
|
||||
seg.bytecnt = handle->length;
|
||||
seg.kind = 0; // code
|
||||
seg.mapped = map.org;
|
||||
seg.entry = 0;
|
||||
seg.mapped = org;
|
||||
seg.data = handle;
|
||||
segments.push_back(seg);
|
||||
} else {
|
||||
@ -40,13 +41,6 @@ bool OMF::load(const char *filename) {
|
||||
if (!relocSegments()) {
|
||||
return false;
|
||||
}
|
||||
// add the first entry point
|
||||
for (auto &s : segments) {
|
||||
if ((s.kind & 0x1f) == 0) { // code
|
||||
map.addEntry(s.mapped + s.entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::sort(segments.begin(), segments.end(), compareSegments);
|
||||
return true;
|
||||
|
@ -26,8 +26,8 @@ struct Segment {
|
||||
|
||||
class OMF {
|
||||
public:
|
||||
explicit OMF(const Map &map);
|
||||
bool load(const char *filename);
|
||||
explicit OMF();
|
||||
bool load(const char *filename, uint32_t org);
|
||||
std::vector<Segment> get() const;
|
||||
|
||||
private:
|
||||
@ -39,6 +39,5 @@ class OMF {
|
||||
uint32_t value);
|
||||
|
||||
Handle handle;
|
||||
const Map ↦
|
||||
std::vector<Segment> segments;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user