From ef5253e4401ed6a07b07eafc4fe00557111acbe6 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Sun, 12 Jul 2026 01:23:46 +0100 Subject: [PATCH] Support shared AXE objects and PE fixes --- axe.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ axe.h | 5 +++ ld.h | 4 ++- lib.c | 17 +++++---- pe.c | 25 +++++++------ 5 files changed, 147 insertions(+), 17 deletions(-) diff --git a/axe.c b/axe.c index d1d462f..5aff0a4 100644 --- a/axe.c +++ b/axe.c @@ -12,6 +12,119 @@ #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 b259eb7..2a66a96 100644 --- 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 d69eb86..e5f6f92 100644 --- 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 336eec0..cea728c 100644 --- a/lib.c +++ b/lib.c @@ -8,6 +8,7 @@ #include #include +#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 4797117..158ed1f 100644 --- 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); -- 2.34.1