+//
+// Helper function for ELF output
+//
+int DepositELFSectionHeader(uint8_t * ptr, uint32_t name, uint32_t type, uint32_t flags, uint32_t addr, uint32_t offset, uint32_t size, uint32_t link, uint32_t info, uint32_t addralign, uint32_t entsize)
+{
+ chptr = ptr;
+ ch_size = 0;
+ D_long(name);
+ D_long(type);
+ D_long(flags);
+ D_long(addr);
+ D_long(offset);
+ D_long(size);
+ D_long(link);
+ D_long(info);
+ D_long(addralign);
+ D_long(entsize);
+ return 40;
+}
+
+
+//
+// Deposit an entry in the Section Header string table
+//
+uint32_t DepositELFSHSTEntry(uint8_t ** pTable, const uint8_t * s)
+{
+#ifdef DEBUG_ELF
+printf("DepositELFSHSTEntry: s = \"%s\"\n", s);
+#endif
+ uint32_t strSize = strlen(s);
+ strcpy(*pTable, s);
+ *pTable += strSize + 1;
+ return strSize + 1;
+}
+
+
+//
+// Deposit a symbol table entry in the ELF Symbol Table
+//
+uint32_t DepositELFSymbol(uint8_t * ptr, uint32_t name, uint32_t addr, uint32_t size, uint8_t info, uint8_t other, uint16_t shndx)
+{
+ chptr = ptr;
+ ch_size = 0;
+ D_long(name);
+ D_long(addr);
+ D_long(size);
+ *chptr++ = info;
+ *chptr++ = other;
+ D_word(shndx);
+ return 16;
+}
+
+
+//
+// Write an object file to the passed in file descriptor
+// N.B.: Return value is ignored...
+//
+int WriteObject(int fd)
+{
+ LONG t; // Scratch long
+ LONG tds; // TEXT & DATA segment size
+ int i; // Temporary int
+ CHUNK * cp; // Chunk (for gather)
+ uint8_t * buf; // Scratch area
+ uint8_t * p; // Temporary ptr
+ LONG trsize, drsize; // Size of relocations
+ long unused; // For supressing 'write' warnings
+
+ if (verb_flag)
+ {
+ 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 (if it was ALCYON format)
+ obj_format = BSD;
+
+ if (verb_flag)
+ {
+ printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
+ }
+
+ 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(0x800000); // Allocate 8MB object file image memory
+
+ if (buf == NULL)
+ {
+ error("cannot allocate object file memory (in BSD mode)");
+ return ERROR;
+ }
+
+ memset(buf, 0, 0x800000); // Clear allocated memory
+ objImage = buf; // Set global object image pointer
+ strtable = malloc(0x200000); // Allocate 2MB string table buffer
+
+ if (strtable == NULL)
+ {
+ error("cannot allocate string table memory (in BSD mode)");
+ return ERROR;
+ }
+
+ memset(strtable, 0, 0x200000); // Clear allocated memory
+
+ // Build object file header
+ chptr = buf; // Base of header (for D_foo macros)
+ 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); // DATA relocation size
+
+ // Construct TEXT and DATA segments (without relocation changes)
+ p = buf + BSDHDRSIZE;
+
+ 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;
+ }
+ }
+
+ // Do relocation tables (and make changes to segment data)
+ p = buf + BSDHDRSIZE + tds; // Move obj image ptr to reloc info
+ trsize = MarkBSDImage(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table
+ chptr = buf + 0x18; // Point to relocation hdr entry
+ D_long(trsize); // Write the relocation table size
+
+ // Move obj image ptr to reloc info
+ p = buf + BSDHDRSIZE + tds + trsize;
+ drsize = MarkBSDImage(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table
+ chptr = buf + 0x1C; // Point to relocation hdr entry
+ D_long(drsize); // Write the relocation table size
+
+ // Point to start of symbol table
+ p = buf + BSDHDRSIZE + tds + trsize + drsize;
+ sy_assign(p, AddBSDSymEntry); // Build symbol and string tables
+ chptr = buf + 0x10; // 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
+ 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 (verb_flag)
+ {
+ printf("TextRel size: %d bytes\n", trsize);
+ printf("DataRel size: %d bytes\n", drsize);
+ }
+
+ if (buf)
+ {
+ free(strtable); // Free allocated memory
+ free(buf); // Free allocated memory
+ }
+ }
+ else if (obj_format == ALCYON)
+ {
+ if (verb_flag)
+ {
+ if (prg_flag)
+ printf("TOS header : 28 bytes\n");
+
+ printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc + (prg_flag ? 28 : 0));
+ }
+
+ // Assign index numbers to the symbols, get # of symbols (we assume
+ // that all symbols can potentially be extended, hence the x28)
+ uint32_t symbolMaxSize = sy_assign(NULL, NULL) * 28;
+
+ // Alloc memory for header + text + data, symbol and relocation
+ // information construction.
+ tds = sect[TEXT].sloc + sect[DATA].sloc;
+ buf = malloc(HDRSIZE + tds + symbolMaxSize);
+
+ // Build object file header just before the text+data image
+ chptr = buf; // -> base of header
+ D_word(0x601A); // 00 - magic number
+ D_long(sect[TEXT].sloc); // 02 - TEXT size
+ D_long(sect[DATA].sloc); // 06 - DATA size
+ D_long(sect[BSS].sloc); // 0A - BSS size
+ D_long(0); // 0E - symbol table size (filled later)
+ 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 + HDRSIZE;
+
+ 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;
+ }
+ }
+
+ // Do a first pass on the Alcyon image, if in PRG mode
+ if (prg_flag)
+ MarkImage(buf + HDRSIZE, tds, sect[TEXT].sloc, 0);
+
+ // Construct symbol table and update the header entry, if necessary
+ if (prg_flag > 1)
+ {
+ // sy_assign with AddSymEntry updates symsize (stays 0 otherwise)
+ sy_assign(buf + HDRSIZE + tds, AddSymEntry);
+ chptr = buf + 0x0E; // Point to symbol table size entry
+ D_long(symsize);
+ }
+
+ // Write out the header + text & data + symbol table (if any)
+ unused = write(fd, buf, HDRSIZE + tds + symsize);
+
+ // Construct and write relocation information; the size of it changes if
+ // we're writing a RELMODed executable. N.B.: Destroys buffer!
+ tds = MarkImage(buf, tds, sect[TEXT].sloc, 1);
+ unused = write(fd, buf, tds);
+ }
+ else if (obj_format == ELF)
+ {
+ // Allocate 6MB object file image memory
+ buf = malloc(0x600000);
+
+ if (buf == NULL)
+ {
+ error("cannot allocate object file memory (in ELF mode)");
+ return ERROR;
+ }
+
+ memset(buf, 0, 0x600000);
+ objImage = buf; // Set global object image pointer
+ strtable = malloc(0x200000); // Allocate 2MB string table buffer
+
+ if (strtable == NULL)
+ {
+ error("cannot allocate string table memory (in ELF mode)");
+ return ERROR;
+ }
+
+ memset(strtable, 0, 0x200000);
+
+ // This is pretty much a first pass at this shite, so there's room for
+ // improvement. :-P
+ uint8_t headers[4 * 10 * 10]; // (DWORD * 10) = 1 hdr, 10 entries
+ int headerSize = 0;
+ uint8_t shstrtab[128]; // The section header string table proper
+ uint32_t shstTab[9]; // Index into shstrtab for strings
+ uint8_t * shstPtr = shstrtab; // Temp pointer
+ uint32_t shstSize = 0;
+ int numEntries = 4; // There are always at *least* 4 sections
+ int shstIndex = 1; // The section where the shstrtab lives
+ int elfSize = 0; // Size of the ELF object
+ // Clear the header numbers
+ memset(elfHdrNum, 0, 9 * sizeof(int));
+
+ //
+ // First step is to see what sections need to be made; we also
+ // construct the section header string table here at the same time.
+ //
+ shstTab[ES_NULL] = shstSize;
+ shstSize += DepositELFSHSTEntry(&shstPtr, "");
+ shstTab[ES_SHSTRTAB] = shstSize;
+ shstSize += DepositELFSHSTEntry(&shstPtr, ".shstrtab");
+ shstTab[ES_SYMTAB] = shstSize;
+ shstSize += DepositELFSHSTEntry(&shstPtr, ".symtab");
+ shstTab[ES_STRTAB] = shstSize;
+ shstSize += DepositELFSHSTEntry(&shstPtr, ".strtab");
+
+ if (sect[TEXT].sloc > 0)
+ {
+ elfHdrNum[ES_TEXT] = shstIndex;
+ shstTab[ES_TEXT] = shstSize;
+ shstSize += DepositELFSHSTEntry(&shstPtr, ".text");
+ shstIndex++;
+ numEntries++;
+ }
+
+ if (sect[DATA].sloc > 0)
+ {
+ elfHdrNum[ES_DATA] = shstIndex;
+ shstTab[ES_DATA] = shstSize;
+ shstSize += DepositELFSHSTEntry(&shstPtr, ".data");
+ shstIndex++;
+ numEntries++;
+ }
+
+ if (sect[BSS].sloc > 0)
+ {
+ elfHdrNum[ES_BSS] = shstIndex;
+ shstTab[ES_BSS] = shstSize;
+ shstSize += DepositELFSHSTEntry(&shstPtr, ".bss");
+ shstIndex++;
+ numEntries++;
+ }