CC := gcc
CFLAGS := -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
-CSRC := aout.c coff.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
+CSRC := aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
ifeq ($(OS), Windows_NT)
all: slink.exe
CC := gcc
CFLAGS := -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra
-CSRC := aout.c coff.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
+CSRC := aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
all: slink.exe
SRCDIR ?= $(CURDIR)
VPATH := $(SRCDIR)
-SRC := aout.c coff.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
+SRC := aout.c coff.c dx.c elf.c elks.c hashtab.c ld.c lib.c link.c macho.c map.c mz.c omf.c pe.c report.c section.c symbol.c vector.c write7x.c
all: slink.exe
--- /dev/null
+/******************************************************************************
+ * @file dx.c
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dx.h"
+#include "ld.h"
+#include "lib.h"
+#include "reloc.h"
+#include "report.h"
+#include "section.h"
+#include "symbol.h"
+
+static unsigned long section_alignment = DEFAULT_SECTION_ALIGNMENT;
+
+static unsigned long section_get_num_relocs (struct section *section) {
+
+ unsigned long num_relocs = 0, i;
+
+ struct section_part *part;
+ struct reloc_howto *howto;
+
+ for (part = section->first_part; part; part = part->next) {
+
+ for (i = 0; i < part->reloc_cnt; i++) {
+
+ howto = part->reloc_arr[i].howto;
+
+ if (howto == &reloc_howtos[RELOC_TYPE_64] || howto == &reloc_howtos[RELOC_TYPE_32] || howto == &reloc_howtos[RELOC_TYPE_16] || howto == &reloc_howtos[RELOC_TYPE_8]) {
+ num_relocs++;
+ }
+
+ }
+
+ }
+
+ return num_relocs;
+
+}
+
+static unsigned char *write_relocs_for_section (unsigned char *pos, struct section *section) {
+
+ struct section_part *part;
+ struct dx_relocation_info rel;
+
+ struct symbol *symbol;
+ unsigned long size_log2, i, r_symbolnum;
+
+ for (part = section->first_part; part; part = part->next) {
+
+ for (i = 0; i < part->reloc_cnt; i++) {
+
+ memset (&rel, 0, sizeof (rel));
+
+ if (part->reloc_arr[i].howto == &reloc_howtos[RELOC_TYPE_64]) {
+ size_log2 = 3;
+ } else if (part->reloc_arr[i].howto == &reloc_howtos[RELOC_TYPE_32]) {
+ size_log2 = 2;
+ } else if (part->reloc_arr[i].howto == &reloc_howtos[RELOC_TYPE_16]) {
+ size_log2 = 1;
+ } else if (part->reloc_arr[i].howto == &reloc_howtos[RELOC_TYPE_8]) {
+ size_log2 = 0;
+ } else {
+ continue;
+ }
+
+ symbol = part->reloc_arr[i].symbol;
+
+ if (symbol_is_undefined (symbol)) {
+ symbol = symbol_find (symbol->name);
+ }
+
+ integer_to_array (part->rva - part->section->rva + part->reloc_arr[i].offset, rel.r_address, 4, 0);
+
+ if (!symbol->part || strcmp (symbol->part->section->name, ".text") == 0) {
+ r_symbolnum = N_TEXT;
+ } else if (strcmp (symbol->part->section->name, ".data") == 0) {
+ r_symbolnum = N_DATA;
+ } else if (strcmp (symbol->part->section->name, ".bss") == 0) {
+ r_symbolnum = N_BSS;
+ } else {
+ r_symbolnum = N_TEXT;
+ }
+
+ if ((part->reloc_arr[i].r_symbolnum >> 27) & 1) {
+ r_symbolnum |= (1LU << 27);
+ }
+
+ integer_to_array (r_symbolnum | (size_log2 << 25), rel.r_symbolnum, 4, 0);
+
+ memcpy (pos, &rel, sizeof (rel));
+ pos += sizeof (rel);
+
+ }
+
+ }
+
+ return pos;
+
+}
+
+void dx_write (const char *filename) {
+
+ FILE *fp;
+
+ unsigned char *data, *pos;
+ unsigned long image_size;
+
+ struct section *text_section, *data_section, *bss_section;
+ unsigned long text_size = 0, data_size = 0, bss_size = 0;
+
+ struct dx_exec exec;
+ memset (&exec, 0, sizeof (exec));
+
+ if (!(fp = fopen (filename, "wb"))) {
+
+ report_at (program_name, 0, REPORT_ERROR, "failed to open '%s' for writing", filename);
+ return;
+
+ }
+
+ text_section = section_find (".text");
+ data_section = section_find (".data");
+ bss_section = section_find (".bss");
+
+ integer_to_array (DX_MAGIC, exec.a_magic, 4, 0);
+
+ exec.a_cpu = (state->format == LD_FORMAT_I386_DX) ? 0x10 : 0x04;
+ exec.a_hdrlen = sizeof (exec);
+
+ if (text_section) {
+
+ if (state->impure) {
+ text_size = text_section->total_size;
+ } else {
+ text_size = ALIGN (text_section->total_size, section_alignment);
+ }
+
+ }
+
+ if (data_section) {
+
+ if (state->impure) {
+ data_size = data_section->total_size;
+ } else {
+ data_size = ALIGN (data_section->total_size, section_alignment);
+ }
+
+ }
+
+ if (bss_section) {
+
+ if (state->impure) {
+ bss_size = bss_section->total_size;
+ } else {
+ bss_size = ALIGN (bss_section->total_size, section_alignment);
+ }
+
+ }
+
+ integer_to_array (text_size, exec.a_text, 4, 0);
+ integer_to_array (data_size, exec.a_data, 4, 0);
+
+ integer_to_array (bss_size, exec.a_bss, 4, 0);
+ integer_to_array (state->entry_point, exec.a_entry, 4, 0);
+
+ integer_to_array (array_to_integer (exec.a_text, 4, 0) + array_to_integer (exec.a_data, 4, 0), exec.a_total, 4, 0);
+
+ if (text_section) {
+ integer_to_array (section_get_num_relocs (text_section) * sizeof (struct dx_relocation_info), exec.a_trsize, 4, 0);
+ }
+
+ if (data_section) {
+ integer_to_array (section_get_num_relocs (data_section) * sizeof (struct dx_relocation_info), exec.a_drsize, 4, 0);
+ }
+
+ image_size = sizeof (exec);
+
+ image_size += (array_to_integer (exec.a_text, 4, 0) + array_to_integer (exec.a_data, 4, 0));
+ image_size += (array_to_integer (exec.a_trsize, 4, 0) + array_to_integer (exec.a_drsize, 4, 0));
+
+ image_size += 4;
+
+ data = xmalloc (image_size);
+ memcpy (data, &exec, sizeof (exec));
+
+ pos = data + sizeof (exec);
+
+ if (text_section) {
+ section_write (text_section, pos);
+ }
+
+ pos += array_to_integer (exec.a_text, 4, 0);
+
+ if (data_section) {
+ section_write (data_section, pos);
+ }
+
+ pos += array_to_integer (exec.a_data, 4, 0);
+
+ if (text_section) {
+ pos = write_relocs_for_section (pos, text_section);
+ }
+
+ if (data_section) {
+ pos = write_relocs_for_section (pos, data_section);
+ }
+
+ integer_to_array (4, pos, 4, 0);
+
+ if (fwrite (data, image_size, 1, fp) != 1) {
+ report_at (program_name, 0, REPORT_ERROR, "failed to write data to '%s'", filename);
+ }
+
+ free (data);
+ fclose (fp);
+
+}
+
+
+void dx_before_link (void) {
+
+ if (!state->impure) {
+
+ struct section *section;
+
+ for (section = all_sections; section; section = section->next) {
+
+ if (section->section_alignment < section_alignment) {
+ section->section_alignment = section_alignment;
+ }
+
+ }
+
+ }
+
+}
--- /dev/null
+/******************************************************************************
+ * @file dx.h
+ *****************************************************************************/
+#ifndef _DX_H
+#define _DX_H
+
+struct dx_exec {
+
+ /* offset 0 */
+ unsigned char a_magic[2];
+ unsigned char a_flags;
+ unsigned char a_cpu;
+ unsigned char a_hdrlen;
+ unsigned char a_unused;
+ unsigned char a_version[2];
+
+ /* offset 8 */
+ unsigned char a_text[4];
+ unsigned char a_data[4];
+ unsigned char a_bss[4];
+ unsigned char a_entry[4];
+ unsigned char a_total[4];
+ unsigned char a_syms[4];
+
+ /* offset 32 */
+ unsigned char a_trsize[4];
+ unsigned char a_drsize[4];
+ unsigned char a_trbase[4];
+ unsigned char a_drbase[4];
+
+};
+
+#define N_UNDF 0x00
+#define N_ABS 0x02
+#define N_TEXT 0x04
+#define N_DATA 0x06
+#define N_BSS 0x08
+#define N_COMM 0x12
+
+struct dx_relocation_info {
+
+ unsigned char r_address[4];
+ unsigned char r_symbolnum[4];
+
+};
+
+#define N_EXT 0x01
+
+struct dx_nlist {
+
+ unsigned char n_strx[4];
+ unsigned char n_type;
+
+ unsigned char n_other;
+ unsigned char n_desc[2];
+
+ unsigned char n_value[4];
+
+};
+
+#define DX_MAGIC 0x5844
+#define N_TYPE 0x1e
+
+void dx_before_link (void);
+void dx_write (const char *filename);
+
+#endif /* _DX_H */
}
-#define ELF64_R_SYM(i) ((i) >> 32)
-#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#ifndef NO_LONG_LONG
+# define ELF64_R_SYM(i) ((i) >> 32)
+# define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#endif
static void translate_relocation64_addend (const char *filename, struct reloc_entry *reloc, struct elf64_rela *input_reloc, struct section_part *part, int endianess) {
- uint64_t r_info = array_to_integer (input_reloc->r_info, 8, endianess);
- uint64_t r_offset = array_to_integer (input_reloc->r_offset, 8, endianess);
-
- uint32_t symbol_index = ELF64_R_SYM (r_info), rel_type = ELF64_R_TYPE (r_info);
+ uint64_t r_info, r_offset;
+ uint32_t symbol_index, rel_type;
+
+#if defined (NO_LONG_LONG)
+ r_info = array_to_integer (input_reloc->r_info + 4, 4, endianess);
+ r_offset = array_to_integer (input_reloc->r_offset, 4, endianess);
+
+ rel_type = array_to_integer (input_reloc->r_info, 4, endianess);
+ symbol_index = r_info;
+#else
+ r_info = array_to_integer (input_reloc->r_info, 8, endianess);
+ r_offset = array_to_integer (input_reloc->r_offset, 8, endianess);
+
+ symbol_index = ELF64_R_SYM (r_info);
+ rel_type = ELF64_R_TYPE (r_info);
+#endif
if (symbol_index >= part->of->symbol_cnt) {
void elf_before_link (void);
void read_elf32_object (const char *filename, unsigned char *data, unsigned long data_size, int endianess);
-void read_elf64_object (const char *filename, unsigned char *data, unsigned long data_size, int endianess);
-
void elf32_write (const char *filename);
+
+void read_elf64_object (const char *filename, unsigned char *data, unsigned long data_size, int endianess);
void elf64_write (const char *filename);
#include "stdint.h"
image_size += 4;
data = xmalloc (image_size);
- data = xmalloc (data_size);
memcpy (data, &exec, sizeof (exec));
pos = data + sizeof (exec);
};
-#define N_TYPE 0x1e
#define ELKS_MAGIC 0403
+#define N_TYPE 0x1e
void read_elks_object (const char *filename, unsigned char *data, unsigned long data_size);
# define I64_FMT "I64"
#elif defined (__PRI_64_LENGTH_MODIFIER__) /* Mac */
# define I64_FMT __PRI_64_LENGTH_MODIFIER__
-#elif (defined (SIZEOF_LONG) && SIZEOF_LONG >= 8) || ULONG_MAX > 4294967295UL
+#elif (defined (SIZEOF_LONG) && SIZEOF_LONG >= 8) || ((ULONG_MAX >> 16) >> 16) == 0xffffffff
# define I64_FMT "l"
#else
# define I64_FMT "ll"
#include "aout.h"
#include "ar.h"
#include "coff.h"
+#include "dx.h"
#include "elf.h"
#include "elks.h"
#include "ld.h"
}
- if (state->format == LD_FORMAT_I386_AOUT || state->format == LD_FORMAT_I386_ELKS || state->format == LD_FORMAT_IA16_ELKS || state->format == LD_FORMAT_MZ) {
+ if (state->format == LD_FORMAT_I386_AOUT || state->format == LD_FORMAT_I386_DX || state->format == LD_FORMAT_IA16_DX || state->format == LD_FORMAT_I386_ELKS || state->format == LD_FORMAT_IA16_ELKS || state->format == LD_FORMAT_MZ) {
section_find_or_make (".text");
section_find_or_make (".data");
section_find_or_make (".bss");
+
+ if (state->format == LD_FORMAT_IA16_DX) {
+ state->impure = 1;
+ }
}
state->base_address = 0x00400000;
}
+ } else if (state->format == LD_FORMAT_AMD64_ELF || state->format == LD_FORMAT_I386_ELF) {
+ state->base_address = 0x0040000;
+#if defined(NO_LONG_LONG)
+ } else if (state->format == LD_FORMAT_AMD64_MACHO || state->format == LD_FORMAT_AARCH64_MACHO) {
+ state->base_address = 0x10000000;
+ } else if (state->format == LD_FORMAT_AARCH64_ELF) {
+ state->base_address = 0x14000000;
+ }
+#else
} else if (state->format == LD_FORMAT_AMD64_MACHO || state->format == LD_FORMAT_AARCH64_MACHO) {
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;
}
-
+#endif
}
if (state->format == LD_FORMAT_I386_AOUT) {
aout_before_link ();
} else if (state->format == LD_FORMAT_I386_COFF) {
coff_before_link ();
+ } else if (state->format == LD_FORMAT_I386_DX) {
+ dx_before_link ();
} else if (state->format == LD_FORMAT_I386_ELKS) {
elks_before_link ();
} else if (state->format == LD_FORMAT_I386_PE) {
mz_write (state->output_filename);
} else if (state->format == LD_FORMAT_I386_AOUT) {
aout_write (state->output_filename);
+ } else if (state->format == LD_FORMAT_I386_DX || state->format == LD_FORMAT_IA16_DX) {
+ dx_write (state->output_filename);
} else if (state->format == LD_FORMAT_I386_ELKS || state->format == LD_FORMAT_IA16_ELKS) {
elks_write (state->output_filename);
} else if (state->format == LD_FORMAT_I386_ELF) {
elf32_write (state->output_filename);
- } 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) {
pe_after_link ();
coff_after_link ();
coff_write (state->output_filename);
+ } 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_AMD64_MACHO || state->format == LD_FORMAT_AARCH64_MACHO) {
macho_write (state->output_filename);
}
#define LD_EMULATION_NONE 0x00
-#define LD_EMULATION_IA16_ELKS 0x01
+#define LD_EMULATION_IA16_DX 0x01
#define LD_EMULATION_IA16_MZ 0x02
#define LD_EMULATION_I386_AOUT 0x03
#define LD_EMULATION_I386_COFF 0x04
-#define LD_EMULATION_I386_ELKS 0x05
+#define LD_EMULATION_I386_DX 0x05
#define LD_EMULATION_I386_PE 0x06
#define LD_EMULATION_MACHO 0x07
#define LD_FORMAT_COM 0x00
#define LD_FORMAT_MZ 0x01
#define LD_FORMAT_BIN 0x02
+
#define LD_FORMAT_IA16_ELKS 0x03
+#define LD_FORMAT_IA16_DX 0x04
-#define LD_FORMAT_I386_ELKS (LD_TARGET_MACHINE_I386 | 0x04)
-#define LD_FORMAT_I386_AOUT (LD_TARGET_MACHINE_I386 | 0x05)
-#define LD_FORMAT_I386_COFF (LD_TARGET_MACHINE_I386 | 0x06)
-#define LD_FORMAT_I386_PE (LD_TARGET_MACHINE_I386 | 0x07)
-#define LD_FORMAT_I386_ELF (LD_TARGET_MACHINE_I386 | 0x08)
+#define LD_FORMAT_I386_ELKS (LD_TARGET_MACHINE_I386 | 0x05)
+#define LD_FORMAT_I386_DX (LD_TARGET_MACHINE_I386 | 0x06)
+#define LD_FORMAT_I386_AOUT (LD_TARGET_MACHINE_I386 | 0x07)
+#define LD_FORMAT_I386_COFF (LD_TARGET_MACHINE_I386 | 0x08)
+#define LD_FORMAT_I386_PE (LD_TARGET_MACHINE_I386 | 0x09)
+#define LD_FORMAT_I386_ELF (LD_TARGET_MACHINE_I386 | 0x10)
-#define LD_FORMAT_AMD64_MACHO (LD_TARGET_MACHINE_AMD64 | 0x09)
-#define LD_FORMAT_AMD64_ELF (LD_TARGET_MACHINE_AMD64 | 0x10)
+#define LD_FORMAT_AMD64_MACHO (LD_TARGET_MACHINE_AMD64 | 0x11)
+#define LD_FORMAT_AMD64_ELF (LD_TARGET_MACHINE_AMD64 | 0x12)
-#define LD_FORMAT_AARCH64_MACHO (LD_TARGET_MACHINE_AARCH64 | 0x11)
-#define LD_FORMAT_AARCH64_ELF (LD_TARGET_MACHINE_AARCH64 | 0x12)
+#define LD_FORMAT_AARCH64_MACHO (LD_TARGET_MACHINE_AARCH64 | 0x13)
+#define LD_FORMAT_AARCH64_ELF (LD_TARGET_MACHINE_AARCH64 | 0x14)
extern struct ld_state *state;
case LD_OPTION_EMULATION: {
- if (xstrcasecmp (optarg, "ia16_elks") == 0) {
+ if (xstrcasecmp (optarg, "ia16_dx") == 0) {
- state->emulation = LD_EMULATION_IA16_ELKS;
+ state->emulation = LD_EMULATION_IA16_DX;
break;
}
}
- if (xstrcasecmp (optarg, "i386elks") == 0) {
+ if (xstrcasecmp (optarg, "i386dx") == 0) {
- state->emulation = LD_EMULATION_I386_ELKS;
+ state->emulation = LD_EMULATION_I386_DX;
break;
}
}
+ if (xstrcasecmp (optarg, "dx-ia16") == 0) {
+
+ state->format = LD_FORMAT_IA16_DX;
+
+ if (state->emulation == LD_EMULATION_NONE) {
+ state->emulation = LD_EMULATION_IA16_DX;
+ }
+
+ break;
+
+ }
+
+ if (xstrcasecmp (optarg, "dx-i386") == 0) {
+
+ state->format = LD_FORMAT_I386_DX;
+
+ if (state->emulation == LD_EMULATION_NONE) {
+ state->emulation = LD_EMULATION_I386_DX;
+ }
+
+ break;
+
+ }
+
if (xstrcasecmp (optarg, "elks-ia16") == 0) {
state->format = LD_FORMAT_IA16_ELKS;
- if (state->emulation == LD_EMULATION_NONE) {
+ /*if (state->emulation == LD_EMULATION_NONE) {
state->emulation = LD_EMULATION_IA16_ELKS;
- }
+ }*/
break;
state->format = LD_FORMAT_I386_ELKS;
- if (state->emulation == LD_EMULATION_NONE) {
+ /*if (state->emulation == LD_EMULATION_NONE) {
state->emulation = LD_EMULATION_I386_ELKS;
- }
+ }*/
break;
uint64_t value = 0;
int i;
-#if defined (NO_LONG_LONG) && ULONG_MAX <= 4294967295UL
+#if defined (NO_LONG_LONG) && ((ULONG_MAX >> 16) >> 16) < 0xffffffff
if (size == 8) { size = 4; }
#endif
void integer_to_array (uint64_t value, unsigned char *dest, int size, int big_endian) {
-#if defined (NO_LONG_LONG) && ULONG_MAX <= 4294967295UL
+#if defined (NO_LONG_LONG) && ((ULONG_MAX >> 16) >> 16) < 0xffffffff
if (size == 8) { size = 4; }
#endif
}
- if (state->emulation == LD_EMULATION_IA16_ELKS || state->emulation == LD_EMULATION_IA16_MZ) {
+ if (state->emulation == LD_EMULATION_IA16_DX || state->emulation == LD_EMULATION_IA16_MZ) {
if (opcode == 0x9A || opcode == 0xFF || rel->n_type == 4) {
}
- if (state->emulation == LD_EMULATION_IA16_ELKS || state->emulation == LD_EMULATION_IA16_MZ) {
+ if (state->emulation == LD_EMULATION_IA16_DX || state->emulation == LD_EMULATION_IA16_MZ) {
value = 0;
uint64_t result = array_to_integer (p->part->content + p->reloc_entry->offset, 8, 0);
result -= state->base_address;
-#if !defined (NO_LONG_LONG) || ULONG_MAX > 4294967295UL
+#if defined (NO_LONG_LONG) && ((ULONG_MAX >> 16) >> 16) < 0xffffffff
+
+ integer_to_array (result, p->part->content + p->reloc_entry->offset, 4, 0);
+
+ if (p + 1 != part_rels + num_relocs) {
+
+ uint64_t rva1, rva2;
+
+ rva1 = p->part->rva + p->reloc_entry->offset;
+ rva2 = p[1].part->rva + p[1].reloc_entry->offset;
+
+ if (FLOOR_TO (rva1, PAGE_SIZE) != FLOOR_TO (rva2, PAGE_SIZE)) {
+
+ p++;
+ break;
+
+ }
+
+ result = (((rva2 - rva1) / 4) & 0xfff) << 19;
+ integer_to_array (result, p->part->content + p->reloc_entry->offset + 4, 4, 0);
+
+ }
+
+#else
result &= 0xfffffffff;
result |= (((rva2 - rva1) / 4) & 0xfff) << 51;
}
-
-#endif
integer_to_array (result, p->part->content + p->reloc_entry->offset, 8, 0);
+
+#endif
}
#ifndef _INT64_T
#define _INT64_T
-#if defined (NO_LONG_LONG) || ULONG_MAX > 4294967295UL
+#if defined (NO_LONG_LONG) || ((ULONG_MAX >> 16) >> 16) == 0xffffffff
typedef signed long int64_t;
#else
typedef signed long long int64_t;
#ifndef _UINT64_T
#define _UINT64_T
-#if defined (NO_LONG_LONG) || ULONG_MAX > 4294967295UL
+#if defined (NO_LONG_LONG) || ((ULONG_MAX >> 16) >> 16) == 0xffffffff
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;