Generate symbol table relative to the data section
authorRobert Pengelly <robertapengelly@hotmail.com>
Thu, 12 Dec 2024 17:34:20 +0000 (17:34 +0000)
committerRobert Pengelly <robertapengelly@hotmail.com>
Thu, 12 Dec 2024 17:34:20 +0000 (17:34 +0000)
ld.h
lib.c
link.c
section.c

diff --git a/ld.h b/ld.h
index ddfdf9e36da2a9d9629b1d3ad8eb09091d23d8a8..b500a3e1103cf8a64821b7a8cbd6aa2538453a8f 100644 (file)
--- a/ld.h
+++ b/ld.h
@@ -22,6 +22,8 @@ struct ld_state {
     
     int emit_relocs, use_custom_base_address;
     unsigned long size_of_headers;
+    
+    int generate_symbols_table;
 
 };
 
diff --git a/lib.c b/lib.c
index d82463c99f93d60d876e816b7d375fbf4488c59b..4fd0116c0dc267cec6b3bcd27d5b256d2ea3a0f3 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -31,40 +31,42 @@ static struct options_with_use fmt_tbl[] = {
 
 };
 
-#define     LD_OPTION_IGNORED           0
-#define     LD_OPTION_EMIT_RELOCS       1
-#define     LD_OPTION_ENTRY             2
-#define     LD_OPTION_FORMAT            3
-#define     LD_OPTION_HELP              4
-#define     LD_OPTION_IMAGE_BASE        5
-#define     LD_OPTION_MAP               6
-#define     LD_OPTION_MAP_FILE          7
-#define     LD_OPTION_OUTFILE           8
+#define     LD_OPTION_IGNORED                               0
+#define     LD_OPTION_EMIT_RELOCS                           1
+#define     LD_OPTION_ENTRY                                 2
+#define     LD_OPTION_FORMAT                                3
+#define     LD_OPTION_GENERATE_SYMBOLS_TABLE                4
+#define     LD_OPTION_HELP                                  5
+#define     LD_OPTION_IMAGE_BASE                            6
+#define     LD_OPTION_MAP                                   7
+#define     LD_OPTION_MAP_FILE                              8
+#define     LD_OPTION_OUTFILE                               9
 
 static struct ld_option opts[] = {
 
-    {   "-M",                   LD_OPTION_MAP,              LD_OPTION_NO_ARG    },
-    {   "-Map",                 LD_OPTION_MAP_FILE,         LD_OPTION_HAS_ARG   },
-    {   "-N",                   LD_OPTION_IGNORED,          LD_OPTION_NO_ARG    },
+    {   "-M",                           LD_OPTION_MAP,                          LD_OPTION_NO_ARG    },
+    {   "-Map",                         LD_OPTION_MAP_FILE,                     LD_OPTION_HAS_ARG   },
+    {   "-N",                           LD_OPTION_IGNORED,                      LD_OPTION_NO_ARG    },
     
-    {   "-e",                   LD_OPTION_ENTRY,            LD_OPTION_HAS_ARG   },
-    {   "-o",                   LD_OPTION_OUTFILE,          LD_OPTION_HAS_ARG   },
-    {   "-s",                   LD_OPTION_IGNORED,          LD_OPTION_NO_ARG    },
-    {   "-q",                   LD_OPTION_EMIT_RELOCS,      LD_OPTION_NO_ARG    },
+    {   "-e",                           LD_OPTION_ENTRY,                        LD_OPTION_HAS_ARG   },
+    {   "-o",                           LD_OPTION_OUTFILE,                      LD_OPTION_HAS_ARG   },
+    {   "-s",                           LD_OPTION_IGNORED,                      LD_OPTION_NO_ARG    },
+    {   "-q",                           LD_OPTION_EMIT_RELOCS,                  LD_OPTION_NO_ARG    },
     
     
-    {   "--emit_relocs",        LD_OPTION_EMIT_RELOCS,      LD_OPTION_NO_ARG    },
-    {   "--entry",              LD_OPTION_ENTRY,            LD_OPTION_HAS_ARG   },
-    {   "--help",               LD_OPTION_HELP,             LD_OPTION_NO_ARG    },
-    {   "--image_base",         LD_OPTION_IMAGE_BASE,       LD_OPTION_HAS_ARG   },
-    {   "--oformat",            LD_OPTION_FORMAT,           LD_OPTION_HAS_ARG   },
-    {   "--omagic",             LD_OPTION_IGNORED,          LD_OPTION_NO_ARG    },
-    {   "--output",             LD_OPTION_OUTFILE,          LD_OPTION_HAS_ARG   },
-    {   "--print-map",          LD_OPTION_MAP,              LD_OPTION_NO_ARG    },
-    {   "--strip-all",          LD_OPTION_IGNORED,          LD_OPTION_NO_ARG    },
+    {   "--emit-relocs",                LD_OPTION_EMIT_RELOCS,                  LD_OPTION_NO_ARG    },
+    {   "--entry",                      LD_OPTION_ENTRY,                        LD_OPTION_HAS_ARG   },
+    {   "--help",                       LD_OPTION_HELP,                         LD_OPTION_NO_ARG    },
+    {   "--image-base",                 LD_OPTION_IMAGE_BASE,                   LD_OPTION_HAS_ARG   },
+    {   "--oformat",                    LD_OPTION_FORMAT,                       LD_OPTION_HAS_ARG   },
+    {   "--omagic",                     LD_OPTION_IGNORED,                      LD_OPTION_NO_ARG    },
+    {   "--output",                     LD_OPTION_OUTFILE,                      LD_OPTION_HAS_ARG   },
+    {   "--print-map",                  LD_OPTION_MAP,                          LD_OPTION_NO_ARG    },
+    {   "--strip-all",                  LD_OPTION_IGNORED,                      LD_OPTION_NO_ARG    },
     
     
-    {   0,                      0,                          0                   }
+    {   "--generate-symbols-table",     LD_OPTION_GENERATE_SYMBOLS_TABLE,       LD_OPTION_NO_ARG    },
+    {   0,                              0,                                      0                   }
 
 };
 
@@ -90,6 +92,7 @@ static void print_usage (void) {
         
         fprintf (stderr, "\n");
         
+        fprintf (stderr, "    --generate-symbols-table          Generate a symbols table from global symbols.\n");
         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");
@@ -189,6 +192,13 @@ static void use_option (const char *cmd_arg, int idx, const char *optarg) {
         
         }
         
+        case LD_OPTION_GENERATE_SYMBOLS_TABLE: {
+        
+            state->generate_symbols_table = 1;
+            break;
+        
+        }
+        
         case LD_OPTION_HELP: {
         
             print_usage ();
diff --git a/link.c b/link.c
index b478f5fc7dc366f8fb65f273271afa373bc81494..2cf0921d7d36e48a6646057753406f389fed0056 100644 (file)
--- a/link.c
+++ b/link.c
@@ -2,6 +2,8 @@
  * @file            link.c
  *****************************************************************************/
 #include    <limits.h>
+#include    <stdio.h>
+#include    <stdlib.h>
 #include    <string.h>
 
 #include    "ld.h"
@@ -30,6 +32,168 @@ struct reloc_howto reloc_howtos[RELOC_TYPE_END] = {
 
 };
 
+static void output_symbols () {
+
+    struct section *section = section_find_or_make (".data");
+    
+    struct object_file *of;
+    struct symbol *symbol;
+    
+    struct section_part *part = section_part_new (section, 0);
+    unsigned long pos = 0, i;
+    
+    for (of = all_object_files; of; of = of->next) {
+    
+        for (i = 0; i < of->symbol_cnt; i++) {
+        
+            symbol = of->symbol_arr + i;
+            
+            if (symbol->auxiliary || symbol_is_undefined (symbol) || (symbol->flags & SYMBOL_FLAG_SECTION_SYMBOL) || !symbol->name) {
+                continue;
+            }
+            
+            if (!(symbol = symbol_find (symbol->name))) {
+                continue;
+            }
+            
+            part->content_size += (strlen (symbol->name) + 1);
+        
+        }
+    
+    }
+    
+    if (!part->content_size) {
+    
+        free (part);
+        return;
+    
+    }
+    
+    part->content = xmalloc (part->content_size);
+    
+    for (of = all_object_files; of; of = of->next) {
+    
+        for (i = 0; i < of->symbol_cnt; i++) {
+        
+            symbol = of->symbol_arr + i;
+            
+            if (symbol->auxiliary || symbol_is_undefined (symbol) || (symbol->flags & SYMBOL_FLAG_SECTION_SYMBOL) || !symbol->name) {
+                continue;
+            }
+            
+            if (!(symbol = symbol_find (symbol->name))) {
+                continue;
+            }
+            
+            pos += (sprintf ((char *) part->content + pos, "%s", symbol->name) + 1);
+        
+        }
+    
+    }
+    
+    section_append_section_part (section, part);
+
+}
+
+static void generate_symbols_table (unsigned long offset) {
+
+    struct section *section = section_find_or_make (".data");
+    
+    struct object_file *of;
+    struct symbol *symbol;
+    
+    struct section_part *part = section_part_new (section, 0);
+    unsigned long pos = 0, i;
+    
+    for (of = all_object_files; of; of = of->next) {
+    
+        for (i = 0; i < of->symbol_cnt; i++) {
+        
+            symbol = of->symbol_arr + i;
+            
+            if (symbol->auxiliary || symbol_is_undefined (symbol) || (symbol->flags & SYMBOL_FLAG_SECTION_SYMBOL) || !symbol->name) {
+                continue;
+            }
+            
+            if (!(symbol = symbol_find (symbol->name))) {
+                continue;
+            }
+            
+            part->content_size += 8;
+        
+        }
+    
+    }
+    
+    if (!part->content_size) {
+
+        free (part);
+        return;
+
+    }
+    
+    if ((symbol = symbol_find ("__symbol_table_start")) && symbol_is_undefined (symbol)) {
+    
+        of = object_file_make (FAKE_LD_FILENAME, 1);
+        
+        symbol = of->symbol_arr;
+        symbol->name = xstrdup ("__symbol_table_start");
+        
+        symbol->section_number = ABSOLUTE_SECTION_NUMBER;
+        symbol->value = offset;
+        
+        symbol_record_external_symbol (symbol);
+    
+    }
+    
+    part->content = xmalloc (part->content_size);
+    
+    if ((symbol = symbol_find ("__symbol_table_end")) && symbol_is_undefined (symbol)) {
+    
+        of = object_file_make (FAKE_LD_FILENAME, 1);
+        
+        symbol = of->symbol_arr;
+        symbol->name = xstrdup ("__symbol_table_end");
+        
+        symbol->section_number = ABSOLUTE_SECTION_NUMBER;
+        symbol->value = offset + part->content_size;
+        
+        symbol_record_external_symbol (symbol);
+    
+    }
+    
+    section->total_size += part->content_size;
+    
+    for (of = all_object_files; of; of = of->next) {
+    
+        for (i = 0; i < of->symbol_cnt; i++) {
+        
+            symbol = of->symbol_arr + i;
+            
+            if (symbol->auxiliary || symbol_is_undefined (symbol) || (symbol->flags & SYMBOL_FLAG_SECTION_SYMBOL) || !symbol->name) {
+                continue;
+            }
+            
+            if (!(symbol = symbol_find (symbol->name))) {
+                continue;
+            }
+            
+            integer_to_array (symbol_get_value_no_base (symbol), part->content + pos, 4);
+            pos += 4;
+            
+            integer_to_array (offset, part->content + pos, 4);
+            pos += 4;
+            
+            offset += strlen (symbol->name) + 1;
+        
+        }
+    
+    }
+    
+    section_append_section_part (section, part);
+
+}
+
 static void check_unresolved (void) {
 
     struct object_file *of;
@@ -398,15 +562,38 @@ static unsigned long align_section_if_needed (unsigned long value) {
 
 void link (void) {
 
+    unsigned long value = 0, offset = 0;
+    
     struct section *section;
-    unsigned long value = 0;
+    struct section_part *part;
     
     struct object_file *of;
     struct symbol *symbol;
     
     collapse_subsections ();
+    
+    if (state->generate_symbols_table) {
+        output_symbols ();
+    }
+    
     calculate_section_sizes_and_rvas ();
     
+    if (state->generate_symbols_table) {
+    
+        if ((section = section_find (".data"))) {
+        
+            offset += (section->rva % 16);
+            
+            for (part = section->first_part; part; part = part->next) {
+                offset += part->content_size;
+            }
+            
+            generate_symbols_table (offset);
+        
+        }
+    
+    }
+    
     if ((symbol = symbol_find ("__edata")) && symbol_is_undefined (symbol)) {
     
         if ((section = section_find (".text"))) {
@@ -443,7 +630,7 @@ void link (void) {
         symbol->name = xstrdup ("__end");
         
         symbol->section_number = ABSOLUTE_SECTION_NUMBER;
-        symbol->value = value % 16;
+        symbol->value = value/* % 16*/;
         
         symbol_record_external_symbol (symbol);
     
index f8a9d482100f71212fdcbd448bf530357c00f5a6..c4e2c32baab04c8c547568d4d746acd9b9c106e0 100644 (file)
--- a/section.c
+++ b/section.c
@@ -140,8 +140,12 @@ void section_write (struct section *section, unsigned char *memory) {
     
     for (part = section->first_part; part; part = part->next) {
     
-        memcpy (memory, part->content, part->content_size);
-        memory += part->content_size;
+        if (part->content_size > 0) {
+        
+            memcpy (memory, part->content, part->content_size);
+            memory += part->content_size;
+        
+        }
     
     }