Compare commits

...

2 Commits

Author SHA1 Message Date
Kelvin Sherlock
9ccab300f2 update github action 2022-12-06 23:27:29 -05:00
Kelvin Sherlock
64aa57a9ed support for v1 omf (VER 1). 2022-12-06 23:25:44 -05:00
3 changed files with 37 additions and 14 deletions

View File

@ -10,7 +10,7 @@ jobs:
matrix: matrix:
os: [macos-latest, ubuntu-latest] os: [macos-latest, ubuntu-latest]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
submodules: true submodules: true

View File

@ -30,7 +30,7 @@
#include "link.h" #include "link.h"
#include "script.h" #include "script.h"
void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool compress, bool expressload); void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool compress, bool expressload, unsigned version = 2);
void save_bin(const std::string &path, omf::segment &segment); void save_bin(const std::string &path, omf::segment &segment);
int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type, std::error_code &ec); int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type, std::error_code &ec);
@ -1255,7 +1255,7 @@ void evaluate(label_t label, opcode_t opcode, const char *cursor) {
/* OMF version, 1 or 2 */ /* OMF version, 1 or 2 */
uint32_t value = number_operand(cursor, local_symbol_table); uint32_t value = number_operand(cursor, local_symbol_table);
if (value != 2) if (value < 1 || value > 2)
throw std::runtime_error("bad OMF version"); throw std::runtime_error("bad OMF version");
ver = value; ver = value;
break; break;

45
omf.cpp
View File

@ -32,20 +32,20 @@ enum class endian {
#pragma pack(push, 1) #pragma pack(push, 1)
struct omf_header { struct omf_header {
uint32_t bytecount = 0; uint32_t bytecount = 0; // block count in v1
uint32_t reserved_space = 0; uint32_t reserved_space = 0;
uint32_t length = 0; uint32_t length = 0;
uint8_t unused1 = 0; uint8_t unused1 = 0; // kind in v1
uint8_t lablen = 0; uint8_t lablen = 0;
uint8_t numlen = 4; uint8_t numlen = 4;
uint8_t version = 2; uint8_t version = 2;
uint32_t banksize = 0; uint32_t banksize = 0;
uint16_t kind = 0; uint16_t kind = 0; // unused in v1
uint16_t unused2 = 0; uint16_t unused2 = 0;
uint32_t org = 0; uint32_t org = 0;
uint32_t alignment = 0; uint32_t alignment = 0;
uint8_t numsex = 0; uint8_t numsex = 0;
uint8_t unused3 = 0; uint8_t unused3 = 0; // lcbank in v1
uint16_t segnum = 0; uint16_t segnum = 0;
uint32_t entry = 0; uint32_t entry = 0;
uint16_t dispname = 0; uint16_t dispname = 0;
@ -74,6 +74,7 @@ struct omf_express_header {
uint16_t dispdata = 0; uint16_t dispdata = 0;
}; };
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(omf_header) == 44, "OMF Header not packed"); static_assert(sizeof(omf_header) == 44, "OMF Header not packed");
@ -160,6 +161,17 @@ static void to_little(struct omf_express_header &h) {
} }
} }
static void to_v1(struct omf_header &h) {
// KIND op value used as-is, no translation.
h.version = 1;
// byte count -> block count
h.bytecount = (h.bytecount + 511) >> 9;
h.unused1 = h.kind;
h.kind = 0;
}
void push(std::vector<uint8_t> &v, uint8_t x) { void push(std::vector<uint8_t> &v, uint8_t x) {
v.push_back(x); v.push_back(x);
} }
@ -288,7 +300,7 @@ enum {
SUPER_INTERSEG36, SUPER_INTERSEG36,
}; };
uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment &seg, bool compress) { uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment &seg, bool compress, bool super) {
std::array< std::optional<super_helper>, 38 > ss; std::array< std::optional<super_helper>, 38 > ss;
@ -297,9 +309,9 @@ uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment
for (auto &r : seg.relocs) { for (auto &r : seg.relocs) {
if (r.can_compress()) { if (compress && r.can_compress()) {
if (compress) { if (super) {
if (r.shift == 0 && r.size == 2) { if (r.shift == 0 && r.size == 2) {
constexpr int n = SUPER_RELOC2; constexpr int n = SUPER_RELOC2;
@ -361,9 +373,9 @@ uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment
} }
for (const auto &r : seg.intersegs) { for (const auto &r : seg.intersegs) {
if (r.can_compress()) { if (compress && r.can_compress()) {
if (compress) { if (super) {
if (r.shift == 0 && r.size == 3) { if (r.shift == 0 && r.size == 3) {
constexpr int n = SUPER_INTERSEG1; constexpr int n = SUPER_INTERSEG1;
@ -516,11 +528,21 @@ void save_object(const std::string &path, omf::segment &s, uint32_t length) {
close(fd); close(fd);
} }
void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool compress, bool expressload) { void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool compress, bool expressload, unsigned version) {
// expressload doesn't support links to other files. // expressload doesn't support links to other files.
// fortunately, we don't either. // fortunately, we don't either.
// "compress" really means SUPER, not cRELOC/cINTERSEG
// version 1 OMF lacks support for SUPER records or expressload.
if (version == 1) {
compress = false;
expressload = false;
}
std::vector<uint8_t> expr_headers; std::vector<uint8_t> expr_headers;
std::vector<unsigned> expr_offsets; std::vector<unsigned> expr_offsets;
@ -603,7 +625,7 @@ void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool
uint32_t reloc_offset = offset + sizeof(omf_header) + data.size(); uint32_t reloc_offset = offset + sizeof(omf_header) + data.size();
uint32_t reloc_size = 0; uint32_t reloc_size = 0;
reloc_size = add_relocs(data, data_offset, s, compress); reloc_size = add_relocs(data, data_offset, s, true, compress);
// end-of-record // end-of-record
push(data, (uint8_t)omf::END); push(data, (uint8_t)omf::END);
@ -643,6 +665,7 @@ void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool
push(expr_headers, s.segname); push(expr_headers, s.segname);
} }
if (version == 1) to_v1(h);
to_little(h); to_little(h);
offset += write(fd, &h, sizeof(h)); offset += write(fd, &h, sizeof(h));
offset += write(fd, data.data(), data.size()); offset += write(fd, data.data(), data.size());