From: Aaron Taylor Date: Mon, 12 Jul 2021 05:08:10 +0000 (-0700) Subject: Added 'objdump.c' for dumping the text segment of NED a.out files as a binary blob. X-Git-Url: http://git.subgeniuskitty.com/ned1/.git/commitdiff_plain Added 'objdump.c' for dumping the text segment of NED a.out files as a binary blob. Using this for the NEDsim screensaver. --- diff --git a/misc/objdump.c b/misc/objdump.c new file mode 100644 index 0000000..609c335 --- /dev/null +++ b/misc/objdump.c @@ -0,0 +1,151 @@ +/* + * © 2021 Aaron Taylor + * See LICENSE.txt file for copyright and license details. + */ + +/* + * This program dumps the text segment of a NED1 a.out format executable as a + * binary blob. + */ + +#include +#include +#include +#include +#include +#include + +#include "../common/a.out.h" + +#define VERSION 1 + +void +print_usage(char ** argv) +{ + printf( "NED objdump v%d (www.subgeniuskitty.com)\n" + "Usage: %s -i -o \n" + " -h Help (prints this message)\n" + " -i Specify NED a.out format input file.\n" + " -o Specify output filename for binary blob.\n" + , VERSION, argv[0] + ); +} + +void +die(FILE * in, FILE * out, const char * msg) +{ + fclose(in); + fclose(out); + fprintf(stderr, "%s\n", msg); + exit(EXIT_FAILURE); +} + +void +dump_aout_file(FILE * in_file, FILE * out_file) +{ + uint32_t read_count = 0; + struct exec aout_exec; + + /* 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, in_file); break; + case 1: read_count = fread(&(aout_exec.a_text), 4, 1, in_file); break; + case 2: read_count = fread(&(aout_exec.a_data), 4, 1, in_file); break; + case 3: read_count = fread(&(aout_exec.a_bss), 4, 1, in_file); break; + case 4: read_count = fread(&(aout_exec.a_syms), 4, 1, in_file); break; + case 5: read_count = fread(&(aout_exec.a_entry), 4, 1, in_file); break; + case 6: read_count = fread(&(aout_exec.a_trsize), 4, 1, in_file); break; + case 7: read_count = fread(&(aout_exec.a_drsize), 4, 1, in_file); break; + } + if (read_count != 1) { + die(in_file, out_file, "ERROR: Invalid a.out header."); + } + } + if (N_BADMAG(aout_exec)) { + die(in_file, out_file, "ERROR: Invalid magic number in a.out header."); + } else if (N_GETMID(aout_exec) != MID_NED) { + die(in_file, out_file, "ERROR: Executable not intended for NED Machine ID."); + } + + /* Read in the text segment. */ + uint32_t text_segment_size = (N_DATOFF(aout_exec) - N_TXTOFF(aout_exec)); + uint8_t * text_segment = malloc(text_segment_size); + read_count = fread(text_segment, 1, text_segment_size, in_file); + if (read_count != text_segment_size) { + die(in_file, out_file, "ERROR: Failed to read entire text segment."); + } + + /* Correct the byte order. */ + for (uint32_t i=0; i < (text_segment_size / 4); i++) { + uint8_t temp_word[4]; + for (uint8_t j=0; j<4; j++) temp_word[j] = text_segment[((i*4)+j)]; + for (uint8_t j=0; j<4; j++) text_segment[((i*4)+j)] = temp_word[(3-j)]; + } + + /* Write text segment to file. */ + uint32_t write_count = fwrite(text_segment, text_segment_size, 1, out_file); + if (write_count != 1) { + die(in_file, out_file, "ERROR: Unable to write to output file."); + } + + /* Clean up and return */ + free(text_segment); +} + +int +main(int argc, char ** argv) +{ + /* + * Process command line arguments + */ + int c; + FILE * in_file = NULL; + FILE * out_file = NULL; + while ((c = getopt(argc, argv, "hi:o:")) != -1) { + switch (c) { + case 'i': + if ((in_file = fopen(optarg, "r")) == NULL) { + fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + break; + case 'o': + if ((out_file = fopen(optarg, "wx")) == NULL) { + fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + break; + case 'h': + print_usage(argv); + exit(EXIT_SUCCESS); + break; + default: + print_usage(argv); + exit(EXIT_FAILURE); + break; + } + } + if (in_file == NULL) { + fprintf(stderr, "ERROR: Must specify NED1 a.out format file with -i flag.\n"); + print_usage(argv); + exit(EXIT_FAILURE); + } + if (out_file == NULL) { + fprintf(stderr, "ERROR: Must specify destination file with -o flag.\n"); + print_usage(argv); + exit(EXIT_FAILURE); + } + + /* + * Perform the conversion + */ + dump_aout_file(in_file, out_file); + + /* + * Clean up and terminate + */ + fclose(in_file); + fclose(out_file); + exit(EXIT_SUCCESS); +}