]> Shamusworld >> Repos - rmac/blobdiff - mark.c
Long forgotten helper script which is used to create tables for VS builds
[rmac] / mark.c
diff --git a/mark.c b/mark.c
index 855d925b253e31b5021c9cb970af2b294f919f43..1cb0f05131472f9d097dbdf5fe152ba58ef8c03e 100644 (file)
--- a/mark.c
+++ b/mark.c
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+//
+// RMAC - Reboot's Macro Assembler for all Atari computers
 // MARK.C - A record of things that are defined relative to any of the sections
-// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2019 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 "mark.h"
 #include "error.h"
 #include "object.h"
-#include "risca.h"
+#include "riscasm.h"
+#include "sect.h"
 
-MCHUNK *firstmch;                                           // First mark chunk
-MCHUNK *curmch;                                             // Current mark chunk
-PTR markptr;                                                // Deposit point in current mark chunk
-LONG mcalloc;                                               // #bytes alloc'd to current mark chunk
-LONG mcused;                                                // #bytes used in current mark chunk
-WORD curfrom;                                               // Current "from" section
 
-//
-// --- Initialize Marker ---------------------------------------------------------------------------
-//
+#define MARK_ALLOC_INCR 1024           // # bytes to alloc for more mark space
+#define MIN_MARK_MEM    (3 * sizeof(uint16_t) + 1 * sizeof(uint32_t) + sizeof(SYM *))
 
-void init_mark(void) {
-   firstmch = curmch = NULL;
-   mcalloc = mcused = 0;
-   curfrom = 0;
-}
+MCHUNK * firstmch;             // First mark chunk
+MCHUNK * curmch;               // Current mark chunk
+PTR markptr;                   // Deposit point in current mark chunk
+uint32_t mcalloc;              // # bytes alloc'd to current mark chunk
+uint32_t mcused;               // # bytes used in current mark chunk
+uint16_t curfrom;              // Current "from" section
 
-//
-// --- Wrap up marker (called after final mark is made) --------------------------------------------
-//
+// Table to convert from TDB to fixup triad
+static uint8_t mark_tr[] = {
+       0,              // (N/A)
+       2,              // TEXT relocatable
+       1, 0,   // DATA relocatable
+       3               // BSS relocatable
+};
+
+//#define DEBUG_IMAGE_MARKING
 
-void stopmark(void) {
-   if(curmch) {
-      *markptr.wp = MCHEND;                                 // Mark end of block
-      curmch->mcused = mcused;                              // Update #used in mark block
-   }
-}
 
 //
-// --- Mark a word or longword relocatable ---------------------------------------------------------
+// Initialize marker
 //
+void InitMark(void)
+{
+       firstmch = curmch = NULL;
+       mcalloc = mcused = 0;
+       curfrom = 0;
+       sect[TEXT].relocs = sect[DATA].relocs = sect[BSS].relocs = 0;
+}
 
-int rmark(int from, LONG loc, int to, int size, SYM *symbol) {
-   WORD w;
-
-   if((mcalloc - mcused) < MIN_MARK_MEM)
-      amark();
-
-   w = (WORD)(size | to);
-   if(from != curfrom)
-      w |= MCHFROM;
-   if(symbol != NULL)
-      w |= MSYMBOL;
-
-   mcused += sizeof(WORD) + sizeof(LONG);
-   *markptr.wp++ = w;
-   *markptr.lp++ = loc;
-
-   if(w & MCHFROM) {
-      *markptr.wp++ = (WORD)from;
-      curfrom = (WORD)from;
-      mcused += sizeof(WORD);
-   }
 
-   if(w & MSYMBOL) {
-      *markptr.sy++ = symbol;
-      mcused += sizeof(LONG);
-   }
+//
+// Wrap up marker (called after final mark is made)
+//
+void StopMark(void)
+{
+       if (curmch)
+       {
+               *markptr.wp = MCHEND;           // Mark end of block
+               curmch->mcused = mcused;        // Update # used in mark block
+       }
+}
 
-   *markptr.wp = 0x0000;
 
-   return(0);
+//
+// Mark a word or longword as relocatable
+//
+// Record is either 2, 3, or 4 pieces of data long. A mark is of the form:
+// .W    <to+flags>    section mark is relative to, and flags in upper byte
+// .L    <loc>         location of mark in "from" section
+// .W    [from]                new from section (if different from current)
+// .L    [symbol]      symbol involved in external reference (if any)
+//
+uint32_t MarkRelocatable(uint16_t section, uint32_t loc, uint16_t to, uint16_t flags, SYM * symbol)
+{
+#ifdef DEBUG_IMAGE_MARKING
+printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=%p\n", section, loc, to, flags, symbol);
+if (symbol)
+       printf("      symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%li, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname);
+#endif
+
+       if ((mcalloc - mcused) < MIN_MARK_MEM)
+               AllocateMark();
+
+       // Set up flags
+       flags |= to;
+
+       if (section != curfrom)
+               flags |= MCHFROM;
+
+       if (symbol != NULL)
+               flags |= MSYMBOL;
+
+       //
+       // Complain about some things are not allowed in '-p' (PRG) mode:
+       //  o  Marks that aren't to LONGs
+       //  o  External references
+       //
+       if (prg_flag)
+       {
+               if (symbol != NULL)
+                       error("illegal external reference (in .PRG mode) to '%s'",
+                               symbol->sname);
+       }
+
+       // Dump crap into the mark
+       *markptr.wp++ = flags;
+       *markptr.lp++ = loc;
+       mcused += sizeof(uint16_t) + sizeof(uint32_t);
+
+       if (flags & MCHFROM)
+       {
+               curfrom = section;
+               *markptr.wp++ = section;
+               mcused += sizeof(uint16_t);
+       }
+
+       if (flags & MSYMBOL)
+       {
+               *markptr.sy++ = symbol;
+               mcused += sizeof(SYM *);
+       }
+
+       // Increment # of relocs in this section
+       sect[section].relocs++;
+
+       // Not sure what this is about (making sure the next mark is clear until
+       // it's marked as the end--I think)...
+       *markptr.wp = 0x0000;
+
+       return 0;
 }
 
+
 //
-// --- Allocate another chunk of mark space --------------------------------------------------------
+// Allocate another chunk of mark space
 //
+uint32_t AllocateMark(void)
+{
+       // Alloc mark block header (and data) and set it up.
+       MCHUNK * p = malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR);
+       p->mcnext = NULL;
+       p->mcalloc = MARK_ALLOC_INCR;
+       p->mcptr.cp = (uint8_t *)p + sizeof(MCHUNK);
+       p->mcused = 0;
+
+       if (firstmch == NULL)
+               firstmch = p;
+
+       if (curmch)
+       {
+               // Link onto previous chunk
+               *markptr.wp++ = MCHEND;         // Mark end of block
+               curmch->mcused = mcused;
+               curmch->mcnext = p;
+       }
+
+       // Setup global vars
+       curmch = p;
+       markptr = p->mcptr;
+       mcalloc = MARK_ALLOC_INCR;
+       mcused = 0;
+
+       return 0;
+}
 
-int amark(void) {
-   MCHUNK *p;
-
-   // Alloc mark block header (and data) and set it up.
-   p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR);
-   p->mcnext = NULL;
-   p->mcalloc = MARK_ALLOC_INCR;
-   p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK));
 
-   if(curmch) {                                             // Link onto previous chunk 
-      *markptr.wp++ = MCHEND;                               // Mark end of block 
-      curmch->mcused = mcused;
-      curmch->mcnext = p;
-   }
-   if(!firstmch)
-      firstmch = p;
+//
+// Make mark image for Alcyon .o file
+// okflag: 1, ok to deposit reloc information
+//
+uint32_t MarkImage(register uint8_t * mp, uint32_t siz, uint32_t tsize, int okflag)
+{
+       uint16_t from = 0;              // Section fixups are currently FROM
+       uint32_t loc;                   // Location (temp)
+       uint32_t lastloc;               // Last location fixed up (RELMOD)
+       uint8_t * wp;                   // Pointer into raw relocation information
+       register uint8_t * dp;  // Deposit point for RELMOD information
+
+       if (okflag)
+               memset(mp, 0, siz);             // zero relocation buffer
+
+       for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
+       {
+               for(PTR p=mch->mcptr;;)
+               {
+                       uint16_t w = *p.wp++;// w = next mark entry
+
+                       if (w & MCHEND)         // (end of mark chunk)
+                               break;
+
+                       // Get mark record
+                       SYM * symbol = NULL;
+                       loc = *p.lp++;          // mark location
+
+                       if (w & MCHFROM)        // maybe change "from" section
+                               from = *p.wp++;
+
+                       if (w & MSYMBOL)        // maybe includes a symbol
+                               symbol = *p.sy++;
+
+                       // Compute mark position in relocation information; in RELMOD mode,
+                       // get address of data to fix up.
+                       if (from == DATA)
+                               loc += tsize;
+
+                       wp = (uint8_t *)(mp + loc);
+
+                       if (okflag && (w & MLONG)) // indicate first word of long
+                       {
+                               wp[1] = 5;
+                               wp += 2;
+                       }
+
+                       if (symbol)
+                       {
+                               // Deposit external reference
+                               if (okflag)
+                               {
+                                       if (w & MPCREL)
+                                               w = 6;          // PC-relative fixup
+                                       else
+                                               w = 4;          // Absolute fixup
+
+                                       w |= symbol->senv << 3;
+                                       *wp++ = w >> 8;
+                                       *wp = (uint8_t)w;
+                               }
+                       }
+                       else
+                       {
+                               // Deposit section-relative mark; in RELMOD mode, fix it up in
+                               // the chunk, kind of like a sleazoid linker.
+                               //
+                               // In RELMOD mode, marks to words (MWORDs) "cannot happen,"
+                               // checks are made when mark() is called, so we don't have to
+                               // check again here.
+                               w &= TDB;
+
+                               if (okflag)
+                                       wp[1] = mark_tr[w];
+                               else if (prg_flag && (w & (DATA | BSS)))
+                               {
+                                       uint32_t diff = GETBE32(wp, 0);
+#ifdef DO_DEBUG
+                                       DEBUG printf("diff=%lx ==> ", diff);
+#endif
+                                       diff += sect[TEXT].sloc;
+
+                                       if (w == BSS)
+                                               diff += sect[DATA].sloc;
+
+                                       SETBE32(wp, 0, diff)
+#ifdef DO_DEBUG
+                                       DEBUG printf("%lx\n", diff);
+#endif
+                               }
+                       }
+               }
+       }
+
+       // Generate ".PRG" relocation information in place in the relocation words
+       // (the "RELMOD" operation).
+       if (okflag && prg_flag)
+       {
+               int firstp = 1;
+               wp = dp = mp;
+
+               for(loc=0; loc<siz;)
+               {
+                       if ((wp[1] & 7) == 5)
+                       {
+                               if (firstp)
+                               {
+                                       SETBE32(dp, 0, loc);
+                                       dp += 4;
+                                       firstp = 0;
+                               }
+                               else
+                               {
+                                       uint32_t diff;
+
+                                       for(diff=loc-lastloc; diff>254; diff-=254)
+                                               *dp++ = 1;
+
+                                       *dp++ = (uint8_t)diff;
+                               }
+
+                               lastloc = loc;
+                               loc += 4;
+                               wp += 4;
+                       }
+                       else
+                       {
+                               loc += 2;
+                               wp += 2;
+                       }
+               }
+
+               // Terminate relocation list with 0L (if there was no relocation) or
+               // 0.B (if relocation information was written).
+               if (!firstp)
+                       *dp++ = 0;
+               else
+                       for(firstp=0; firstp<4; firstp++)
+                               *dp++ = 0;
+
+               // Return size of relocation information
+               loc = dp - mp;
+               return loc;
+       }
+
+       return siz;
+}
 
-   curmch = p;                                              // Setup global vars 
-   markptr = p->mcptr;
-   mcalloc = MARK_ALLOC_INCR;
-   mcused = 0;
 
-   return(0);
+//
+// Make mark image for BSD .o file
+//
+// Assumptions about mark records (for BSD): if there is a symbol, the mark is
+// for an undefined symbol, otherwise it's just a normal TDB relocation.
+// N.B.: tsize is only used if reqseg is DATA
+//
+uint32_t MarkBSDImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg)
+{
+       uint16_t from = 0;                      // Section fixups are currently FROM
+       uint32_t rsize = 0;                     // Relocation table size (written to mp)
+       int validsegment = 0;           // We are not yet in a valid segment...
+
+#ifdef DEBUG_IMAGE_MARKING
+printf("MarkBSDImage():\n");
+#endif
+       // Initialize relocation table point (for D_foo macros)
+       chptr = mp;
+
+       // Run through all the relocation mark chunks
+       for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
+       {
+               for(PTR p=mch->mcptr;;)
+               {
+                       SYM * symbol = NULL;
+                       uint16_t w = *p.wp++;   // Next mark entry
+
+                       // If we hit the end of a chunk, go get the next one
+                       if (w & MCHEND)
+                               break;
+
+                       // Get the rest of the mark record
+                       uint32_t loc = *p.lp++; // Mark location
+
+                       // Maybe change "from" section
+                       if (w & MCHFROM)
+                       {
+                               from = *p.wp++;
+
+                               if (((reqseg == TEXT) && (from == TEXT))
+                                       || ((reqseg == DATA) && (from == DATA)))
+                                       validsegment = 1;
+                               else
+                                       validsegment = 0;
+                       }
+
+                       // Maybe includes a symbol
+                       if (w & MSYMBOL)
+                               symbol = *p.sy++;
+
+                       if (!validsegment)
+                               continue;
+
+#ifdef DEBUG_IMAGE_MARKING
+printf(" validsegment: raddr = $%08X\n", loc);
+#endif
+                       uint32_t rflag = 0x00000040;    // Absolute relocation
+
+                       if (w & MPCREL)
+                               rflag = 0x000000A0;                     // PC-relative relocation
+
+                       // This flag tells the linker to WORD swap the LONG when doing the
+                       // relocation.
+                       if (w & MMOVEI)
+                               rflag |= 0x00000001;
+
+                       // This tells the linker to do a WORD relocation (otherwise it
+                       // defaults to doing a LONG, throwing things off for WORD sized
+                       // fixups)
+                       if (!(w & (MLONG | MQUAD)))
+                               rflag |= 0x00000002;
+
+                       // Tell the linker that the fixup is an OL QUAD data address
+                       if (w & MQUAD)
+                               rflag |= 0x00000004;
+
+                       if (symbol != NULL)
+                       {
+                               // Deposit external reference
+                               rflag |= 0x00000010;                    // Set external reloc flag bit
+                               rflag |= (symbol->senv << 8);   // Put symbol index in flags
+
+#ifdef DEBUG_IMAGE_MARKING
+printf("  validsegment(2): rflag = $%08X\n", rflag);
+#endif
+                       }
+                       else
+                       {
+#ifdef DEBUG_IMAGE_MARKING
+printf("  w = $%04X\n", w);
+#endif
+                               w &= TDB;                               // Set reloc flags to segment
+
+                               switch (w)
+                               {
+                               case TEXT: rflag |= 0x00000400; break;
+                               case DATA: rflag |= 0x00000600; break;
+                               case BSS:  rflag |= 0x00000800; break;
+                               }
+
+#ifdef DEBUG_IMAGE_MARKING
+printf("  validsegment(3): rflag = $%08X\n", rflag);
+#endif
+                               // Fix relocation by adding in start of TEXT segment, since it's
+                               // currently relative to the start of the DATA (or BSS) segment
+                               if (w & (DATA | BSS))
+                               {
+                                       uint8_t * dp = objImage + BSDHDRSIZE + loc;
+                                       uint32_t olBitsSave = 0;
+
+                                       // Bump the start of the section if it's DATA (& not TEXT)
+                                       if (from == DATA)
+                                               dp += tsize;
+
+                                       uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0));
+
+                                       // Special handling for OP (data addr) relocation...
+                                       if (rflag & 0x04)
+                                       {
+                                               olBitsSave = diff & 0x7FF;
+                                               diff = (diff & 0xFFFFF800) >> 8;
+                                       }
+
+                                       DEBUG printf("diff=%uX ==> ", diff);
+#ifdef DEBUG_IMAGE_MARKING
+printf("  validsegment(4): diff = $%08X ", diff);
+#endif
+                                       if (rflag & 0x01)
+                                               diff = WORDSWAP32(diff);
+
+#ifdef DEBUG_IMAGE_MARKING
+printf("(sect[TEXT].sloc=$%X) --> ", sect[TEXT].sloc);
+#endif
+                                       diff += sect[TEXT].sloc;
+
+                                       if (w == BSS)
+                                               diff += sect[DATA].sloc;
+
+                                       if (rflag & 0x01)
+                                               diff = WORDSWAP32(diff);
+
+                                       // Make sure to deposit the correct size payload
+                                       // N.B.: The braces around the SETBExx macros are needed
+                                       //       because the macro supplies its own set of braces,
+                                       //       thus leaving a naked semicolon afterwards to
+                                       //       screw up the if/else structure. This is the price
+                                       //       you pay when using macros pretending to be code.
+                                       if (rflag & 0x02)               // WORD relocation
+                                       {
+                                               SETBE16(dp, 0, diff);
+                                       }
+                                       else if (rflag & 0x04)  // OP data address relocation
+                                       {
+                                               // We do it this way because we might have an offset
+                                               // that is not a multiple of 8 and thus we need this in
+                                               // place to prevent a bad address at link time. :-P As
+                                               // a consequence of this, the highest address we can
+                                               // have here is $1FFFF8.
+                                               uint32_t diffsave = diff;
+                                               diff = ((diff & 0x001FFFFF) << 11) | olBitsSave;
+                                               SETBE32(dp, 0, diff);
+                                               // But we need those 3 bits, otherwise we can get in
+                                               // trouble with things like OL data that is in the cart
+                                               // space, and BOOM! So the 2nd phrase of the fixup (it
+                                               // will *always* have a 2nd phrase) has a few spare
+                                               // bits, we chuck them in there.
+                                               uint32_t p2 = GETBE32(dp, 8);
+                                               p2 &= 0x1FFFFFFF;
+                                               p2 |= (diffsave & 0x00E00000) << 8;
+                                               SETBE32(dp, 8, p2);
+                                       }
+                                       else                                    // LONG relocation
+                                       {
+                                               SETBE32(dp, 0, diff);
+                                       }
+
+                                       DEBUG printf("%uX\n", diff);
+#ifdef DEBUG_IMAGE_MARKING
+printf("$%08X\n", diff);
+#endif
+                               }
+                       }
+
+                       D_long(loc);            // Write relocation address
+                       D_long(rflag);          // Write relocation flags
+                       rsize += 0x08;          // Increment relocation size
+               }
+       }
+
+       // Return relocation table's size
+#ifdef DEBUG_IMAGE_MARKING
+printf("  rsize = $%X\n", rsize);
+#endif
+       return rsize;
 }
 
+
 //
-// --- Make mark image for BSD .o file -------------------------------------------------------------
-//
-
-LONG bsdmarkimg(char *mp, LONG siz, LONG tsize, int reqseg) {
-   MCHUNK *mch;                                             // Mark chunk
-   PTR p;                                                   // Source point from within mark chunk
-   WORD from;                                               // Section fixups are currently FROM
-   WORD w;                                                  // A word (temp)
-   LONG loc;                                                // Location (temp) 
-   SYM *symbol;                                             // Symbols (temp)
-   char *wp;                                                // Pointer into raw relocation info
-   char *dp;                                                // Deposit point for RELMOD info
-   LONG diff;                                               // Difference to relocate (RELMOD)
-   LONG raddr, rflag = 0;                                   // BSD relocation address and flags
-   LONG rsize;                                              // Relocation size
-   int validsegment = 0;                                    // Valid segment being processed
-
-   rsize = 0;                                               // Initialise relocation size
-   chptr = mp;
-
-   from = 0;
-   for(mch = firstmch; mch != NULL; mch = mch->mcnext)
-      for(p = mch->mcptr;;) {
-         w = *p.wp++;                                       // Next mark entry
-
-         if(w & MCHEND) break;                              // End of mark chunk
-
-         // Get mark record
-         symbol = NULL;
-         loc = *p.lp++;                                     // Mark location
-         if(w & MCHFROM) {                                  // Maybe change "from" section
-            from = *p.wp++;
-            if(obj_format == BSD) {
-               if(reqseg == TEXT) {                         // Requested segment is TEXT
-                  if(from == TEXT) validsegment = 1; 
-                  else validsegment = 0;
-               } else {                                     // Requested segment is DATA
-                  if(from == DATA) validsegment = 1; 
-                  else validsegment = 0;
-               }
-            }
-         }
-
-         if(w & MSYMBOL)                                    // Maybe includes a symbol
-            symbol = *p.sy++;
-
-         if(obj_format == BSD) {
-            raddr = loc;                                    // Set relocation address
-            if(validsegment)
-               D_long(raddr);                               // Write relocation address
-            if(w & MPCREL)
-               rflag = 0x000000A0;                          // PC-relative fixup
-            else
-               rflag = 0x00000040;                          // Absolute fixup
-            if(w & MMOVEI)
-               rflag |= 0x00000001;
-         }
-
-         // Compute mark position in relocation information;
-         // in RELMOD mode, get address of data to fix up.
-         if(from == DATA)
-            loc += tsize;
-         wp = (char *)(mp + loc);
-
-         if(symbol) {
-            // Deposit external reference
-            if(obj_format == BSD) {
-               rflag |= 0x00000010;                         // Set external reloc flag bit
-               rflag |= (symbol->senv << 8);                // Put symbol index in flags
-               if(symbol->sattre & RISCSYM) rflag |= 0x00000001;
-               if(validsegment) {
-                  D_long(rflag);                            // Write relocation flags
-                  rsize += 8;                               // Increment relocation size
-               }
-            }
-
-         } else {
-
-            if(obj_format == BSD) {
-               w &= TDB;                                    // Set reloc flags to segment
-               switch(w) {
-                  case TEXT: rflag |= 0x00000400; break;
-                  case DATA: rflag |= 0x00000600; break;
-                  case BSS:  rflag |= 0x00000800; break;
-               }
-               if(validsegment) {
-                  D_long(rflag);                            // Write relocation flags
-                  rsize += 8;                               // Increment relocation size
-               }
-               w &= TDB;
-               if(validsegment) {
-                  if(w & (DATA|BSS)) {
-                     dp = objimage + BSDHDRSIZE + loc;
-                     diff = ((LONG)(*dp++ & 0xff)) << 24;
-                     diff |= ((LONG)(*dp++ & 0xff)) << 16;
-                     diff |= ((LONG)(*dp++ & 0xff)) << 8;
-                     diff |= (LONG)(*dp & 0xff);
-                     DEBUG printf("diff=%lx ==> ", diff);
-                     if(rflag & 0x01)
-                        diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
-                     diff += sect[TEXT].sloc;
-                     if(w == BSS)
-                        diff += sect[DATA].sloc;
-                     if(rflag & 0x01)
-                        diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000);
-                     dp = objimage + BSDHDRSIZE + loc;
-                     *dp++ = (char)(diff >> 24);
-                     *dp++ = (char)(diff >> 16);
-                     *dp++ = (char)(diff >> 8);
-                     *dp = (char)diff;
-                     DEBUG printf("%lx\n", diff);
-                  }
-               }
-            }
-         }
-      }
-
-   if(obj_format == BSD)                                    // Return relocation size
-      return(rsize);                                        
-   else
-      return(siz);
+// Make relocation record for ELF .o file.
+// Returns the size of the relocation record.
+//
+uint32_t CreateELFRelocationRecord(uint8_t * buf, uint8_t * secBuf, uint16_t section)
+{
+       uint16_t from = 0;              // Section fixups are currently FROM
+       uint32_t rsize = 0;             // Size of the relocation table
+
+       // Setup pointer for D_long/word/byte macros
+       chptr = buf;
+       ch_size = 0;
+
+       for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext)
+       {
+               for(register PTR p=mch->mcptr;;)
+               {
+                       register uint16_t w = *p.wp++;  // w = next mark entry
+
+                       if (w & MCHEND)         // (end of mark chunk)
+                               break;
+
+                       // Get mark record
+                       SYM * symbol = NULL;
+                       uint16_t symFlags = 0;
+                       uint32_t r_offset = *p.lp++;    // Mark's location
+
+                       if (w & MCHFROM)                // Maybe change "from" section
+                               from = *p.wp++;
+
+                       if (w & MSYMBOL)                // Maybe includes a symbol
+                       {
+                               symbol = *p.sy++;
+
+                               if (symbol)
+                                       symFlags = symbol->sattr;
+                       }
+
+                       // Create relocation record for ELF object, if the mark is in the
+                       // current section.
+                       if (from & section)
+                       {
+                               uint32_t r_sym = 0;
+                               uint32_t r_type = 0;
+                               uint32_t r_addend = 0;
+
+                               // Since we're chucking all symbols here for ELF objects by
+                               // default (cf. sect.c), we discriminate here (normally, if
+                               // there is a symbol in the mark record, it means an undefined
+                               // symbol) :-P
+                               if (symbol && !(symFlags & DEFINED) && (symFlags & GLOBAL))
+                                       r_sym = symbol->senv + extraSyms;
+                               else if (w & TEXT)
+                                       r_sym = elfHdrNum[ES_TEXT];     // Mark TEXT segment
+                               else if (w & DATA)
+                                       r_sym = elfHdrNum[ES_DATA];     // Mark DATA segment
+                               else if (w & BSS)
+                                       r_sym = elfHdrNum[ES_BSS];      // Mark BSS segment
+
+                               // Set the relocation type next
+                               if (w & MPCREL)
+                                       r_type = 5;  // R_68K_PC16
+                               // N.B.: Since we've established that (from & section) is non-
+                               //       zero, this condition will *never* be satisfied... :-P
+                               //       It might be better to check the symbol's senv; that is,
+                               //       if this is a real problem that needs addressing...
+                               else if ((from & section) == 0)
+                                       // In the case of a section referring to a label in another
+                                       // section (for example text->data) use a R_68K_PC32 mark.
+                                       r_type = 4;  // R_68K_PC32
+                               else
+                                       r_type = 1;  // R_68K_32
+
+                               r_addend = GETBE32(secBuf + r_offset, 0);
+
+                               // Deposit the relocation record
+                               D_long(r_offset);
+                               D_long(((r_sym << 8) | r_type));
+                               D_long(r_addend);
+                               rsize += 0x0C;
+                       }
+               }
+       }
+
+       return rsize;
 }
+