]> Shamusworld >> Repos - rmac/blobdiff - object.c
Fix for bug #78: Thanks to ggn for reporting and supplying the patch.
[rmac] / object.c
index d8b4b577017d2729031544cf7639325960a65bdb..4614c38d66ed373eed028d7f0ed9a849f1282017 100644 (file)
--- a/object.c
+++ b/object.c
 #include "mark.h"
 #include "error.h"
 #include "riscasm.h"
+#include "mark.h"
+
+/*
+ *  Imports
+ */
+extern int obj_format;         // object file format to write
+extern int prg_flag;           // generate Atari ST direct executable
 
 LONG symsize = 0;                      // Size of BSD symbol table
 LONG strindx = 0x00000004;     // BSD string table index
@@ -71,6 +78,132 @@ char * constr_bsdsymtab(char * buf, SYM * sym, int globflag)
 }
 
 
+/*
+ *  Alcyon symbol flags
+ */
+#define        AL_DEFINED      0x8000
+#define        AL_EQUATED      0x4000
+#define        AL_GLOBAL       0x2000
+#define        AL_EQUREG       0x1000
+#define        AL_EXTERN       0x0800
+#define        AL_DATA         0x0400
+#define        AL_TEXT         0x0200
+#define        AL_BSS          0x0100
+#define        AL_FILE         0x0080
+
+LONG PRGFLAGS;         /* PRGFLAGS as defined in Atari Compendium Chapter 2 */
+                                       /* Definition   Bit(s)  Meaning */
+                                       /* PF_FASTLOAD  0               If set, clear only the BSS area on program load,              */
+                                       /*                                              otherwise clear the entire heap.                              */
+                                       /* PF_TTRAMLOAD 1               If set, the program may be loaded into alternative RAM,       */
+                                       /*                                              otherwise it must be loaded into standard RAM.                */
+                                       /* PF_TTRAMMEM  2               If set, the program's Malloc() requests may be satisfied      */
+                                       /*                                              from alternative RAM, otherwise they must be satisfied        */
+                                       /*                                              from standard RAM.                                            */
+                                       /* -                    3               Currently unused.                                             */
+                                       /* See left.    4 & 5   If these bits are set to 0 (PF_PRIVATE), the processes'       */
+                                       /*                                              entire memory space will be considered private                */
+                                       /*                                              (when memory protection is enabled).If these bits are         */
+                                       /*                                              set to 1 (PF_GLOBAL), the processes' entire memory space      */
+                                       /*                                              will be readable and writable by any process (i.e. global).   */
+                                       /*                                              If these bits are set to 2 (PF_SUPERVISOR), the processes'    */
+                                       /*                                              entire memory space will only be readable and writable by     */
+                                       /*                                              itself and any other process in supervisor mode.If these      */
+                                       /*                                              bits are set to 3 (PF_READABLE), the processes' entire memory */
+                                       /*                                              space will be readable by any application but only            */
+                                       /*                                              writable by itself.                                           */
+                                       /* -                    6-15    Currently unused.                                             */
+
+static WORD tdb_tab[] = {
+       0,                              /* absolute */
+       AL_TEXT,                /* TEXT segment based */
+       AL_DATA, 0,             /* DATA segment based */
+       AL_BSS                  /* BSS segment based */
+};
+
+
+#define HDRSIZE 0x1C           /* size of Alcyon header */
+
+
+/*
+ *  Add entry to symbol table;
+ *  if `globflag' is 1, make the symbol global;
+ *  if in .PRG mode, adjust symbol values for fake link.
+ *
+ */
+char * constr_symtab(register char * buf, SYM * sym, int globflag)
+{
+       register int i;
+       register char * s;
+       register WORD w;
+       register LONG z;
+       register WORD w1;
+
+       /*
+        *  Copy symbol name
+        */
+       s = sym->sname;
+
+       for(i=0; i<8 && *s; i++)
+               *buf++ = *s++;
+
+       while (i++ < 8)
+               *buf++ = '\0';
+
+       /*
+        *  Construct and deposit flag word
+        *
+        *      o  all symbols are AL_DEFINED
+        *      o  install T/D/B/A base
+        *    o  install 'equated'
+        *    o  commons (COMMON) are AL_EXTERN, but not BSS
+        *      o  exports (DEFINED) are AL_GLOBAL
+        *      o  imports (~DEFINED) are AL_EXTERN
+        *
+        */
+       w1 = sym->sattr;
+       w = AL_DEFINED | tdb_tab[w1 & TDB];
+
+       if (w1 & EQUATED)               /* equated */
+               w |= AL_EQUATED;
+
+       if (w1 & COMMON)
+       {
+               w |= AL_EXTERN | AL_GLOBAL;     /* common symbol */
+               w &= ~AL_BSS;           /* they're not BSS in Alcyon object files */
+       }
+       else if (w1 & DEFINED)
+       {
+               if (globflag)           /* export the symbol */
+                       w |= AL_GLOBAL;
+       }
+       else w |= AL_EXTERN;            /* imported symbol */
+
+       *buf++ = w >> 8;
+       *buf++ = (char)w;
+
+       z = sym->svalue;
+
+       if (prg_flag)                   /* relocate value in .PRG segment */
+       {
+               w1 &= DATA | BSS;
+
+               if (w1)
+                       z += sect[TEXT].sloc;
+
+               if (w1 & BSS)
+                       z += sect[DATA].sloc;
+       }
+
+       *buf++ = z >> 24;               /* deposit symbol value */
+       *buf++ = z >> 16;
+       *buf++ = z >> 8;
+       *buf++ = z;
+
+       return buf;
+}
+
+
 //
 // Write an object file to the passed in file descriptor
 // N.B.: Return value is ignored...
@@ -87,10 +220,24 @@ int WriteObject(int fd)
        LONG trsize, drsize;    // Size of relocations
        long unused;                    // For supressing 'write' warnings
 
-       // Write requested object file...
-       switch (obj_format)
+       if (verb_flag)
        {
-       case BSD:
+               printf("TEXT segment: %d bytes\n", sect[TEXT].sloc);
+               printf("DATA segment: %d bytes\n", sect[DATA].sloc);
+               printf("BSS  segment: %d bytes\n", sect[BSS].sloc);
+       }
+
+       // Write requested object file...
+       if ((obj_format == BSD) || ((obj_format == ALCYON) && (prg_flag == 0)))
+    {
+               // Force BSD format from here onwards
+               obj_format = BSD;
+
+               if (verb_flag)
+               {
+                       printf("Total       : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
+               }
+
                ssize = ((LONG)sy_assign(NULL, NULL));          // Assign index numbers to the symbols
                tds = sect[TEXT].sloc + sect[DATA].sloc;        // Get size of TEXT and DATA segment
                buf = malloc(0x600000);                                         // Allocate 6mb object file image memory
@@ -168,7 +315,94 @@ int WriteObject(int fd)
                if (buf)
                        free(buf);                                      // Free allocated memory
 
-               break;
+    }
+    else if (obj_format==ALCYON)
+    {
+               if (verb_flag)
+               {
+                       if (prg_flag)
+                       {
+                               printf("TOS header  : 28 bytes\n");
+                               printf("Total       : %d bytes\n", 28 + sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
+                       }
+                       else
+                       {
+                               printf("Total       : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
+                       }
+               }
+               /*
+                *  Compute size of symbol table;
+                *   assign numbers to the symbols...
+                */
+               ssize = 0;
+
+               if (prg_flag != 1)
+                       ssize = ((LONG)sy_assign(NULL, NULL)) * 14;
+
+               /*
+                *  Alloc memory for header+text+data, symbol and
+                *   relocation information construction.
+                */
+               t = tds = sect[TEXT].sloc + sect[DATA].sloc;
+
+               if (t < ssize)
+                       t = ssize;
+
+               buf = (char *)((int)malloc(t + HDRSIZE) + HDRSIZE);
+
+               /*
+                *  Build object file header
+                *   just before the text+data image
+                */
+               chptr = buf - HDRSIZE;  /* -> base of header */
+               D_word(0x601a);                 /* 00 - magic number */
+               t = sect[TEXT].sloc;    /* 02 - TEXT size */
+               D_long(t);
+               t = sect[DATA].sloc;    /* 06 - DATA size */
+               D_long(t);
+               t = sect[BSS].sloc;             /* 0a - BSS size */
+               D_long(t);
+               D_long(ssize);                  /* 0e - symbol table size */
+               D_long(0);                              /* 12 - stack size (unused) */
+               D_long(PRGFLAGS);               /* 16 - PRGFLAGS */
+               D_word(0);                              /* 1a - relocation information exists */
+
+               /*
+                *  Construct text and data segments;
+                *  fixup relocatable longs in .PRG mode;
+                *  finally write the header+text+data
+                */
+               p = buf;
+
+               for(i=TEXT; i<=DATA; i++)
+               {
+                       for (cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext)
+                       {
+                               memcpy(p, cp->chptr, cp->ch_size);
+                               p += cp->ch_size;
+                       }
+               }
+
+               if (prg_flag)
+                       markimg(buf, tds, sect[TEXT].sloc, 0);
+
+               write(fd, buf - HDRSIZE, tds + HDRSIZE);
+
+               /*
+                *  Construct and write symbol table
+                */
+               if (prg_flag != 1)
+               {
+                       sy_assign(buf, constr_symtab);
+                       write(fd, buf, ssize);
+               }
+
+               /*
+                *  Construct and write relocation information;
+                *   the size of it changes if we're writing a RELMODed executable.
+                */
+               tds = markimg(buf, tds, sect[TEXT].sloc, 1);
+               write(fd, buf, tds);
        }
 
        return 0;