};
-#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 }
};
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");
}
+ case LD_OPTION_GENERATE_SYMBOLS_TABLE: {
+
+ state->generate_symbols_table = 1;
+ break;
+
+ }
+
case LD_OPTION_HELP: {
print_usage ();
* @file link.c
*****************************************************************************/
#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "ld.h"
};
+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;
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"))) {
symbol->name = xstrdup ("__end");
symbol->section_number = ABSOLUTE_SECTION_NUMBER;
- symbol->value = value % 16;
+ symbol->value = value/* % 16*/;
symbol_record_external_symbol (symbol);