mirror of
https://github.com/ksherlock/wdc-utils.git
synced 2024-09-28 00:54:50 +00:00
Compare commits
3 Commits
3ab26264f6
...
a455e48a2b
Author | SHA1 | Date | |
---|---|---|---|
|
a455e48a2b | ||
|
65d373be25 | ||
|
42347e4d40 |
2
.github/workflows/make.yml
vendored
2
.github/workflows/make.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
- name: make
|
||||
|
4
.github/workflows/msys2.yml
vendored
4
.github/workflows/msys2.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
matrix:
|
||||
msys: [MSYS, MINGW32, MINGW64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@ -26,7 +26,7 @@ jobs:
|
||||
run: msys2 -c 'make'
|
||||
|
||||
- name: Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: binaries - ${{ matrix.msys }}
|
||||
path: "*.exe"
|
||||
|
54
link.cpp
54
link.cpp
@ -41,8 +41,6 @@
|
||||
|
||||
struct {
|
||||
bool v = false;
|
||||
bool C = false;
|
||||
bool X = false;
|
||||
bool S = false;
|
||||
std::string o;
|
||||
|
||||
@ -50,8 +48,10 @@ struct {
|
||||
std::vector<std::string> L;
|
||||
|
||||
unsigned errors = 0;
|
||||
uint16_t file_type;
|
||||
uint32_t aux_type;
|
||||
uint16_t file_type = 0;
|
||||
uint32_t aux_type = 0;
|
||||
|
||||
unsigned omf_flags = 0;
|
||||
} flags;
|
||||
|
||||
|
||||
@ -1647,24 +1647,44 @@ bool parse_ft(const std::string &s) {
|
||||
}
|
||||
|
||||
|
||||
void help() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void usage() {
|
||||
exit(EX_USAGE);
|
||||
|
||||
void usage(int rv) {
|
||||
fputs(
|
||||
"wdclink [flags] file ...\n\n"
|
||||
"Flags:\n"
|
||||
" -h show usage\n"
|
||||
" -v be verbose\n"
|
||||
" -X inhibit ExpressLoad segment\n"
|
||||
" -C inhibit SUPER records\n"
|
||||
" -S add stack segment\n"
|
||||
" -1 generate version 1 OMF File\n"
|
||||
" -o file specify outfile name\n"
|
||||
" -l library specify library\n"
|
||||
" -L path specify library path\n"
|
||||
" -t xx[:xxxx] specify file type\n",
|
||||
stdout
|
||||
);
|
||||
exit(rv);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "vCXL:l:o:t:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "vCXSL:l:o:t:")) != -1) {
|
||||
switch(c) {
|
||||
case 'h': usage(0); break;
|
||||
|
||||
case 'v': flags.v = true; break;
|
||||
case 'X': flags.X = true; break;
|
||||
case 'C': flags.C = true; break;
|
||||
case 'S': flags.S = true; break;
|
||||
|
||||
case '1': flags.omf_flags |= OMF_V1; break;
|
||||
case 'X': flags.omf_flags |= OMF_NO_EXPRESS; break;
|
||||
case 'C': flags.omf_flags |= OMF_NO_SUPER; break;
|
||||
|
||||
case 'o': flags.o = optarg; break;
|
||||
|
||||
case 'l': {
|
||||
if (*optarg) flags.l.emplace_back(optarg);
|
||||
break;
|
||||
@ -1676,7 +1696,6 @@ int main(int argc, char **argv) {
|
||||
flags.L.emplace_back(std::move(tmp));
|
||||
break;
|
||||
}
|
||||
case 'h': help(); break;
|
||||
case 't': {
|
||||
// -t xx[:xxxx] -- set file/auxtype.
|
||||
if (!parse_ft(optarg)) {
|
||||
@ -1685,17 +1704,19 @@ int main(int argc, char **argv) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case ':':
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
usage(EX_USAGE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0) usage();
|
||||
if (argc == 0) usage(EX_USAGE);
|
||||
|
||||
init();
|
||||
|
||||
@ -1759,10 +1780,9 @@ int main(int argc, char **argv) {
|
||||
flags.file_type = 0xb3;
|
||||
}
|
||||
|
||||
void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool compress, bool expressload);
|
||||
int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type);
|
||||
|
||||
save_omf(flags.o, omf_segments, !flags.C, !flags.X);
|
||||
save_omf(flags.o, omf_segments, flags.omf_flags);
|
||||
set_file_type(flags.o, flags.file_type, flags.aux_type);
|
||||
}
|
||||
|
||||
|
134
omf.cpp
134
omf.cpp
@ -17,6 +17,18 @@
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
enum class endian {
|
||||
#ifdef _WIN32
|
||||
little = 0,
|
||||
big = 1,
|
||||
native = little
|
||||
#else
|
||||
little = __ORDER_LITTLE_ENDIAN__,
|
||||
big = __ORDER_BIG_ENDIAN__,
|
||||
native = __BYTE_ORDER__
|
||||
#endif
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct omf_header {
|
||||
uint32_t bytecount = 0;
|
||||
@ -66,6 +78,87 @@ struct omf_express_header {
|
||||
static_assert(sizeof(omf_header) == 44, "OMF Header not packed");
|
||||
static_assert(sizeof(omf_express_header) == 48, "OMF Express Header not packed");
|
||||
|
||||
|
||||
static void swap(uint8_t &x) {}
|
||||
static void swap(uint16_t &x) {
|
||||
#if defined(__GNUC__)
|
||||
x = __builtin_bswap16(x);
|
||||
#else
|
||||
x = (x >> 8) | (x << 8);
|
||||
#endif
|
||||
}
|
||||
static void swap(uint32_t &x) {
|
||||
#if defined(__GNUC__)
|
||||
x = __builtin_bswap32(x);
|
||||
#else
|
||||
x = ((x & 0xff000000) >> 24) |
|
||||
((x & 0x00ff0000) >> 8) |
|
||||
((x & 0x0000ff00) << 8) |
|
||||
((x & 0x000000ff) << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void to_little(struct omf_header &h) {
|
||||
if (endian::native != endian::little) {
|
||||
swap(h.bytecount);
|
||||
swap(h.reserved_space);
|
||||
swap(h.length);
|
||||
swap(h.unused1);
|
||||
swap(h.lablen);
|
||||
swap(h.numlen);
|
||||
swap(h.version);
|
||||
swap(h.banksize);
|
||||
swap(h.kind);
|
||||
swap(h.unused2);
|
||||
swap(h.org);
|
||||
swap(h.alignment);
|
||||
swap(h.numsex);
|
||||
swap(h.unused3);
|
||||
swap(h.segnum);
|
||||
swap(h.entry);
|
||||
swap(h.dispname);
|
||||
swap(h.dispdata);
|
||||
}
|
||||
}
|
||||
|
||||
static void to_little(struct omf_express_header &h) {
|
||||
if (endian::native != endian::little) {
|
||||
swap(h.lconst_mark);
|
||||
swap(h.lconst_size);
|
||||
swap(h.reloc_mark);
|
||||
swap(h.reloc_size);
|
||||
swap(h.unused1);
|
||||
swap(h.lablen);
|
||||
swap(h.numlen);
|
||||
swap(h.version);
|
||||
swap(h.banksize);
|
||||
swap(h.kind);
|
||||
swap(h.unused2);
|
||||
swap(h.org);
|
||||
swap(h.alignment);
|
||||
swap(h.numsex);
|
||||
swap(h.unused3);
|
||||
swap(h.segnum);
|
||||
swap(h.entry);
|
||||
swap(h.dispname);
|
||||
swap(h.dispdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
v.push_back(x);
|
||||
}
|
||||
@ -194,7 +287,7 @@ enum {
|
||||
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< optional<super_helper>, 38 > ss;
|
||||
|
||||
@ -203,9 +296,9 @@ uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment
|
||||
|
||||
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) {
|
||||
constexpr int n = SUPER_RELOC2;
|
||||
|
||||
@ -267,9 +360,9 @@ uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment
|
||||
}
|
||||
|
||||
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) {
|
||||
constexpr int n = SUPER_INTERSEG1;
|
||||
@ -384,7 +477,7 @@ void save_bin(const std::string &path, omf::segment &segment, uint32_t org) {
|
||||
}
|
||||
|
||||
|
||||
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, unsigned flags) {
|
||||
|
||||
// expressload doesn't support links to other files.
|
||||
// fortunately, we don't either.
|
||||
@ -392,6 +485,17 @@ void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool
|
||||
std::vector<uint8_t> expr_headers;
|
||||
std::vector<unsigned> expr_offsets;
|
||||
|
||||
|
||||
bool compress = !(flags & OMF_NO_COMPRESS);
|
||||
bool super = !(flags & OMF_NO_SUPER);
|
||||
bool expressload = !(flags & OMF_NO_EXPRESS);
|
||||
bool v1 = flags & OMF_V1;
|
||||
|
||||
if (v1) {
|
||||
expressload = false;
|
||||
super = false;
|
||||
}
|
||||
|
||||
int fd;
|
||||
fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
||||
if (fd < 0) {
|
||||
@ -470,17 +574,13 @@ 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_size = 0;
|
||||
|
||||
reloc_size = add_relocs(data, data_offset, s, compress);
|
||||
reloc_size = add_relocs(data, data_offset, s, compress, super);
|
||||
|
||||
// end-of-record
|
||||
push(data, (uint8_t)omf::END);
|
||||
|
||||
h.bytecount = data.size() + sizeof(omf_header);
|
||||
|
||||
// todo -- byteswap to little-endian!
|
||||
offset += write(fd, &h, sizeof(h));
|
||||
offset += write(fd, data.data(), data.size());
|
||||
|
||||
if (expressload) {
|
||||
|
||||
expr_offsets.emplace_back(expr_headers.size());
|
||||
@ -514,6 +614,17 @@ void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool
|
||||
push(expr_headers, s.segname);
|
||||
}
|
||||
|
||||
if (v1) to_v1(h);
|
||||
to_little(h);
|
||||
|
||||
offset += write(fd, &h, sizeof(h));
|
||||
offset += write(fd, data.data(), data.size());
|
||||
|
||||
// version 1 needs 512-byte padding for all but final segment.
|
||||
if (v1 && &s != &segments.back()) {
|
||||
static uint8_t zero[512];
|
||||
offset += write(fd, zero, 512 - (offset & 511) );
|
||||
}
|
||||
}
|
||||
|
||||
if (expressload) {
|
||||
@ -553,6 +664,7 @@ void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool
|
||||
|
||||
h.bytecount = data.size() + sizeof(omf_header);
|
||||
|
||||
to_little(h);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, &h, sizeof(h));
|
||||
write(fd, data.data(), data.size());
|
||||
|
14
omf.h
14
omf.h
@ -5,6 +5,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace omf {
|
||||
|
||||
enum opcode : uint8_t {
|
||||
@ -78,4 +79,17 @@ namespace omf {
|
||||
|
||||
}
|
||||
|
||||
enum {
|
||||
// flags
|
||||
OMF_V1 = 1,
|
||||
OMF_V2 = 0,
|
||||
OMF_NO_SUPER = 2,
|
||||
OMF_NO_COMPRESS = 4,
|
||||
OMF_NO_EXPRESS = 8
|
||||
|
||||
};
|
||||
|
||||
void save_omf(const std::string &path, std::vector<omf::segment> &segments, unsigned flags);
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user