Fixes for large model
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 14 Apr 2025 03:34:54 +0000 (04:34 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 14 Apr 2025 03:34:54 +0000 (04:34 +0100)
aout.c
elks.c
link.c
mz.c

diff --git a/aout.c b/aout.c
index 4c496107c857e90645a23622b1cbd62d5ebafdc7..fd39cb90edb83d33b512ddc18247c8f778ca3947 100644 (file)
--- a/aout.c
+++ b/aout.c
@@ -52,9 +52,11 @@ static void translate_relocation (struct reloc_entry *reloc, struct aout_relocat
     
     reloc->symbolnum = r_symbolnum;
     reloc->offset = r_address;
-    reloc->n_type = 24;
     reloc->n_ext = 27;
     
+    reloc->n_type = ((r_symbolnum >> 24) & 0xff);
+    reloc->n_type &= ~(1 << 3);
+    
     switch (1U << ((r_symbolnum >> 25) & 3)) {
     
         case 8:
diff --git a/elks.c b/elks.c
index 6db7e50b6c396d3516d2e72dbee29b5242f5ab33..a74cfadc0f1808e78de1b0b23bb899f3a19f3969 100644 (file)
--- a/elks.c
+++ b/elks.c
@@ -53,9 +53,11 @@ static void translate_relocation (struct reloc_entry *reloc, struct elks_relocat
     
     reloc->symbolnum = r_symbolnum;
     reloc->offset = r_address;
-    reloc->n_type = 28;
     reloc->n_ext = 31;
     
+    reloc->n_type = ((r_symbolnum >> 28) & 0xff);
+    reloc->n_type &= ~(1 << 4);
+    
     switch (1U << ((r_symbolnum >> 29) & 3)) {
     
         case 8:
diff --git a/link.c b/link.c
index 578f17cef6e25ef0316f13bd7e9e08eb469bf8bd..79670d7ca9a5b59a19711dc17a7dfa87ba83645a 100644 (file)
--- a/link.c
+++ b/link.c
@@ -367,7 +367,7 @@ static void reloc_generic (struct section_part *part, struct reloc_entry *rel, s
             
                 /*report_at (__FILE__, __LINE__, REPORT_FATAL_ERROR, "symbol: %s, %lx", symbol->name, ((rel->symbolnum) >> 28));*/
                 
-                if (((rel->symbolnum >> 27) & 1) || ((rel->symbolnum >> rel->n_type) & 0xff) != 2) {
+                if (((rel->symbolnum >> 27) & 1) || rel->n_type != 2) {
                     report_at (program_name, 0, REPORT_ERROR, "%s:(%s+%#lu): segment relocation", part->of->filename, part->section->name, offset);
                 }
             
@@ -379,7 +379,7 @@ static void reloc_generic (struct section_part *part, struct reloc_entry *rel, s
             
                 int is_section = (xstrcasecmp (symbol->name, ".text") == 0) || (xstrcasecmp (symbol->name, ".data") == 0) || (xstrcasecmp (symbol->name, ".bss") == 0);
                 
-                if (is_section || (((rel->symbolnum >> rel->n_type) & 0xff) != 4 && ((rel->symbolnum >> rel->n_type) & 0xff) != 6 && ((rel->symbolnum >> rel->n_type) & 0xff) != 8)) {
+                if (is_section || (rel->n_type != 4 && rel->n_type != 6 && rel->n_type != 8)) {
                 
                     if (rel->howto == &reloc_howtos[RELOC_TYPE_64]) {
                         rel->howto = &reloc_howtos[RELOC_TYPE_PC64];
@@ -397,7 +397,7 @@ static void reloc_generic (struct section_part *part, struct reloc_entry *rel, s
         
         }
         
-        if (xstrcasecmp (symbol->name, "DGROUP__edata") == 0 || xstrcasecmp (symbol->name, "DGROUP__end") == 0 || xstrcasecmp (symbol->name, "__etext") == 0 || xstrcasecmp (symbol->name, "__edata") == 0 || xstrcasecmp (symbol->name, "__end") == 0) {
+        if (strcasecmp (symbol->name, "DGROUP__edata") == 0 || xstrcasecmp (symbol->name, "DGROUP__end") == 0 || xstrcasecmp (symbol->name, "__etext") == 0 || xstrcasecmp (symbol->name, "__edata") == 0 || xstrcasecmp (symbol->name, "__end") == 0) {
         
             if (rel->howto == &reloc_howtos[RELOC_TYPE_64]) {
                 rel->howto = &reloc_howtos[RELOC_TYPE_PC64];
@@ -422,27 +422,48 @@ static void reloc_generic (struct section_part *part, struct reloc_entry *rel, s
     
     result >>= rel->howto->final_right_shift;
     
-    if (opcode == 0xff || opcode == 0x9A) {
+    /*printf ("%lx\n", n_type);*/
     
-        if (result >= 65535) {
+    if (opcode == 0xFF || opcode == 0x9A || rel->n_type == 0x04) {
+    
+        /*printf ("%lx\n", (rel->symbolnum >> rel->n_type) & 0xff);*/
+        
+        unsigned char *p = part->content + offset;
         
-            /*report_at (program_name, 0, REPORT_ERROR, "%s:(%s+%#lu): call exceeds 65535 bytes", part->of->filename, part->section->name, offset);*/
+        if ((opcode != 0x9A && opcode != 0xFF) || result >= 65535) {
+        
+            if (opcode == 0x9A || opcode == 0xFF) {
             
-            if (rel->howto == &reloc_howtos[RELOC_TYPE_PC64]) {
-                rel->howto = &reloc_howtos[RELOC_TYPE_64];
-            } else if (rel->howto == &reloc_howtos[RELOC_TYPE_PC32]) {
-                rel->howto = &reloc_howtos[RELOC_TYPE_32];
-            } else if (rel->howto == &reloc_howtos[RELOC_TYPE_PC16]) {
-                rel->howto = &reloc_howtos[RELOC_TYPE_16];
-            } else if (rel->howto == &reloc_howtos[RELOC_TYPE_PC8]) {
-                rel->howto = &reloc_howtos[RELOC_TYPE_8];
-            }
+                *(p - 1) = 0x9A;
             
-            result = (((unsigned long) result / 16) << 16) | (unsigned long) result % 16;
+                if (rel->howto == &reloc_howtos[RELOC_TYPE_PC64]) {
+                    rel->howto = &reloc_howtos[RELOC_TYPE_64];
+                } else if (rel->howto == &reloc_howtos[RELOC_TYPE_PC32]) {
+                    rel->howto = &reloc_howtos[RELOC_TYPE_32];
+                } else if (rel->howto == &reloc_howtos[RELOC_TYPE_PC16]) {
+                    rel->howto = &reloc_howtos[RELOC_TYPE_16];
+                } else if (rel->howto == &reloc_howtos[RELOC_TYPE_PC8]) {
+                    rel->howto = &reloc_howtos[RELOC_TYPE_8];
+                }
+                
+                result = (((unsigned long) result / 16) << 16) | (unsigned long) result % 16;
+                
+                /*if (opcode != 0x9A && opcode != 0xFF) {
+                    printf ("%x, %lx, %lx, %lx\n", rel->n_type, part->rva + offset + 0x30, result, size);
+                }*/
+                
+                while (rel->howto->size > 2) {
+                
+                    rel->howto->size--;
+                    rel->offset++;
+                
+                }
+            
+            }
         
         } else {
         
-            unsigned char *p = part->content + offset;
+            /*printf ("%x, %lx, %lx, %lx\n", rel->n_type, part->rva + offset + 0x30, result, size);*/
             
             if (rel->howto == &reloc_howtos[RELOC_TYPE_64]) {
                 rel->howto = &reloc_howtos[RELOC_TYPE_PC64];
@@ -454,45 +475,65 @@ static void reloc_generic (struct section_part *part, struct reloc_entry *rel, s
                 rel->howto = &reloc_howtos[RELOC_TYPE_PC8];
             }
             
-            *(p - 1) = 0x0E;
-            *(p + 0) = 0xE8;
-            *(p + 3) = 0x90;
+            if (opcode == 0x9A) {
             
-            result -= part->rva + offset;
-            result -= size;
+                *(p - 1) = 0x0E;
+                *(p + 0) = 0xE8;
+                *(p + 3) = 0x90;
+                
+                result -= part->rva + offset;
+                result -= size;
+                
+                while (size > 2) {
+                    size--;
+                }
+                
+                offset++;
+                result++;
             
-            while (size > 2) {
+            } else {
             
-                size--;
-                /*result--;*/
+                *(p - 1) = 0x0E;
+                *(p + 0) = 0x3E;
+                *(p + 1) = 0xE8;
+                
+                result -= part->rva + offset;
+                result -= size;
+                
+                while (size > 2) {
+                
+                    offset++;
+                    size--;
+                
+                }
             
             }
-            
-            offset++;
-            result++;
         
         }
     
-    } else {
+    } else if (opcode != 0xE8 && rel->n_type != 0x04) {
     
         /*if (!rel->howto->pc_rel && !rel->howto->no_base) {*/
         /*if (!((rel->symbolnum >> rel->n_ext) & 1) || symbol->section_number == ABSOLUTE_SECTION_NUMBER) {*/
         
-            if (has_dgroup/* && ((rel->symbolnum >> rel->n_type) & 0xff) != N_ABS*/) {
+            if (has_dgroup/* && rel->n_type != N_ABS*/) {
             
-                if (xstrcasecmp (symbol->name, "__etext") != 0 && xstrcasecmp (symbol->name, "__edata") != 0 && xstrcasecmp (symbol->name, "__end") != 0) {
+                if (xstrcasecmp (symbol->name, "DGROUP__edata") != 0 && xstrcasecmp (symbol->name, "DGROUP__end") != 0 && xstrcasecmp (symbol->name, "__etext") != 0 && xstrcasecmp (symbol->name, "__edata") != 0 && xstrcasecmp (symbol->name, "__end") != 0) {
                 
                     if (result >= dgroup_start) {
                         result -= (dgroup_start & 0xfffffff0);
+                        /*printf ("%lx, %lx, %lx\n", part->rva + offset + 0x30, result, dgroup_start);*/
                     }
                 
                 }
             
             }
         
-        /*} else if (result >= dgroup_start && ((rel->symbolnum >> rel->n_type) & 0xff) != N_ABS) {
+        /*} else if (result >= dgroup_start && rel->n_type != 2) {
             printf ("%x, %lx, %lx, %lx\n", opcode, part->rva + offset + 0x30, result, dgroup_start);
         }*/
+        
+        /*printf ("%lx, %lx, %lx, %lx\n", (rel->symbolnum >> rel->n_type) & 0xff, part->rva + offset + 0x30, result, dgroup_start);*/
     
     }
     
@@ -782,6 +823,7 @@ void link (void) {
         }
         
         of = object_file_make (FAKE_LD_FILENAME, 1);
+        value -= (dgroup_start & 0xfffffff0);
         
         symbol = of->symbol_arr;
         symbol->name = xstrdup ("DGROUP__edata");
@@ -797,10 +839,6 @@ void link (void) {
     
     if ((symbol = symbol_find ("DGROUP__end")) && symbol_is_undefined (symbol)) {
     
-        if ((section = section_find (".text"))) {
-            value += align_section_if_needed (section->total_size);
-        }
-        
         if ((section = section_find (".data"))) {
             value += align_section_if_needed (section->total_size);
         }
diff --git a/mz.c b/mz.c
index ee382ea0eaee9c3c90044748c81c2c3942d5776c..ba735db6a97c5fce2f52ff2e6b301586dab22e1a 100644 (file)
--- a/mz.c
+++ b/mz.c
@@ -107,11 +107,16 @@ void mz_write (const char *filename) {
     reloc_size = ALIGN (reloc_count * 4, 16);
     
     data_size += header_size + reloc_size;
+    ibss_addr += header_size + reloc_size;
+    
+    /*stack_addr += header_size + reloc_size;*/
     
     if (text_section) {
     
         data_size += text_section->total_size;
         ibss_addr += text_section->total_size;
+        
+        stack_addr += text_section->total_size;
     
     }
     
@@ -119,6 +124,8 @@ void mz_write (const char *filename) {
     
         data_size += data_section->total_size;
         ibss_addr += data_section->total_size;
+        
+        stack_addr += data_section->total_size;
     
     }
     
@@ -126,7 +133,8 @@ void mz_write (const char *filename) {
         ibss_size = bss_section->total_size;
     }
     
-    stack_addr = header_size + reloc_size + ibss_addr + ibss_size;
+    stack_addr = ALIGN (stack_addr + ibss_size, 16);
+    /*stack_addr = ALIGN (ibss_addr + ibss_size, 16);*/
     stack_size = 0x1000;        /* Maybe get this from command line in the future. */
     
     exec.e_magic[0] = 'M';