X-Git-Url: https://git.subgeniuskitty.com/ned1/.git/blobdiff_plain/bc5b63cf94c1f263bbe3757237b242f40711203b..dc87d2445f5e13146058bd672ad8399fad9e73fb:/neddis/neddis.c diff --git a/neddis/neddis.c b/neddis/neddis.c index 96256d0..306666e 100644 --- a/neddis/neddis.c +++ b/neddis/neddis.c @@ -8,8 +8,11 @@ #include #include #include +#include -#define VERSION 1 +#include "../common/a.out.h" + +#define VERSION 2 enum syllables { MVSTCK = 0b00001111, @@ -60,6 +63,8 @@ print_usage(char ** argv) "Usage: %s -i \n" " -h Help (prints this message)\n" " -i Specify a binary image file to disassemble.\n" + " -s Print summary of information in a.out exec header.\n" + " -l Print labels and organize disassembled code by label.\n" , VERSION, argv[0] ); } @@ -160,6 +165,110 @@ print_formatC_mnemonics(uint32_t word) } } +void +parse_aout_file(FILE * input, struct exec * aout_exec, uint32_t ** text_segment, + struct nlist ** symbol_table, uint32_t * symbol_count) +{ + uint32_t read_count = 0; + + /* Read in and check the a.out header. */ + for (uint32_t i=0; i<8; i++) { + switch (i) { + case 0: read_count = fread(&(aout_exec->a_midmag), 4, 1, input); break; + case 1: read_count = fread(&(aout_exec->a_text), 4, 1, input); break; + case 2: read_count = fread(&(aout_exec->a_data), 4, 1, input); break; + case 3: read_count = fread(&(aout_exec->a_bss), 4, 1, input); break; + case 4: read_count = fread(&(aout_exec->a_syms), 4, 1, input); break; + case 5: read_count = fread(&(aout_exec->a_entry), 4, 1, input); break; + case 6: read_count = fread(&(aout_exec->a_trsize), 4, 1, input); break; + case 7: read_count = fread(&(aout_exec->a_drsize), 4, 1, input); break; + } + if (read_count != 1) { + fprintf(stderr, "ERROR: Invalid a.out header.\n"); + exit(EXIT_FAILURE); + } + } + if (N_BADMAG(*aout_exec)) { + fprintf(stderr, "ERROR: Invalid magic number in a.out header.\n"); + exit(EXIT_FAILURE); + } else if (N_GETMID(*aout_exec) != MID_NED) { + fprintf(stderr, "ERROR: Executable not intended for NED Machine ID.\n"); + exit(EXIT_FAILURE); + } + + /* Read in the text segment. */ + uint32_t text_segment_size = (N_DATOFF(*aout_exec) - N_TXTOFF(*aout_exec)); + *text_segment = malloc(text_segment_size + 4); + (*text_segment)[0] = text_segment_size / 4; + read_count = fread(&((*text_segment)[1]), 1, text_segment_size, input); + if (read_count != text_segment_size) { + fprintf(stderr, "ERROR: Failed to read entire text segment.\n"); + exit(EXIT_FAILURE); + } + + /* Read in the symbol table. */ + *symbol_count = ((N_STROFF(*aout_exec) - N_SYMOFF(*aout_exec)) / 20); /* 20 bytes per symbol. */ + *symbol_table = malloc((*symbol_count) * sizeof(struct nlist)); + for (uint32_t i=0; i < *symbol_count; i++) { + for (uint32_t j=0; j<5; j++) { + switch (j) { + case 0: read_count = fread(&((*symbol_table)[i].n_un.n_strx), 4, 1, input); break; + case 1: read_count = fread(&((*symbol_table)[i].n_type), 4, 1, input); break; + case 2: read_count = fread(&((*symbol_table)[i].n_other), 4, 1, input); break; + case 3: read_count = fread(&((*symbol_table)[i].n_desc), 4, 1, input); break; + case 4: read_count = fread(&((*symbol_table)[i].n_value), 4, 1, input); break; + } + if (read_count != 1) { + fprintf(stderr, "ERROR: Unable to read entire symbol table.\n"); + exit(EXIT_FAILURE); + } + } + } + + /* Read in the string table and update the symbol table entries with pointers to new strings. */ + uint32_t string_table_size; + read_count = fread(&string_table_size, 4, 1, input); + if (read_count != 1) { + fprintf(stderr, "ERROR: Failed to read string table size.\n"); + exit(EXIT_FAILURE); + } + for (uint32_t i=0; i < *symbol_count; i++) { + uint32_t len = 0; + if (i < ((*symbol_count)-1)) { + len = ((*symbol_table)[i+1].n_un.n_strx - (*symbol_table)[i].n_un.n_strx); + } else { + len = (string_table_size - (*symbol_table)[i].n_un.n_strx); + } + (*symbol_table)[i].n_un.n_name = malloc(len); + read_count = fread((*symbol_table)[i].n_un.n_name, 1, len, input); + if (read_count != len) { + fprintf(stderr, "ERROR: Failed to read a string from the string table.\n"); + exit(EXIT_FAILURE); + } + } +} + +void +print_aout_summary(struct exec * aout_exec) +{ + printf("\n Summary\n" + " =====================================\n" + " Magic: 0x%08x\n" + " Machine ID: 0x%08x\n" + " Flags: 0x%08x\n" + " Text Size: 0x%08x bytes\n" + " Data Size: 0x%08x bytes\n" + " BSS Size: 0x%08x bytes\n" + " Symbol Table Size: 0x%08x bytes\n" + " Entry Point: 0x%08x\n" + " Text Reloc. Size: 0x%08x bytes\n" + " Data Reloc. Size: 0x%08x bytes\n\n\n", + N_GETMAGIC(*aout_exec), N_GETMID(*aout_exec), N_GETFLAG(*aout_exec), + aout_exec->a_text, aout_exec->a_data, aout_exec->a_bss, aout_exec->a_syms, + aout_exec->a_entry, aout_exec->a_trsize, aout_exec->a_drsize + ); +} + int main(int argc, char ** argv) { @@ -168,8 +277,16 @@ main(int argc, char ** argv) */ int c; FILE * input = NULL; - while ((c = getopt(argc,argv,"i:h")) != -1) { + bool display_summary = false; + bool display_labels = false; + while ((c = getopt(argc,argv,"i:hsl")) != -1) { switch (c) { + case 'l': + display_labels = true; + break; + case 's': + display_summary = true; + break; case 'i': if ((input = fopen(optarg, "r")) == NULL) { fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno)); @@ -189,14 +306,33 @@ main(int argc, char ** argv) exit(EXIT_FAILURE); } + struct exec aout_exec; + uint32_t * text_segment; + struct nlist * symbol_table; + uint32_t symbol_count; + parse_aout_file(input, &aout_exec, &text_segment, &symbol_table, &symbol_count); + + if (display_summary) print_aout_summary(&aout_exec); + /* * Main Loop */ + print_header(); uint32_t word; - uint32_t offset = 0; + uint32_t offset = aout_exec.a_entry; /* Since all NED instructions are one word (4 bytes) wide, read in one word increments. */ - while (fread(&word, 4, 1, input)) { + uint32_t i = 1; + while (i < text_segment[0]) { + if (display_labels) { + for (uint32_t i=0; i < symbol_count; i++) { + if (offset == symbol_table[i].n_value) { + printf("\n%s:\n", symbol_table[i].n_un.n_name); + } + } + } + word = text_segment[i]; + i++; printf("0x%08x", offset); printf(" "); printf("0x%08x", word);