Added -m for emulation and based checks around that instead of format
authorRobert Pengelly <robertapengelly@hotmail.com>
Thu, 17 Apr 2025 04:57:26 +0000 (05:57 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Thu, 17 Apr 2025 04:57:26 +0000 (05:57 +0100)
ld.h
lib.c
link.c

diff --git a/ld.h b/ld.h
index fd9d8719364fd4745082d2b1333d1d42ca19e8c7..5f1296dd193101c47548eecac1983ae314b81757 100644 (file)
--- a/ld.h
+++ b/ld.h
@@ -24,9 +24,22 @@ struct ld_state {
     unsigned long size_of_headers;
     
     int generate_symbols_table;
+    int emulation;
 
 };
 
+
+#define     LD_EMULATION_NONE           0x00
+
+#define     LD_EMULATION_IA16_ELKS      0x01
+#define     LD_EMULATION_IA16_MZ        0x02
+
+#define     LD_EMULATION_I386_AOUT      0x03
+#define     LD_EMULATION_I386_COFF      0x04
+#define     LD_EMULATION_I386_ELKS      0x05
+#define     LD_EMULATION_I386_PE        0x06
+
+
 #define     LD_FORMAT_COM               0x00
 #define     LD_FORMAT_MZ                0x01
 #define     LD_FORMAT_BIN               0x02
@@ -39,6 +52,7 @@ struct ld_state {
 
 #define     LD_FORMAT_I386_PE           0x07
 
+
 extern struct ld_state *state;
 extern const char *program_name;
 
diff --git a/lib.c b/lib.c
index fc1976fef3ff6b8e38dceb3431329c142454b8f8..7edc8bcb11aa7a03e4e6980fb4353af07ea0a164 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -33,14 +33,15 @@ static struct options_with_use fmt_tbl[] = {
 
 #define     LD_OPTION_IGNORED                               0
 #define     LD_OPTION_EMIT_RELOCS                           1
-#define     LD_OPTION_ENTRY                                 2
-#define     LD_OPTION_FORMAT                                3
-#define     LD_OPTION_GENERATE_SYMBOLS_TABLE                4
-#define     LD_OPTION_HELP                                  5
-#define     LD_OPTION_IMAGE_BASE                            6
-#define     LD_OPTION_MAP                                   7
-#define     LD_OPTION_MAP_FILE                              8
-#define     LD_OPTION_OUTFILE                               9
+#define     LD_OPTION_EMULATION                             2
+#define     LD_OPTION_ENTRY                                 3
+#define     LD_OPTION_FORMAT                                4
+#define     LD_OPTION_GENERATE_SYMBOLS_TABLE                5
+#define     LD_OPTION_HELP                                  6
+#define     LD_OPTION_IMAGE_BASE                            7
+#define     LD_OPTION_MAP                                   8
+#define     LD_OPTION_MAP_FILE                              9
+#define     LD_OPTION_OUTFILE                               10
 
 static struct ld_option opts[] = {
 
@@ -49,6 +50,7 @@ static struct ld_option opts[] = {
     {   "-N",                           LD_OPTION_IGNORED,                      LD_OPTION_NO_ARG    },
     
     {   "-e",                           LD_OPTION_ENTRY,                        LD_OPTION_HAS_ARG   },
+    {   "-m",                           LD_OPTION_EMULATION,                    LD_OPTION_HAS_ARG   },
     {   "-o",                           LD_OPTION_OUTFILE,                      LD_OPTION_HAS_ARG   },
     {   "-s",                           LD_OPTION_IGNORED,                      LD_OPTION_NO_ARG    },
     {   "-q",                           LD_OPTION_EMIT_RELOCS,                  LD_OPTION_NO_ARG    },
@@ -79,6 +81,10 @@ static void print_usage (void) {
         fprintf (stderr, "Options:\n\n");
         
         fprintf (stderr, "    -e ADDRESS, --entry ADDRESS       Set start address.\n");
+        fprintf (stderr, "    -m EMULATION                      Set emulation. (default none)\n");
+        fprintf (stderr, "                                          Supported emualtions are:\n");
+        fprintf (stderr, "                                              i386aout, i386coff, i386elks, i386pe\n");
+        fprintf (stderr, "                                              ia16_elks, ia16_mz\n");
         fprintf (stderr, "    -q, --emit-relocs                 Generate relocations in final output.\n");
         fprintf (stderr, "    -s, --strip-all                   Ignored.\n");
         
@@ -94,7 +100,7 @@ static void print_usage (void) {
         
         fprintf (stderr, "    --generate-symbols-table          Generate a symbols table from global symbols.\n");
         fprintf (stderr, "    --help                            Print option help.\n");
-        fprintf (stderr, "    --oformat FORMAT                  Specify the format of output file (default msdos)\n");
+        fprintf (stderr, "    --oformat FORMAT                  Specify the format of output file (default msdos).\n");
         fprintf (stderr, "                                          Supported formats are:\n");
         fprintf (stderr, "                                              a.out-i386, elks-ia16, elks-i386, pe-i386\n");
         fprintf (stderr, "                                              binary, msdos\n");
@@ -125,6 +131,55 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
         
         }
         
+        case LD_OPTION_EMULATION: {
+        
+            if (xstrcasecmp (optarg, "ia16_elks") == 0) {
+            
+                state->emulation = LD_EMULATION_IA16_ELKS;
+                break;
+            
+            }
+            
+            if (xstrcasecmp (optarg, "ia16_mz") == 0) {
+            
+                state->emulation = LD_EMULATION_IA16_MZ;
+                break;
+            
+            }
+            
+            if (xstrcasecmp (optarg, "i386aout") == 0) {
+            
+                state->emulation = LD_EMULATION_I386_AOUT;
+                break;
+            
+            }
+            
+            if (xstrcasecmp (optarg, "i386coff") == 0) {
+            
+                state->emulation = LD_EMULATION_I386_COFF;
+                break;
+            
+            }
+            
+            if (xstrcasecmp (optarg, "i386elks") == 0) {
+            
+                state->emulation = LD_EMULATION_I386_ELKS;
+                break;
+            
+            }
+            
+            if (xstrcasecmp (optarg, "i386pe") == 0) {
+            
+                state->emulation = LD_EMULATION_I386_PE;
+                break;
+            
+            }
+            
+            report_at (program_name, 0, REPORT_ERROR, "unrecognised emulation mode '%s'", optarg);
+            exit (EXIT_FAILURE);
+        
+        }
+        
         case LD_OPTION_ENTRY: {
         
             char *p;
@@ -162,6 +217,11 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             if (xstrcasecmp (optarg, "msdos-mz") == 0) {
             
                 state->format = LD_FORMAT_MZ;
+                
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_IA16_MZ;
+                }
+                
                 break;
             
             }
@@ -169,6 +229,11 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             if (xstrcasecmp (optarg, "elks-ia16") == 0) {
             
                 state->format = LD_FORMAT_IA16_ELKS;
+                
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_IA16_ELKS;
+                }
+                
                 break;
             
             }
@@ -176,6 +241,11 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             if (xstrcasecmp (optarg, "elks-i386") == 0) {
             
                 state->format = LD_FORMAT_I386_ELKS;
+                
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_I386_ELKS;
+                }
+                
                 break;
             
             }
@@ -183,6 +253,11 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             if (xstrcasecmp (optarg, "a.out-i386") == 0) {
             
                 state->format = LD_FORMAT_I386_AOUT;
+                
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_I386_AOUT;
+                }
+                
                 break;
             
             }
@@ -190,6 +265,11 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             if (xstrcasecmp (optarg, "pe-i386") == 0) {
             
                 state->format = LD_FORMAT_I386_PE;
+                
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_I386_PE;
+                }
+                
                 break;
             
             }
@@ -197,6 +277,11 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             if (xstrcasecmp (optarg, "coff-i386") == 0) {
             
                 state->format = LD_FORMAT_I386_COFF;
+                
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_I386_COFF;
+                }
+                
                 break;
             
             }
@@ -484,16 +569,20 @@ void parse_args (int argc, char **argv, int optind) {
         
         }
         
-        options_with_use = &fmt_tbl[state->format];
-        
-        if (options_with_use->check_option && options_with_use->use_option) {
+        if (state->emulation != LD_EMULATION_NONE) {
         
-            int idx;
+            options_with_use = &fmt_tbl[state->emulation - 1];
             
-            if ((idx = options_with_use->check_option (r, argc, argv, &optind, &optarg)) >= 0) {
+            if (options_with_use->check_option && options_with_use->use_option) {
             
-                options_with_use->use_option (r, idx, optarg);
-                continue;
+                int idx;
+                
+                if ((idx = options_with_use->check_option (r, argc, argv, &optind, &optarg)) >= 0) {
+                
+                    options_with_use->use_option (r, idx, optarg);
+                    continue;
+                
+                }
             
             }
         
diff --git a/link.c b/link.c
index b84293b1a572d251f182fb943867d496bd5eb3e3..bef6bb7eac0f6c2fac616827831041e8c34702c9 100644 (file)
--- a/link.c
+++ b/link.c
@@ -424,7 +424,7 @@ static void reloc_generic (struct section_part *part, struct reloc_entry *rel, s
     
     /*printf ("%lx\n", n_type);*/
     
-    if (state->format == LD_FORMAT_MZ || state->format == LD_FORMAT_IA16_ELKS) {
+    if (state->emulation == LD_EMULATION_IA16_ELKS || state->format == LD_EMULATION_IA16_MZ) {
     
         if (opcode == 0x9A || opcode == 0xFF || rel->n_type == 4) {
         
@@ -773,72 +773,76 @@ void link (void) {
     
     }
     
-    value = 0;
-    
-    if ((symbol = symbol_find ("DGROUP")) && symbol_is_undefined (symbol)) {
+    if (state->emulation == LD_EMULATION_IA16_ELKS || state->format == LD_EMULATION_IA16_MZ) {
     
-        if ((section = section_find (".data"))) {
-            value += align_section_if_needed (section->rva);
-        } else if ((section = section_find (".bss"))) {
-            value += align_section_if_needed (section->rva);
-        }
+        value = 0;
         
-        dgroup_start = value;
-        has_dgroup = 1;
+        if ((symbol = symbol_find ("DGROUP")) && symbol_is_undefined (symbol)) {
         
-        of = object_file_make (FAKE_LD_FILENAME, 1);
-        
-        symbol = of->symbol_arr;
-        symbol->name = xstrdup ("DGROUP");
-        
-        symbol->section_number = ABSOLUTE_SECTION_NUMBER;
-        symbol->value = value / 16;
+            if ((section = section_find (".data"))) {
+                value += align_section_if_needed (section->rva);
+            } else if ((section = section_find (".bss"))) {
+                value += align_section_if_needed (section->rva);
+            }
+            
+            dgroup_start = value;
+            has_dgroup = 1;
+            
+            of = object_file_make (FAKE_LD_FILENAME, 1);
+            
+            symbol = of->symbol_arr;
+            symbol->name = xstrdup ("DGROUP");
+            
+            symbol->section_number = ABSOLUTE_SECTION_NUMBER;
+            symbol->value = value / 16;
+            
+            symbol_record_external_symbol (symbol);
         
-        symbol_record_external_symbol (symbol);
-    
-    }
-    
-    value = 0;
-    
-    if ((symbol = symbol_find ("DGROUP__edata")) && symbol_is_undefined (symbol)) {
-    
-        if ((section = section_find (".data"))) {
-            value += align_section_if_needed (section->rva + section->total_size);
         }
         
-        of = object_file_make (FAKE_LD_FILENAME, 1);
-        value -= (dgroup_start & 0xfffffff0);
+        value = 0;
         
-        symbol = of->symbol_arr;
-        symbol->name = xstrdup ("DGROUP__edata");
+        if ((symbol = symbol_find ("DGROUP__edata")) && symbol_is_undefined (symbol)) {
         
-        symbol->section_number = ABSOLUTE_SECTION_NUMBER;
-        symbol->value = value;
+            if ((section = section_find (".data"))) {
+                value += align_section_if_needed (section->rva + section->total_size);
+            }
+            
+            of = object_file_make (FAKE_LD_FILENAME, 1);
+            value -= (dgroup_start & 0xfffffff0);
+            
+            symbol = of->symbol_arr;
+            symbol->name = xstrdup ("DGROUP__edata");
+            
+            symbol->section_number = ABSOLUTE_SECTION_NUMBER;
+            symbol->value = value;
+            
+            symbol_record_external_symbol (symbol);
         
-        symbol_record_external_symbol (symbol);
-    
-    }
-    
-    value = 0;
-    
-    if ((symbol = symbol_find ("DGROUP__end")) && symbol_is_undefined (symbol)) {
-    
-        if ((section = section_find (".bss"))) {
-            value += align_section_if_needed (section->rva + section->total_size);
-        } else if ((section = section_find (".data"))) {
-            value += align_section_if_needed (section->rva + section->total_size);
         }
         
-        of = object_file_make (FAKE_LD_FILENAME, 1);
-        value -= (dgroup_start & 0xfffffff0);
+        value = 0;
         
-        symbol = of->symbol_arr;
-        symbol->name = xstrdup ("DGROUP__end");
+        if ((symbol = symbol_find ("DGROUP__end")) && symbol_is_undefined (symbol)) {
         
-        symbol->section_number = ABSOLUTE_SECTION_NUMBER;
-        symbol->value = value;
+            if ((section = section_find (".bss"))) {
+                value += align_section_if_needed (section->rva + section->total_size);
+            } else if ((section = section_find (".data"))) {
+                value += align_section_if_needed (section->rva + section->total_size);
+            }
+            
+            of = object_file_make (FAKE_LD_FILENAME, 1);
+            value -= (dgroup_start & 0xfffffff0);
+            
+            symbol = of->symbol_arr;
+            symbol->name = xstrdup ("DGROUP__end");
+            
+            symbol->section_number = ABSOLUTE_SECTION_NUMBER;
+            symbol->value = value;
+            
+            symbol_record_external_symbol (symbol);
         
-        symbol_record_external_symbol (symbol);
+        }
     
     }