Added 'objdump.c' for dumping the text segment of NED a.out files as a binary blob. master origin/HEAD origin/master
authorAaron Taylor <ataylor@subgeniuskitty.com>
Mon, 12 Jul 2021 05:08:10 +0000 (22:08 -0700)
committerAaron Taylor <ataylor@subgeniuskitty.com>
Mon, 12 Jul 2021 05:08:10 +0000 (22:08 -0700)
Using this for the NEDsim screensaver.

misc/objdump.c [new file with mode: 0644]

diff --git a/misc/objdump.c b/misc/objdump.c
new file mode 100644 (file)
index 0000000..609c335
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * © 2021 Aaron Taylor <ataylor at subgeniuskitty dot com>
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#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 <file> -o <file>\n"
+            "  -h                      Help (prints this message)\n"
+            "  -i <file>               Specify NED a.out format input file.\n"
+            "  -o <file>               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);
+}