From acb065e970d62165fb2be7ca0b91d0a48f93d0d0 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Thu, 6 Nov 2025 05:19:38 +0000 Subject: [PATCH] Create AARCH64 ELF executables --- elf.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- elf.h | 17 +++++++++++ ld.c | 8 +++-- ld.h | 1 + lib.c | 15 ++++++++- 5 files changed, 133 insertions(+), 6 deletions(-) diff --git a/elf.c b/elf.c index 5773355..7accc07 100644 --- a/elf.c +++ b/elf.c @@ -112,7 +112,93 @@ static void translate_relocation64_addend (const char *filename, struct reloc_en reloc->offset = r_offset; reloc->addend = array_to_integer (input_reloc->r_addend, 8, endianess); - if ((state->format & LD_TARGET_MACHINE_AMD64)) { + if ((state->format & LD_TARGET_MACHINE_AARCH64)) { + + switch (rel_type) { + + case R_AARCH64_NONE: + + goto bad; + + case R_AARCH64_PREL32: + + reloc->howto = &reloc_howtos[RELOC_TYPE_PC32]; + reloc->addend += 4; + + break; + + case R_AARCH64_ABS64: + + reloc->howto = &reloc_howtos[RELOC_TYPE_64]; + + integer_to_array (0, part->content + reloc->offset, 8, endianess); + break; + + case R_AARCH64_ABS32: + + reloc->howto = &reloc_howtos[RELOC_TYPE_32]; + + integer_to_array (0, part->content + reloc->offset, 4, endianess); + break; + + case R_AARCH64_ADR_PREL_PG_HI21: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_ADR_PREL_PG_HI21]; + break; + + case R_AARCH64_ADD_ABS_LO12_NC: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_ADD_ABS_LO12_NC]; + break; + + case R_AARCH64_LDST8_ABS_LO12_NC: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_LDST8_ABS_LO12_NC]; + break; + + case R_AARCH64_LDST16_ABS_LO12_NC: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_LDST16_ABS_LO12_NC]; + break; + + case R_AARCH64_LDST32_ABS_LO12_NC: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_LDST32_ABS_LO12_NC]; + break; + + case R_AARCH64_LDST64_ABS_LO12_NC: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_LDST64_ABS_LO12_NC]; + break; + + case R_AARCH64_LDST128_ABS_LO12_NC: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_LDST128_ABS_LO12_NC]; + break; + + case R_AARCH64_JUMP26: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_JUMP26]; + break; + + case R_AARCH64_CALL26: + + reloc->howto = &reloc_howtos[RELOC_TYPE_AARCH64_CALL26]; + break; + + case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_LD64_GOT_LO12_NC: + + report_at (__FILE__, __LINE__, REPORT_WARNING, "Position Independent Executables are not supported, ignoring relocation type %u", rel_type); + goto bad; + + default: + + report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "+++relocation type 0x%02x not supported yet", rel_type); + exit (EXIT_FAILURE); + + } + + } else if ((state->format & LD_TARGET_MACHINE_AMD64)) { switch (rel_type) { @@ -1196,7 +1282,9 @@ uint64_t elf_get_first_section_rva (void) { #define PT_LOAD 1 #define EM_I386 3 + #define EM_AMD64 62 +#define EM_AARCH64 183 static uint32_t translate_section_flags_to_sh_flags (uint32_t flags) { @@ -1580,7 +1668,13 @@ void elf64_write (const char *filename) { header.e_ident[EI_VERSION] = EV_CURRENT; integer_to_array (ET_EXEC, header.e_type, 2, 0); - integer_to_array (EM_AMD64, header.e_machine, 2, 0); + + if ((state->format & LD_TARGET_MACHINE_AARCH64)) { + integer_to_array (EM_AARCH64, header.e_machine, 2, 0); + } else if ((state->format & LD_TARGET_MACHINE_AMD64)) { + integer_to_array (EM_AMD64, header.e_machine, 2, 0); + } + integer_to_array (EV_CURRENT, header.e_version, 4, 0); integer_to_array (state->entry_point + state->base_address, header.e_entry, 8, 0); diff --git a/elf.h b/elf.h index 536ae0c..eb4a337 100644 --- a/elf.h +++ b/elf.h @@ -166,6 +166,23 @@ struct elf64_rel { #define R_AMD64_32 10 #define R_AMD64_32S 11 +#define R_AARCH64_NONE 0 +#define R_AARCH64_ABS64 257 +#define R_AARCH64_ABS32 258 +#define R_AARCH64_PREL32 261 +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_LDST8_ABS_LO12_NC 278 +#define R_AARCH64_LDST16_ABS_LO12_NC 284 +#define R_AARCH64_LDST32_ABS_LO12_NC 285 +#define R_AARCH64_LDST64_ABS_LO12_NC 286 +#define R_AARCH64_LDST128_ABS_LO12_NC 299 +#define R_AARCH64_JUMP26 282 +#define R_AARCH64_CALL26 283 +#define R_AARCH64_ADR_GOT_PAGE 311 +#define R_AARCH64_LD64_GOT_LO12_NC 312 + struct elf32_phdr { unsigned char p_type[4]; diff --git a/ld.c b/ld.c index f032dde..98fefa2 100644 --- a/ld.c +++ b/ld.c @@ -536,6 +536,8 @@ int main (int argc, char **argv) { state->base_address = 0x100000000; } else if (state->format == LD_FORMAT_AMD64_ELF || state->format == LD_FORMAT_I386_ELF) { state->base_address = 0x00400000; + } else if (state->format == LD_FORMAT_AARCH64_ELF) { + state->base_address = 0x140000000; } } @@ -548,9 +550,9 @@ int main (int argc, char **argv) { elks_before_link (); } else if (state->format == LD_FORMAT_I386_PE) { pe_before_link (); - } else if (state->format == LD_FORMAT_AMD64_MACHO || state->format == LD_FORMAT_AARCH64_MACHO) { + } else if (state->format == LD_FORMAT_AARCH64_MACHO || state->format == LD_FORMAT_AMD64_MACHO) { macho_before_link (); - } else if (state->format == LD_FORMAT_AMD64_ELF || state->format == LD_FORMAT_I386_ELF) { + } else if (state->format == LD_FORMAT_AARCH64_ELF || state->format == LD_FORMAT_AMD64_ELF || state->format == LD_FORMAT_I386_ELF) { elf_before_link (); } @@ -611,7 +613,7 @@ int main (int argc, char **argv) { elks_write (state->output_filename); } else if (state->format == LD_FORMAT_I386_ELF) { elf32_write (state->output_filename); - } else if (state->format == LD_FORMAT_AMD64_ELF) { + } else if (state->format == LD_FORMAT_AARCH64_ELF || state->format == LD_FORMAT_AMD64_ELF) { elf64_write (state->output_filename); } else if (state->format == LD_FORMAT_I386_PE) { diff --git a/ld.h b/ld.h index c19a7ce..f85d8ea 100644 --- a/ld.h +++ b/ld.h @@ -60,6 +60,7 @@ struct ld_state { #define LD_FORMAT_AMD64_ELF (LD_TARGET_MACHINE_AMD64 | 0x10) #define LD_FORMAT_AARCH64_MACHO (LD_TARGET_MACHINE_AARCH64 | 0x11) +#define LD_FORMAT_AARCH64_ELF (LD_TARGET_MACHINE_AARCH64 | 0x12) extern struct ld_state *state; diff --git a/lib.c b/lib.c index 17105bb..ba38e27 100644 --- a/lib.c +++ b/lib.c @@ -109,7 +109,8 @@ static void print_usage (void) { fprintf (stderr, " --help Print option help.\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, elf-amd64, elf-i386\n"); + fprintf (stderr, " a.out-i386, elf-aarch64\n"); + fprintf (stderr, " elf-amd64, elf-i386\n"); fprintf (stderr, " elks-ia16, elks-i386\n"); fprintf (stderr, " macho-aarch64, macho-amd64\n"); fprintf (stderr, " pe-i386, binary, msdos\n"); @@ -352,6 +353,18 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) { } + if (xstrcasecmp (optarg, "elf-aarch64") == 0) { + + state->format = LD_FORMAT_AARCH64_ELF; + + /*if (state->emulation == LD_EMULATION_NONE) { + state->emulation = LD_EMULATION_I386_COFF; + }*/ + + break; + + } + report_at (program_name, 0, REPORT_ERROR, "unrecognised output format '%s'", optarg); exit (EXIT_FAILURE); -- 2.34.1