FreeCalypso > hg > freecalypso-reveng
changeset 308:f8344bc4fd61
dspanal: char2coff utility written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 28 Oct 2019 05:20:50 +0000 |
parents | 8e816bba2ff7 |
children | 493f73198267 |
files | .hgignore dspanal/Makefile dspanal/char2coff.c dspanal/charparse.c dspanal/coffout.c dspanal/coffout.h |
diffstat | 6 files changed, 474 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Mon Oct 28 02:37:47 2019 +0000 +++ b/.hgignore Mon Oct 28 05:20:50 2019 +0000 @@ -22,6 +22,7 @@ ^compal/osmovoodoo ^dspanal/char2bin$ +^dspanal/char2coff$ ^dspanal/patchanal$ ^leo-obj/.*\.ctypes$
--- a/dspanal/Makefile Mon Oct 28 02:37:47 2019 +0000 +++ b/dspanal/Makefile Mon Oct 28 05:20:50 2019 +0000 @@ -1,14 +1,19 @@ CC= gcc CFLAGS= -O2 -PROGS= char2bin patchanal +SIMPLE= char2bin patchanal +CMPLX= char2coff +PROGS= ${SIMPLE} ${CMPLX} all: ${PROGS} -${PROGS}: +${SIMPLE}: ${CC} ${CFLAGS} -o $@ $@.c char2bin: char2bin.c patchanal: patchanal.c +char2coff: char2coff.o charparse.o coffout.o + ${CC} ${CFLAGS} -o $@ $^ + clean: rm -f ${PROGS} *.o *errs *.out
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dspanal/char2coff.c Mon Oct 28 05:20:50 2019 +0000 @@ -0,0 +1,93 @@ +/* + * This program will convert C char array files into COFF + * for disassembly analysis. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include "coffout.h" + +extern unsigned read_char_file(); + +static u_char binbuffer[300000]; +static unsigned array_size; +static u_char *array_ptr, *array_end; + +#define MAX_SECTIONS 256 + +static struct coff_section sections[MAX_SECTIONS]; +static unsigned nsections; + +static void +add_section(addr, size, data) + uint32_t addr, size; + u_char *data; +{ + struct coff_section *sec; + + if (nsections >= MAX_SECTIONS) { + fprintf(stderr, "error: too many sections\n"); + exit(1); + } + sec = sections + nsections; + sec->addr = addr; + sec->size = size; + sec->data = data; + sec->flags = 0x0020; + sec->mempage = 0x00; + nsections++; +} + +static uint32_t +get_longword() +{ + uint32_t datum; + + if (array_ptr + 4 > array_end) { + fprintf(stderr, "error: parse spills past end of array\n"); + exit(1); + } + datum = (array_ptr[3] << 24) | (array_ptr[2] << 16) | + (array_ptr[1] << 8) | array_ptr[0]; + array_ptr += 4; + return datum; +} + +main(argc, argv) + char **argv; +{ + uint32_t addr, size; + + if (argc != 3) { + fprintf(stderr, "usage: %s char-array-file coff-output-file\n", + argv[0]); + exit(1); + } + array_size = read_char_file(argv[1], binbuffer, sizeof binbuffer); + array_ptr = binbuffer; + array_end = array_ptr + array_size; + if (get_longword() != 0) { + fprintf(stderr, "error: initial tag 0 is missing\n"); + exit(1); + } + if (get_longword() != 3) { + fprintf(stderr, "error: initial vers 3 is missing\n"); + exit(1); + } + for (;;) { + size = get_longword(); + if (size > 0x10000) { + fprintf(stderr, "error: section size unreasonable\n"); + exit(1); + } + addr = get_longword(); + if (!size) + break; + add_section(addr, size, array_ptr); + array_ptr += size << 1; + } + emit_coff_output(argv[2], sections, nsections); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dspanal/charparse.c Mon Oct 28 05:20:50 2019 +0000 @@ -0,0 +1,297 @@ +/* + * This module reads C char array files; it will be linked into programs + * that do further processing. + */ + +#include <sys/types.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +/* lexer tokens */ +#define WORD 256 +#define NUMBER 257 +#define HEXBYTE 258 + +/* limits */ +#define MAXWORD 63 +#define MAXDIGITS 5 + +static char *parser_filename; +static FILE *parser_readF; +static int parser_lineno; +static char parser_read_word[MAXWORD+1]; +static int parser_read_number; + +static void +parse_error(msg) + char *msg; +{ + fprintf(stderr, "%s line %d: %s\n", parser_filename, parser_lineno, + msg); + exit(1); +} + +static +my_getchar() +{ + register int c; + + c = getc(parser_readF); + if (c < 0) + return(c); + if (!isascii(c)) + parse_error("non-ASCII character"); + if (iscntrl(c) && c != '\n' && c != '\t') + parse_error("invalid control character"); + return(c); +} + +static void +handle_trad_comment() +{ + register int c, flag; + + for (flag = 0; ; ) { + c = my_getchar(); + if (c < 0) + parse_error("/* comment ends in EOF"); + if (c == '\n') + parser_lineno++; + if (c == '/' && flag) + return; + flag = (c == '*'); + } +} + +static void +handle_line_comment() +{ + register int c; + + for (;;) { + c = my_getchar(); + if (c < 0) + parse_error("// comment ends in EOF"); + if (c == '\n') { + parser_lineno++; + return; + } + } +} + +static void +handle_comment() +{ + int c; + + c = my_getchar(); + switch (c) { + case '*': + /* traditional C comment style */ + handle_trad_comment(); + return; + case '/': + /* new-fangled double slash comment style */ + handle_line_comment(); + return; + default: + parse_error("character after '/' is not '*' or '/'"); + exit(1); + } +} + +static void +handle_num_token(first_digit) +{ + register int c, n; + + parser_read_number = first_digit - '0'; + for (n = 1; ; n++) { + c = my_getchar(); + if (!isdigit(c)) + break; + parser_read_number *= 10; + parser_read_number += c - '0'; + } + if (c >= 0) { + if (isalpha(c) || c == '_') + parse_error( + "digits followed by letters: neither word nor number"); + ungetc(c, parser_readF); + } + if (n > MAXDIGITS) + parse_error("number is too long (MAXDIGITS exceeded)"); +} + +static int +decode_hex_digit(c) + register int c; +{ + if (isdigit(c)) + return(c - '0'); + else if (isupper(c)) + return(c - 'A' + 10); + else + return(c - 'a' + 10); +} + +static void +handle_hex_token() +{ + register int c, n; + + c = my_getchar(); + if (c != 'x' && c != 'X') + parse_error("\'0\' not followed by \'x\'"); + parser_read_number = 0; + for (n = 0; n < 2; n++) { + c = my_getchar(); + if (!isxdigit(c)) + parse_error("0x not followed by two hex digits"); + parser_read_number <<= 4; + parser_read_number += decode_hex_digit(c); + } +} + +static void +handle_word_token(first_char) +{ + register int c; + register char *cp; + register int len; + + cp = parser_read_word; + *cp++ = first_char; + for (len = 1; ; ) { + c = my_getchar(); + if (!isalnum(c) && c != '_') + break; + if (len >= MAXWORD) + parse_error("text token is too long"); + *cp++ = c; + len++; + } + *cp = '\0'; + if (c < 0) + return; + ungetc(c, parser_readF); +} + +static int +get_token() +{ + register int c; + +loop: c = my_getchar(); + switch (c) { + case EOF: + return(0); + case ' ': + case '\t': + goto loop; + case '\n': + parser_lineno++; + goto loop; + case '/': + handle_comment(); + goto loop; + case ',': + case ';': + case '=': + case '[': + case ']': + case '{': + case '}': + return(c); + case '0': + handle_hex_token(); + return(HEXBYTE); + } + if (isdigit(c)) { + handle_num_token(c); + return(NUMBER); + } + if (isalpha(c) || c == '_') { + handle_word_token(c); + return(WORD); + } + fprintf(stderr, "%s line %d: bad character \'%c\'\n", parser_filename, + parser_lineno, c); + exit(1); +} + +unsigned +read_char_file(filename, outbuf, buflimit) + char *filename; + u_char *outbuf; + unsigned buflimit; +{ + register int t; + u_char *outptr; + unsigned bytecnt; + + parser_filename = filename; + parser_readF = fopen(parser_filename, "r"); + if (!parser_readF) { + perror(parser_filename); + exit(1); + } + parser_lineno = 1; + t = get_token(); + if (t != WORD || strcmp(parser_read_word, "const")) + parse_error("expected \"const\" keyword"); + t = get_token(); + if (t != WORD || strcmp(parser_read_word, "unsigned")) + parse_error("expected \"unsigned\" keyword"); + t = get_token(); + if (t != WORD || strcmp(parser_read_word, "char")) + parse_error("expected \"char\" keyword"); + t = get_token(); + if (t != WORD) + parse_error("expected char array name"); + t = get_token(); + if (t != '[') + parse_error("expected \'[\'"); + t = get_token(); + if (t == NUMBER) + t = get_token(); + if (t != ']') + parse_error("expected \']\'"); + t = get_token(); + if (t != '=') + parse_error("expected \'=\'"); + t = get_token(); + if (t != '{') + parse_error("expected \'{\'"); + /* get first hex byte */ + t = get_token(); + if (t != HEXBYTE) + parse_error("expected first hex byte"); + outptr = outbuf; + *outptr++ = parser_read_number; + bytecnt = 1; + for (;;) { + t = get_token(); + if (t == '}') + break; + if (t != ',') + parse_error("expected comma between bytes"); + t = get_token(); + if (t == '}') + break; + if (t != HEXBYTE) + parse_error("expected next hex byte"); + if (bytecnt >= buflimit) + parse_error("buffer limit exceeded"); + *outptr++ = parser_read_number; + bytecnt++; + } + t = get_token(); + if (t != ';') + parse_error("expected terminating \';\'"); + fclose(parser_readF); + return bytecnt; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dspanal/coffout.c Mon Oct 28 05:20:50 2019 +0000 @@ -0,0 +1,69 @@ +#include <sys/types.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include "coffout.h" + +static FILE *outF; + +static void +write16(val) + unsigned val; +{ + putc(val, outF); + putc(val >> 8, outF); +} + +static void +write32(val) + unsigned val; +{ + putc(val, outF); + putc(val >> 8, outF); + putc(val >> 16, outF); + putc(val >> 24, outF); +} + +emit_coff_output(filename, sections, nsect) + char *filename; + struct coff_section *sections; + unsigned nsect; +{ + uint32_t dataptr; + unsigned n; + char section_name[32]; + + outF = fopen(filename, "w"); + if (!outF) { + perror(filename); + exit(1); + } + write16(0x00C1); + write16(nsect); + write32(0); + write32(0); + write32(0); + write16(0); + write16(0x0117); + write16(0x0098); + dataptr = 0x22 + 0x28 * nsect; + for (n = 0; n < nsect; n++) { + sprintf(section_name, "chunk%03u", n); + fwrite(section_name, 1, 8, outF); + write32(sections[n].addr); + write32(sections[n].addr); + write32(sections[n].size); + write32(dataptr); + dataptr += sections[n].size << 1; + write32(0); + write32(0); + write32(0); + write16(sections[n].flags); + putc(0, outF); + putc(sections[n].mempage, outF); + } + for (n = 0; n < nsect; n++) + fwrite(sections[n].data, 2, sections[n].size, outF); + fclose(outF); + return(0); +}