Support shared AXE objects and PE fixes
authorRobert Pengelly <robertapengelly@hotmail.com>
Sun, 12 Jul 2026 00:23:46 +0000 (01:23 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Sun, 12 Jul 2026 00:23:46 +0000 (01:23 +0100)
axe.c
axe.h
ld.h
lib.c
pe.c

diff --git a/axe.c b/axe.c
index d1d462fc512c619a406b15926419ef499c6cb2ad..5aff0a47b069fb4f8397b0c132b0e2293cd84c31 100644 (file)
--- a/axe.c
+++ b/axe.c
 #include    "section.h"
 #include    "symbol.h"
 
+#define     LD_OPTION_IGNORED                               0
+#define     LD_OPTION_SHARED                                1
+
+static struct ld_option opts[] = {
+
+    {   "--shared",                 LD_OPTION_TYPE_LONG,        LD_OPTION_SHARED,               LD_OPTION_NO_ARG    },
+    {   "-Bshareable",              LD_OPTION_TYPE_LONG,        LD_OPTION_SHARED,               LD_OPTION_NO_ARG    },
+    
+    {   0,                          0,                          0,                              0                   }
+
+};
+
+int axe_check_option (const char *cmd_arg, int argc, char **argv, int *optind, const char **optarg) {
+
+    struct ld_option *popt;
+    
+    for (popt = opts; ; popt++) {
+    
+        const char *p1 = popt->name;
+        const char *r1 = cmd_arg;
+        
+        if (!p1) {
+            break;    
+        }
+        
+        if (!strstart (p1, &r1)) {
+        
+            if (popt->type == LD_OPTION_TYPE_LONG) {
+            
+                if (*r1 != '-') {
+                    continue;
+                }
+                
+                p1 = popt->name + 1;
+                r1 = cmd_arg;
+                
+                if (!strstart (p1, &r1)) {
+                    continue;
+                }
+            
+            } else {
+                continue;
+            }
+        
+        }
+        
+        (*optarg) = r1;
+        
+        if (popt->flgs & LD_OPTION_HAS_ARG) {
+        
+            if (*r1 == '\0') {
+            
+                if ((*optind) >= argc) {
+                
+                    report_at (program_name, 0, REPORT_ERROR, "argument to '%s' is missing", cmd_arg);
+                    exit (EXIT_FAILURE);
+                
+                }
+                
+                (*optarg) = argv[(*optind)++];
+            
+            }
+        
+        } else if (*r1 != '\0') {
+            continue;
+        }
+        
+        return popt->idx;
+    
+    }
+    
+    return -1;
+
+}
+
+void axe_use_option (const char *cmd_arg, int idx, const char *optarg) {
+
+    (void) optarg;
+    
+    switch (idx) {
+    
+        case LD_OPTION_IGNORED: {
+        
+            break;
+        
+        }
+        
+        case LD_OPTION_SHARED: {
+        
+            state->create_shared_library = 1;
+            break;
+        
+        }
+        
+        default: {
+        
+            report_at (program_name, 0, REPORT_ERROR, "unsupported option '%s'", cmd_arg);
+            exit (EXIT_FAILURE);
+        
+        }
+    
+    }
+
+}
+
+void axe_print_help (void) {
+
+    fprintf (stderr, "axe:\n\n");
+    fprintf (stderr, "    -shared, -Bshareable              Create a shared library.\n");
+
+}
+
+
 #define     EM_I386                     3
 #define     EM_AMD64                    62
 
diff --git a/axe.h b/axe.h
index b259eb7265aa92d7536ca4a24e17ae5f486cacb1..2a66a9627e35b6a416c5c85147723f1f35103deb 100644 (file)
--- a/axe.h
+++ b/axe.h
@@ -66,6 +66,11 @@ struct axe_nlist {
 };
 
 #define     AXE_TYPE                      0x1e
+int axe_check_option (const char *cmd_arg, int argc, char **argv, int *optind, const char **optarg);
+
+void axe_print_help (void);
+void axe_use_option (const char *cmd_arg, int idx, const char *optarg);
+
 void axe_before_link (void);
 
 void axe_write32 (const char *filename);
diff --git a/ld.h b/ld.h
index d69eb86493e291ebc6ab88c511b1d3a01e9fbddd..e5f6f92efdec0cc257efd9b70303c8bd81edb5f8 100644 (file)
--- a/ld.h
+++ b/ld.h
@@ -25,6 +25,7 @@ struct ld_state {
     unsigned long size_of_headers;
     
     int emulation, generate_symbols_table, impure;
+    int leading_underscore;
 
 };
 
@@ -44,7 +45,8 @@ struct ld_state {
 #define     LD_EMULATION_I386_DX        0x05
 #define     LD_EMULATION_I386_PE        0x06
 
-#define     LD_EMULATION_MACHO          0x07
+#define     LD_EMULATION_AXE            0x07
+#define     LD_EMULATION_MACHO          0x08
 
 
 #define     LD_FORMAT_COM               0x00
diff --git a/lib.c b/lib.c
index 336eec09449ba372008ba226d1e6c000a73c86f4..cea728c6b5424f651eeabb41480616e6d82127ec 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -8,6 +8,7 @@
 #include    <stdlib.h>
 #include    <string.h>
 
+#include    "axe.h"
 #include    "ld.h"
 #include    "lib.h"
 #include    "macho.h"
@@ -33,6 +34,7 @@ static struct options_with_use emulation_table[] = {
     {   0,                      0,                      0                   },
     {   0,                      0,                      0                   },
     {   &pe_print_help,         &pe_check_option,       &pe_use_option      },
+    {   &axe_print_help,        &axe_check_option,      &axe_use_option     },
     {   &macho_print_help,      &macho_check_option,    &macho_use_option   }
 
 };
@@ -323,9 +325,9 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             
                 state->format = LD_FORMAT_I386_AXE;
                 
-                /*if (state->emulation == LD_EMULATION_NONE) {
-                    state->emulation = LD_EMULATION_I386_AOUT;
-                }*/
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_AXE;
+                }
                 
                 break;
             
@@ -335,9 +337,9 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
             
                 state->format = LD_FORMAT_AMD64_AXE;
                 
-                /*if (state->emulation == LD_EMULATION_NONE) {
-                    state->emulation = LD_EMULATION_I386_AOUT;
-                }*/
+                if (state->emulation == LD_EMULATION_NONE) {
+                    state->emulation = LD_EMULATION_AXE;
+                }
                 
                 break;
             
@@ -363,6 +365,7 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
                     state->emulation = LD_EMULATION_I386_PE;
                 }
                 
+                state->leading_underscore = 0;
                 break;
             
             }
@@ -708,6 +711,8 @@ void parse_args (int argc, char **argv, int optind) {
     
     }
     
+    state->leading_underscore = 1;
+    
     while (optind < argc) {
     
         r = argv[optind++];
diff --git a/pe.c b/pe.c
index 479711785305f4e2ed353744b26f05a3388fe172..158ed1f4a3297167b59fd7f9c783fb00ea067928 100644 (file)
--- a/pe.c
+++ b/pe.c
@@ -20,7 +20,7 @@
 #include    "write7x.h"
 
 static char *output_implib_filename = 0;
-static int kill_at = 0, leading_underscore = 1;
+static int kill_at = 0;
 
 static unsigned short subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
 
@@ -168,7 +168,6 @@ void pe_use_option (const char *cmd_arg, int idx, const char *optarg) {
             
             }
             
-            leading_underscore = 0;
             break;
         
         }
@@ -320,7 +319,7 @@ static void export_symbol_callback (struct symbol *symbol) {
     
     name_list = xmalloc (sizeof (*name_list));
     
-    if (leading_underscore && symbol->name[0] == '_') {
+    if (state->leading_underscore && symbol->name[0] == '_') {
         name_list->name = xstrdup (symbol->name + 1);
     } else {
         name_list->name = xstrdup (symbol->name);
@@ -953,7 +952,7 @@ struct symbol_info *create_symbol_list (struct export_name *export_name, unsigne
         symbol_info = xmalloc (sizeof (*symbol_info));
         symbol_info->name = xmalloc (7 + strlen (export_name[i].name) + 1);
         
-        if (leading_underscore) {
+        if (state->leading_underscore) {
             sprintf (symbol_info->name, "__imp__%s", export_name[i].name);
         } else {
             sprintf (symbol_info->name, "__imp_%s", export_name[i].name);
@@ -1548,7 +1547,7 @@ static void write_implib (struct export_name *export_names, unsigned long num_na
         
         offsets[4 + i] = offset2;
         
-        if (leading_underscore) {
+        if (state->leading_underscore) {
             offset2 += write_file_header (outfile, header_name, bHeaderName, sizeof (import_hdr) + 1 + strlen (export_names[i].name) + 1 + module_name_length + 1, 0);
         } else {
             offset2 += write_file_header (outfile, header_name, bHeaderName, sizeof (import_hdr) + strlen (export_names[i].name) + 1 + module_name_length + 1, 0);
@@ -1565,7 +1564,7 @@ static void write_implib (struct export_name *export_names, unsigned long num_na
             integer_to_array (IMAGE_FILE_MACHINE_I386, import_hdr.Machine, 2, 0);
         }
         
-        if (leading_underscore) {
+        if (state->leading_underscore) {
             integer_to_array (1 + strlen (export_names[i].name) + 1 + module_name_length + 1, import_hdr.SizeOfData, 4, 0);
         } else {
             integer_to_array (strlen (export_names[i].name) + 1 + module_name_length + 1, import_hdr.SizeOfData, 4, 0);
@@ -1592,12 +1591,18 @@ static void write_implib (struct export_name *export_names, unsigned long num_na
         
         }
         
-        type |= (kill_at ? IMPORT_NAME_UNDECORATE : IMPORT_NAME_NOPREFIX) << 2;
+        if (kill_at) {
+            type |= IMPORT_NAME_UNDECORATE << 2;
+        } else if (state->leading_underscore) {
+            type |= IMPORT_NAME_NOPREFIX << 2;
+        } else {
+            type |= IMPORT_NAME << 2;
+        }
         
         integer_to_array (type, import_hdr.Type, 2, 0);
         offset2 += write_data (outfile, &import_hdr, sizeof (import_hdr));
         
-        if (leading_underscore) {
+        if (state->leading_underscore) {
         
             name = xmalloc (1 + strlen (export_names[i].name) + 1);
             sprintf (name, "_%s", export_names[i].name);
@@ -1762,7 +1767,7 @@ static void generate_edata (void) {
     
     for (i = 0; i < num_names; i++) {
     
-        if (leading_underscore) {
+        if (state->leading_underscore) {
         
             symbol->name = xmalloc (1 + strlen (export_names[i].name) + 1);
             sprintf (symbol->name, "_%s", export_names[i].name);
@@ -2674,7 +2679,7 @@ static void import_generate_import (const char *import_name, short ordinal_hint,
     
     symbol->name = xmalloc (6 + strlen (import_name) + 1);
     
-    if (leading_underscore) {
+    if (state->leading_underscore) {
         sprintf (symbol->name, "__imp_%s", import_name);
     } else {
         sprintf (symbol->name, "__imp%s", import_name);