Added coff object support and refactor to keep code under 64K
authorRobert Pengelly <robertapengelly@hotmail.com>
Sun, 11 May 2025 15:09:18 +0000 (16:09 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Sun, 11 May 2025 15:09:18 +0000 (16:09 +0100)
28 files changed:
Makefile.p32
Makefile.pdw
Makefile.std
Makefile.unix
Makefile.w32
Makefile.wat
as.c
as.h
bin.c
coff.c [new file with mode: 0644]
coff.h [new file with mode: 0644]
elks.c
expr.c
fixup.c
fixup.h
intel.c
kwd.c
lex.c
lex.h
lib.c
lib.h
macro.c
macro.h
process.c
section.c
section.h
symbol.c
symbol.h

index 77e1a8790927bbe271ca16198de75c2c9e133283..5f20489b6d4680bde77b451eab432fbcd13863e1 100644 (file)
@@ -6,7 +6,7 @@ CC=gcc386
 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
 
index 01ab4cf04003c3fae76ab602ea801493c2d45691..13643cfcd38b22a8ff46c077ff657b1ee57e0289 100644 (file)
@@ -6,7 +6,7 @@ CC=gccwin
 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
 
index 756ac2904e5d855c21733bea2a78eb18a394e4f1..7497cde403d1be27b511ff802726ce3d9f5fd703 100644 (file)
@@ -8,7 +8,7 @@ LD=pdld
 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
 
index 6870fa34b3e28f194195d5983269690afdc7ef78..95c06c74e85fada569ae3b0f952724d8223ceab1 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 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
index 10643476896adf76fd3b4c0be20cc865553787f6..999c74cb4185335e09ec271ebe450499884bb6f6 100644 (file)
@@ -7,7 +7,7 @@ VPATH               :=  $(SRCDIR)
 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
 
index 788c3d3bfefb4d15b98fadb82bbbcdd7f4eb1106..acbb2ed5113a80df65d89637339f1655c4d11aa2 100644 (file)
@@ -4,7 +4,7 @@
 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
 
diff --git a/as.c b/as.c
index 961c38381694f173be81a58cb9d273325e0d3e19..6d3905c31718e6596c1b682b3f3523ca557f632f 100644 (file)
--- a/as.c
+++ b/as.c
@@ -17,6 +17,7 @@ struct as_state *state = 0;
 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);
@@ -59,7 +60,6 @@ int main (int argc, char **argv) {
     }
     
     atexit (cleanup);
-    lex_init ();
     
     state = xmalloc (sizeof (*state));
     parse_args (argc, argv, 1);
@@ -124,50 +124,6 @@ int main (int argc, char **argv) {
         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);
@@ -175,7 +131,11 @@ int main (int argc, char **argv) {
     
     }
     
-    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;
diff --git a/as.h b/as.h
index 15d33f6e4756442e91e040db5e04ac33a6849363..aa97d137dc62b763137d2f45f2a3693192c88351 100644 (file)
--- a/as.h
+++ b/as.h
@@ -33,7 +33,8 @@ struct segment {
 #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 {
 
diff --git a/bin.c b/bin.c
index a22eaa3aba5bccd6ced973bf92d428a9bbd13b0b..eecb406299f925981ae3322dd75ce39d6ec37672 100644 (file)
--- a/bin.c
+++ b/bin.c
@@ -23,28 +23,10 @@ void output_binary (FILE *fp) {
     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);
     
diff --git a/coff.c b/coff.c
new file mode 100644 (file)
index 0000000..905b842
--- /dev/null
+++ b/coff.c
@@ -0,0 +1,444 @@
+/******************************************************************************
+ * @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;
+        
+        }
+    
+    }
+
+}
diff --git a/coff.h b/coff.h
new file mode 100644 (file)
index 0000000..adc7b8a
--- /dev/null
+++ b/coff.h
@@ -0,0 +1,120 @@
+/******************************************************************************
+ * @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 */
diff --git a/elks.c b/elks.c
index fe3463375bd41034291ba797e7cea66fdf137198..47ee19266d8c5c4322f8e7c567978fb3a436b70a 100644 (file)
--- a/elks.c
+++ b/elks.c
 #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;
@@ -126,46 +116,12 @@ void output_elks (FILE *fp) {
     }
     
     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);
     
diff --git a/expr.c b/expr.c
index b8400cf69e7dc50c825134556a7b0da09cf34e21..00d0f1550a859026b7731031fb9a29abac2c4679 100644 (file)
--- a/expr.c
+++ b/expr.c
@@ -331,7 +331,7 @@ static enum expr_type operator (char *p, unsigned int *operator_size) {
 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;
@@ -345,6 +345,23 @@ static struct section *operand (char *start, char **pp, struct expr *expr, int e
         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':
@@ -371,6 +388,8 @@ static struct section *operand (char *start, char **pp, struct expr *expr, int e
                 
                     (*pp)++;
                     
+                is_hex:
+                    
                     integer_constant (start, pp, expr, 16);
                     break;
                 
diff --git a/fixup.c b/fixup.c
index 379fec1f74e1d54273a486bcd105d179c7a71ef1..a944fc086432b7d82ea2dfefb7511e0b3dbcb9ec 100644 (file)
--- a/fixup.c
+++ b/fixup.c
@@ -237,21 +237,6 @@ static void relax_section (struct section *section) {
                         
                         }
                     
-                    } 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);
@@ -580,7 +565,7 @@ void fixup_code (void) {
         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;
diff --git a/fixup.h b/fixup.h
index 833117fc915282f6fdcb19ba3a74b5beb24de064..0cf2572016946906b7188123d3b0f96c57481802 100644 (file)
--- a/fixup.h
+++ b/fixup.h
@@ -8,6 +8,7 @@
 
 #define     RELOC_TYPE_DEFAULT          0
 #define     RELOC_TYPE_FAR_CALL         1
+#define     RELOC_TYPE_RVA              2
 
 struct fixup {
 
diff --git a/intel.c b/intel.c
index afde45af27f8431d8d74fffe189fa846c204b936..c4c7c5aa1a5f3dac49e5bf909586e40a842227b6 100644 (file)
--- a/intel.c
+++ b/intel.c
@@ -117,6 +117,8 @@ int operand_type_check (struct operand_type a, enum operand_type_group g) {
             exit (EXIT_FAILURE);
     
     }
+    
+    return 0;
 
 }
 
@@ -215,6 +217,7 @@ struct relax_table_entry relax_table[] = {
 
 static struct hashtab hashtab_templates = { 0 };
 static struct hashtab hashtab_regs = { 0 };
+static struct hashtab hashtab_models = { 0 };
 
 #define     DEFAULT_CPU_ARCH_NAME       "ALL"
 
@@ -1376,6 +1379,26 @@ static struct reg_entry reg_table[] = {
 
 };
 
+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'
@@ -1481,6 +1504,31 @@ struct reg_entry *machine_dependent_find_reg_entry (char *name) {
 
 }
 
+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
 
@@ -1774,16 +1822,6 @@ static void machine_dependent_set_bits (int new_bits, int cause_fatal_error) {
 }
 
 
-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;
@@ -1956,6 +1994,8 @@ static void handler_extern (char *start, char **pp) {
 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))) {
@@ -1969,35 +2009,10 @@ static void handler_model (char *start, char **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) {
     
@@ -2137,8 +2152,6 @@ static void handler_option (char *start, char **pp) {
 
 static struct pseudo_op_entry pseudo_op_table[] = {
 
-    {   ".amd64",       &handler_amd64      },
-    
     {   ".8086",        &handler_8086       },
     {   ".8087",        &handler_8087       },
     
@@ -2178,6 +2191,8 @@ void machine_dependent_init (void) {
     struct templates *templates;
     
     struct template *template = template_table;
+    struct model_entry *model_entry;
+    
     int ch;
     
     templates = xmalloc (sizeof (*templates));
@@ -2268,6 +2283,26 @@ void machine_dependent_init (void) {
     
     }
     
+    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)) {
@@ -2280,8 +2315,22 @@ void machine_dependent_init (void) {
     
     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);
 
@@ -2522,7 +2571,13 @@ static int add_prefix (unsigned char prefix) {
     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) {
@@ -3804,6 +3859,7 @@ static const struct intel_type intel_types[] = {
     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 }  },
@@ -4385,7 +4441,7 @@ static int match_template (char mnemonic_suffix) {
             
             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:
@@ -4411,12 +4467,16 @@ static int match_template (char mnemonic_suffix) {
     
     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;
         }
     
     }
@@ -5479,7 +5539,24 @@ static void output_call_or_jumpbyte (void) {
     }
     
     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;
+        
+        }
+    
     }
 
 }
@@ -5555,6 +5632,10 @@ static long convert_number_to_size (unsigned long value, int size) {
         
             mask = 0xffffffff;
             break;
+        
+        case 8:
+        
+            return value;
 
         default:
         
@@ -5590,6 +5671,24 @@ static int disp_size (struct operand_type operand_type) {
 
 }
 
+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;
@@ -5607,8 +5706,31 @@ static void output_disps (void) {
             
             } 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;
+                }
             
             }
         
@@ -5618,20 +5740,6 @@ static void output_disps (void) {
 
 }
 
-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;
@@ -5823,6 +5931,7 @@ signed long machine_dependent_estimate_size_before_relax (struct frag *frag, str
 
     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;
@@ -5834,7 +5943,7 @@ signed long machine_dependent_estimate_size_before_relax (struct frag *frag, str
             
                 *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;
@@ -5851,7 +5960,7 @@ signed long machine_dependent_estimate_size_before_relax (struct frag *frag, str
                     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;
                 
@@ -5864,7 +5973,7 @@ signed long machine_dependent_estimate_size_before_relax (struct frag *frag, str
                 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;
@@ -5873,7 +5982,7 @@ signed long machine_dependent_estimate_size_before_relax (struct frag *frag, str
             
                 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;
@@ -5886,6 +5995,14 @@ signed long machine_dependent_estimate_size_before_relax (struct frag *frag, str
         
         }
         
+        /**
+         * 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;
     
@@ -6090,7 +6207,7 @@ void machine_dependent_finish_frag (struct frag *frag) {
 
 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));
@@ -6103,6 +6220,10 @@ void machine_dependent_assemble_line (char *start, char *line) {
     
     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.
diff --git a/kwd.c b/kwd.c
index 01a2df41a4e70331f7f2097a5c8b264f1635e08f..60c014b1f17d10f485a277b85c735614a4f08d69 100644 (file)
--- a/kwd.c
+++ b/kwd.c
@@ -191,6 +191,8 @@ static void align_bytes (char *start, char **pp, int first_arg_is_bytes) {
 
 }
 
+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;
@@ -306,13 +308,7 @@ static void handle_constant (char *start, char **pp, int size) {
             }
             
             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);
diff --git a/lex.c b/lex.c
index 7fa85a4b38be739119abb0ec4a32913e98e66ad3..66cade61ab06d139c8622c9b2eb756faf4570dc7 100644 (file)
--- a/lex.c
+++ b/lex.c
@@ -3,33 +3,19 @@
  *****************************************************************************/
 #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{|}~      */
 
-}
+};
diff --git a/lex.h b/lex.h
index f295e8b09f6f7b9326e167ad4d5b441db8550fc9..fe82705dacc179788c391d9c62d0cb9677a2f42f 100644 (file)
--- a/lex.h
+++ b/lex.h
@@ -13,6 +13,4 @@ extern char lex_table[];
 #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 */
diff --git a/lib.c b/lib.c
index 9b555c123dac4f51c84a46f16689e03b75a19ebe..dd87125a5df8a7b04e2a730f2a035a0c503e8097 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -86,7 +86,8 @@ static void _print_usage (void) {
         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");
         
@@ -277,6 +278,16 @@ void add_include_path (const char *__p) {
 
 }
 
+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]) {
@@ -393,23 +404,30 @@ void parse_args (int argc, char **argv, int optind) {
             
             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;
                 
                 }
diff --git a/lib.h b/lib.h
index 72e9461efeb5f9e3b9b250852405b093d6c36e52..45886b856ecd6e3b78bac6dfe9eefc1578c1b9a2 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -18,7 +18,9 @@ int xstrcasecmp (const char *__s1, const char *__s2);
 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);
diff --git a/macro.c b/macro.c
index f196af6f953afccc8bc09c20950b40fcebf58717..31c3741a793dbccbc5619517cb9db40b13ad645b 100644 (file)
--- a/macro.c
+++ b/macro.c
 
 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;
@@ -305,8 +285,6 @@ void remove_macro (char *start, char **pp, int report_line) {
     
     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 {
@@ -315,10 +293,6 @@ void remove_macro (char *start, char **pp, int report_line) {
         
         return;
     
-    }
-        
-        return;
-    
     }
     
     if ((key = find_macro (sname))) {
@@ -549,7 +523,3 @@ char *process_macro (char *start, char **pp, struct macro *m) {
     return m->value;
 
 }
-
-void push_macro (struct hashtab_name *key, struct macro *m) {
-    hashtab_put (&hashtab_macros, key, m);
-}
diff --git a/macro.h b/macro.h
index 220bef0d741232afd49fd97991b636b0a4eec072..75230863497372d4f02af76d720cea4b000da129 100644 (file)
--- a/macro.h
+++ b/macro.h
@@ -20,15 +20,13 @@ struct macro {
 };
 
 #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 */
index 62fe72f6374235234002945f56ac4e16d5de26e1..0402d20c4b42e36350c4b14d875ee764f03d403c 100644 (file)
--- a/process.c
+++ b/process.c
@@ -497,14 +497,14 @@ static struct pp_pseudo_op_entry cond_pseudo_op_table[] = {
 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;
@@ -518,7 +518,7 @@ static void install_cond_pseudo_op_table (struct pp_pseudo_op_entry *table) {
         
         }
         
-        hashtab_put (&hashtab_cond_pseudo_ops, key, entry);
+        hashtab_put (hashatb_table, key, entry);
     
     }
 
@@ -682,33 +682,6 @@ static struct pp_pseudo_op_entry pseudo_op_table[] = {
 
 };
 
-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;
@@ -727,29 +700,6 @@ struct pp_pseudo_op_entry *find_directive (char *name) {
 }
 
 
-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;
@@ -758,14 +708,6 @@ int preprocess_init (void) {
     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;
@@ -789,29 +731,25 @@ int preprocess_init (void) {
             
                 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:
@@ -825,8 +763,8 @@ int preprocess_init (void) {
     
     }
     
-    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;
 
index 8922fa4be2be5aa29dd0d634bb394420b83b8738..a640346f62a93f0cc7317967a1da622c38cca359 100644 (file)
--- a/section.c
+++ b/section.c
@@ -1,21 +1,28 @@
 /******************************************************************************
  * @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;
 
 };
@@ -37,6 +44,8 @@ struct section *current_section;
 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;
@@ -72,11 +81,38 @@ struct section *section_get_next_section (struct section *section) {
 
 struct section *section_set (struct section *section) {
 
+    struct frag_chain *frag_chain, **p_next;
+    unsigned long subsection = 0;
+    
     current_section = section;
     
-    current_frag_chain = &current_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;
 
 }
@@ -93,14 +129,54 @@ const char *section_get_name (struct section *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)];        \
@@ -120,16 +196,13 @@ void sections_init (void) {
     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);
@@ -137,3 +210,21 @@ void sections_init (void) {
 }
 
 #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;
+}
index d4faeaaaa84006a305d4f76adffe3d5988a94cab..cce2903ebecac39f47ec506fe55a1c699a96893a 100644 (file)
--- a/section.h
+++ b/section.h
@@ -4,15 +4,34 @@
 #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))
 
@@ -37,6 +56,16 @@ struct section *section_set_by_name (const char *name);
 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 */
index 4cc341c35857566103bfe84e91332d5e82f21e6d..c857281a2f6f5449e4c856b863acf9655ed59d12 100644 (file)
--- a/symbol.c
+++ b/symbol.c
@@ -370,6 +370,10 @@ int symbol_uses_reloc_symbol (struct symbol *symbol) {
     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);
 }
@@ -776,6 +780,10 @@ void symbol_set_section (struct symbol *symbol, struct section *section) {
     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;
index 3c5760eb48001dee1a828ce6acdb995d07b9d9cb..9fdde013e5605692de480ca112697578e5d837e7 100644 (file)
--- a/symbol.h
+++ b/symbol.h
@@ -18,9 +18,11 @@ struct symbol {
     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;
 
 };
@@ -56,6 +58,7 @@ int symbol_is_undefined (struct symbol *symbol);
 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);
 
@@ -63,6 +66,7 @@ void symbol_add_to_chain (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);