+//
+// 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;