mirror of
https://github.com/ksherlock/wdc-utils.git
synced 2024-12-14 01:29:11 +00:00
.
This commit is contained in:
commit
9055a46c62
508
dumpobj.cpp
Normal file
508
dumpobj.cpp
Normal file
@ -0,0 +1,508 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <err.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "obj816.h"
|
||||||
|
|
||||||
|
enum class endian {
|
||||||
|
little = __ORDER_LITTLE_ENDIAN__,
|
||||||
|
big = __ORDER_BIG_ENDIAN__,
|
||||||
|
native = __BYTE_ORDER__
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
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<class T>
|
||||||
|
void le_to_host(T &value) {
|
||||||
|
swap_if(value, std::integral_constant<bool, endian::native == endian::big>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage() {
|
||||||
|
exit(EX_USAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct Header {
|
||||||
|
uint32_t h_magic; /* magic number for detection */
|
||||||
|
uint16_t h_version; /* version number of object format */
|
||||||
|
uint8_t h_filtyp; /* file type, object or library */
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
uint8_t read_8(T &iter) {
|
||||||
|
uint8_t tmp = *iter;
|
||||||
|
++iter;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
uint16_t read_16(T &iter) {
|
||||||
|
uint16_t tmp = 0;
|
||||||
|
|
||||||
|
tmp |= *iter << 0;
|
||||||
|
++iter;
|
||||||
|
tmp |= *iter << 8;
|
||||||
|
++iter;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
uint16_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<class T>
|
||||||
|
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<class T>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_obj(const char *name, int fd)
|
||||||
|
{
|
||||||
|
static const char *sections[] = { "PAGE0", "CODE", "KDATA", "DATA", "UDATA" };
|
||||||
|
static const char *types[] = { "S_UND", "S_ABS", "S_REL", "S_EXP", "S_REG", "S_FREG" };
|
||||||
|
|
||||||
|
Mod_head h;
|
||||||
|
ssize_t ok;
|
||||||
|
|
||||||
|
ok = read(fd, &h, sizeof(h));
|
||||||
|
if (ok != sizeof(h))
|
||||||
|
errx(EX_DATAERR, "%s is not an object file", name);
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// now read the name (h_namlen includes 0 terminator.)
|
||||||
|
std::vector<char> oname;
|
||||||
|
oname.resize(h.h_namlen);
|
||||||
|
ok = read(fd, oname.data(), h.h_namlen);
|
||||||
|
if (ok != h.h_namlen) errx(EX_DATAERR, "%s", name);
|
||||||
|
|
||||||
|
|
||||||
|
printf("name: %s\n", oname.data());
|
||||||
|
printf("record size: %04x\n", h.h_recsize);
|
||||||
|
printf("section size: %04x\n", h.h_secsize);
|
||||||
|
printf("symbol size: %04x\n", h.h_symsize);
|
||||||
|
printf("option size: %04x\n", h.h_optsize);
|
||||||
|
printf("number sections: %04x\n", h.h_num_secs);
|
||||||
|
printf("number symbols: %04x\n", h.h_num_syms);
|
||||||
|
|
||||||
|
// records [until record_eof]
|
||||||
|
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
data.resize(h.h_recsize);
|
||||||
|
ok = read(fd, data.data(), h.h_recsize);
|
||||||
|
if (ok != h.h_recsize) errx(EX_DATAERR, "%s truncated", name);
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t op = REC_END;
|
||||||
|
uint32_t pc = 0;
|
||||||
|
|
||||||
|
auto iter = data.begin();
|
||||||
|
while (iter != data.end()) {
|
||||||
|
|
||||||
|
op = read_8(iter);
|
||||||
|
if (op == 0) break;
|
||||||
|
if (op < 0xf0) {
|
||||||
|
iter += op;
|
||||||
|
pc += op;
|
||||||
|
printf("DATA: %02x\n", op);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(op) {
|
||||||
|
|
||||||
|
case REC_EXPR:
|
||||||
|
{
|
||||||
|
uint8_t bytes;
|
||||||
|
uint8_t op = 0;
|
||||||
|
bytes = read_8(iter);
|
||||||
|
|
||||||
|
printf("EXPR: %02x : ", bytes);
|
||||||
|
pc += bytes;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
op = read_8(iter);
|
||||||
|
if (op == OP_END) break;
|
||||||
|
switch (op) {
|
||||||
|
case OP_LOC: {
|
||||||
|
uint8_t section = read_8(iter);
|
||||||
|
uint32_t offset = read_32(iter);
|
||||||
|
if (section < sizeof(sections) / sizeof(sections[0]))
|
||||||
|
printf("%s+%04x ", sections[section], offset);
|
||||||
|
else
|
||||||
|
printf("section %02x+%04x ", section, offset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OP_VAL:
|
||||||
|
printf("%04x ", read_32(iter));
|
||||||
|
break;
|
||||||
|
case OP_SYM:
|
||||||
|
printf("symbol %02x ", read_16(iter));
|
||||||
|
break;
|
||||||
|
case OP_SHR: printf(">> "); break;
|
||||||
|
case OP_SHL: printf("<< "); break;
|
||||||
|
default:
|
||||||
|
printf("\n");
|
||||||
|
errx(EX_DATAERR, "%s: unknown expression opcode %02x", name, op);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REC_DEBUG:
|
||||||
|
{
|
||||||
|
|
||||||
|
static const char *debugs[] = {
|
||||||
|
"D_C_FILE",
|
||||||
|
"D_C_LINE",
|
||||||
|
"D_C_SYM",
|
||||||
|
"D_C_STAG",
|
||||||
|
"D_C_ETAG",
|
||||||
|
"D_C_UTAG",
|
||||||
|
"D_C_MEMBER",
|
||||||
|
"D_C_EOS",
|
||||||
|
"D_C_FUNC",
|
||||||
|
"D_C_ENDFUNC",
|
||||||
|
"D_C_BLOCK",
|
||||||
|
"D_C_ENDBLOCK",
|
||||||
|
"D_LONGA_ON",
|
||||||
|
"D_LONGA_OFF",
|
||||||
|
"D_LONGI_ON",
|
||||||
|
"D_LONGI_OFF",
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t size = read_16(iter);
|
||||||
|
printf("\t;DEBUG\n");
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < size; ++i) {
|
||||||
|
uint8_t op = read_8(iter);
|
||||||
|
switch(op) {
|
||||||
|
case D_LONGA_ON:
|
||||||
|
printf("\tlonga\ton\n");
|
||||||
|
break;
|
||||||
|
case D_LONGA_OFF:
|
||||||
|
printf("\tlonga\toff\n");
|
||||||
|
break;
|
||||||
|
case D_LONGI_ON:
|
||||||
|
printf("\tlongi\ton\n");
|
||||||
|
break;
|
||||||
|
case D_LONGI_OFF:
|
||||||
|
printf("\tlongi\toff\n");
|
||||||
|
break;
|
||||||
|
case D_C_FILE: {
|
||||||
|
std::string s = read_cstring(iter);
|
||||||
|
uint16_t line = read_16(iter);
|
||||||
|
printf("\t.file\t\"%s\",%d\n", s.c_str(), line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case D_C_LINE: {
|
||||||
|
uint16_t line = read_16(iter);
|
||||||
|
printf("\t.line\t%d\n", line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case D_C_BLOCK: {
|
||||||
|
uint16_t block = read_16(iter);
|
||||||
|
printf("\t.block\t%d\n", block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case D_C_SYM: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
errx(EX_DATAERR, "%s: unknown debug opcode %02x", name, op);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REC_SECT: {
|
||||||
|
uint8_t section = read_8(iter);
|
||||||
|
printf("\t.sect\t%d\n", section);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REC_SPACE:
|
||||||
|
case REC_ORG:
|
||||||
|
case REC_RELEXP:
|
||||||
|
case REC_LINE:
|
||||||
|
default:
|
||||||
|
errx(EX_DATAERR, "%s: unknown opcode %02x", name, op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter != data.end() || op != REC_END) errx(EX_DATAERR, "%s records ended early", name);
|
||||||
|
|
||||||
|
|
||||||
|
// section info
|
||||||
|
|
||||||
|
data.resize(h.h_secsize);
|
||||||
|
ok = read(fd, data.data(), h.h_secsize);
|
||||||
|
if (ok != h.h_secsize) errx(EX_DATAERR, "%s truncated", name);
|
||||||
|
|
||||||
|
printf("\nSections\n");
|
||||||
|
|
||||||
|
iter = data.begin();
|
||||||
|
while (iter != data.end()) {
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t number = read_8(iter);
|
||||||
|
uint8_t flags = read_8(iter);
|
||||||
|
uint32_t size = read_32(iter);
|
||||||
|
uint32_t org = read_32(iter);
|
||||||
|
|
||||||
|
printf("section %d\n", number);
|
||||||
|
printf("flags: %02x ", flags);
|
||||||
|
|
||||||
|
#undef _
|
||||||
|
#define _(x) if (flags & x) fputs(#x " ", stdout)
|
||||||
|
_(SEC_OFFSET);
|
||||||
|
_(SEC_INDIRECT);
|
||||||
|
_(SEC_STACKED);
|
||||||
|
_(SEC_REF_ONLY);
|
||||||
|
_(SEC_CONST);
|
||||||
|
_(SEC_DIRECT);
|
||||||
|
_(SEC_NONAME);
|
||||||
|
fputs("\n", stdout);
|
||||||
|
|
||||||
|
// todo -- section name -- cstring?
|
||||||
|
//assert(flags & SEC_NONAME);
|
||||||
|
std::string s;
|
||||||
|
if (!(flags & SEC_NONAME)) s = read_cstring(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// symbol info
|
||||||
|
data.resize(h.h_symsize);
|
||||||
|
ok = read(fd, data.data(), h.h_symsize);
|
||||||
|
if (ok != h.h_symsize) errx(EX_DATAERR, "%s truncated", name);
|
||||||
|
|
||||||
|
printf("\nSymbols\n");
|
||||||
|
|
||||||
|
iter = data.begin();
|
||||||
|
while (iter != data.end()) {
|
||||||
|
uint8_t type = read_8(iter);
|
||||||
|
uint8_t flags = read_8(iter);
|
||||||
|
uint8_t section = read_8(iter);
|
||||||
|
uint32_t offset = type == S_UND ? 0 : read_32(iter);
|
||||||
|
std::string name = read_cstring(iter);
|
||||||
|
|
||||||
|
printf("name: %s\n", name.c_str());
|
||||||
|
printf("type: %02x %s\n", type, type < sizeof(types) / sizeof(types[0]) ? types[type] : "");
|
||||||
|
printf("flags: %02x ", flags);
|
||||||
|
#undef _
|
||||||
|
#define _(x) if (flags & x) fputs(#x " ", stdout)
|
||||||
|
_(SF_GBL);
|
||||||
|
_(SF_DEF);
|
||||||
|
_(SF_REF);
|
||||||
|
_(SF_VAR);
|
||||||
|
_(SF_PG0);
|
||||||
|
_(SF_TMP);
|
||||||
|
_(SF_DEF2);
|
||||||
|
_(SF_LIB);
|
||||||
|
fputs("\n", stdout);
|
||||||
|
printf("section: %02x %s\n", section,
|
||||||
|
section < sizeof(sections) / sizeof(sections[0]) ? sections[section] : "");
|
||||||
|
if (type != S_UND)
|
||||||
|
printf("offset: %04x\n", offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void dump_lib(const char *name, int fd)
|
||||||
|
{
|
||||||
|
Lib_head h;
|
||||||
|
ssize_t ok;
|
||||||
|
|
||||||
|
ok = read(fd, &h, sizeof(h));
|
||||||
|
if (ok != sizeof(h))
|
||||||
|
errx(EX_DATAERR, "%s is not an object file", name);
|
||||||
|
|
||||||
|
|
||||||
|
le_to_host(h.l_magic);
|
||||||
|
le_to_host(h.l_version);
|
||||||
|
le_to_host(h.l_filtyp);
|
||||||
|
le_to_host(h.l_modstart);
|
||||||
|
le_to_host(h.l_numsyms);
|
||||||
|
le_to_host(h.l_symsize);
|
||||||
|
le_to_host(h.l_numfiles);
|
||||||
|
|
||||||
|
assert(h.l_magic == MOD_MAGIC);
|
||||||
|
assert(h.l_version == 1);
|
||||||
|
assert(h.l_filtyp == 2);
|
||||||
|
|
||||||
|
printf("modstart: %04x\n", h.l_modstart);
|
||||||
|
printf("number symbols: %04x\n", h.l_numsyms);
|
||||||
|
printf("number files: %04x\n", h.l_numfiles);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
long count = h.l_modstart - sizeof(h);
|
||||||
|
if (count < 0) errx(EX_DATAERR, "%s", name);
|
||||||
|
data.reserve(count);
|
||||||
|
ok = read(fd, data.data(), count);
|
||||||
|
if (ok != count) errx(EX_DATAERR, "%s truncated", name);
|
||||||
|
|
||||||
|
|
||||||
|
// files
|
||||||
|
auto iter = data.begin();
|
||||||
|
for (int i = 0; i < h.l_numfiles; ++i) {
|
||||||
|
uint16_t file_number = read_16(iter);
|
||||||
|
std::string s = read_pstring(iter);
|
||||||
|
printf("%02x %s\n", file_number, s.c_str());
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// symbols
|
||||||
|
auto name_iter = iter + h.l_numsyms * 8;
|
||||||
|
for (int i = 0; i < h.l_numsyms; ++i) {
|
||||||
|
uint16_t name_offset = read_16(iter);
|
||||||
|
uint16_t file_number = read_16(iter);
|
||||||
|
uint32_t offset = read_32(iter);
|
||||||
|
std::string name = read_pstring(name_iter);
|
||||||
|
|
||||||
|
printf("symbol: %04x %s\n", i, name.c_str());
|
||||||
|
//printf("name offset: %02x\n", name_offset);
|
||||||
|
printf("file_number: %02x\n", file_number);
|
||||||
|
printf("module offset: %04x\n", offset);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < h.l_numfiles; ++i) {
|
||||||
|
dump_obj(name, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump(const char *name) {
|
||||||
|
Header h;
|
||||||
|
int fd;
|
||||||
|
ssize_t ok;
|
||||||
|
|
||||||
|
fd = open(name, O_RDONLY);
|
||||||
|
if (fd < 0) err(EX_NOINPUT, "Unable to open %s", name);
|
||||||
|
|
||||||
|
|
||||||
|
ok = read(fd, &h, sizeof(h));
|
||||||
|
if (ok != sizeof(h))
|
||||||
|
errx(EX_DATAERR, "%s is not an object file", name);
|
||||||
|
|
||||||
|
le_to_host(h.h_magic);
|
||||||
|
le_to_host(h.h_version);
|
||||||
|
le_to_host(h.h_filtyp);
|
||||||
|
|
||||||
|
if (h.h_magic != MOD_MAGIC || h.h_version != 1 || h.h_filtyp > 2)
|
||||||
|
errx(EX_DATAERR, "%s is not an object file", name);
|
||||||
|
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
if (h.h_filtyp == 1) dump_obj(name, fd);
|
||||||
|
else dump_lib(name, fd);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = getopt(argc, argv, "")) != -1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
argv += optind;
|
||||||
|
argc -= optind;
|
||||||
|
|
||||||
|
if (argc == 0) usage();
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; ++i) {
|
||||||
|
dump(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
175
obj816.h
Normal file
175
obj816.h
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
#define VERS " 3.01 " /* version number for programs */
|
||||||
|
#define CDATE "1992-1997" /* copyright date for programs */
|
||||||
|
|
||||||
|
typedef struct Mod_head {
|
||||||
|
uint32_t h_magic; /* magic number for detection */
|
||||||
|
uint16_t h_version; /* version number of object format */
|
||||||
|
uint8_t h_filtyp; /* file type, object or library */
|
||||||
|
uint8_t h_namlen; /* length of module name */
|
||||||
|
uint32_t h_recsize; /* sizeof records section */
|
||||||
|
uint16_t h_secsize; /* sizeof section section */
|
||||||
|
uint32_t h_symsize; /* sizeof symbol section */
|
||||||
|
uint16_t h_optsize; /* sizeof options section */
|
||||||
|
uint8_t h_tot_secs; /* total number of sections in module */
|
||||||
|
uint8_t h_num_secs; /* number of sections referenced */
|
||||||
|
uint16_t h_num_syms; /* number of symbols */
|
||||||
|
} Mod_head;
|
||||||
|
|
||||||
|
typedef struct Lib_head {
|
||||||
|
uint32_t l_magic; /* magic number for detection */
|
||||||
|
uint16_t l_version; /* version number of object format */
|
||||||
|
uint8_t l_filtyp; /* file type, object or library */
|
||||||
|
uint8_t l_unused1;
|
||||||
|
uint32_t l_modstart; /* offset of modules start */
|
||||||
|
uint32_t l_numsyms; /* number of symbol entries */
|
||||||
|
uint32_t l_symsize; /* sizeof symbol section */
|
||||||
|
uint32_t l_numfiles; /* number of files */
|
||||||
|
} Lib_head;
|
||||||
|
|
||||||
|
#define MOD_CONVERT "lwbblslsbbw"
|
||||||
|
#define LIB_CONVERT "lwbbllll"
|
||||||
|
|
||||||
|
#define MOD_REC_OFF(x) (sizeof(x)+x.h_namlen)
|
||||||
|
#define MOD_SEC_OFF(x) (MOD_REC_OFF(x)+x.h_recsize)
|
||||||
|
#define MOD_SYM_OFF(x) (MOD_SEC_OFF(x)+x.h_secsize)
|
||||||
|
#define MOD_OPT_OFF(x) (MOD_SYM_OFF(x)+x.h_symsize)
|
||||||
|
#define MOD_NEXT_OFF(x) (MOD_OPT_OFF(x)+x.h_optsize)
|
||||||
|
|
||||||
|
#define MOD_MAGIC 0x5a44525a /* 'ZRDZ' */
|
||||||
|
#define MOD_VERSION 1
|
||||||
|
#define MOD_OBJECT 1
|
||||||
|
#define MOD_LIBRARY 2
|
||||||
|
#define MOD_OBJ68K 3
|
||||||
|
|
||||||
|
#define REC_END 0
|
||||||
|
/* 1-xx are numbers of constant data bytes */
|
||||||
|
#define REC_SECT 0xf0 /* next word is section number */
|
||||||
|
#define REC_EXPR 0xf1 /* expression follows */
|
||||||
|
#define REC_SPACE 0xf2 /* word count of bytes to reserve */
|
||||||
|
#define REC_ORG 0xf3 /* long word new pc */
|
||||||
|
#define REC_RELEXP 0xf4 /* pc-relative expression */
|
||||||
|
#define REC_DEBUG 0xf5 /* debug info record */
|
||||||
|
#define REC_LINE 0xf6 /* bump line counter */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
OP_END=0, /* end of expression */
|
||||||
|
OP_SYM, /* ref to extern symbol */
|
||||||
|
OP_VAL, /* constant value */
|
||||||
|
OP_LOC, /* ref to offset from start of section */
|
||||||
|
|
||||||
|
OP_UNA=10,
|
||||||
|
OP_NOT=10,
|
||||||
|
OP_NEG,
|
||||||
|
OP_FLP,
|
||||||
|
|
||||||
|
OP_BIN=20,
|
||||||
|
OP_EXP=20, OP_MUL, OP_DIV, OP_MOD, OP_SHR,
|
||||||
|
OP_SHL, OP_ADD, OP_SUB, OP_AND, OP_OR,
|
||||||
|
OP_XOR, OP_EQ, OP_GT, OP_LT, OP_UGT,
|
||||||
|
OP_ULT,
|
||||||
|
OP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { S_UND, S_ABS, S_REL, S_EXP, S_REG, S_FREG }; /* symbol type */
|
||||||
|
enum { ST_NOSIZE, ST_8BIT, ST_16BIT, ST_32BIT,
|
||||||
|
ST_FLOAT, ST_DOUBLE, ST_8051, ST_Z8, ST_DS, ST_EQU };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
D_C_FILE=100,
|
||||||
|
D_C_LINE,
|
||||||
|
D_C_SYM,
|
||||||
|
D_C_STAG,
|
||||||
|
D_C_ETAG,
|
||||||
|
D_C_UTAG,
|
||||||
|
D_C_MEMBER,
|
||||||
|
D_C_EOS,
|
||||||
|
D_C_FUNC,
|
||||||
|
D_C_ENDFUNC,
|
||||||
|
D_C_BLOCK,
|
||||||
|
D_C_ENDBLOCK,
|
||||||
|
D_LONGA_ON,
|
||||||
|
D_LONGA_OFF,
|
||||||
|
D_LONGI_ON,
|
||||||
|
D_LONGI_OFF
|
||||||
|
};
|
||||||
|
|
||||||
|
/* used for generating source level debugging information */
|
||||||
|
|
||||||
|
enum { DT_NON, DT_PTR, DT_FCN, DT_ARY, DT_FPTR, DT_FFCN };
|
||||||
|
enum { T_NULL, T_VOID, T_SCHAR, T_CHAR, T_SHORT, T_INT16, T_INT32, T_LONG,
|
||||||
|
T_FLOAT, T_DOUBLE, T_STRUCT, T_UNION, T_ENUM, T_LDOUBLE,
|
||||||
|
T_UCHAR, T_USHORT, T_UINT16, T_UINT32, T_ULONG };
|
||||||
|
enum { C_NULL, C_AUTO, C_EXT, C_STAT, C_REG, C_EXTDEF, C_ARG,
|
||||||
|
C_STRTAG, C_MOS, C_EOS, C_UNTAG, C_MOU, C_ENTAG, C_MOE,
|
||||||
|
C_TPDEF, C_USTATIC, C_REGPARM, C_FIELD, C_UEXT, C_STATLAB,
|
||||||
|
C_EXTLAB, C_BLOCK, C_EBLOCK, C_FUNC, C_EFUNC, C_FILE, C_LINE,
|
||||||
|
C_FRAME };
|
||||||
|
|
||||||
|
|
||||||
|
#define SF_GBL 0x01 /* label is global */
|
||||||
|
#define SF_DEF 0x02 /* label is defined in this module */
|
||||||
|
#define SF_REF 0x04 /* label is referenced in this module */
|
||||||
|
#define SF_VAR 0x08 /* label is variable */
|
||||||
|
#define SF_PG0 0x10 /* label is Page0 type */
|
||||||
|
#define SF_TMP 0x20 /* label is temporary (LLCHAR) */
|
||||||
|
#define SF_DEF2 0x40 /* label has been defined in pass 2 ( ZAS only ) */
|
||||||
|
#define SF_LIB 0x40 /* label in library (used by ZLN) */
|
||||||
|
|
||||||
|
#define SEC_OFFSET 0x0001
|
||||||
|
#define SEC_INDIRECT 0x0002
|
||||||
|
#define SEC_STACKED 0x0004
|
||||||
|
#define SEC_REF_ONLY 0x0008
|
||||||
|
#define SEC_CONST 0x0010
|
||||||
|
#define SEC_DIRECT 0x0020
|
||||||
|
#define SEC_NONAME 0x0040
|
||||||
|
|
||||||
|
/* pre-defined sections */
|
||||||
|
enum {SECT_PAGE0, SECT_CODE, SECT_KDATA, SECT_DATA, SECT_UDATA };
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module format:
|
||||||
|
Module header
|
||||||
|
s: Module name (null terminated)
|
||||||
|
Records
|
||||||
|
Each record is in stack order terminated by REC_END
|
||||||
|
Section info
|
||||||
|
Section info format: --- for each section that has references
|
||||||
|
b: section number
|
||||||
|
b: section flags
|
||||||
|
l: size
|
||||||
|
l: org
|
||||||
|
s: name of section (only if SEC_NONAME not in flags)
|
||||||
|
Symbol info
|
||||||
|
Symbol info format: --- for each symbol
|
||||||
|
b: type
|
||||||
|
b: flags
|
||||||
|
b: section number
|
||||||
|
l: offset (only if type != S_UND)
|
||||||
|
s: name of symbol (null terminated)
|
||||||
|
|
||||||
|
Library format:
|
||||||
|
Library header
|
||||||
|
File info - for each file
|
||||||
|
w: file number
|
||||||
|
b: file name len
|
||||||
|
c: file name (no null)
|
||||||
|
Symbol data - for each symbol
|
||||||
|
w: offset of name
|
||||||
|
w: file number
|
||||||
|
l: module offset - Hdr.l_modstart
|
||||||
|
Symbol names - for each symbol
|
||||||
|
b: length of name
|
||||||
|
c: symbol name (no null)
|
||||||
|
Modules - each module
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************/
|
||||||
|
/* End of File OBJ816.H */
|
||||||
|
/**************************************************/
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
116
wdclib.1
Normal file
116
wdclib.1
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
.Dd December 24, 2016
|
||||||
|
.Dt WDCLIB 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm wdclib
|
||||||
|
.Nd WDC Librarian
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl F Ar argfile
|
||||||
|
.Op Fl A | D | L | S | X
|
||||||
|
.Ar library
|
||||||
|
.Op Ar objfile ...
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
is a utility program that manipulates libraries of object modules.
|
||||||
|
.Nm
|
||||||
|
makes it possible to create a library of commonly used functions. This
|
||||||
|
library can be very efficiently searched and any modules required by the
|
||||||
|
program can be extracted from the library and placed in the output file.
|
||||||
|
.Pp
|
||||||
|
Since several object
|
||||||
|
modules may be contained in the same original source file,
|
||||||
|
.Nm
|
||||||
|
keeps track of the name of the file that each module comes from.
|
||||||
|
This allows all the modules associated with a file to be manipulated
|
||||||
|
without tediously typing in the name of each module. Options may be
|
||||||
|
specified individually or together.
|
||||||
|
.Sh OPTIONS
|
||||||
|
.Bl -tag -width indent
|
||||||
|
.It Fl A
|
||||||
|
This option tells
|
||||||
|
.Nm
|
||||||
|
to add the specified files to the library. The symbol dictionary is updated
|
||||||
|
to include the names of symbols defined in the object modules in the files.
|
||||||
|
If none of the options
|
||||||
|
.Fl A , D ,
|
||||||
|
or
|
||||||
|
.Fl X
|
||||||
|
are given, the default is to assume option
|
||||||
|
.Fl A .
|
||||||
|
To create a library from a set of object files, use the command:
|
||||||
|
.Pp
|
||||||
|
.Dl WDCLIB -A MYLIB.LIB LIBSRC1.OBJ LIBSRC2.OBJ LIBSRC3.OBJ
|
||||||
|
.Pp
|
||||||
|
which will create a library file called
|
||||||
|
.Ar MYLIB.LIB
|
||||||
|
and add all the modules
|
||||||
|
from the three object files. If
|
||||||
|
.Ar MYLIB.LIB
|
||||||
|
already existed, the modules
|
||||||
|
from the three object files will be added to the library.
|
||||||
|
.It Fl D
|
||||||
|
The modules in the library that originally came from the named files are
|
||||||
|
deleted from the library. Modules must be deleted before being replaced
|
||||||
|
with new ones.
|
||||||
|
.Pp
|
||||||
|
The following example shows how to remove the modules associated with an
|
||||||
|
object file.
|
||||||
|
.Pp
|
||||||
|
.Dl WDCLIB -D MYLIB.LIB LIBSRC3.OBJ
|
||||||
|
.Pp
|
||||||
|
All of the modules associated with the file
|
||||||
|
.Ar LIBSRC3.OBJ
|
||||||
|
will be deleted from the library.
|
||||||
|
.Pp
|
||||||
|
This example shows how to replace a file in a library.
|
||||||
|
.Pp
|
||||||
|
.Dl WDCLIB -D MYLIB.LIB LIBSRC2.OBJ
|
||||||
|
.Dl WDCLIB -A MYLIB.LIB LIBSRC2.OBJ
|
||||||
|
.Pp
|
||||||
|
The modules associated with
|
||||||
|
.Ar LIBSRC2.OBJ
|
||||||
|
will first be deleted from the library and then added from the new version
|
||||||
|
of the file. The following options display information about the library
|
||||||
|
file after the modification arguments, if any, have been processed.
|
||||||
|
.It Fl F
|
||||||
|
This option must be followed by the name of a text file. The file will be
|
||||||
|
read and arguments will be extracted from the file. When the end of file
|
||||||
|
is reached, additional arguments are again extracted from the command
|
||||||
|
line. This allows more object modules than will fit on the standard command
|
||||||
|
line to be processed at one time.
|
||||||
|
.Pp
|
||||||
|
For example, these commands add all files with a
|
||||||
|
.Ar .OBJ
|
||||||
|
extension to the library.
|
||||||
|
.Pp
|
||||||
|
.Dl DIR *.OBJ > OBJLIST
|
||||||
|
.Dl WDCLIB -A MYLIB.LIB -F OBJLIST
|
||||||
|
.It Fl L
|
||||||
|
This option causes a list of the files in the library to be printed.
|
||||||
|
Associated with each file name is a file number. This number will also
|
||||||
|
appear in the symbol listing which indicates which file contains the
|
||||||
|
module that defines that symbol. This command will display the names
|
||||||
|
of all files added to a library.
|
||||||
|
.Pp
|
||||||
|
.Dl WDCLIB -L MYLIB.LIB
|
||||||
|
.Pp
|
||||||
|
This command adds two files to the library.
|
||||||
|
.Pp
|
||||||
|
.Dl WDCLIB -AL MYLIB.LIB LIBSRC1.OBJ LIBSRC2.OBJ
|
||||||
|
.Pp
|
||||||
|
After the files are added, a list of all the files in the library will
|
||||||
|
be printed.
|
||||||
|
.It Fl S
|
||||||
|
This option causes the dictionary of symbols contained in the library to
|
||||||
|
be printed. The dictionary is printed in alphabetical order. The number
|
||||||
|
of the file that defined the symbol along with the offset into the
|
||||||
|
library of the module that defined it are printed beside the symbol name.
|
||||||
|
.It Fl X
|
||||||
|
The modules in the library that originally came from the named files
|
||||||
|
are extracted from the library and placed into files with the same
|
||||||
|
name. After extraction, the modules in the library are deleted.
|
||||||
|
.Pp
|
||||||
|
The following example extracts two files from a library.
|
||||||
|
.Pp
|
||||||
|
.Dl WDCLIB -X MYLIB.LIB LIBSRC3.OBJ LIBSRC1.OBJ
|
Loading…
Reference in New Issue
Block a user