mirror of
https://github.com/ksherlock/wdc-utils.git
synced 2024-12-12 19:30:38 +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