From 89e87af7430a7a2726be9b028b5e07f4df7fe8bf Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Thu, 12 Dec 2024 17:34:20 +0000 Subject: [PATCH] Generate symbol table relative to the data section --- ld.h | 2 + lib.c | 62 ++++++++++-------- link.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++- section.c | 8 ++- 4 files changed, 233 insertions(+), 30 deletions(-) diff --git a/ld.h b/ld.h index ddfdf9e..b500a3e 100644 --- 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 d82463c..4fd0116 100644 --- 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 b478f5f..2cf0921 100644 --- a/link.c +++ b/link.c @@ -2,6 +2,8 @@ * @file link.c *****************************************************************************/ #include +#include +#include #include #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); diff --git a/section.c b/section.c index f8a9d48..c4e2c32 100644 --- 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; + + } } -- 2.34.1