diff --git a/Makefile b/Makefile index 6db3f56..937a589 100644 --- a/Makefile +++ b/Makefile @@ -2,20 +2,28 @@ LINK.o = $(LINK.cc) CXXFLAGS = -std=c++11 -g -Wall CCFLAGS = -g -OBJS = dumpobj.o disassembler.o zrdz_disassembler.o +DUMP_OBJS = dumpobj.o disassembler.o zrdz_disassembler.o +LINK_OBJS = link.o expression.o #UNAME_S := $(shell uname -s) #ifeq ($(UNAME_S),MINGW64_NT-10.0) ifeq ($(MSYSTEM),MINGW64) - OBJS += mingw/err.o + DUMP_OBJS += mingw/err.o + LINK_OBJS += mingw/err.o CPPFLAGS += -I mingw/ LDLIBS += -static endif +.PHONY: all +all: wdcdumpobj wdclink -wdcdumpobj : $(OBJS) +wdcdumpobj : $(DUMP_OBJS) $(LINK.o) $^ $(LDLIBS) -o $@ +wdclink : $(LINK_OBJS) + $(LINK.o) $^ $(LDLIBS) -o $@ + + disassembler.o : disassembler.cpp disassembler.h zrdz_disassembler.o : zrdz_disassembler.cpp zrdz_disassembler.h disassembler.h dumpobj.o : dumpobj.cpp zrdz_disassembler.h disassembler.h @@ -23,7 +31,7 @@ mingw/err.o : mingw/err.c mingw/err.h .PHONY: clean clean: - $(RM) wdcdumpobj $(OBJS) + $(RM) wdcdumpobj $(DUMP_OBJS) $(LINK_OBJS) .PHONY: variables diff --git a/dumpobj.cpp b/dumpobj.cpp index 5e2969b..fa5fe0e 100644 --- a/dumpobj.cpp +++ b/dumpobj.cpp @@ -72,7 +72,7 @@ void usage() { struct Header { uint32_t magic; /* magic number for detection */ uint16_t version; /* version number of object format */ - uint8_t filetype; /* file type, object or library */ + uint8_t filetype; /* file type, object or library */ }; #pragma pack(pop) diff --git a/expression.cpp b/expression.cpp new file mode 100644 index 0000000..abb1c58 --- /dev/null +++ b/expression.cpp @@ -0,0 +1,169 @@ +#include "expression.h" +#include +#include "obj816.h" + +/* a ** b */ +uint32_t power(uint32_t a, uint32_t b) { + + uint32_t rv = 1; + for( ; b; b >>= 1) { + if (b & 0x01) rv *= a; + a = a * a; + } + return rv; +} + +bool unary_op(unsigned op, std::vector &v) { + if (v.size() >=1 ) { + expr &a = v.back(); + if (a.tag == OP_VAL) { + switch(a.tag) { + case OP_NOT: a.value = !a.value; break; + case OP_NEG: a.value = -a.value; break; + case OP_FLP: a.value = ~a.value; break; + } + return true; + } + } + v.emplace_back(op); + return false; +} + + +bool binary_op(unsigned op, std::vector &v) { + if (v.size() >= 2) { + expr &a = v[v.size() - 2]; + expr &b = v[v.size() - 1]; + + if (a.tag == OP_VAL && b.tag == OP_VAL) { + uint32_t value = 0; + switch(op) { + case OP_EXP: value = power(a.value, b.value); break; + case OP_MUL: value = a.value * b.value; break; + case OP_DIV: value = a.value / b.value; break; + case OP_MOD: value = a.value % b.value; break; + case OP_SHR: value = a.value >> b.value; break; + case OP_SHL: value = a.value << b.value; break; + case OP_ADD: value = a.value + b.value; break; + case OP_SUB: value = a.value - b.value; break; + case OP_AND: value = a.value & b.value; break; + case OP_OR: value = a.value | b.value; break; + case OP_XOR: value = a.value ^ b.value; break; + case OP_EQ: value = a.value == b.value; break; + case OP_GT: value = (int32_t)a.value > (int32_t)b.value; break; + case OP_LT: value = (int32_t)a.value < (int32_t)b.value; break; + case OP_UGT: value = a.value > b.value; break; + case OP_ULT: value = a.value < b.value; break; + } + v.pop_back(); + v.back().value = value; + return true; + } + if (a.tag == OP_VAL && b.tag == OP_LOC) { + switch(op) { + case OP_ADD: { + // constant + symbol + expr tmp = b; + tmp.value = a.value + b.value; + v.pop_back(); + v.pop_back(); + v.emplace_back(tmp); + return true; + } + #if 0 + case OP_SUB: { + // constant - symbol .. does this even make sense? + expr tmp = b; + tmp.value = a.value - b.value; + v.pop_back(); + v.pop_back(); + v.emplace_back(tmp); + return true; + } + #endif + } + } + if (a.tag == OP_LOC && b.tag == OP_VAL) { + switch(op) { + case OP_ADD: a.value += b.value; return true; + case OP_SUB: a.value -= b.value; return true; + } + } + + if (a.tag == OP_LOC && b.tag == OP_LOC && a.section == b.section) { + uint32_t value = 0; + bool rv = false; + switch (op) { + case OP_SUB: + // end - start + value = a.value - b.value; + rv = true; break; + case OP_EQ: + value = a.value == b.value; + rv = true; break; + case OP_GT: + case OP_UGT: + value = a.value > b.value; + rv = true; break; + case OP_LT: + case OP_ULT: + value = a.value < b.value; + rv = true; break; + } + if (rv) { + v.pop_back(); + v.pop_back(); + v.emplace_back(OP_VAL, value); + return true; + } + } + + + } + v.emplace_back(op); + return false; +} + + +bool simplify_expression(expression &e) { + std::vector tmp; + bool rv = false; + for (auto &t : e.stack) { + if (t.tag >= OP_BIN) { + rv = binary_op(t.tag, tmp) || rv; + } else if (t.tag >= OP_UNA) { + rv = unary_op(t.tag, tmp) || rv; + } else { + tmp.emplace_back(t); + } + } + if (rv) e.stack = std::move(tmp); + return rv; +} + +/* + * if force is true, treat OP_LOC records as OP_VAL (for omf) + */ + +// should return std::optional... + +uint32_t evaluate_expression(expression &e, bool force) { + std::vector tmp; + for (const auto &t : e.stack) { + if (t.tag == OP_LOC && force) { + tmp.emplace_back(OP_VAL, t.value); + continue; + } + if (t.tag >= OP_BIN) { + binary_op(t.tag, tmp); + } else if (t.tag >= OP_UNA) { + unary_op(t.tag, tmp); + } else { + tmp.emplace_back(t); + } + } + + if (tmp.size() == 1 && tmp.front().tag == OP_VAL) return tmp.front().value; + return 0; +} + diff --git a/expression.h b/expression.h new file mode 100644 index 0000000..db3c56d --- /dev/null +++ b/expression.h @@ -0,0 +1,32 @@ +#ifndef __expression_h__ +#define __expression_h__ + +#include +#include + +struct expr { + expr(int t = 0, uint32_t v = 0, uint32_t s = 0) + : tag(t), value(v), section(s) + {} + int tag = 0; + uint32_t value = 0; + unsigned section = 0; +}; + + +struct expression { + unsigned section = 0; + uint32_t offset = 0; + uint8_t size = 0; + uint8_t relative = false; + bool undefined = false; + + std::vector stack; + +}; + +uint32_t evaluate_expression(expression &e, bool force = false); + +bool simplify_expression(expression &e); + +#endif diff --git a/link.cpp b/link.cpp index ff9efb1..9c274ad 100644 --- a/link.cpp +++ b/link.cpp @@ -7,7 +7,818 @@ #include #include #include +#include #include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "obj816.h" +#include "expression.h" + + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +enum class endian { + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__ +}; + + +template +void swap_if(T &t, std::false_type) {} + +void swap_if(uint8_t &, std::true_type) {} + +void swap_if(uint16_t &value, std::true_type) { + value = __builtin_bswap16(value); +} + +void swap_if(uint32_t &value, std::true_type) { + value = __builtin_bswap32(value); +} + +void swap_if(uint64_t &value, std::true_type) { + value = __builtin_bswap64(value); +} + +template +void le_to_host(T &value) { + swap_if(value, std::integral_constant{}); +} + + +#pragma pack(push, 1) +struct Header { + uint32_t magic; /* magic number for detection */ + uint16_t version; /* version number of object format */ + uint8_t filetype; /* file type, object or library */ +}; + +#pragma pack(pop) + + +struct section { + std::string name; + uint8_t flags = 0; + uint32_t org = 0; + uint32_t size = 0; + + unsigned number = -1; + std::vector data; + std::vector expressions; + + unsigned end_symbol = 0; // auto-generated _END_{name} symbol. +}; + +struct symbol { + std::string name; + uint8_t type = 0; + uint8_t flags = 0; + uint32_t offset = 0; + int section = -1; +}; + +template +uint8_t read_8(T &iter) { + uint8_t tmp = *iter; + ++iter; + return tmp; +} + +template +uint16_t read_16(T &iter) { + uint16_t tmp = 0; + + tmp |= *iter << 0; + ++iter; + tmp |= *iter << 8; + ++iter; + return tmp; +} + +template +uint32_t read_32(T &iter) { + uint32_t tmp = 0; + + tmp |= *iter << 0; + ++iter; + tmp |= *iter << 8; + ++iter; + tmp |= *iter << 16; + ++iter; + tmp |= *iter << 24; + ++iter; + + + return tmp; +} + +template +std::string read_cstring(T &iter) { + std::string s; + for(;;) { + uint8_t c = *iter; + ++iter; + if (!c) break; + s.push_back(c); + } + return s; +} + + +template +std::string read_pstring(T &iter) { + std::string s; + unsigned size = *iter; + ++iter; + s.reserve(size); + while (size--) { + uint8_t c = *iter; + ++iter; + s.push_back(c); + } + return s; +} + + +std::vector
read_sections(const std::vector §ion_data) { + + std::vector
sections; + auto iter = section_data.begin(); + while (iter != section_data.end()) { + + section s; + + s.number = read_8(iter); + s.flags = read_8(iter); + s.size = read_32(iter); + s.org = read_32(iter); + + if (!(s.flags & SEC_NONAME)) s.name = read_cstring(iter); + + sections.emplace_back(std::move(s)); + } + return sections; +} + + +std::vector read_symbols(const std::vector &symbol_data) { + + std::vector symbols; + + auto iter = symbol_data.begin(); + while (iter != symbol_data.end()) { + symbol s; + s.type = read_8(iter); + s.flags = read_8(iter); + s.section = read_8(iter); + s.offset = s.type == S_UND ? 0 : read_32(iter); + s.name = read_cstring(iter); + + + symbols.emplace_back(std::move(s)); + } + + return symbols; +} + + +std::unordered_map section_map; +std::vector
sections; + +std::unordered_map symbol_map; +std::vector symbols; + +std::unordered_set undefined_symbols; + + + + + +/* + * replace undefined symbols (if possible) and simplify expressions. + * + */ +void simplify() { + for (auto &s : sections) { + for (auto &e : s.expressions) { + bool delta = false; + + // first check for undefined symbols. + if (e.undefined) { + e.undefined = false; + for (auto &t : e.stack) { + + if (t.tag == OP_SYM) { + const auto &ss = symbols[t.section]; + switch(ss.type & 0x0f) { + case S_UND: + e.undefined = true; + break; + case S_REL: + t = expr{OP_LOC, ss.offset, (uint32_t)ss.section}; + delta = true; + break; + case S_ABS: + t = expr{OP_VAL, (uint32_t)ss.offset}; + delta = true; + break; + } + } + } + } + if (e.stack.size() > 1) simplify_expression(e); + } + } +} + + + +/* + * read and process all sections... + * if section > 5, remap based on name. + * + */ + +void one_module(const std::vector &data, const std::vector §ion_data, const std::vector &symbol_data) { + + std::array remap_section; + + int current_section = SECT_CODE; + std::vector *data_ptr = §ions[current_section].data; + + std::fill(remap_section.begin(), remap_section.end(), -1); + remap_section[SECT_PAGE0] = SECT_PAGE0; + remap_section[SECT_CODE] = SECT_CODE; + remap_section[SECT_KDATA] = SECT_KDATA; + remap_section[SECT_DATA] = SECT_DATA; + remap_section[SECT_UDATA] = SECT_UDATA; + + std::vector
local_sections = read_sections(section_data); + std::vector local_symbols = read_symbols(symbol_data); + + // convert local sections to global + for (auto &s : local_sections) { + if (s.number <= SECT_UDATA) continue; + + auto iter = section_map.find(s.name); + if (iter == section_map.end()) { + int virtual_section = sections.size(); + remap_section[s.number] = virtual_section; + s.number = virtual_section; + sections.emplace_back(s); + symbol_map.emplace(s.name, virtual_section); + } else { + const auto &ss = sections[iter->second]; + assert(ss.flags == s.flags); // check org???? + remap_section[s.number] = iter->second; + s.number = iter->second; + } + } + + // convert local symbols to global. + for (auto &s : local_symbols) { + if (s.type == S_UND) { + auto iter = symbol_map.find(s.name); + if (iter == symbol_map.end()) { + s.section = symbols.size(); + symbol_map.emplace(s.name, s.section); + undefined_symbols.emplace(s.name); + } + else { + // already exists... + const auto &ss = symbols[iter->second]; + if (ss.type != S_UND) s = ss; + } + continue; + } + + // remap and fudge the offset. + if ((s.type & 0x0f) == S_REL) { + int virtual_section = remap_section[s.section]; + assert(virtual_section != -1); + s.section = virtual_section; + s.offset += sections[virtual_section].data.size(); + } else { + s.section = -1; + } + + constexpr const unsigned mask = SF_GBL | SF_DEF; + if ((s.flags & mask) == mask) { + + auto iter = symbol_map.find(s.name); + + if (iter == symbol_map.end()) { + unsigned tmp = symbols.size(); + symbol_map.emplace(s.name, tmp); + symbols.emplace_back(s); + } else { + auto &ss = symbols[iter->second]; + + // if it was undefined, define it! + if (ss.type == S_UND) { + ss = s; + undefined_symbols.erase(s.name); + } + else { + // ok if symbols are identical.. + assert(ss.type == ss.type && ss.flags == s.flags && ss.section == s.section && ss.offset == s.offset); + } + } + + } + + } + + + auto iter = data.begin(); + for(;;) { + uint8_t op = read_8(iter); + if (op == REC_END) return; + + ++iter; + if (op < 0xf0) { + data_ptr->insert(data_ptr->end(), iter, iter + op); + iter += op; + continue; + } + + switch(op) { + case REC_SPACE: { + uint16_t count = read_16(iter); + data_ptr->insert(data_ptr->end(), count, 0); + break; + } + + case REC_SECT: { + /* switch sections */ + uint8_t s = read_8(iter); + current_section = remap_section[s]; + assert(current_section > 0 && current_section < sections.size()); + + data_ptr = §ions[current_section].data; + break; + } + + case REC_ORG: { + assert(!"ORG not supported."); + break; + } + + case REC_RELEXP: + case REC_EXPR: { + + expression e; + e.relative = op == REC_RELEXP; + + e.offset = data_ptr->size(); + e.size = read_8(iter); + + data_ptr->insert(data_ptr->end(), e.size, 0); + + /**/ + for(;;) { + op = read_8(iter); + if (op == OP_END) break; + + switch(op) { + case OP_VAL: { + uint32_t offset = read_32(iter); + e.stack.emplace_back(op, offset); + break; + } + case OP_SYM: { + uint16_t symbol = read_16(iter); + assert(symbol < local_symbols.size()); + auto &s = local_symbols[symbol]; + switch (s.type & 0x0f) { + case S_UND: + // S_UND indicates it's still undefined globally. + e.stack.emplace_back(OP_SYM, 0, s.section); /* section is actually a symbol number */ + e.undefined = true; + break; + case S_REL: + e.stack.emplace_back(OP_LOC, s.offset, s.section); + break; + + case S_ABS: + e.stack.emplace_back(OP_VAL, s.offset); + break; + + default: + assert(!"unsupported symbol flags."); + } + break; + } + case OP_LOC: { + uint8_t section = read_8(iter); + uint32_t offset = read_32(iter); + int real_section = remap_section[section]; + assert(real_section >= 0); + e.stack.emplace_back(op, offset, real_section); + break; + } + // operations.. + //unary + case OP_NOT: + case OP_NEG: + case OP_FLP: + // binary + case OP_EXP: + case OP_MUL: + case OP_DIV: + case OP_MOD: + case OP_SHR: + case OP_SHL: + case OP_ADD: + case OP_SUB: + case OP_AND: + case OP_OR: + case OP_XOR: + case OP_EQ: + case OP_GT: + case OP_LT: + case OP_UGT: + case OP_ULT: + e.stack.emplace_back(op); + break; + default: + assert(!"unsupported expression opcode."); + } + } + break; + } + + + case REC_LINE: break; + case REC_DEBUG: { + uint16_t size = read_16(iter); + iter += size; + break; + } + + } + } +} + + + +void init() { + + sections.resize(5); + + sections[SECT_PAGE0].number = SECT_PAGE0; + sections[SECT_PAGE0].flags = SEC_DATA | SEC_NONAME | SEC_DIRECT | SEC_REF_ONLY; + sections[SECT_PAGE0].name = "page0"; + + sections[SECT_CODE].number = SECT_CODE; + sections[SECT_CODE].flags = SEC_NONAME; + sections[SECT_CODE].name = "code"; + + sections[SECT_KDATA].number = SECT_KDATA; + sections[SECT_KDATA].flags = SEC_DATA | SEC_NONAME; + sections[SECT_KDATA].name = "kdata"; + + sections[SECT_DATA].number = SECT_DATA; + sections[SECT_DATA].flags = SEC_DATA | SEC_NONAME; + sections[SECT_DATA].name = "data"; + + sections[SECT_UDATA].number = SECT_UDATA; + sections[SECT_UDATA].flags = SEC_DATA | SEC_NONAME | SEC_REF_ONLY; + sections[SECT_UDATA].name = "udata"; + + /* + * For each section, [the linker] creates three symbols, + * _ROM_BEG_secname, _BEG_secname and _END_secname, which + * correspond to the rom location and the execution beginning + * and end of the section. These will be used more in the next + * two sections of code. + */ + + // n.b - only for pre-defined sections [?], skip the _ROM_BEG_* symbols... + + static std::string names[] = { + "_BEG_PAGE0", "_END_PAGE0", + "_BEG_CODE", "_END_CODE", + "_BEG_KDATA", "_END_KDATA" + "_BEG_DATA", "_END_DATA" + "_BEG_UDATA", "_END_UDATA" + }; + + for (int i = 0; i < 5; ++i) { + + // begin is 0. + symbol s; + s.name = names[i * 2]; + s.section = i; + s.type = S_REL; + s.flags = SF_DEF | SF_GBL; + symbol_map.emplace(s.name, i * 2); + symbols.emplace_back(s); + + // end is undefined... + s.name = names[i * 2 + 1]; + s.section = i * 2 + 1; // symbol number. + s.type = S_UND; + s.flags = 0; + + symbol_map.emplace(s.name, i * 2 + 1); + symbols.emplace_back(s); + + } + +} + + +void generate_end() { + const std::string names[] = { + "_END_PAGE0", + "_END_CODE", + "_END_KDATA" + "_END_DATA" + "_END_UDATA" + }; + + for (int i = 0; i < 5; ++i) { + symbol s; + s.section = i; + s.type = S_REL; + s.flags = SF_DEF | SF_GBL; + s.offset = sections[i].data.size(); + + symbols[i * 2 + 1] = s; + } +} + +void merge_data() { + + // merge data sections -- kdata, data, udata. + // merge custom data sections? + + std::vector new_data; + std::vector new_expr; + + unsigned new_number = 0; + + uint32_t total_data_size = 0; + uint32_t total_code_size = 0; + for (const auto &s : sections) { + if (s.flags & SEC_REF_ONLY) continue; + if (s.flags & SEC_DATA) total_data_size += s.data.size(); + else total_code_size += s.data.size(); + } + + + // also merge code if total size is ok... + uint32_t size = 0; + for (int i = 1; i < 5; ++i) { + size += sections[i].data.size(); + } + if (size <= 0xffff) { + new_data = std::move(sections[SECT_CODE].data); + new_expr = std::move(sections[SECT_CODE].expressions); + new_number = 1; + } + + std::vector< std::pair > remap; + remap.reserve(sections.size()); + + for (unsigned i = 0; i < sections.size(); ++i) + remap.emplace_back(std::make_pair(i, i)); + + + uint32_t fudge_kdata = 0; + uint32_t fudge_data = 0; + uint32_t fudge_udata = 0; + + section *s = §ions[SECT_KDATA]; + fudge_kdata = new_data.size(); + + new_data.insert(new_data.end(), s->data.begin(), s->data.end()); + new_expr.insert(new_expr.end(), + std::make_move_iterator(s->expressions.begin()), + std::make_move_iterator(s->expressions.end()) + ); + *s = section{}; + + s = §ions[SECT_DATA]; + fudge_data = new_data.size(); + + new_data.insert(new_data.end(), s->data.begin(), s->data.end()); + new_expr.insert(new_expr.end(), + std::make_move_iterator(s->expressions.begin()), + std::make_move_iterator(s->expressions.end()) + ); + *s = section{}; + + + s = §ions[SECT_UDATA]; + fudge_udata = new_data.size(); + + new_data.insert(new_data.end(), s->data.begin(), s->data.end()); + new_expr.insert(new_expr.end(), + std::make_move_iterator(s->expressions.begin()), + std::make_move_iterator(s->expressions.end()) + ); + *s = section{}; + + + + if (size > 0xffff) { + // not merged into code. + + new_number = sections.size(); + + section tmp; + tmp.name = "data"; + tmp.flags = SEC_DATA; + tmp.data = std::move(new_data); + tmp.expressions = std::move(new_expr); + sections.emplace_back(tmp); + } + + + // update all symbols with the new location / offset. + + for (auto &s : symbols) { + if ((s.type & 0x0f) == S_REL) switch(s.section) { + case SECT_DATA: + s.section = new_number; + s.offset += fudge_data; + break; + case SECT_KDATA: + s.section = new_number; + s.offset += fudge_kdata; + break; + case SECT_UDATA: + s.section = new_number; + s.offset += fudge_udata; + break; + } + } + + // update expressions with new section / offset. + for (auto &s : sections) { + for (auto &e : s.expressions) { + bool delta = false; + for (auto &t : e.stack) { + if (t.tag == OP_LOC) { + switch(t.section) { + case SECT_DATA: + t.section = new_number; + t.value += fudge_data; + delta = true; + break; + case SECT_KDATA: + t.section = new_number; + t.value += fudge_kdata; + delta = true; + break; + case SECT_UDATA: + t.section = new_number; + t.value += fudge_udata; + delta = true; + break; + } + } + } + if (delta) simplify_expression(e); + } + } + + + +} + + +bool one_file(const std::string &name) { + + int fd = open(name.c_str(), O_RDONLY | O_BINARY); + if (fd < 0) { + warn("Unable to open %s", name.c_str()); + return false; + } + bool rv = false; + + Header h; + ssize_t ok; + + ok = read(fd, &h, sizeof(h)); + if (ok != sizeof(h)) { + warnx("Invalid object file: %s", name.c_str()); + close(fd); + return false; + } + + le_to_host(h.magic); + le_to_host(h.version); + le_to_host(h.filetype); + + if (h.magic != MOD_MAGIC || h.version != MOD_VERSION || h.filetype < MOD_OBJECT || h.filetype > MOD_LIBRARY) { + warnx("Invalid object file: %s", name.c_str()); + close(fd); + return false; + } + + if (h.filetype == MOD_LIBRARY) { + warnx("%s is a library", name.c_str()); + close(fd); + // todo -- add to library list... + return true; + } + + // + rv = true; + lseek(fd, 0, SEEK_SET); + for(;;) { + Mod_head h; + + ok = read(fd, &h, sizeof(h)); + if (ok == 0) break; // eof. + + rv = false; + if (ok < sizeof(h)) { + warnx("Invalid object file: %s", name.c_str()); + break; + } + + le_to_host(h.h_magic); + le_to_host(h.h_version); + le_to_host(h.h_filtyp); + le_to_host(h.h_namlen); + le_to_host(h.h_recsize); + le_to_host(h.h_secsize); + le_to_host(h.h_symsize); + le_to_host(h.h_optsize); + le_to_host(h.h_tot_secs); + le_to_host(h.h_num_secs); + le_to_host(h.h_num_syms); + + assert(h.h_magic == MOD_MAGIC); + assert(h.h_version == 1); + assert(h.h_filtyp == 1); + + + std::string module_name; + { + // now read the name (h_namlen includes 0 terminator.) + std::vector tmp; + tmp.resize(h.h_namlen); + ok = read(fd, tmp.data(), h.h_namlen); + if (ok != h.h_namlen) { + warnx("Invalid object file: %s", name.c_str()); + break; + } + module_name.assign(tmp.data()); + } + + std::vector record_data; + std::vector symbol_data; + std::vector section_data; + + record_data.resize(h.h_recsize); + ok = read(fd, record_data.data(), h.h_recsize); + if (ok != h.h_recsize) { + warnx("Truncated object file: %s", name.c_str()); + break; + } + + section_data.resize(h.h_secsize); + ok = read(fd, section_data.data(), h.h_secsize); + if (ok != h.h_secsize) { + warnx("Truncated object file: %s", name.c_str()); + break; + } + + symbol_data.resize(h.h_symsize); + ok = read(fd, symbol_data.data(), h.h_symsize); + if (ok != h.h_symsize) { + warnx("Truncated object file: %s", name.c_str()); + break; + } + + // should probably pass in name and module.... + one_module(record_data, section_data, symbol_data); + rv = true; + } + + + close(fd); + return rv; +} void help() { exit(0); @@ -48,11 +859,26 @@ int main(int argc, char **argv) { if (argc == 0) usage(); + init(); + + for (int i = 0 ; i < argc; ++i) { + one_file(argv[i]); + } + + // + simplify(); + + // for each undefined, try to find it in a library... + + for (const auto & s : undefined_symbols) { + printf("%s\n", s.c_str()); + } + + generate_end(); + + merge_data(); + + + } - - -struct section { - std::vector data; - uint32_t offset; -} \ No newline at end of file