LD=ld386
COPTS=-S -O2 -fno-common -ansi -I. -I./include -I../pdos/pdpclib -I../pdos/src -D__PDOS386__ -D__32BIT__ -D__NOBIVA__ -D__PDOS__ -Wall -Werror -ansi -m32 -pedantic
-COBJ=aout.o coff.o elks.o hashtab.o ld.o lib.o link.o map.o pe.o report.o section.o symbol.o vector.o write7x.o
+COBJ=aout.o coff.o elks.o hashtab.o ld.o lib.o link.o map.o mz.o pe.o report.o section.o symbol.o vector.o write7x.o
all: clean slink.exe
LD=ldwin
COPTS=-S -O2 -fno-common -ansi -I. -I./include -I../pdos/pdpclib -I../pdos/src -D__WIN32__ -D__NOBIVA__ -D__PDOS__ -Wall -Werror -ansi -m32 -pedantic
-COBJ=aout.o coff.o elks.o hashtab.o ld.o lib.o link.o map.o pe.o report.o section.o symbol.o vector.o write7x.o
+COBJ=aout.o coff.o elks.o hashtab.o ld.o lib.o link.o map.o mz.o pe.o report.o section.o symbol.o vector.o write7x.o
all: clean slink.exe
CC := gcc
CFLAGS := -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
-CSRC := aout.c coff.c elks.c hashtab.c ld.c lib.c link.c map.c pe.c report.c section.c symbol.c vector.c write7x.c
+CSRC := aout.c coff.c elks.c hashtab.c ld.c lib.c link.c map.c mz.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 -ansi -pedantic -std=c90
-CSRC := aout.c coff.c elks.c hashtab.c ld.c lib.c link.c map.c pe.c report.c section.c symbol.c vector.c write7x.c
+CSRC := aout.c coff.c elks.c hashtab.c ld.c lib.c link.c map.c mz.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 elks.c hashtab.c ld.c lib.c link.c map.c pe.c report.c section.c symbol.c vector.c write7x.c
+SRC := aout.c coff.c elks.c hashtab.c ld.c lib.c link.c map.c mz.c pe.c report.c section.c symbol.c vector.c write7x.c
all: slink.exe
reloc->symbolnum = r_symbolnum;
reloc->offset = r_address;
+ reloc->n_type = 24;
+ reloc->n_ext = 27;
switch (1U << ((r_symbolnum >> 25) & 3)) {
reloc->symbolnum = r_symbolnum;
reloc->offset = r_address;
+ reloc->n_type = 28;
+ reloc->n_ext = 31;
switch (1U << ((r_symbolnum >> 29) & 3)) {
#include "elks.h"
#include "ld.h"
#include "lib.h"
+#include "mz.h"
#include "pe.h"
#include "report.h"
#include "section.h"
}
- if (state->format == LD_FORMAT_I386_AOUT || state->format == LD_FORMAT_I386_ELKS || state->format == LD_FORMAT_IA16_ELKS) {
+ if (state->format == LD_FORMAT_I386_AOUT || 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");
free (data);
fclose (fp);
+ } else if (state->format == LD_FORMAT_MZ) {
+ 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_ELKS || state->format == LD_FORMAT_IA16_ELKS) {
};
#define LD_FORMAT_COM 0x00
-#define LD_FORMAT_BIN 0x01
+#define LD_FORMAT_MZ 0x01
+#define LD_FORMAT_BIN 0x02
-#define LD_FORMAT_IA16_ELKS 0x02
-#define LD_FORMAT_I386_ELKS 0x03
+#define LD_FORMAT_IA16_ELKS 0x03
+#define LD_FORMAT_I386_ELKS 0x04
-#define LD_FORMAT_I386_AOUT 0x04
-#define LD_FORMAT_I386_COFF 0x05
-#define LD_FORMAT_I386_PE 0x06
+#define LD_FORMAT_I386_AOUT 0x05
+#define LD_FORMAT_I386_COFF 0x06
+
+#define LD_FORMAT_I386_PE 0x07
extern struct ld_state *state;
extern const char *program_name;
}
+ if (xstrcasecmp (optarg, "msdos-mz") == 0) {
+
+ state->format = LD_FORMAT_MZ;
+ break;
+
+ }
+
if (xstrcasecmp (optarg, "elks-ia16") == 0) {
state->format = LD_FORMAT_IA16_ELKS;
if (state->format == LD_FORMAT_BIN || state->format == LD_FORMAT_COM) {
- if (!((rel->symbolnum >> 31) & 1)/* || (symbol->n_type & N_TYPE) == N_BSS || (symbol->n_type & N_TYPE) == N_DATA || (symbol->n_type & N_TYPE) == N_TEXT*/) {
+ if (!((rel->symbolnum >> rel->n_ext) & 1)/* || (symbol->n_type & N_TYPE) == N_BSS || (symbol->n_type & N_TYPE) == N_DATA || (symbol->n_type & N_TYPE) == N_TEXT*/) {
/*report_at (__FILE__, __LINE__, REPORT_FATAL_ERROR, "symbol: %s, %lx", symbol->name, ((rel->symbolnum) >> 28));*/
- if (((rel->symbolnum >> 27) & 1) || (((rel->symbolnum) >> 28) & 0xff) != N_ABS) {
+ if (((rel->symbolnum >> 27) & 1) || ((rel->symbolnum >> rel->n_type) & 0xff) != N_ABS) {
report_at (program_name, 0, REPORT_ERROR, "%s:(%s+%#lu): segment relocation", part->of->filename, part->section->name, offset);
}
}
+ } else if (state->format == LD_FORMAT_MZ) {
+
+ if (((rel->symbolnum >> rel->n_type) & 0xff) == N_ABS) {
+
+ if (rel->howto == &reloc_howtos[RELOC_TYPE_64]) {
+ rel->howto = &reloc_howtos[RELOC_TYPE_PC64];
+ } else if (rel->howto == &reloc_howtos[RELOC_TYPE_32]) {
+ rel->howto = &reloc_howtos[RELOC_TYPE_PC32];
+ } else if (rel->howto == &reloc_howtos[RELOC_TYPE_16]) {
+ rel->howto = &reloc_howtos[RELOC_TYPE_PC16];
+ } else if (rel->howto == &reloc_howtos[RELOC_TYPE_8]) {
+ rel->howto = &reloc_howtos[RELOC_TYPE_PC8];
+ }
+
+ }
+
}
if (xstrcasecmp (symbol->name, "__etext") == 0 || xstrcasecmp (symbol->name, "__edata") == 0 || xstrcasecmp (symbol->name, "__end") == 0) {
--- /dev/null
+/******************************************************************************
+ * @file mz.c
+ *****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ld.h"
+#include "lib.h"
+#include "mz.h"
+#include "report.h"
+#include "section.h"
+#include "symbol.h"
+#include "write7x.h"
+
+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_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;
+ unsigned long i, addr;
+
+ for (part = section->first_part; part; part = part->next) {
+
+ for (i = 0; i < part->reloc_cnt; i++) {
+
+ if (part->reloc_arr[i].howto == &reloc_howtos[RELOC_TYPE_8] || part->reloc_arr[i].howto == &reloc_howtos[RELOC_TYPE_16] || part->reloc_arr[i].howto == &reloc_howtos[RELOC_TYPE_32]) {
+
+ addr = part->rva + part->reloc_arr[i].offset;
+
+ integer_to_array (addr % 16, pos, 2);
+ pos += 2;
+
+ integer_to_array (addr / 16, pos, 2);
+ pos += 2;
+
+ }
+
+ }
+
+ }
+
+ return pos;
+
+}
+
+void mz_write (const char *filename) {
+
+ FILE *fp;
+
+ unsigned char *data, *pos;
+ unsigned long data_size;
+
+ struct section *text_section, *data_section, *bss_section;
+ unsigned long header_size;
+
+ unsigned long reloc_size = 0, reloc_count = 0;
+ unsigned long ibss_addr = 0, ibss_size = 0;
+ unsigned long stack_addr = 0, stack_size = 0;
+
+ struct mz_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");
+
+ if (text_section) {
+ reloc_count += section_get_num_relocs (text_section);
+ }
+
+ if (data_section) {
+ reloc_count += section_get_num_relocs (data_section);
+ }
+
+ reloc_size = ALIGN (reloc_count * 4, 32);
+ header_size = ALIGN (sizeof (exec), 16);
+
+ if (data_section) {
+
+ ibss_addr += data_section->rva;
+
+ if (bss_section) {
+ ibss_addr += bss_section->rva - data_section->rva;
+ } else {
+ ibss_addr += data_section->total_size;
+ }
+
+ } else {
+
+ if (bss_section) {
+ ibss_addr += bss_section->rva;
+ } else {
+ ibss_addr += text_section ? text_section->total_size : 0;
+ }
+
+ }
+
+ ibss_addr = ibss_addr + reloc_size;
+
+ if (bss_section) {
+ ibss_size = bss_section->total_size;
+ }
+
+ stack_addr = ibss_addr + ibss_size;
+ stack_size = 0x1000; /* Maybe get this from command line in future. */
+
+ exec.e_magic[0] = 'M';
+ exec.e_magic[1] = 'Z';
+
+ write721_to_byte_array (exec.e_cblp, (ibss_addr % 512));
+ write721_to_byte_array (exec.e_cp, ALIGN (ibss_addr, 512) / 512);
+
+ write721_to_byte_array (exec.e_crlc, reloc_count);
+ write721_to_byte_array (exec.e_cparhdr, (header_size + reloc_size) / 16);
+
+ write721_to_byte_array (exec.e_minalloc, (ALIGN (ibss_size + stack_size, 16) / 16));
+ write721_to_byte_array (exec.e_maxalloc, 0xFFFF);
+
+ write721_to_byte_array (exec.e_ss, (stack_addr / 16));
+ write721_to_byte_array (exec.e_sp, ALIGN (stack_addr % 16 + stack_size, 16));
+
+ write721_to_byte_array (exec.e_ip, state->entry_point % 16);
+ write721_to_byte_array (exec.e_cs, state->entry_point / 16);
+
+ write721_to_byte_array (exec.e_lfarlc, header_size);
+
+ data_size = header_size + reloc_size;
+
+ if (text_section) {
+ data_size += text_section->total_size;
+ }
+
+ if (data_section) {
+ data_size += data_section->total_size;
+ }
+
+ data = xmalloc (data_size);
+ memcpy (data, &exec, sizeof (exec));
+
+ pos = data + header_size;
+
+ if (text_section) {
+ pos = write_relocs_for_section (pos, text_section);
+ }
+
+ if (data_section) {
+ pos = write_relocs_for_section (pos, data_section);
+ }
+
+ pos = data + header_size + reloc_size;
+
+ if (text_section) {
+
+ section_write (text_section, pos);
+ pos += text_section->total_size;
+
+ }
+
+ if (data_section) {
+ section_write (data_section, pos);
+ }
+
+ if (fwrite (data, data_size, 1, fp) != 1) {
+ report_at (program_name, 0, REPORT_ERROR, "failed to write data to '%s'", filename);
+ }
+
+ free (data);
+ fclose (fp);
+
+}
--- /dev/null
+/******************************************************************************
+ * @file pe.h
+ *****************************************************************************/
+#ifndef _MZ_H
+#define _MZ_H
+
+#define DEFAULT_SECTION_ALIGNMENT 0x1000
+#define DEFAULT_FILE_ALIGNMENT 0x0200
+
+struct mz_exec {
+
+ unsigned char e_magic[2]; /* Magic number */
+ unsigned char e_cblp[2]; /* Bytes on last page of file */
+ unsigned char e_cp[2]; /* Pages in file */
+ unsigned char e_crlc[2]; /* Relocations */
+ unsigned char e_cparhdr[2]; /* Size of header in paragraphs */
+ unsigned char e_minalloc[2]; /* Minimum extra paragraphs needed */
+ unsigned char e_maxalloc[2]; /* Maximum extra paragraphs needed */
+ unsigned char e_ss[2]; /* Initial (relative) SS value */
+ unsigned char e_sp[2]; /* Initial SP value */
+ unsigned char e_csum[2]; /* Checksum */
+ unsigned char e_ip[2]; /* Initial IP value */
+ unsigned char e_cs[2]; /* Initial (relative) CS value */
+ unsigned char e_lfarlc[2]; /* File address of relocation table */
+ unsigned char e_ovno[2]; /* Overlay number */
+
+};
+
+void mz_write (const char *filename);
+
+#endif /* _MZ_H */
#ifndef _PE_H
#define _PE_H
-#define DEFAULT_SECTION_ALIGNMENT 0x1000
-#define DEFAULT_FILE_ALIGNMENT 0x0200
+#define DEFAULT_SECTION_ALIGNMENT 0x1000
+#define DEFAULT_FILE_ALIGNMENT 0x0200
struct msdos_header {
unsigned long offset;
unsigned long addend;
+ unsigned int n_type, n_ext;
unsigned long symbolnum;
+
struct reloc_howto *howto;
};