home *** CD-ROM | disk | FTP | other *** search
- /*
- * OMDS - The 99% solution for converting OMD output into assembleable sources.
- * ©1991, Mike Schwartz, all rights reserved.
- * Placed in the public domain, with the limitation that NO printed version
- * may be sold for ANY price.
- *
- * Description:
- * SAS C 5.10a comes with a program called OMD, which is capable of
- * disassembling object files created by the SAS C compiler. The
- * only drawback is that OMD prepares a "worthless" pretty listing
- * of the disassembly which is not suitable for use with an assembler.
- * The process of converting the output of OMD to source code by hand
- * is tedious and prone to human error, especially if a large number
- * of files need to be converted. This program will assist greatly
- * in the conversion process.
- *
- * Use:
- * First, you must compile your sources withe the C compiler using
- * at least -d1 (debugging info) option. Then you need to run OMD
- * on the .o file created by the compiler to create a listing file
- * (redirect stdout). Then you run OMDS on the listing file and
- * it will create an assemblable source file as output.
- *
- * Invocation:
- * OMD listingFile outputFile
- * Where:
- * listingFile is the output file from OMD
- * outputFile is the file that OMDS will write
- *
- * Limitations:
- * The SAS 'C' compiler sometimes creates code for twitch statements
- * that cause OMD to not disassemble correctly. OMDS will complain
- * about "syntax" of the listing file in this case. In order to get
- * an assemblable source file, the switch statement must be recoded
- * as if...else if .... else if ...
- *
- * Also, when OMD generates data for the initialized and uninitialized
- * data for the .o file, it generates a "hex dump" format in the listing
- * file. OMD has problems with this hex dump format when it looks like
- * this:
- * oooo xx xx xx xx gg .....
- * Where
- * oooo is a 4 digit hex offset
- * xx is a two digit hex number/value
- * gg (followed by a space) is the first three characters of
- * the ascii part of the hex dump
- * .... is the rest of the ascii part of the hex dump
- * The workaround for this problem is to edit the listing file
- * and delete the ascii portion of the hex dump altogether.
- *
- * Disclaimer:
- * The author makes no guarantees or warantees as to the correctness
- * or buglessness of the program. Sorry about the lack of comments,
- * but 'C' is a write-once language anyway :) It should compile with
- * no problems under Manx 'C', but who'd want to anyway :)
- */
- #include "exec/types.h"
- #include "fcntl.h"
- #include "stdio.h"
-
- typedef struct SYMBOL {
- char name[256];
- ULONG section;
- ULONG offset;
- } SYMBOL;
-
- #define MAXSYMS 1024
- SYMBOL *symArray;
- int nextSym = 0;
-
- FILE *infp, *outfp;
- char inbuf[256], *inp;
- char token[256], *tokp;
-
- int pass;
- int sect2Size = 0;
-
- BOOL getin() {
- if (!fgets(inbuf, 256, infp)) { inp = 0; return 0; }
- inbuf[strlen(inbuf)-1] = '\0';
- inp = &inbuf[0];
- return !0;
- }
-
- BOOL gettok() {
- char *outp = &token[0];
- short parenCnt = 0;
-
- while (*inp && (*inp == ' ' || *inp == '\t' || *inp == ',')) inp++;
- while (*inp && (*inp != ' ' && *inp != '\t')) {
- if (*inp == '(') parenCnt++;
- else if (*inp == ')') parenCnt--;
- else if (!parenCnt && *inp == ',') break;
- *outp++ = *inp++;
- }
- *outp = '\0';
- tokp = &token[0];
- return strlen(token) ? !0 : 0;
- }
-
- ULONG hex(c)
- char c;
- {
- if (c >= 'A' && c <= 'F') c = c-'A'+10;
- else if (c >= 'a' && c <= 'f') c = c-'a'+10;
- else c = c-'0';
- return (ULONG)c;
- }
-
- BOOL ishex(c)
- {
- if (c >= '0' && c <= '9') return !0;
- if (c >= 'A' && c <= 'F') return !0;
- if (c >= 'a' && c <= 'f') return !0;
- return 0;
- }
-
- ULONG htoi(s)
- char *s;
- {
- ULONG v = 0;
-
- while (ishex(*s)) {
- v <<= 4;
- v += hex(*s++);
- }
- return v;
- }
-
- char *branches[] = {
- "BCC", "BCS", "BEQ", "BGE", "BGT", "BHI", "BLE", "BLS", "BLT", "BMI", "BNE", "BPL", "BVC", "BVS", "BRA",
- "BSR",
- 0,
- };
-
- BOOL isbranch(b)
- char *b;
- {
- short i;
-
- for (i=0; branches[i]; i++)
- if (!strncmp(b, branches[i], 3)) return !0;
- return 0;
- }
-
- char *registers[] = {
- "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "SP",
- 0,
- };
-
- BOOL isregister(b)
- char *b;
- {
- short i;
-
- for (i=0; registers[i]; i++)
- if (!strncmp(b, registers[i], 2)) return !0;
- return 0;
- }
-
- void add_symbol(lab, sect, off)
- char *lab;
- ULONG sect;
- ULONG off;
- {
- SYMBOL *ps = &symArray[nextSym];
- short i;
-
- for (i=0; i<nextSym; i++) {
- if (sect != symArray[i].section || off != symArray[i].offset || strcmp(lab, symArray[i].name))
- continue;
- if (symArray[i].name[0] != '_') strcpy(symArray[i].name, lab);
- return;
- }
- if (nextSym >= MAXSYMS) {
- printf("too many symbols\n");
- exit(999);
- }
- strcpy(ps->name, lab);
- ps->section = sect;
- ps->offset = off;
- nextSym++;
- }
-
- SYMBOL *lookup_value(v, sect)
- ULONG v, sect;
- {
- short i;
-
- for (i=0; i<nextSym; i++)
- if (symArray[i].offset == v && symArray[i].section == sect) return &symArray[i];
- return 0;
- }
-
- void ParseExternalDefinitions() {
- char label[256];
- ULONG offset, section;
- int i;
- SYMBOL *ps;
-
- while (getin()) {
- if (strcmp(inbuf, "EXTERNAL DEFINITIONS")) continue;
- if (!getin()) break;
- while (getin() && strlen(inbuf)) {
- while (gettok()) {
- if (!token[0]) break;
- strcpy(label, token);
- if (!gettok()) {
- printf("error in EXTERNAL DEFINITIONS\n");
- exit(999);
- }
- offset = 0;
- while (*tokp != '-') offset = (offset<<4)+hex(*tokp++);
- tokp++;
- section = hex(*tokp++);
- section = (section*16)+hex(*tokp++);
- if (pass == 1) add_symbol(label, section, offset);
- }
- }
- if (pass == 2) return;
- for (i=0; i<nextSym; i++) {
- ps = &symArray[i];
- fprintf(outfp, "\t\tXDEF\t%s\t\t; sect: %d offset: %04x\n", ps->name, ps->section, ps->offset);
- }
- fprintf(outfp, "\n");
- return;
- }
- printf("No EXTERNAL DEFINITIONS found, OMD file must be incorrect!\n");
- exit(999);
- }
-
- void CheckOperand(op)
- char *op;
- {
- char work[256];
- SYMBOL *ps;
-
- if (!strncmp(op, "01.", 3)) {
- strcpy(work, "D");
- strcat(work, &op[3]);
- if (pass == 1) {
- if (!lookup_value(htoi(&op[3], 1))) add_symbol(work, 1, htoi(&op[3]));
- }
- else {
- if (ps = lookup_value(htoi(&op[3], 1)))
- strcpy(op, ps->name);
- else
- strcpy(op, work);
- }
- }
- else if (!strncmp(op, "02.", 3)) {
- strcpy(work, "B");
- strcat(work, &op[3]);
- if (pass == 1) {
- if (!lookup_value(htoi(&op[3], 2))) add_symbol(work, 2, htoi(&op[3]));
- }
- else {
- if (ps = lookup_value(htoi(&op[3], 2)))
- strcpy(op, ps->name);
- else
- strcpy(op, work);
- }
- }
- else if (!isregister(op) && ishex(op[0])) {
- strcpy(work, "$");
- strcat(work, op);
- strcpy(op, work);
- }
- }
-
- void ParseSection00() {
- ULONG offset;
- int i;
- char opcode[256], op1[256], op2[256];
-
- if (!getin()) {
- printf("Premature end of file in Section 00\n");
- exit(999);
- }
- if (strncmp(inbuf, "SECTION 00", 10)) {
- printf("Invalid text in Section00:\n%s\n", inbuf);
- exit(999);
- }
- while (getin()) {
- if (inbuf[0] == ';') { if (pass == 2) fprintf(outfp, "%s\n", inbuf); continue; }
- if (!gettok()) break;
- if (token[0] != '|' || !gettok()) {
- printf("Invalid text in Section00:\n%s\n", inbuf);
- exit(999);
- }
- offset = 0;
- while (*tokp) offset = (offset*16)+hex(*tokp++);
- tokp++;
- for (i=0; i<nextSym; i++) {
- if (symArray[i].section == 0 && offset == symArray[i].offset) {
- if (pass == 2) {
- if (strlen(symArray[i].name) < 8)
- fprintf(outfp, "%s\t\t", symArray[i].name);
- else
- fprintf(outfp, "%s\t", symArray[i].name);
- }
- break;
- }
- }
- if (pass == 2 && i >= nextSym) fprintf(outfp, "\t\t");
- inp = &inbuf[45];
- while (*inp != ' ') inp++;
- if (!gettok()) {
- printf("Invalid text in Section 00:\n%s\n", inbuf);
- exit(999);
- }
- strcpy(opcode, token);
- op1[0] = '\0';
- if (gettok()) strcpy(op1, token);
- op2[0] = '\0';
- if (gettok()) strcpy(op2, token);
-
- if (isbranch(opcode)) {
- SYMBOL *ps = lookup_value(htoi(op1));
-
- if (!ps) {
- strcpy(op2, "L");
- strcat(op2, op1);
- }
- else {
- strcpy(op2, ps->name);
- }
- if (pass == 1)
- add_symbol(op2, 0, htoi(op1));
- else
- fprintf(outfp, "%s\t%s\n", opcode, op2);
- continue;
- }
- if (op1[0] == '#')
- CheckOperand(&op1[1]);
- else
- CheckOperand(op1);
- if (op2[0] == '#')
- CheckOperand(&op2[1]);
- else
- CheckOperand(op2);
-
- if (pass == 1) continue;
- if (!op2[0])
- fprintf(outfp, "%s\t%s\n", opcode, op1);
- else
- fprintf(outfp, "%s\t%s,%s\n", opcode, op1, op2);
- }
- fprintf(outfp, "\n");
- }
-
- static ULONG dsoffset = 0;
-
- void DefineStorageByte() {
- SYMBOL *ps = lookup_value(dsoffset, 2);
-
- if (pass == 1) return;
- if (!ps) {
- fprintf(outfp, "\t\tDS.B\t1\t\t; offset = $%04x\n", dsoffset);
- }
- else if (strlen(ps->name)< 8) {
- fprintf(outfp, "%s\t\tDS.B\t1\t\t; offset = $%04x\n", ps->name, dsoffset);
- }
- else {
- fprintf(outfp, "%s\tDS.B\t1\t\t; offset = $%04x\n", ps->name, dsoffset);
- }
- dsoffset++;
- }
-
- static ULONG dcoffset = 0;
-
- void DefineConstantByte(c)
- UBYTE c;
- {
- SYMBOL *ps = lookup_value(dcoffset, 1);
-
- if (pass == 1) return;
- if (!ps) {
- fprintf(outfp, "\t\tDC.B\t$%02x\t\t; offset = $%04x\n", c, dcoffset);
- }
- else if (strlen(ps->name)< 8) {
- fprintf(outfp, "%s\t\tDC.B\t$%02x\t\t; offset = $%04x\n", ps->name, c, dcoffset);
- }
- else {
- fprintf(outfp, "%s\tDC.B\t$%02x\t\t; offset = $%04x\n", ps->name, c, dcoffset);
- }
- dcoffset++;
- }
-
- void DefineConstantLongName(name)
- char *name;
- {
- SYMBOL *ps = lookup_value(dcoffset, 1);
-
- if (pass == 1) return;
- if (!ps) {
- fprintf(outfp, "\t\tDC.L\t%s\t\t; offset = $%04x\n", name, dcoffset);
- }
- else if (strlen(ps->name)< 8) {
- fprintf(outfp, "%s\t\tDC.L\t%s\t\t; offset = $%04x\n", ps->name, name, dcoffset);
- }
- else {
- fprintf(outfp, "%s\tDC.L\t%s\t\t; offset = $%04x\n", ps->name, name, dcoffset);
- }
- dcoffset += 4;
- }
-
- void gettok01() {
- if (!gettok()) {
- printf("Syntax error ParseSection01:\n%s\n", inbuf);
- exit(999);
- }
- }
-
- void ParseSection01() {
- ULONG start, end;
-
- if (!getin()) return;
- if (!strncmp(inp, "SECTION 02", 10)) {
- if (pass == 2) fprintf(outfp, ";***** Uninitialized data\n\n");
- end = htoi(&inp[15]);
- for (start = 0; start<=end; start++) DefineStorageByte();
- return;
- }
- if (strncmp(inp, "SECTION 01", 10)) {
- printf("Syntax error ParseSection01: \n%s\n", inp);
- exit(999);
- }
- if (pass == 2) fprintf(outfp, ";***** Initialized data\n\n");
-
- while (getin() && strlen(inp)) {
- if (!strncmp(inp, "OFFSETS", 7)) {
- inp = &inp[7];
- gettok01();
- start = htoi(token);
- gettok01(); /* THROUGH */
- gettok01();
- end = htoi(token);
- while (start <= end) {
- DefineConstantByte(0); start++;
- }
- }
- else {
- gettok01(); /* hex offset */
- gettok01();
- if (strlen(token) != 2) { /* dc.l required */
- if (!gettok()) {
- printf("Syntax error parsesection01:\n%s\n", inbuf);
- exit(999);
- }
- CheckOperand(token);
- DefineConstantLongName(token);
- continue;
- }
- for (start=0; start<16; start++) {
- DefineConstantByte(htoi(token));
- if (!gettok()) break;
- if (strlen(token) != 2) break;
- }
- }
- }
- }
- void ParseSection02() {
- ULONG start, end;
-
- if (!getin()) return;
- if (!strncmp(inp, "SECTION 02", 10)) {
- if (pass == 2) fprintf(outfp, "\n;***** Uninitialized data\n\n");
- end = htoi(&inp[15]);
- for (start = 0; start<=end; start++) DefineStorageByte();
- }
- }
-
- main(ac, av)
- int ac;
- char *av[];
- {
- if (ac != 3) {
- printf("Usage: omds omdfile outfile\n");
- printf("\tconverts OMD output into assembly source\n");
- exit(999);
- }
- symArray = (SYMBOL *)malloc(MAXSYMS*sizeof(SYMBOL));
- if (!symArray) {
- printf("Insufficient memory\n");
- exit(999);
- }
- infp = fopen(av[1], "r");
- if (!infp) {
- printf("Can't open %s\n", av[1]);
- exit(999);
- }
- outfp = fopen(av[2], "w");
- if (!outfp) {
- printf("Can't open %s\n", av[2]);
- exit(999);
- }
- printf("Converting %s to %s\n", av[1], av[2]);
- fprintf(outfp, "; OMDS of file: %s\n\n", av[1]);
- pass = 1;
- ParseExternalDefinitions();
- ParseSection00();
- ParseSection01();
- ParseSection02();
- fclose(infp);
- infp = fopen(av[1], "r");
- if (!infp) {
- printf("Can't open %s\n", av[1]);
- exit(999);
- }
- pass = 2;
- ParseExternalDefinitions();
- ParseSection00();
- ParseSection01();
- ParseSection02();
- fclose(outfp);
- }
-
-