Create a.out executables
authorRobert Pengelly <robertapengelly@hotmail.com>
Sat, 8 Jun 2024 17:07:30 +0000 (18:07 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Sat, 8 Jun 2024 17:07:30 +0000 (18:07 +0100)
aout.c
aout.h
ld.c
ld.h
lib.c

diff --git a/aout.c b/aout.c
index c2d6e9125916a0f3fd7d6f8fb7bc7048ae5e2b68..27cf88dc97de03f0551fa6517d8ca3cfff3c1f09 100644 (file)
--- a/aout.c
+++ b/aout.c
@@ -27,6 +27,8 @@ typedef     signed int                  int32_t;
 static unsigned long header_size = 0, output_size = 0;
 static void *data = 0, *output = 0, *text = 0;
 
+static struct aout_exec *aout_hdr;
+
 
 struct gr {
 
@@ -85,6 +87,22 @@ static int get_symbol (struct aout_object **obj_out, long *index, const char *na
 
 }
 
+static unsigned long get_entry (void) {
+
+    struct aout_object *symobj;
+    long symidx;
+    
+    if (get_symbol (&symobj, &symidx, state->entry, 1)) {
+    
+        report_at (program_name, 0, REPORT_WARNING, "cannot find entry symbol %s; defaulting to 00000000", state->entry);
+        return 0;
+    
+    }
+    
+    return GET_UINT32 (symobj->symtab[symidx].n_value);
+
+}
+
 static void number_to_chars (unsigned char *p, unsigned long number, unsigned long size) {
     
     unsigned long i;
@@ -358,9 +376,9 @@ static int relocate (struct aout_object *object, struct relocation_info *r, int
             r_symbolnum = GET_UINT32 (r->r_symbolnum) & (3L << 29);
             r_address = GET_INT32 (r->r_address);
             
-            if (((r_symbolnum >> 28) & 0xff) != N_ABS) {
+            if (/*state->format == LD_FORMAT_I386_AOUT || */((r_symbolnum >> 28) & 0xff) != N_ABS) {
             
-                if (state->format == LD_OUTPUT_BIN || state->format == LD_OUTPUT_COM) {
+                if (state->format == LD_FORMAT_BIN || state->format == LD_FORMAT_COM) {
                 
                     report_at (object->filename, 0, REPORT_ERROR, "segment relocation at %04x:%04x", r_address / 0xffff, r_address % 0xffff);
                     return 1;
@@ -462,23 +480,106 @@ static int glue (struct aout_object *object) {
 }
 
 
-int create_executable_from_aout_objects (void) {
+static int init_aout_object (void) {
 
-    struct aout_object *object;
-    long i;
+    header_size = sizeof (*aout_hdr);
     
-    int err = 0;
-    output_size = state->text_size + state->data_size;
+    if (!state->impure) {
+        header_size = ALIGN_UP (header_size, SECTION_ALIGNMENT);
+    }
+    
+    output_size = header_size + state->text_size + state->data_size;
     
     if ((output = malloc (output_size)) == NULL) {
-        return EXIT_FAILURE;
+        return 1;
     }
     
     memset (output, 0, output_size);
+    aout_hdr = output;
     
-    text = (void *) (char *) output;
+    text = (void *) ((char *) output + header_size);
     data = (void *) ((char *) text + state->text_size);
     
+    return 0;
+
+}
+
+static int write_aout_object (unsigned long a_entry) {
+
+    write741_to_byte_array (aout_hdr->a_info, state->impure ? OMAGIC : ZMAGIC);
+    write741_to_byte_array (aout_hdr->a_text, state->text_size);
+    write741_to_byte_array (aout_hdr->a_data, state->data_size);
+    write741_to_byte_array (aout_hdr->a_bss, state->bss_size);
+    write741_to_byte_array (aout_hdr->a_entry, a_entry);
+    write741_to_byte_array (aout_hdr->a_trsize, tgr.relocations_count * sizeof (struct relocation_info));
+    write741_to_byte_array (aout_hdr->a_drsize, dgr.relocations_count * sizeof (struct relocation_info));
+    
+    if (fwrite ((char *) output, output_size, 1, state->ofp) != 1) {
+    
+        report_at (program_name, 0, REPORT_ERROR, "failed to write data to '%s'", state->ofile);
+        return 1;
+    
+    }
+    
+    if (tgr.relocations_count > 0) {
+    
+        if (fwrite (tgr.relocations, tgr.relocations_count * sizeof (struct relocation_info), 1, state->ofp) != 1) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to write text relocations to '%s'", state->ofile);
+            return 1;
+        
+        }
+    
+    }
+    
+    if (dgr.relocations_count > 0) {
+    
+        if (fwrite (dgr.relocations, dgr.relocations_count * sizeof (struct relocation_info), 1, state->ofp) != 1) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to write data relocations to '%s'", state->ofile);
+            return 1;
+        
+        }
+    
+    }
+    
+    return 0;
+
+}
+
+
+int create_executable_from_aout_objects (void) {
+
+    struct aout_object *object;
+    long i;
+    
+    unsigned long entry = 0;
+    int err = 0;
+    
+    if (state->format == LD_FORMAT_BIN || state->format == LD_FORMAT_COM) {
+    
+        output_size = state->text_size + state->data_size;
+        
+        if ((output = malloc (output_size)) == NULL) {
+            return EXIT_FAILURE;
+        }
+        
+        memset (output, 0, output_size);
+        
+        text = (void *) (char *) output;
+        data = (void *) ((char *) text + state->text_size);
+    
+    } else if (state->format == LD_FORMAT_I386_AOUT) {
+    
+        if (init_aout_object ()) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to initialize a.out object");
+            return EXIT_FAILURE;
+        
+        }
+    
+    }
+    
     for (i = 0; i < state->nb_aout_objs; ++i) {
         paste (state->aout_objs[i]);
     }
@@ -503,7 +604,13 @@ int create_executable_from_aout_objects (void) {
     
     }
     
-    if (err) { return EXIT_FAILURE; }
+    if (err) {
+        return EXIT_FAILURE;
+    }
+    
+    if (state->format == LD_FORMAT_I386_AOUT) {
+        entry = get_entry ();
+    }
     
     for (i = 0; i < state->nb_aout_objs; i++) {
     
@@ -538,10 +645,23 @@ int create_executable_from_aout_objects (void) {
     
     }
     
-    if (fwrite ((char *) output, output_size, 1, state->ofp) != 1) {
+    if (state->format == LD_FORMAT_BIN || state->format == LD_FORMAT_COM) {
     
-        report_at (program_name, 0, REPORT_ERROR, "failed to write data to '%s'", state->ofile);
-        return EXIT_FAILURE;
+        if (fwrite ((char *) output, output_size, 1, state->ofp) != 1) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to write data to '%s'", state->ofile);
+            return EXIT_FAILURE;
+        
+        }
+    
+    } else if (state->format == LD_FORMAT_I386_AOUT) {
+    
+        if (write_aout_object (entry)) {
+        
+            report_at (program_name, 0, REPORT_ERROR, "failed to write a.out object");
+            return EXIT_FAILURE;
+        
+        }
     
     }
     
diff --git a/aout.h b/aout.h
index 885ff80a258f325a29e4f39c967cc5eb80eee351..e30be07f58b4b49600cce9271955c5225cd73798 100644 (file)
--- a/aout.h
+++ b/aout.h
@@ -41,6 +41,21 @@ struct nlist {
 
 };
 
+#define     OMAGIC                      0407
+#define     ZMAGIC                      0413
+
+/*struct aout_nlist {
+
+    unsigned char n_strx[4];
+    unsigned char n_type;
+    
+    unsigned char n_other;
+    unsigned char n_desc[2];
+    
+    unsigned char n_value[4];
+
+};*/
+
 #define     N_TYPE                      0x1e
 int create_executable_from_aout_objects (void);
 
diff --git a/ld.c b/ld.c
index 76eaa15daa72b8cffe837ca68575142aa768cd14..f9612a513dc3ab5ad1c13b697ae9554cb3e97845 100644 (file)
--- a/ld.c
+++ b/ld.c
@@ -651,13 +651,17 @@ int main (int argc, char **argv) {
     
     }
     
+    if (!state->entry || strcmp (state->entry, "") == 0) {
+        state->entry = "_start";
+    }
+    
     if (!state->ofile) {
         state->ofile = xstrdup ("a.out");
     }
     
-    if (state->format == LD_OUTPUT_BIN || state->format == LD_OUTPUT_COM) {
+    if (state->format == LD_FORMAT_BIN || state->format == LD_FORMAT_COM) {
     
-        if (state->format == LD_OUTPUT_COM) {
+        if (state->format == LD_FORMAT_COM) {
             state->psp = 0x100;
         }
         
diff --git a/ld.h b/ld.h
index 741a068bb5e3b191dbb6392e3f0d7096599c4f03..5c1f393ff0ef7ff53d83e2feeb510f0a6f4677c9 100644 (file)
--- a/ld.h
+++ b/ld.h
@@ -44,11 +44,13 @@ struct ld_state {
     long nb_aout_objs;
     
     unsigned long text_size, data_size, bss_size;
+    char *entry;
 
 };
 
-#define     LD_OUTPUT_COM               0x00
-#define     LD_OUTPUT_BIN               0x01
+#define     LD_FORMAT_COM               0x00
+#define     LD_FORMAT_BIN               0x01
+#define     LD_FORMAT_I386_AOUT         0x02
 
 extern struct ld_state *state;
 extern const char *program_name;
diff --git a/lib.c b/lib.c
index 07fb4f6b357fdfcea95f1631558341bfe98d6418..f92ad155561598a1b1664f39ec1950acf1b27646 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -27,14 +27,17 @@ struct ld_option {
 #define     LD_OPTION_HAS_ARG           1
 
 #define     LD_OPTION_NONE              0
-#define     LD_OPTION_FORMAT            1
-#define     LD_OPTION_HELP              2
-#define     LD_OPTION_IMPURE            3
-#define     LD_OPTION_MAP               4
-#define     LD_OPTION_OUTFILE           5
+#define     LD_OPTION_ENTRY             1
+#define     LD_OPTION_FORMAT            2
+#define     LD_OPTION_HELP              3
+#define     LD_OPTION_IMPURE            4
+#define     LD_OPTION_MAP               5
+#define     LD_OPTION_OUTFILE           6
 
 static struct ld_option opts[] = {
 
+    {   "-N",           LD_OPTION_IMPURE,       LD_OPTION_NO_ARG    },
+    {   "-e",           LD_OPTION_ENTRY,        LD_OPTION_HAS_ARG   },
     {   "-o",           LD_OPTION_OUTFILE,      LD_OPTION_HAS_ARG   },
     
     {   "--oformat",    LD_OPTION_FORMAT,       LD_OPTION_HAS_ARG   },
@@ -53,13 +56,13 @@ static void print_usage (void) {
         fprintf (stderr, "Options:\n\n");
         
         fprintf (stderr, "    -N                    Do not page align data.\n");
-        /*fprintf (stderr, "    -T OFFSET             Offset addresses by the specified offset\n");*/
+        /*fprintf (stderr, "    -T OFFSET             Offset addresses by the specified offset.\n");*/
         
         fprintf (stderr, "    --oformat FORMAT      Specify the format of output file (default msdos)\n");
         fprintf (stderr, "                              Supported formats are:\n");
-        fprintf (stderr, "                                  binary, msdos\n");
+        fprintf (stderr, "                                  a.out-i386, binary, msdos\n");
         
-        /*fprintf (stderr, "    -e ADDRESS            Set start address.\n");*/
+        fprintf (stderr, "    -e ADDRESS            Set start address.\n");
         fprintf (stderr, "    -s                    Ignored.\n");
         
         fprintf (stderr, "    -o FILE               Set output file name (default a.out).\n");
@@ -219,18 +222,36 @@ void parse_args (int argc, char **argv, int optind) {
         
         switch (popt->idx) {
         
+            case LD_OPTION_ENTRY: {
+            
+                if (state->entry) {
+                    free (state->entry);
+                }
+                
+                state->entry = xstrdup (optarg);
+                break;
+            
+            }
+            
             case LD_OPTION_FORMAT: {
             
                 if (xstrcasecmp (optarg, "binary") == 0) {
                 
-                    state->format = LD_OUTPUT_BIN;
+                    state->format = LD_FORMAT_BIN;
                     break;
                 
                 }
                 
                 if (xstrcasecmp (optarg, "msdos") == 0) {
                 
-                    state->format = LD_OUTPUT_COM;
+                    state->format = LD_FORMAT_COM;
+                    break;
+                
+                }
+                
+                if (xstrcasecmp (optarg, "a.out-i386") == 0) {
+                
+                    state->format = LD_FORMAT_I386_AOUT;
                     break;
                 
                 }