Create AARCH64 ELF executables
authorRobert Pengelly <robertapengelly@hotmail.com>
Thu, 6 Nov 2025 05:19:38 +0000 (05:19 +0000)
committerRobert Pengelly <robertapengelly@hotmail.com>
Thu, 6 Nov 2025 05:19:38 +0000 (05:19 +0000)
elf.c
elf.h
ld.c
ld.h
lib.c

diff --git a/elf.c b/elf.c
index 57733559bdb450296804890409a8cac4999ddf34..7accc07fbf0517d64c7c8ed440f1b1f9474cca02 100644 (file)
--- 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 536ae0c4b7b62323b76a21ff839c72572e747064..eb4a337a2cf7697090142ace8739914b90be1278 100644 (file)
--- 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 f032dde72062e9a08fb4359717ba43f584f2e765..98fefa242fc6b847f2fb6f7b52285ff347d70fa9 100644 (file)
--- 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 c19a7ce3d37dde56f6f2652a0dc12f8d0e6ab462..f85d8eafb9d1583161dcae6d10a72d31d87dfec0 100644 (file)
--- 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 17105bb903fba79b380af3ab4104e8e04d7fb57b..ba38e27fbbe38676bbc4205588d95961005ec599 100644 (file)
--- 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);