]> Shamusworld >> Repos - rmac/blobdiff - object.c
Fix for bug #33. Thanks to Linkovitch for reporting!
[rmac] / object.c
index 4e9613f5a258a2a02f3c079ef7a8c23cea9809cf..2702c54ad4dd4cdf586f63351d5fc6bb7d60474b 100644 (file)
--- a/object.c
+++ b/object.c
@@ -3,7 +3,7 @@
 // OBJECT.C - Writing Object Files
 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
-// Source Utilised with the Kind Permission of Landon Dyer
+// Source utilised with the kind permission of Landon Dyer
 //
 
 #include "object.h"
 #include "error.h"
 #include "riscasm.h"
 
-LONG symsize = 0;                                                      // Size of BSD symbol table
-LONG strindx = 0x00000004;                                     // BSD string table index
-char * strtable;                                                       // Pointer to the symbol string table
-char * objimage;                                                       // Global object image pointer
+/*
+ *  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
+char * strtable;                       // Pointer to the symbol string table
+char * objImage;                       // Global object image pointer
 
 
 //
@@ -24,20 +30,16 @@ char * objimage;                                                    // Global object image pointer
 //
 char * constr_bsdsymtab(char * buf, SYM * sym, int globflag)
 {
-       LONG z;                                                                 // Scratch long
-       WORD w1;                                                                // Scratch word
-       int w2;                                                                 // Scratch long
-
-       chptr = buf;                                                    // Point to buffer for deposit longs
-       D_long(strindx);                                                // Deposit the symbol string index
+       chptr = buf;                                            // Point to buffer for deposit longs
+       D_long(strindx);                                        // Deposit the symbol string index
 
-       w1 = sym->sattr;                                                // Obtain symbol attribute
-       w2 = sym->sattre;
-       z = 0;                                                                  // Initialise resulting symbol flags
+       WORD w1 = sym->sattr;                           // Obtain symbol attribute
+       int w2 = sym->sattre;
+       LONG z = 0;                                                     // Initialise resulting symbol flags
 
        if (w1 & EQUATED)
        {                                       
-               z = 0x02000000;                                         // Set equated flag
+               z = 0x02000000;                                 // Set equated flag
        }
        else
        {
@@ -50,35 +52,140 @@ char * constr_bsdsymtab(char * buf, SYM * sym, int globflag)
        }
 
        if (globflag)
-               z |= 0x01000000;                                        // Set global flag if requested
+               z |= 0x01000000;                                // Set global flag if requested
 
-       D_long(z);                                                              // Deposit symbol attribute
+       D_long(z);                                                      // Deposit symbol attribute
 
-       z = sym->svalue;                                                // Obtain symbol value
-       w1 &= DATA | BSS;                                               // Determine DATA or BSS flag
+       z = sym->svalue;                                        // Obtain symbol value
+       w1 &= DATA | BSS;                                       // Determine DATA or BSS flag
 
        if (w1)                                                   
-               z += sect[TEXT].sloc;                           // If DATA or BSS add TEXT segment size
+               z += sect[TEXT].sloc;                   // If DATA or BSS add TEXT segment size
 
        if (w1 & BSS) 
-               z += sect[DATA].sloc;                           // If BSS add DATA segment size
+               z += sect[DATA].sloc;                   // If BSS add DATA segment size
 
-       D_long(z);                                                              // Deposit symbol value
+       D_long(z);                                                      // Deposit symbol value
 
        strcpy(strtable + strindx, sym->sname);
 
-       strindx += strlen(sym->sname) + 1;              // Incr string index incl null terminate
-       buf += 12;                                                              // Increment buffer to next record
-       symsize += 12;                                                  // Increment symbol table size
+       strindx += strlen(sym->sname) + 1;      // Incr string index incl null terminate
+       buf += 12;                                                      // Increment buffer to next record
+       symsize += 12;                                          // Increment symbol table size
+
+       return buf;
+}
+
+
+/*
+ *  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
+
+
+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++ = 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;
 }
 
 
 //
-// Generate object file
+// Write an object file to the passed in file descriptor
+// N.B.: Return value is ignored...
 //
-int object(WORD fd)
+int WriteObject(int fd)
 {
        LONG t;                                 // Scratch long
        LONG tds;                               // TEXT & DATA segment size
@@ -104,9 +211,9 @@ int object(WORD fd)
                        return ERROR;
                }
 
-               memset(buf, 0, 0x600000);                                       // Reset allocated memory
-               objimage = buf;                                                         // Set global object image pointer
-               strtable = malloc(0x200000);                            // Allocate 2mb scratch buffer 
+               memset(buf, 0, 0x600000);               // Reset allocated memory
+               objImage = buf;                                 // Set global object image pointer
+               strtable = malloc(0x200000);    // Allocate 2mb scratch buffer 
 
                if (strtable == NULL)
                {
@@ -114,18 +221,18 @@ int object(WORD fd)
                        return ERROR;
                }
 
-               memset(strtable, 0, 0x200000);                          // Reset allocated memory
+               memset(strtable, 0, 0x200000);  // Reset allocated memory
 
                // Build object file header
-               chptr = buf;                                                            // Base of header
-               D_long(0x00000107);                                                     // Magic number
-               D_long(sect[TEXT].sloc);                                        // TEXT size 
-               D_long(sect[DATA].sloc);                                        // DATA size 
-               D_long(sect[BSS].sloc);                                         // BSS size 
-               D_long(0x00000000);                                                     // Symbol size
-               D_long(0x00000000);                                                     // First entry (0L)
-               D_long(0x00000000);                                                     // TEXT relocation size
-               D_long(0x00000000);                                                     // BSD relocation size
+               chptr = buf;                                    // Base of header
+               D_long(0x00000107);                             // Magic number
+               D_long(sect[TEXT].sloc);                // TEXT size 
+               D_long(sect[DATA].sloc);                // DATA size 
+               D_long(sect[BSS].sloc);                 // BSS size 
+               D_long(0x00000000);                             // Symbol size
+               D_long(0x00000000);                             // First entry (0L)
+               D_long(0x00000000);                             // TEXT relocation size
+               D_long(0x00000000);                             // BSD relocation size
 
                // Construct TEXT and DATA segments (without relocation changes)
                p = buf + BSDHDRSIZE;
@@ -134,45 +241,122 @@ int object(WORD fd)
                {
                        for(cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext)
                        {
-                               copy(p, cp->chptr, cp->ch_size);
+                               memcpy(p, cp->chptr, cp->ch_size);
                                p += cp->ch_size;
                        }
                }
 
                // Do relocation tables (and make changes to segment data)
-               p = buf + (BSDHDRSIZE + tds);                           // Move obj image ptr to reloc info
+               p = buf + (BSDHDRSIZE + tds);   // Move obj image ptr to reloc info
                trsize = bsdmarkimg(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table
-               chptr = buf + 24;                                                       // Point to relocation hdr entry
-               D_long(trsize);                                                         // Write the relocation table size
-               p = buf + (BSDHDRSIZE + tds + trsize);          // Move obj image ptr to reloc info
+               chptr = buf + 24;                               // Point to relocation hdr entry
+               D_long(trsize);                                 // Write the relocation table size
+               p = buf + (BSDHDRSIZE + tds + trsize);  // Move obj image ptr to reloc info
                drsize = bsdmarkimg(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table
-               chptr = buf + 28;                                                       // Point to relocation hdr entry
-               D_long(drsize);                                                         // Write the relocation table size
+               chptr = buf + 28;                               // Point to relocation hdr entry
+               D_long(drsize);                                 // Write the relocation table size
 
                p = buf + (BSDHDRSIZE + tds + trsize + drsize);// Point to start of symbol table
-               sy_assign(p, constr_bsdsymtab);                         // Build symbol and string tables
-               chptr = buf + 16;                                                       // Point to sym table size hdr entry
-               D_long(symsize);                                                        // Write the symbol table size
+               sy_assign(p, constr_bsdsymtab); // Build symbol and string tables
+               chptr = buf + 16;                               // Point to sym table size hdr entry
+               D_long(symsize);                                // Write the symbol table size
 
                // Point to string table
                p = buf + (BSDHDRSIZE + tds + trsize + drsize + symsize);    
 
-               memcpy(p, strtable, strindx);                           // Copy string table to object image
+               memcpy(p, strtable, strindx);   // Copy string table to object image
 
                if (buf)
-                       free(strtable);                                                 // Free allocated memory
+                       free(strtable);                         // Free allocated memory
 
-               chptr = p;                                                                      // Point to string table size long
-               D_long(strindx);                                                        // Write string table size
+               chptr = p;                                              // Point to string table size long
+               D_long(strindx);                                // Write string table size
 
                // Write the BSD object file from the object image buffer
                unused = write(fd, buf, BSDHDRSIZE + tds + trsize + drsize + symsize + strindx + 4);
 
                if (buf)
-                       free(buf);                                                              // Free allocated memory
+                       free(buf);                                      // Free allocated memory
+
+               break;
+
+       case ALCYON:
+               /*
+                *  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 = malloc((t + HDRSIZE) + HDRSIZE);
+
+               /*
+                *  Build object file header
+                *   just before the text+data image
+                */
+               chptr = buf - HDRSIZE;  /* -> base of header */
+               D_word(0x601a);                 /* magic number */
+               t = sect[TEXT].sloc;    /* TEXT size */
+               D_long(t);
+               t = sect[DATA].sloc;    /* DATA size */
+               D_long(t);
+               t = sect[BSS].sloc;             /* BSS size */
+               D_long(t);
+               D_long(ssize);                  /* symbol table size */
+               D_long(0);                              /* stack size (unused) */
+               D_long(0);                              /* entry point (unused) */
+               D_word(0);                              /* 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);
                break;
        }
 
        return 0;
 }
+