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=as.o bin.o cstr.o elks.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
+COBJ=as.o coff.o cstr.o elks.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
all: clean sasm.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=as.o bin.o cstr.o elks.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
+COBJ=as.o coff.o cstr.o elks.o expr.o fixup.o frag.o hashtab.o intel.o kwd.o lex.o lib.o list.o listing.o ll.o macro.o process.o report.o section.o symbol.o vector.o
all: clean sasm.exe
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=as.obj bin.obj cstr.obj elks.obj expr.obj fixup.obj frag.obj hashtab.obj \
+COBJ=as.obj coff.obj cstr.obj elks.obj expr.obj fixup.obj frag.obj hashtab.obj \
intel.obj kwd.obj lex.obj lib.obj list.obj listing.obj ll.obj macro.obj \
process.obj report.obj section.obj symbol.obj vector.obj
CC := gcc
CFLAGS := -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
-CSRC := as.c bin.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
+CSRC := as.c coff.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
ifeq ($(OS), Windows_NT)
all: sasm.exe
CC := gcc
CFLAGS := -D_FILE_OFFSET_BITS=64 -O2 -Wall -Werror -Wextra -ansi -pedantic -std=c90
-CSRC := as.c bin.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
+CSRC := as.c coff.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
all: sasm.exe
SRCDIR ?= $(CURDIR)
VPATH := $(SRCDIR)
-SRC := as.c bin.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
+SRC := as.c coff.c cstr.c elks.c expr.c fixup.c frag.c hashtab.c intel.c kwd.c lex.c lib.c list.c listing.c ll.c macro.c process.c report.c section.c symbol.c vector.c
all: sasm.exe
const char *program_name = 0;
extern void output_binary (FILE *fp);
+extern void output_coff (FILE *fp);
extern void output_elks (FILE *fp);
extern void keywords_init (void);
}
atexit (cleanup);
- lex_init ();
state = xmalloc (sizeof (*state));
parse_args (argc, argv, 1);
return EXIT_FAILURE;
}
- if (state->format == AS_OUTPUT_BIN) {
-
- int report_output = 1;
-
- for (symbol = symbols; symbol; symbol = symbol->next) {
-
- if ((symbol_is_external (symbol) && symbol_get_section (symbol) == undefined_section) || symbol_is_undefined (symbol)) {
-
- if (symbol->scope == SYMBOL_SCOPE_GLOBAL) {
-
- report_at (program_name, 0, REPORT_ERROR, "undefined global symbol '%s'", symbol->name);
- continue;
-
- }
-
- if (report_output) {
-
- report_at (program_name, 0, REPORT_ERROR, "%s output does not support external references", state->format == AS_OUTPUT_BIN ? "binary" : "com");
- report_output = 0;
-
- }
-
- report_at (program_name, 0, REPORT_ERROR, "undefined external symbol '%s'", symbol->name);
-
- }
-
- }
-
- if (get_error_count () > 0) {
- return EXIT_FAILURE;
- }
-
- if (!(state->ofp = fopen (state->ofile, "wb"))) {
-
- report_at (program_name, 0, REPORT_ERROR, "failed to open '%s' for writing", state->ofile);
- return EXIT_FAILURE;
-
- }
-
- output_binary (state->ofp);
- return EXIT_SUCCESS;
-
- }
-
if (!(state->ofp = fopen (state->ofile, "wb"))) {
report_at (program_name, 0, REPORT_ERROR, "failed to open '%s' for writing", state->ofile);
}
- output_elks (state->ofp);
+ if (state->format == AS_OUTPUT_I386_ELKS || state->format == AS_OUTPUT_IA16_ELKS) {
+ output_elks (state->ofp);
+ } else if (state->format == AS_OUTPUT_WIN32 || state->format == AS_OUTPUT_WIN64) {
+ output_coff (state->ofp);
+ }
if (get_error_count () > 0) {
return EXIT_FAILURE;
#define AS_OUTPUT_IA16_ELKS 0x00
#define AS_OUTPUT_I386_ELKS 0x01
-#define AS_OUTPUT_BIN 0x02
+#define AS_OUTPUT_WIN32 0x02
+#define AS_OUTPUT_WIN64 0x03
struct as_state {
struct frag *frag;
section_set (text_section);
-
- for (frag = current_frag_chain->first_frag; frag; frag = frag->next) {
-
- if (frag->fixed_size == 0) {
- continue;
- }
-
- text_size += frag->fixed_size;
-
- }
+ text_size = section_write_frag_chain (fp);
section_set (data_section);
-
- for (frag = current_frag_chain->first_frag; frag; frag = frag->next) {
-
- if (frag->fixed_size == 0) {
- continue;
- }
-
- data_size += frag->fixed_size;
-
- }
+ data_size = section_write_frag_chain (fp);
section_set (bss_section);
--- /dev/null
+/******************************************************************************
+ * @file coff.c
+ *****************************************************************************/
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "as.h"
+#include "coff.h"
+#include "fixup.h"
+#include "frag.h"
+#include "lib.h"
+#include "report.h"
+#include "section.h"
+#include "stdint.h"
+#include "symbol.h"
+
+static int output_relocation (FILE *outfile, struct fixup *fixup) {
+
+ struct relocation_entry reloc_entry;
+ unsigned int type = 0;
+
+ if (fixup->add_symbol == NULL) {
+
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "+++output relocation fixup->add_symbol is NULL");
+ exit (EXIT_FAILURE);
+
+ }
+
+ write_to_byte_array (reloc_entry.VirtualAddress, fixup->frag->address + fixup->where, 4);
+
+ if (symbol_is_section_symbol (fixup->add_symbol) && !SECTION_IS_NORMAL (symbol_get_section (fixup->add_symbol))) {
+ write_to_byte_array (reloc_entry.SymbolTableIndex, ~(unsigned long) 0, 4);
+ } else {
+ write_to_byte_array (reloc_entry.SymbolTableIndex, symbol_get_symbol_table_index (fixup->add_symbol), 4);
+ }
+
+ if (state->format == AS_OUTPUT_WIN64) {
+
+ switch (fixup->reloc_type) {
+
+ case RELOC_TYPE_DEFAULT:
+ case RELOC_TYPE_FAR_CALL:
+
+ switch (fixup->size) {
+
+ case 8:
+
+ type = IMAGE_REL_AMD64_ADDR64;
+ break;
+
+ case 4:
+
+ type = (fixup->pcrel ? IMAGE_REL_AMD64_REL32 : IMAGE_REL_AMD64_ADDR32);
+ break;
+
+ default:
+
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "unsupported COFF relocation size %i for reloc_type RELOC_TYPE_DEFAULT", fixup->size);
+ exit (EXIT_FAILURE);
+
+ }
+
+ break;
+
+ case RELOC_TYPE_RVA:
+
+ if (fixup->size != 4) {
+
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "unsupported COFF relocation size %i for reloc_type RELOC_TYPE_RVA", fixup->size);
+ exit (EXIT_FAILURE);
+
+ }
+
+ type = IMAGE_REL_AMD64_ADDR32NB;
+ break;
+
+ default:
+
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "output_relocation invalid reloc_type", fixup->reloc_type);
+ exit (EXIT_FAILURE);
+
+ }
+
+ } else {
+
+ switch (fixup->reloc_type) {
+
+ case RELOC_TYPE_DEFAULT:
+ case RELOC_TYPE_FAR_CALL:
+
+ switch (fixup->size) {
+
+ case 2:
+
+ type = (fixup->pcrel ? IMAGE_REL_I386_REL16 : IMAGE_REL_I386_DIR16);
+ break;
+
+ case 4:
+
+ type = (fixup->pcrel ? IMAGE_REL_I386_REL32 : IMAGE_REL_I386_DIR32);
+ break;
+
+ default:
+
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "unsupported COFF relocation size %i for reloc_type RELOC_TYPE_DEFAULT", fixup->size);
+ exit (EXIT_FAILURE);
+
+ }
+
+ break;
+
+ case RELOC_TYPE_RVA:
+
+ type = IMAGE_REL_I386_DIR32NB;
+ break;
+
+ default:
+
+ report_at (__FILE__, __LINE__, REPORT_INTERNAL_ERROR, "output_relocation invalid reloc_type", fixup->reloc_type);
+ exit (EXIT_FAILURE);
+
+ }
+
+ }
+
+ write_to_byte_array (reloc_entry.Type, type, 2);
+
+ if (fwrite (&reloc_entry, sizeof (reloc_entry), 1, outfile) != 1) {
+ return 1;
+ }
+
+ return 0;
+
+}
+
+#define GET_UINT16(arr) ((uint32_t) arr[0] | (((uint32_t) arr[1]) << 8))
+
+static unsigned long translate_section_flags_to_Characteristics (unsigned int flags) {
+
+ unsigned long Characteristics = 0;
+
+ if (!(flags & SECTION_FLAG_READONLY)) {
+ Characteristics |= IMAGE_SCN_MEM_WRITE;
+ }
+
+ if (flags & SECTION_FLAG_CODE) {
+ Characteristics |= IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE;
+ }
+
+ if (flags & SECTION_FLAG_DATA) {
+ Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
+ }
+
+ if (flags & SECTION_FLAG_NEVER_LOAD) {
+ Characteristics |= IMAGE_SCN_TYPE_NOLOAD;
+ }
+
+ if (flags & SECTION_FLAG_DEBUGGING) {
+ Characteristics |= IMAGE_SCN_LNK_INFO;
+ }
+
+ if (flags & SECTION_FLAG_EXCLUDE) {
+ Characteristics |= IMAGE_SCN_LNK_REMOVE;
+ }
+
+ if (!(flags & SECTION_FLAG_NOREAD)) {
+ Characteristics |= IMAGE_SCN_MEM_READ;
+ }
+
+ if (flags & SECTION_FLAG_SHARED) {
+ Characteristics |= IMAGE_SCN_MEM_SHARED;
+ }
+
+ /* .bss */
+ if ((flags & SECTION_FLAG_ALLOC) && !(flags & SECTION_FLAG_LOAD)) {
+ Characteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ }
+
+ if (flags & SECTION_FLAG_LINK_ONCE) {
+ Characteristics |= IMAGE_SCN_LNK_COMDAT;
+ }
+
+ return Characteristics;
+
+}
+
+void output_coff (FILE *outfile) {
+
+ struct coff_header header;
+ struct symbol *symbol;
+
+ struct section *section;
+ unsigned char temp[4];
+
+ unsigned long string_table_size = 4;
+ uint32_t NumberOfSymbols = 0;
+
+ sections_number (1);
+ memset (&header, 0, sizeof (header));
+
+ if ((outfile = fopen (state->ofile, "wb")) == NULL) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to open '%s' as output file", state->ofile);
+ return;
+
+ }
+
+ write_to_byte_array (header.Machine, (state->format == AS_OUTPUT_WIN64 ? IMAGE_FILE_MACHINE_AMD64 : IMAGE_FILE_MACHINE_I386), 2);
+ write_to_byte_array (header.NumberOfSections, sections_get_count (), 2);
+ write_to_byte_array (header.SizeOfOptionalHeader, 0, 2);
+
+ if (state->format == AS_OUTPUT_WIN64) {
+ write_to_byte_array (header.Characteristics, IMAGE_FILE_LINE_NUMS_STRIPPED, 2);
+ } else {
+ write_to_byte_array (header.Characteristics, IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_32BIT_MACHINE, 2);
+ }
+
+ if (fseek (outfile, (sizeof (header) + sections_get_count () * sizeof (struct section_table_entry)), SEEK_SET)) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to fseek");
+ return;
+
+ }
+
+ for (section = sections; section; section = section_get_next_section (section)) {
+
+ uint32_t SizeOfRawData = 0, PointerToRawData = 0;
+
+ struct section_table_entry *section_header = xmalloc (sizeof (*section_header));
+ section_set_object_format_dependent_data (section, section_header);
+
+ memset (section_header, 0, sizeof (*section_header));
+
+ if (strlen (section_get_name (section)) <= 8) {
+ memcpy (section_header->Name, section_get_name (section), strlen (section_get_name (section)));
+ } else {
+
+ section_header->Name[0] = '/';
+ sprintf (section_header->Name + 1, "%lu", string_table_size);
+
+ string_table_size += strlen (section_get_name (section)) + 1;
+
+ }
+
+ write_to_byte_array (section_header->Characteristics, translate_section_flags_to_Characteristics (section_get_flags (section)), 4);
+
+ if (section != bss_section) {
+
+ PointerToRawData = ftell (outfile);
+ section_set (section);
+
+ SizeOfRawData = section_write_frag_chain (outfile);;
+
+ if (SizeOfRawData == 0) {
+ PointerToRawData = 0;
+ }
+
+ } else {
+
+ struct frag *frag;
+
+ PointerToRawData = 0;
+ section_set (section);
+
+ for (frag = current_frag_chain->first_frag; frag; frag = frag->next) {
+
+ if (frag->fixed_size == 0) {
+ continue;
+ }
+
+ SizeOfRawData += frag->fixed_size;
+
+ }
+
+ }
+
+ write_to_byte_array (section_header->SizeOfRawData, SizeOfRawData, 4);
+ write_to_byte_array (section_header->PointerToRawData, PointerToRawData, 4);
+
+ }
+
+ write_to_byte_array (header.PointerToSymbolTable, ftell (outfile), 4);
+ write_to_byte_array (header.NumberOfSymbols, 0, 4);
+
+ for (symbol = symbols; symbol; symbol = symbol->next) {
+
+ struct symbol_table_entry sym_tbl_ent;
+
+ unsigned long value = symbol_get_value (symbol);
+ unsigned int section_number = 0;
+
+ memset (&sym_tbl_ent, 0, sizeof (sym_tbl_ent));
+
+ if (symbol->section == undefined_section) {
+ section_number = IMAGE_SYM_UNDEFINED;
+ } else if (symbol->section == absolute_section) {
+ section_number = IMAGE_SYM_ABSOLUTE;
+ } else {
+ section_number = section_get_number (symbol->section);
+ }
+
+ write_to_byte_array (sym_tbl_ent.Type, (IMAGE_SYM_DTYPE_NULL << 8) | IMAGE_SYM_TYPE_NULL, 2);
+
+ if (symbol_is_external (symbol) || symbol_is_undefined (symbol)) {
+ sym_tbl_ent.StorageClass[0] = IMAGE_SYM_CLASS_EXTERNAL;
+ } else if (symbol_is_section_symbol (symbol)) {
+ sym_tbl_ent.StorageClass[0] = IMAGE_SYM_CLASS_STATIC;
+ } else if (symbol_get_section (symbol) == text_section) {
+ sym_tbl_ent.StorageClass[0] = IMAGE_SYM_CLASS_LABEL;
+ } else {
+ sym_tbl_ent.StorageClass[0] = IMAGE_SYM_CLASS_STATIC;
+ }
+
+ write_to_byte_array (sym_tbl_ent.Value, value, 4);
+ sym_tbl_ent.NumberOfAuxSymbols[0] = 0;
+
+ write_to_byte_array (sym_tbl_ent.SectionNumber, section_number, 2);
+ symbol->write_name_to_string_table = 0;
+
+ if (strlen (symbol->name) <= 8) {
+ memcpy (sym_tbl_ent.Name, symbol->name, strlen (symbol->name));
+ } else {
+
+ memset (sym_tbl_ent.Name, 0, 4);
+
+ write_to_byte_array ((unsigned char *) sym_tbl_ent.Name + 4, string_table_size, 4);
+ string_table_size += strlen (symbol->name) + 1;
+
+ symbol->write_name_to_string_table = 1;
+
+ }
+
+ if (fwrite (&sym_tbl_ent, sizeof (sym_tbl_ent), 1, outfile) != 1) {
+
+ report_at (NULL, 0, REPORT_ERROR, "error writing symbol table!");
+ return;
+
+ }
+
+ symbol_set_symbol_table_index (symbol, NumberOfSymbols);
+ NumberOfSymbols++;
+
+ }
+
+ write_to_byte_array (header.NumberOfSymbols, NumberOfSymbols, 4);
+ write_to_byte_array (temp, string_table_size, 4);
+
+ if (fwrite (temp, 4, 1, outfile) != 1) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to write string table!");
+ return;
+
+ }
+
+ for (section = sections; section; section = section_get_next_section (section)) {
+
+ if (strlen (section_get_name (section)) > 8) {
+
+ if (fwrite (section_get_name (section), strlen (section_get_name (section)) + 1, 1, outfile) != 1) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to write string table!");
+ return;
+
+ }
+
+ }
+
+ }
+
+ for (symbol = symbols; symbol; symbol = symbol->next) {
+
+ if (symbol->write_name_to_string_table) {
+
+ if (fwrite (symbol->name, strlen (symbol->name) + 1, 1, outfile) != 1) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to write string table!");
+ return;
+
+ }
+
+ }
+
+ }
+
+ for (section = sections; section; section = section_get_next_section (section)) {
+
+ struct section_table_entry *section_header = section_get_object_format_dependent_data (section);
+ struct fixup *fixup;
+
+ uint32_t NumberOfRelocations = 0, PointerToRelocations = ftell (outfile);
+ section_set (section);
+
+ for (fixup = current_frag_chain->first_fixup; fixup; fixup = fixup->next) {
+
+ if (fixup->done) {
+ continue;
+ }
+
+ if (output_relocation (outfile, fixup)) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to write relocation!");
+ return;
+
+ }
+
+ NumberOfRelocations++;
+
+ }
+
+ write_to_byte_array (section_header->NumberOfRelocations, NumberOfRelocations, 2);
+
+ if (NumberOfRelocations == 0) {
+ PointerToRelocations = 0;
+ }
+
+ write_to_byte_array (section_header->PointerToRelocations, PointerToRelocations, 4);
+
+ }
+
+ rewind (outfile);
+
+ if (fwrite (&header, sizeof (header), 1, outfile) != 1) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to write header!");
+ return;
+
+ }
+
+ for (section = sections; section; section = section_get_next_section (section)) {
+
+ struct section_table_entry *section_header = section_get_object_format_dependent_data (section);
+
+ if (fwrite (section_header, sizeof (*section_header), 1, outfile) != 1) {
+
+ report_at (NULL, 0, REPORT_ERROR, "failed to write header!");
+ return;
+
+ }
+
+ }
+
+}
--- /dev/null
+/******************************************************************************
+ * @file coff.h
+ *****************************************************************************/
+#ifndef _COFF_H
+#define _COFF_H
+
+struct coff_header {
+
+ unsigned char Machine[2];
+ unsigned char NumberOfSections[2];
+
+ unsigned char TimeDateStamp[4];
+ unsigned char PointerToSymbolTable[4];
+ unsigned char NumberOfSymbols[4];
+
+ unsigned char SizeOfOptionalHeader[2];
+ unsigned char Characteristics[2];
+
+};
+
+#define IMAGE_FILE_MACHINE_AMD64 0x8664
+#define IMAGE_FILE_MACHINE_I386 0x014C
+
+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
+#define IMAGE_FILE_32BIT_MACHINE 0x0100
+
+struct section_table_entry {
+
+ char Name[8];
+
+ unsigned char VirtualSize[4];
+ unsigned char VirtualAddress[4];
+
+ unsigned char SizeOfRawData[4];
+ unsigned char PointerToRawData[4];
+ unsigned char PointerToRelocations[4];
+ unsigned char PointerToLinenumbers[4];
+
+ unsigned char NumberOfRelocations[2];
+ unsigned char NumberOfLinenumbers[2];
+
+ unsigned char Characteristics[4];
+
+};
+
+#define IMAGE_SCN_TYPE_NOLOAD 0x00000002
+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Obsolete, means the same as IMAGE_SCN_ALIGN_1BYTES. */
+#define IMAGE_SCN_CNT_CODE 0x00000020
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+#define IMAGE_SCN_LNK_INFO 0x00000200
+#define IMAGE_SCN_LNK_REMOVE 0x00000800
+#define IMAGE_SCN_LNK_COMDAT 0x00001000
+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
+#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
+#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
+#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
+#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
+#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
+#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
+#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
+#define IMAGE_SCN_MEM_SHARED 0x10000000
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define IMAGE_SCN_MEM_READ 0x40000000
+#define IMAGE_SCN_MEM_WRITE 0x80000000
+
+struct relocation_entry {
+
+ unsigned char VirtualAddress[4];
+ unsigned char SymbolTableIndex[4];
+
+ unsigned char Type[2];
+
+};
+
+#define IMAGE_REL_AMD64_ABSOLUTE 0x0000
+#define IMAGE_REL_AMD64_ADDR64 0x0001
+#define IMAGE_REL_AMD64_ADDR32 0x0002
+#define IMAGE_REL_AMD64_ADDR32NB 0x0003
+#define IMAGE_REL_AMD64_REL32 0x0004
+
+#define IMAGE_REL_I386_ABSOLUTE 0x0000
+#define IMAGE_REL_I386_DIR16 0x0001
+#define IMAGE_REL_I386_REL16 0x0002
+#define IMAGE_REL_I386_DIR32 0x0006
+#define IMAGE_REL_I386_DIR32NB 0x0007
+#define IMAGE_REL_I386_REL32 0x0014
+
+struct symbol_table_entry {
+
+ char Name[8];
+ unsigned char Value[4];
+
+ unsigned char SectionNumber[2];
+ unsigned char Type[2];
+
+ unsigned char StorageClass[1];
+ unsigned char NumberOfAuxSymbols[1];
+
+};
+
+#define IMAGE_SYM_UNDEFINED 0
+#define IMAGE_SYM_ABSOLUTE -1
+#define IMAGE_SYM_DEBUG -2
+
+#define IMAGE_SYM_TYPE_NULL 0
+#define IMAGE_SYM_DTYPE_NULL 0
+
+#define IMAGE_SYM_CLASS_EXTERNAL 2
+#define IMAGE_SYM_CLASS_STATIC 3
+#define IMAGE_SYM_CLASS_LABEL 6
+#define IMAGE_SYM_CLASS_FILE 103
+
+#endif /* _COFF_H */
#include "section.h"
#include "symbol.h"
-static void write_to_byte_array (unsigned char *arr, unsigned long value, int size) {
-
- int i;
-
- for (i = 0; i < size; i++) {
- arr[i] = (value >> (8 * i)) & 0xff;
- }
-
-}
-
static int output_relocation (struct fixup *fixup, unsigned long start_address_of_section, FILE *fp) {
struct elks_relocation_info reloc;
}
section_set (text_section);
- text_size = 0;
-
- for (frag = current_frag_chain->first_frag; frag; frag = frag->next) {
-
- if (frag->fixed_size == 0) {
- continue;
- }
-
- if (fwrite (frag->buf, frag->fixed_size, 1, fp) != 1) {
-
- report_at (program_name, 0, REPORT_ERROR, "failed whilst writing text");
- return;
-
- }
-
- text_size += frag->fixed_size;
-
- }
+ text_size = section_write_frag_chain (fp);
write_to_byte_array (header.a_text, text_size, 4);
section_set (data_section);
- data_size = 0;
-
- for (frag = current_frag_chain->first_frag; frag; frag = frag->next) {
-
- if (frag->fixed_size == 0) {
- continue;
- }
-
- if (fwrite (frag->buf, frag->fixed_size, 1, fp) != 1) {
-
- report_at (program_name, 0, REPORT_ERROR, "failed whilst writing data");
- return;
-
- }
-
- data_size += frag->fixed_size;
-
- }
+ data_size = section_write_frag_chain (fp);
write_to_byte_array (header.a_data, data_size, 4);
static struct section *operand (char *start, char **pp, struct expr *expr, int expr_mode) {
struct section *ret_section;
- char ch;
+ char *temp, ch;
expr->type = EXPR_TYPE_INVALID;
expr->add_number = 0;
goto end_of_line;
}
+ if (**pp >= '0' && **pp <= '9') {
+
+ temp = (*pp);
+
+ while (*temp && (isxdigit (*temp))) {
+ temp++;
+ }
+
+ if (*temp && *temp == 'h') {
+
+ *temp = ' ';
+ goto is_hex;
+
+ }
+
+ }
+
switch (**pp) {
case '1':
(*pp)++;
+ is_hex:
+
integer_constant (start, pp, expr, 16);
break;
}
- } else if (state->format == AS_OUTPUT_BIN) {
-
- if (frag->offset == root_frag->offset) {
-
- frag->relax_type = RELAX_TYPE_NONE_NEEDED;
- growth = 0;
-
- frag->next->address += target;
- break;
-
- }
-
- frag->relax_type = RELAX_TYPE_NONE_NEEDED;
- report_at (frag->filename, frag->line_number, REPORT_ERROR, "program origin redefined");
-
}
growth = target - (frag->next->address + change);
finish_frags_after_relaxation (section);
}
- {
+ if (state->format == AS_OUTPUT_I386_ELKS || state->format == AS_OUTPUT_IA16_ELKS) {
unsigned long address, text_section_size;
struct frag *frag;
#define RELOC_TYPE_DEFAULT 0
#define RELOC_TYPE_FAR_CALL 1
+#define RELOC_TYPE_RVA 2
struct fixup {
exit (EXIT_FAILURE);
}
+
+ return 0;
}
static struct hashtab hashtab_templates = { 0 };
static struct hashtab hashtab_regs = { 0 };
+static struct hashtab hashtab_models = { 0 };
#define DEFAULT_CPU_ARCH_NAME "ALL"
};
+struct model_entry {
+
+ const char *name;
+ unsigned int data_size, model;
+
+};
+
+static struct model_entry model_table[] = {
+
+ { "tiny", 0, 1 },
+ { "small", 0, 2 },
+ { "compact", 1, 3 },
+ { "medium", 0, 4 },
+ { "large", 1, 5 },
+ { "huge", 2, 6 },
+
+ { 0, 0, 0 }
+
+};
+
#define BYTE_SUFFIX 'b'
#define WORD_SUFFIX 'w'
#define SHORT_SUFFIX 's'
}
+static struct model_entry *find_model_entry (char *name) {
+
+ char *lname;
+
+ struct hashtab_name *key;
+ struct model_entry *entry;
+
+ lname = to_lower (name);
+
+ if ((key = hashtab_get_key (&hashtab_models, lname))) {
+
+ if ((entry = hashtab_get (&hashtab_models, key))) {
+
+ free (lname);
+ return entry;
+
+ }
+
+ }
+
+ free (lname);
+ return 0;
+
+}
+
#define EXPR_TYPE_SHORT EXPR_TYPE_MACHINE_DEPENDENT_0
#define EXPR_TYPE_OFFSET EXPR_TYPE_MACHINE_DEPENDENT_1
}
-static void handler_amd64 (char *start, char **pp) {
-
- (void) start;
- (void) pp;
-
- machine_dependent_set_march ("generic64");
- machine_dependent_set_bits (64, 0);
-
-}
-
static void handler_8086 (char *start, char **pp) {
(void) start;
static void handler_model (char *start, char **pp) {
char *caret = (*pp = skip_whitespace (*pp));
+
+ struct model_entry *model_entry;
char *model, *lang;
if (!(model = symname (pp))) {
*pp = skip_whitespace (*pp);
- if (xstrcasecmp (model, "tiny") == 0) {
-
- state->data_size = 0;
- state->model = 1;
-
- } else if (xstrcasecmp (model, "small") == 0) {
-
- state->data_size = 0;
- state->model = 2;
-
- } else if (xstrcasecmp (model, "compact") == 0) {
-
- state->data_size = 1;
- state->model = 3;
-
- } else if (xstrcasecmp (model, "medium") == 0) {
+ if ((model_entry = find_model_entry (model))) {
- state->data_size = 0;
- state->model = 4;
-
- } else if (xstrcasecmp (model, "large") == 0) {
-
- state->data_size = 1;
- state->model = 5;
-
- } else if (xstrcasecmp (model, "huge") == 0) {
-
- state->data_size = 2;
- state->model = 6;
+ state->data_size = model_entry->data_size;
+ state->model = model_entry->model;
} else if (xstrcasecmp (model, "flat") == 0) {
static struct pseudo_op_entry pseudo_op_table[] = {
- { ".amd64", &handler_amd64 },
-
{ ".8086", &handler_8086 },
{ ".8087", &handler_8087 },
struct templates *templates;
struct template *template = template_table;
+ struct model_entry *model_entry;
+
int ch;
templates = xmalloc (sizeof (*templates));
}
+ for (model_entry = model_table; model_entry->name; model_entry++) {
+
+ if (hashtab_get_key (&hashtab_models, model_entry->name)) {
+
+ report_at (program_name, 0, REPORT_ERROR, "duplicate entry '%s'", reg_entry->name);
+ continue;
+
+ }
+
+ if (!(key = hashtab_alloc_name (model_entry->name))) {
+
+ report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for '%s'", reg_entry->name);
+ continue;
+
+ }
+
+ hashtab_put (&hashtab_models, key, model_entry);
+
+ }
+
for (ch = 0; ch < 255; ch++) {
if (islower (ch) || isdigit (ch)) {
expr_type_set_rank (EXPR_TYPE_FULL_PTR, intel_syntax ? 10 : 0);
- machine_dependent_set_march ("i8086");
- machine_dependent_set_bits (16, 1);
+ if (state->format == AS_OUTPUT_WIN64) {
+
+ machine_dependent_set_march ("generic64");
+ machine_dependent_set_bits (64, 1);
+
+ } else if (state->format == AS_OUTPUT_I386_ELKS || state->format == AS_OUTPUT_WIN32) {
+
+ machine_dependent_set_march ("i386");
+ machine_dependent_set_bits (32, 1);
+
+ } else {
+
+ machine_dependent_set_march ("i8086");
+ machine_dependent_set_bits (16, 1);
+
+ }
install_pseudo_op_table (pseudo_op_table);
int ret = 1;
if (bits == 64 && prefix >= REX_PREFIX_OPCODE && prefix < REX_PREFIX_OPCODE + 16) {
+
prefix_type = REX_PREFIX;
+
+ if (instruction.prefixes[prefix_type] & prefix & ~REX_PREFIX_OPCODE) {
+ ret = 0;
+ }
+
} else {
switch (prefix) {
INTEL_TYPE (WORD, 2),
INTEL_TYPE (DWORD, 4),
INTEL_TYPE (FWORD, 6),
+ INTEL_TYPE (QWORD, 8),
{ "near", EXPR_TYPE_NEAR_PTR, { 0xFF02, 0xFF04 } },
{ "far", EXPR_TYPE_FAR_PTR, { 0xFF05, 0xFF06 } },
case x86_error_invalid_instruction_suffix:
- report_at (get_filename (), get_line_number (), REPORT_ERROR, "invalid instruction suffix for %s", current_templates->name);
+ report_at (get_filename (), get_line_number (), REPORT_ERROR, "invalid instruction suffix '%c' for %s", mnemonic_suffix, current_templates->name);
return 1;
case x86_error_operand_size_mismatch:
if (state->model < 7) {
- if (template->base_opcode == 0xC3 && xstrcasecmp (template->name, "retn") && instruction.operands == 0 && state->model >= 4 && state->procs.length > 0) {
- instruction.template.base_opcode = 0xCB;
- }
+ if (xstrcasecmp (template->name, "retn") && instruction.operands == 0 && state->model >= 4 && state->procs.length > 0) {
+
+ if (template->base_opcode == 0xC3) {
+ instruction.template.base_opcode = 0xCB;
+ }
+
+ if (template->base_opcode == 0xC2) {
+ instruction.template.base_opcode = 0xCA;
+ }
- if (template->base_opcode == 0xC2 && xstrcasecmp (template->name, "retn") && instruction.operands == 1 && state->model >= 4 && state->procs.length > 0) {
- instruction.template.base_opcode = 0xCA;
}
}
}
if (fixup && size == 1) {
- fixup->fixup_signed = 1;
+
+ switch (size) {
+
+ case 1:
+
+ fixup->fixup_signed = 1;
+ break;
+
+ case 4:
+
+ if (bits == 64) {
+ fixup->fixup_signed = 1;
+ }
+
+ break;
+
+ }
+
}
}
mask = 0xffffffff;
break;
+
+ case 8:
+
+ return value;
default:
}
+static int imm_size (struct operand_type operand_type) {
+
+ if (operand_type.imm8 || operand_type.imm8s) {
+ return 1;
+ }
+
+ if (operand_type.imm16) {
+ return 2;
+ }
+
+ if (operand_type.imm64) {
+ return 8;
+ }
+
+ return 4;
+
+}
+
static void output_disps (void) {
int operand;
} else {
- fixup_new_expr (current_frag, current_frag->fixed_size, size, instruction.disps[operand], 0, RELOC_TYPE_DEFAULT);
+ struct fixup *fixup;
+ int pcrel = (instruction.special_types[operand] & OPERAND_PCREL) != 0;
+
+ if (pcrel) {
+
+ /* pcrel displacement is relative to the end of the instruction,
+ * so the size of immediate operands has to be included. */
+ int operand2;
+
+ for (operand2 = 0; operand2 < instruction.operands; operand2++) {
+
+ if (operand_type_check (instruction.types[operand2], imm)) {
+ instruction.disps[operand]->add_number -= imm_size (instruction.types[operand2]);
+ }
+
+ }
+
+ }
+
+ fixup = fixup_new_expr (current_frag, current_frag->fixed_size, size, instruction.disps[operand], pcrel, RELOC_TYPE_DEFAULT);
frag_increase_fixed_size (size);
+
+ if (bits == 64 && size == 4 && pcrel && !instruction.prefixes[ADDR_PREFIX]) {
+ fixup->fixup_signed = 1;
+ }
}
}
-static int imm_size (struct operand_type operand_type) {
-
- if (operand_type.imm8 || operand_type.imm8s) {
- return 1;
- }
-
- if (operand_type.imm16) {
- return 2;
- }
-
- return 4;
-
-}
-
static void output_imms (void) {
int operand;
if (symbol_get_section (frag->symbol) != section) {
+ struct fixup *fixup;
int size = (frag->relax_subtype & RELAX_SUBTYPE_CODE16_JUMP) ? 2 : 4;
unsigned char *opcode_pos = frag->buf + frag->opcode_offset_in_buf;
*opcode_pos = 0xE9;
- fixup_new (frag, frag->fixed_size, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
+ fixup = fixup_new (frag, frag->fixed_size, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
frag->fixed_size += size;
break;
opcode_pos[2] = 0xE9;
frag->fixed_size += 4;
- fixup_new (frag, old_frag_fixed_size + 2, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
+ fixup = fixup_new (frag, old_frag_fixed_size + 2, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
break;
opcode_pos[1] = opcode_pos[0] + 0x10;
opcode_pos[0] = TWOBYTE_OPCODE;
- fixup_new (frag, frag->fixed_size + 1, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
+ fixup = fixup_new (frag, frag->fixed_size + 1, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
frag->fixed_size += size + 1;
break;
size = 1;
- fixup_new (frag, frag->fixed_size, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
+ fixup = fixup_new (frag, frag->fixed_size, size, frag->symbol, frag->offset, 1, RELOC_TYPE_DEFAULT);
frag->fixed_size += size;
break;
}
+ /**
+ * Jumps here are signed but wrapping around is allowed,
+ * only wrapping around at 4 GiB is not allowed in 64-bit mode.
+ */
+ if (size == 4 && bits == 64) {
+ fixup->fixup_signed = 1;
+ }
+
frag->relax_type = RELAX_TYPE_NONE_NEEDED;
return frag->fixed_size - old_frag_fixed_size;
void machine_dependent_assemble_line (char *start, char *line) {
- char mnemonic_suffix;
+ char mnemonic_suffix = 0;
memset (&instruction, 0, sizeof (instruction));
memset (operand_exprs, 0, sizeof (operand_exprs));
mnemonic_suffix = instruction.suffix;
+ if (mnemonic_suffix != INTEL_SUFFIX) {
+ mnemonic_suffix = 0;
+ }
+
/**
* All Intel instructions have reversed operands except "bound" and some other.
* "ljmp" and "lcall" with 2 immediate operands also do not have operands reversed.
}
+void machine_dependent_number_to_chars (unsigned char *p, unsigned int number, unsigned int size);
+
static void handle_constant (char *start, char **pp, int size) {
struct expr expr, val;
}
if (expr.type == EXPR_TYPE_CONSTANT) {
-
- int i;
-
- for (i = 0; i < size; i++) {
- frag_append_1_char ((expr.add_number >> (8 * i)) & 0xff);
- }
-
+ machine_dependent_number_to_chars (frag_increase_fixed_size (size), expr.add_number, size);
} else if (expr.type != EXPR_TYPE_INVALID) {
fixup_new_expr (current_frag, current_frag->fixed_size, size, &expr, 0, RELOC_TYPE_DEFAULT);
*****************************************************************************/
#include "lex.h"
-char is_end_of_line[256] = { 0 };
-char lex_table[256] = { 0 };
+char is_end_of_line[256] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 /* '\0' and '\n' */
+};
-void lex_init (void) {
+char lex_table[256] = {
- int i;
-
- is_end_of_line[0] = 1;
- is_end_of_line[10] = 1;
-
- lex_table[36] = LEX_NAME_START | LEX_NAME_PART;
- lex_table[46] = LEX_NAME_START | LEX_NAME_PART;
-
- for (i = 48; i < 58; i++) {
- lex_table[i] = LEX_NAME_PART;
- }
-
- lex_table[63] = LEX_NAME_PART;
-
- for (i = 65; i < 91; i++) {
- lex_table[i] = LEX_NAME_START | LEX_NAME_PART;
- }
-
- lex_table[95] = LEX_NAME_START | LEX_NAME_PART;
-
- for (i = 97; i < 123; i++) {
- lex_table[i] = LEX_NAME_START | LEX_NAME_PART;
- }
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* SPACE!"#$%&'()*+,-./ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, /* 0123456789:;<=>? */
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, /* #PQRSTUVWXYZ[\]^_ */
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 'abcdefghijklmno */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0 /* pqrstuvwxyz{|}~ */
-}
+};
#define is_name_beginner(c) (lex_table[(c)] & LEX_NAME_START)
#define is_name_part(c) (lex_table[(c)] & LEX_NAME_PART)
-void lex_init (void);
-
#endif /* _LEX_H */
fprintf (stderr, "\n");
fprintf (stderr, " -f FORMAT Specify the format of object file (default elks-ia16)\n");
fprintf (stderr, " Supported formats are:\n");
- fprintf (stderr, " elks-ia16, elks-i386, binary\n");
+ fprintf (stderr, " elks-ia16, elks-i386, binary,\n");
+ fprintf (stderr, " win32, win64\n");
fprintf (stderr, " -l FILE Print listings to file FILE.\n");
fprintf (stderr, " -o OBJFILE Name the object-file output OBJFILE (default a.out).\n");
}
+void write_to_byte_array (unsigned char *arr, unsigned long value, int size) {
+
+ int i;
+
+ for (i = 0; i < size; i++) {
+ arr[i] = (value >> (8 * i)) & 0xff;
+ }
+
+}
+
void ignore_rest_of_line (char **pp) {
while (!is_end_of_line[(int) **pp]) {
case AS_OPTION_FORMAT: {
- if (xstrcasecmp (optarg, "bin") == 0) {
+ if (xstrcasecmp (optarg, "elks-ia16") == 0) {
- state->format = AS_OUTPUT_BIN;
+ state->format = AS_OUTPUT_IA16_ELKS;
break;
}
- if (xstrcasecmp (optarg, "elks-ia16") == 0) {
+ if (xstrcasecmp (optarg, "elks-i386") == 0) {
- state->format = AS_OUTPUT_IA16_ELKS;
+ state->format = AS_OUTPUT_I386_ELKS;
break;
}
- if (xstrcasecmp (optarg, "elks-i386") == 0) {
+ if (xstrcasecmp (optarg, "win32") == 0) {
- state->format = AS_OUTPUT_I386_ELKS;
+ state->format = AS_OUTPUT_WIN32;
+ break;
+
+ }
+
+ if (xstrcasecmp (optarg, "win64") == 0) {
+
+ state->format = AS_OUTPUT_WIN64;
break;
}
int xstrncasecmp (const char *__s1, const char *__s2, unsigned long __len);
char *to_lower (const char *__p);
+
void ignore_rest_of_line (char **pp);
+void write_to_byte_array (unsigned char *arr, unsigned long value, int size);
void add_include_path (const char *__p);
static struct hashtab hashtab_macros = { 0 };
-void remove_all_macros (void) {
-
- struct macro *m;
- int i;
-
- for (i = 0; i < hashtab_macros.capacity; i++) {
-
- if (!(m = (struct macro *) &hashtab_macros.entries[i])) {
- continue;
- }
-
- free (m->name);
- free (m->value);
-
- }
-
- memset (&hashtab_macros, 0, sizeof (hashtab_macros));
-
-}
-
struct hashtab_name *find_macro (char *sname) {
struct hashtab_name *key;
if (!(sname = symname (pp))) {
- if (!(sname = symname (pp))) {
-
if (report_line) {
report_line_at (get_filename (), get_line_number (), REPORT_ERROR, start, caret, "macro names must be identifiers");
} else {
return;
- }
-
- return;
-
}
if ((key = find_macro (sname))) {
return m->value;
}
-
-void push_macro (struct hashtab_name *key, struct macro *m) {
- hashtab_put (&hashtab_macros, key, m);
-}
};
#include "hashtab.h"
+
struct hashtab_name *find_macro (char *sname);
struct macro *get_macro (struct hashtab_name *key);
-void remove_all_macros (void);
-
void add_macro (char *start, char **pp, int report_line);
void remove_macro (char *start, char **pp, int report_line);
char *process_macro (char *start, char **pp, struct macro *m);
-void push_macro (struct hashtab_name *key, struct macro *m);
#endif /* _MACRO_H */
static struct hashtab hashtab_cond_pseudo_ops = { 0 };
static int includes = 0;
-static void install_cond_pseudo_op_table (struct pp_pseudo_op_entry *table) {
+static void install_pp_pseudo_op_table (struct pp_pseudo_op_entry *table, struct hashtab *hashatb_table) {
struct pp_pseudo_op_entry *entry;
struct hashtab_name *key;
for (entry = table; entry->name; entry++) {
- if (hashtab_get_key (&hashtab_cond_pseudo_ops, entry->name)) {
+ if (hashtab_get_key (hashatb_table, entry->name)) {
report_at (program_name, 0, REPORT_ERROR, "duplicate entry '%s'", entry->name);
continue;
}
- hashtab_put (&hashtab_cond_pseudo_ops, key, entry);
+ hashtab_put (hashatb_table, key, entry);
}
};
-static void install_pp_pseudo_op_table (struct pp_pseudo_op_entry *table) {
-
- struct pp_pseudo_op_entry *entry;
- struct hashtab_name *key;
-
- for (entry = table; entry->name; entry++) {
-
- if (hashtab_get_key (&hashtab_pseudo_ops, entry->name)) {
-
- report_at (program_name, 0, REPORT_ERROR, "duplicate entry '%s'", entry->name);
- continue;
-
- }
-
- if (!(key = hashtab_alloc_name (entry->name))) {
-
- report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for '%s'", entry->name);
- continue;
-
- }
-
- hashtab_put (&hashtab_pseudo_ops, key, entry);
-
- }
-
-}
-
struct pp_pseudo_op_entry *find_directive (char *name) {
struct hashtab_name *key;
}
-static void init_builtin_macros (void) {
-
- char *name;
-
- struct hashtab_name *key;
- struct macro *m;
-
- name = xstrdup ("__SASM__");
-
- if ((key = hashtab_alloc_name (name))) {
-
- m = xmalloc (sizeof (*m));
- m->type = MACRO_BUILTIN;
-
- m->name = name;
- m->value = "1";
-
- push_macro (key, m);
-
- }
-
-}
-
int preprocess_init (void) {
struct list *item;
set_filename (xstrdup ("<command-line>"));
set_line_number (1);
- remove_all_macros ();
-
- while ((opt = vec_pop (&vec_include_paths))) {
- free (opt);
- }
-
- init_builtin_macros ();
-
if (state->pplist) {
item = state->pplist;
case 'D':
- opt = nopt = xstrdup (opt + 2);
+ nopt = opt + 2;
if ((p = strrchr (nopt, '='))) {
*p++ = ' ';
}
add_macro (nopt, &nopt, 0);
- free (opt);
-
break;
case 'I':
- vec_push (&vec_include_paths, xstrdup (opt + 2));
+ vec_push (&vec_include_paths, opt + 2);
break;
case 'U':
- opt = nopt = xstrdup (opt + 2);
+ nopt = opt + 2;
remove_macro (nopt, &nopt, 0);
- free (opt);
-
break;
default:
}
- install_cond_pseudo_op_table (cond_pseudo_op_table);
- install_pp_pseudo_op_table (pseudo_op_table);
+ install_pp_pseudo_op_table (cond_pseudo_op_table, &hashtab_cond_pseudo_ops);
+ install_pp_pseudo_op_table (pseudo_op_table, &hashtab_pseudo_ops);
return get_error_count () > 0;
/******************************************************************************
* @file section.c
*****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include "as.h"
#include "frag.h"
#include "lib.h"
+#include "report.h"
#include "section.h"
#include "symbol.h"
struct section {
const char *name;
+ void *object_format_dependent_data;
- struct frag_chain frag_chain;
+ struct frag_chain *frag_chain;
struct symbol *symbol;
- int alignment_power;
+ unsigned int number;
+ unsigned long flags;
+
struct section *next;
};
struct frag_chain *current_frag_chain = 0;
struct section *sections = 0;
+unsigned long current_subsection;
+
static struct section *find_or_make_section_by_name (const char *name) {
struct section *section, **p_next;
struct section *section_set (struct section *section) {
+ struct frag_chain *frag_chain, **p_next;
+ unsigned long subsection = 0;
+
current_section = section;
- current_frag_chain = ¤t_section->frag_chain;
+ for (frag_chain = *(p_next = &(current_section->frag_chain)); frag_chain; frag_chain = *(p_next = &(frag_chain->next))) {
+
+ if (frag_chain->subsection >= subsection) {
+ break;
+ }
+
+ }
+
+ if (!frag_chain || frag_chain->subsection != subsection) {
+
+ struct frag_chain *new_frag_chain = xmalloc (sizeof (*new_frag_chain));
+ new_frag_chain->subsection = subsection;
+
+ new_frag_chain->last_frag = new_frag_chain->first_frag = frag_alloc ();
+ new_frag_chain->last_fixup = new_frag_chain->first_fixup = 0;
+
+ *p_next = new_frag_chain;
+ new_frag_chain->next = frag_chain;
+
+ frag_chain = new_frag_chain;
+
+ }
+
+ current_frag_chain = frag_chain;
current_frag = current_frag_chain->last_frag;
+ current_subsection = subsection;
return section;
}
return section->name;
}
-void section_record_alignment_power (struct section *section, int alignment_power) {
+unsigned int section_get_number (struct section *section) {
+ return section->number;
+}
+
+unsigned int sections_get_count (void) {
+
+ struct section *section;
+ unsigned int count;
+
+ for (section = sections, count = 0; section; section = section->next, count++);
+ return count;
+
+}
+
+unsigned long section_get_flags (struct section *section) {
+ return section->flags;
+}
- if (alignment_power > section->alignment_power) {
- section->alignment_power = alignment_power;
+unsigned long section_write_frag_chain (FILE *fp) {
+
+ struct frag *frag;
+ unsigned long bytes = 0;
+
+ for (frag = current_frag_chain->first_frag; frag; frag = frag->next) {
+
+ if (frag->fixed_size == 0) {
+ continue;
+ }
+
+ if (fwrite (frag->buf, frag->fixed_size, 1, fp) != 1) {
+
+ report_at (program_name, 0, REPORT_ERROR, "failed whilst writing data");
+ return bytes;
+
+ }
+
+ bytes += frag->fixed_size;
+
}
+
+ return bytes;
}
+void section_set_flags (struct section *section, unsigned long flags) {
+ section->flags = flags;
+}
+
#define CREATE_INTERNAL_SECTION(section_var, section_name, section_index) \
(section_var) = &internal_sections[(section_index)]; \
CREATE_INTERNAL_SECTION (reg_section, "*REG*", 3);
text_section = section_set_by_name (".text");
- text_section->frag_chain.last_frag = text_section->frag_chain.first_frag = frag_alloc ();
- text_section->frag_chain.last_fixup = text_section->frag_chain.first_fixup = 0;
+ section_set_flags (text_section, SECTION_FLAG_LOAD | SECTION_FLAG_ALLOC | SECTION_FLAG_READONLY | SECTION_FLAG_CODE);
data_section = section_set_by_name (".data");
- data_section->frag_chain.last_frag = data_section->frag_chain.first_frag = frag_alloc ();
- data_section->frag_chain.last_fixup = data_section->frag_chain.first_fixup = 0;
+ section_set_flags (data_section, SECTION_FLAG_LOAD | SECTION_FLAG_ALLOC | SECTION_FLAG_DATA);
bss_section = section_set_by_name (".bss");
- bss_section->frag_chain.last_frag = bss_section->frag_chain.first_frag = frag_alloc ();
- bss_section->frag_chain.last_fixup = bss_section->frag_chain.first_fixup = 0;
+ section_set_flags (bss_section, SECTION_FLAG_ALLOC);
/* .text section is the default section. */
section_set (text_section);
}
#undef CREATE_INTERNAL_SECTION
+
+void section_set_object_format_dependent_data (struct section *section, void *data) {
+ section->object_format_dependent_data = data;
+}
+
+void sections_number (unsigned int start_at) {
+
+ struct section *section;
+
+ for (section = sections; section; section = section->next) {
+ section->number = start_at++;
+ }
+
+}
+
+void *section_get_object_format_dependent_data (struct section *section) {
+ return section->object_format_dependent_data;
+}
#ifndef _SECTION_H
#define _SECTION_H
+#include <stdio.h>
+
struct frag_chain {
struct fixup *first_fixup, *last_fixup;
struct frag *first_frag, *last_frag;
+ unsigned long subsection;
struct frag_chain *next;
};
+#define SECTION_FLAG_ALLOC (1U << 0)
+#define SECTION_FLAG_LOAD (1U << 1)
+#define SECTION_FLAG_READONLY (1U << 2)
+#define SECTION_FLAG_CODE (1U << 3)
+#define SECTION_FLAG_DATA (1U << 4)
+#define SECTION_FLAG_NEVER_LOAD (1U << 5)
+#define SECTION_FLAG_DEBUGGING (1U << 6)
+#define SECTION_FLAG_EXCLUDE (1U << 7)
+#define SECTION_FLAG_NOREAD (1U << 8)
+#define SECTION_FLAG_SHARED (1U << 9)
+#define SECTION_FLAG_LINK_ONCE (1U << 10)
+#define SECTION_FLAG_LINK_DUPLICATES_DISCARD (1U << 11)
+#define SECTION_FLAG_LINK_DUPLICATES_ONE_ONLY (1U << 12)
+#define SECTION_FLAG_LINK_DUPLICATES_SAME_SIZE (1U << 13)
+#define SECTION_FLAG_LINK_DUPLICATES_SAME_CONTENTS (1U << 14)
+
#define SECTION_IS_NORMAL(section) \
((section != undefined_section) && (section != absolute_section) && (section != expr_section) && (section != reg_section))
struct symbol *section_symbol (struct section *section);
const char *section_get_name (struct section *section);
-void section_record_alignment_power (struct section *section, int alignment_power);
+unsigned int section_get_number (struct section *section);
+unsigned int sections_get_count (void);
+
+unsigned long section_get_flags (struct section *section);
+unsigned long section_write_frag_chain (FILE *outfile);
+
+void section_set_object_format_dependent_data (struct section *section, void *data);
+void section_set_flags (struct section *section, unsigned long flags);
+
+void sections_number (unsigned int start_at);
+void *section_get_object_format_dependent_data (struct section *section);
#endif /* _SECTION_H */
return (symbol->value.type == EXPR_TYPE_SYMBOL && ((symbol_is_resolved (symbol) && symbol->value.op_symbol) || symbol_is_undefined (symbol)));
}
+unsigned long symbol_get_symbol_table_index (struct symbol *symbol) {
+ return symbol->symbol_table_index;
+}
+
unsigned long symbol_get_value (struct symbol *symbol) {
return symbol_resolve_value (symbol);
}
symbol->section = section;
}
+void symbol_set_symbol_table_index (struct symbol *symbol, unsigned long index) {
+ symbol->symbol_table_index = index;
+}
+
void symbol_set_value (struct symbol *symbol, unsigned long value) {
symbol->value.type = EXPR_TYPE_CONSTANT;
struct frag *frag;
struct expr value;
- int flags;
+ int resolved, resolving, flags;
+
+ unsigned long symbol_table_index;
+ int write_name_to_string_table;
- int resolved, resolving;
struct symbol *next;
};
int symbol_uses_other_symbol (struct symbol *symbol);
int symbol_uses_reloc_symbol (struct symbol *symbol);
+unsigned long symbol_get_symbol_table_index (struct symbol *symbol);
unsigned long symbol_get_value (struct symbol *symbol);
unsigned long symbol_resolve_value (struct symbol *symbol);
void symbol_set_frag (struct symbol *symbol, struct frag *frag);
void symbol_set_external (struct symbol *symbol);
void symbol_set_section (struct symbol *symbol, struct section *section);
+void symbol_set_symbol_table_index (struct symbol *symbol, unsigned long index);
void symbol_set_value (struct symbol *symbol, unsigned long value);
void symbol_set_value_expression (struct symbol *symbol, struct expr *expr);