MWCC/compiler_and_linker/unsorted/MachO.c

924 lines
30 KiB
C
Raw Normal View History

2022-12-29 12:32:55 +00:00
#include "compiler/MachO.h"
#include "compiler/CError.h"
#include "compiler/CParser.h"
#include "compiler/CPrep.h"
#include "compiler/CompilerTools.h"
#include "compiler/ObjGenMachO.h"
#include "cos.h"
static MachOSegment *FirstSeg;
static MachOSegment *LastSeg;
static UInt32 SectNum;
static UInt32 SymNum;
static UInt32 NumStabs;
static UInt32 ilocalsym;
static UInt32 nlocalsym;
static UInt32 iextdefsym;
static UInt32 nextdefsym;
static UInt32 iundefsym;
static UInt32 nundefsym;
static MachOSymbol *FirstSym;
static MachOSymbol *LastSym;
static MachOSymbol *FirstStab;
static MachOSymbol *LastStab;
static UInt32 FileOffset;
static UInt32 VmAddr;
static GList ObjFile;
static SInt32 SymPad;
static UInt32 CodeSize;
static UInt32 IdataSize;
static UInt32 UdataSize;
static GList IndirectSymbolTable;
static GList StringTable;
static UInt32 IndirectSymbolTableOffset;
void MachO_Setup(void) {
FirstSeg = LastSeg = NULL;
FirstSym = LastSym = NULL;
FirstStab = LastStab = NULL;
SectNum = 0;
SymNum = 0;
NumStabs = 0;
ilocalsym = -1;
nlocalsym = 0;
iextdefsym = -1;
nextdefsym = 0;
iundefsym = -1;
nundefsym = 0;
InitGList(&IndirectSymbolTable, 256);
InitGList(&StringTable, 4096);
AppendGListByte(&StringTable, 0);
}
static UInt32 GetSectVMAddr(UInt32 id) {
MachOSegment *segment;
MachOSection *section;
for (segment = FirstSeg; segment; segment = segment->next) {
for (section = segment->firstSection; section; section = section->next) {
if (section->num == id)
return section->section.addr;
}
}
return 0;
}
static UInt32 AllocateForLoadCommands(void) {
UInt32 ncmds = 0;
MachOSegment *segment;
MachOSection *section;
for (segment = FirstSeg; segment; segment = segment->next) {
FileOffset += sizeof(struct segment_command);
segment->cmd.cmdsize += sizeof(struct segment_command);
ncmds++;
for (section = segment->firstSection; section; section = section->next) {
segment->cmd.cmdsize += sizeof(struct section);
FileOffset += sizeof(struct section);
}
}
return ncmds;
}
static UInt32 AlignModulus[] = {
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800
};
static void AllocateAddresses(void) {
MachOSegment *segment;
MachOSection *section;
UInt32 pad;
for (segment = FirstSeg; segment; segment = segment->next) {
segment->cmd.vmaddr = VmAddr;
segment->cmd.fileoff = FileOffset;
for (section = segment->firstSection; section; section = section->next) {
if (section->glist.size)
section->section.size = section->glist.size;
pad = AlignModulus[section->section.align] - (VmAddr % AlignModulus[section->section.align]);
pad %= AlignModulus[section->section.align];
VmAddr += pad;
section->section.addr = VmAddr;
VmAddr += section->section.size;
FileOffset += pad;
if (section->glist.size) {
section->section.offset = FileOffset;
FileOffset += section->glist.size;
} else {
section->section.offset = FileOffset;
}
if (!strncmp(section->section.segname, "__TEXT", 6)) {
CodeSize += section->section.size;
} else {
if (section->glist.size)
IdataSize += section->section.size;
else
UdataSize += section->section.size;
}
}
segment->cmd.filesize = FileOffset - segment->cmd.fileoff;
segment->cmd.vmsize = VmAddr - segment->cmd.vmaddr;
}
}
static void ApplyRelocs(void) {
MachOSegment *segment;
MachOSection *section;
MachOReloc *reloc;
enum reloc_type_ppc pairType;
UInt32 pairValue;
UInt32 opMask;
UInt32 argMask;
UInt32 value;
UInt32 *ptr;
for (segment = FirstSeg; segment; segment = segment->next) {
for (section = segment->firstSection; section; section = section->next) {
for (reloc = section->firstReloc; reloc; reloc = reloc->next) {
if (reloc->is_extern) {
opMask = 0xFFFFFFFF;
argMask = 0;
value = 0;
switch (reloc->reltype) {
case PPC_RELOC_HI16:
case PPC_RELOC_LO16:
case PPC_RELOC_HA16:
pairValue = 0;
pairType = reloc->reltype;
break;
}
} else if (reloc->reltype == PPC_RELOC_PAIR) {
if (reloc->value != 0xFFFFFF) {
value = pairValue - (reloc->value + section->section.addr);
value += reloc->address;
} else {
value = pairValue + reloc->address;
}
switch (pairType) {
case PPC_RELOC_HI16:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
value >>= 16;
break;
case PPC_RELOC_HA16:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
if (value & 0x8000)
value += 0x10000;
value >>= 16;
break;
case PPC_RELOC_LO16:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
value = value & 0xFFFF;
break;
case PPC_RELOC_HI16_SECTDIFF:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
value >>= 16;
break;
case PPC_RELOC_HA16_SECTDIFF:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
if (value & 0x8000)
value += 0x10000;
value >>= 16;
break;
case PPC_RELOC_LO16_SECTDIFF:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
value = value & 0xFFFF;
break;
case PPC_RELOC_SECTDIFF:
opMask = 0;
argMask = 0xFFFFFFFF;
break;
default:
CError_FATAL(388);
}
} else {
value = GetSectVMAddr(reloc->value);
switch (reloc->reltype) {
case PPC_RELOC_VANILLA:
opMask = 0;
argMask = 0xFFFFFFFF;
break;
case PPC_RELOC_BR14:
opMask = 0xFFFF0003;
argMask = 0xFFFC;
break;
case PPC_RELOC_BR24:
opMask = 0xFC000003;
argMask = 0x3FFFFFC;
break;
case PPC_RELOC_LO14:
opMask = 0xFFFF0003;
argMask = 0xFFFC;
break;
case PPC_RELOC_HI16:
case PPC_RELOC_HA16:
case PPC_RELOC_LO16:
case PPC_RELOC_HI16_SECTDIFF:
case PPC_RELOC_HA16_SECTDIFF:
case PPC_RELOC_LO16_SECTDIFF:
case PPC_RELOC_SECTDIFF:
// first half of a pair
opMask = 0xFFFF0000;
argMask = 0xFFFF;
pairValue = value;
pairType = reloc->reltype;
value = 0;
break;
case PPC_RELOC_PB_LA_PTR:
CError_FATAL(428);
break;
default:
CError_FATAL(432);
}
}
if (reloc->reltype != PPC_RELOC_PAIR)
ptr = (UInt32 *) ((*section->glist.data) + reloc->address);
if (reloc->is_pcrel) {
if (!reloc->is_extern) {
*ptr = CTool_EndianConvertWord32(
(CTool_EndianConvertWord32(*ptr) & opMask) |
(argMask & (value - (reloc->address + section->section.addr) + (CTool_EndianConvertWord32(*ptr) & argMask))));
}
2022-12-29 12:32:55 +00:00
} else {
if (reloc->reltype == PPC_RELOC_PAIR) {
*ptr = CTool_EndianConvertWord32(
(CTool_EndianConvertWord32(*ptr) & opMask) |
(value & argMask)
);
} else {
*ptr = CTool_EndianConvertWord32(
(CTool_EndianConvertWord32(*ptr) & opMask) |
(argMask & (value + (CTool_EndianConvertWord32(*ptr) & argMask)))
);
}
2022-12-29 12:32:55 +00:00
}
}
}
}
}
static void AllocForRelocs(void) {
MachOSegment *segment;
MachOSection *section;
for (segment = FirstSeg; segment; segment = segment->next) {
for (section = segment->firstSection; section; section = section->next) {
if (section->section.nreloc) {
section->section.reloff = FileOffset;
FileOffset += section->section.nreloc * 8;
}
}
}
}
static void WriteSegLoadCommands(void) {
MachOSegment *segment;
MachOSection *section;
for (segment = FirstSeg; segment; segment = segment->next) {
#ifdef ENDIAN_CONVERSION
struct segment_command c = segment->cmd;
c.cmd = CTool_EndianConvertWord32(c.cmd);
c.cmdsize = CTool_EndianConvertWord32(c.cmdsize);
c.vmaddr = CTool_EndianConvertWord32(c.vmaddr);
c.vmsize = CTool_EndianConvertWord32(c.vmsize);
c.fileoff = CTool_EndianConvertWord32(c.fileoff);
c.filesize = CTool_EndianConvertWord32(c.filesize);
c.maxprot = CTool_EndianConvertWord32(c.maxprot);
c.initprot = CTool_EndianConvertWord32(c.initprot);
c.nsects = CTool_EndianConvertWord32(c.nsects);
c.flags = CTool_EndianConvertWord32(c.flags);
AppendGListData(&ObjFile, &c, sizeof(c));
#else
2022-12-29 12:32:55 +00:00
AppendGListData(&ObjFile, &segment->cmd, sizeof(segment->cmd));
#endif
for (section = segment->firstSection; section; section = section->next) {
#ifdef ENDIAN_CONVERSION
struct section c = section->section;
c.addr = CTool_EndianConvertWord32(c.addr);
c.size = CTool_EndianConvertWord32(c.size);
c.offset = CTool_EndianConvertWord32(c.offset);
c.align = CTool_EndianConvertWord32(c.align);
c.reloff = CTool_EndianConvertWord32(c.reloff);
c.nreloc = CTool_EndianConvertWord32(c.nreloc);
c.flags = CTool_EndianConvertWord32(c.flags);
c.reserved1 = CTool_EndianConvertWord32(c.reserved1);
c.reserved2 = CTool_EndianConvertWord32(c.reserved2);
AppendGListData(&ObjFile, &c, sizeof(c));
#else
2022-12-29 12:32:55 +00:00
AppendGListData(&ObjFile, &section->section, sizeof(section->section));
#endif
}
2022-12-29 12:32:55 +00:00
}
}
static void WriteSymtabLoadCommand(void) {
struct symtab_command cmd;
UInt32 total;
cmd.cmd = CTool_EndianConvertWord32(LC_SYMTAB);
cmd.cmdsize = CTool_EndianConvertWord32(sizeof(cmd));
cmd.symoff = CTool_EndianConvertWord32(FileOffset);
2022-12-29 12:32:55 +00:00
total = SymNum + NumStabs;
2023-01-13 13:40:30 +00:00
cmd.nsyms = CTool_EndianConvertWord32(total);
2022-12-29 12:32:55 +00:00
FileOffset += total * sizeof(struct nlist);
cmd.stroff = CTool_EndianConvertWord32(FileOffset);
cmd.strsize = CTool_EndianConvertWord32(StringTable.size);
2022-12-29 12:32:55 +00:00
AppendGListData(&ObjFile, &cmd, sizeof(cmd));
}
static void WriteDynamicSymtabLoadCommand(void) {
struct dysymtab_command cmd;
if (!nlocalsym)
ilocalsym = 0;
if (!nextdefsym)
iextdefsym = ilocalsym + nlocalsym;
if (!nundefsym)
iundefsym = iextdefsym + nextdefsym;
ilocalsym += NumStabs;
iextdefsym += NumStabs;
iundefsym += NumStabs;
CError_ASSERT(644, (ilocalsym + nlocalsym) <= (SymNum + NumStabs));
CError_ASSERT(648, (iextdefsym + nextdefsym) <= (SymNum + NumStabs));
CError_ASSERT(652, (iundefsym + nundefsym) <= (SymNum + NumStabs));
cmd.cmd = CTool_EndianConvertWord32(LC_DYSYMTAB);
cmd.cmdsize = CTool_EndianConvertWord32(sizeof(cmd));
2022-12-29 12:32:55 +00:00
cmd.ilocalsym = CTool_EndianConvertWord32(ilocalsym);
cmd.nlocalsym = CTool_EndianConvertWord32(nlocalsym);
cmd.iextdefsym = CTool_EndianConvertWord32(iextdefsym);
cmd.nextdefsym = CTool_EndianConvertWord32(nextdefsym);
cmd.iundefsym = CTool_EndianConvertWord32(iundefsym);
cmd.nundefsym = CTool_EndianConvertWord32(nundefsym);
2022-12-29 12:32:55 +00:00
cmd.tocoff = 0;
cmd.ntoc = 0;
cmd.modtaboff = 0;
cmd.nmodtab = 0;
cmd.extrefsymoff = 0;
cmd.nextrefsyms = 0;
cmd.indirectsymoff = CTool_EndianConvertWord32(IndirectSymbolTableOffset);
cmd.nindirectsyms = CTool_EndianConvertWord32(IndirectSymbolTable.size / 4);
2022-12-29 12:32:55 +00:00
cmd.extreloff = 0;
cmd.nextrel = 0;
cmd.locreloff = 0;
cmd.nlocrel = 0;
AppendGListData(&ObjFile, &cmd, sizeof(cmd));
}
static void WriteSectionData(void) {
MachOSegment *segment;
MachOSection *section;
UInt32 pad;
VmAddr = 0;
for (segment = FirstSeg; segment; segment = segment->next) {
for (section = segment->firstSection; section; section = section->next) {
pad = AlignModulus[section->section.align] - (VmAddr % AlignModulus[section->section.align]);
pad %= AlignModulus[section->section.align];
while (pad) {
AppendGListByte(&ObjFile, 0);
VmAddr++;
FileOffset++;
pad--;
}
if (section->glist.size) {
CError_ASSERT(711, ObjFile.size == section->section.offset);
COS_LockHandle(section->glist.data);
AppendGListData(&ObjFile, *section->glist.data, section->glist.size);
COS_UnlockHandle(section->glist.data);
VmAddr += section->glist.size;
FreeGList(&section->glist);
} else {
VmAddr += pad + section->section.size;
}
}
}
}
static void WriteRelocs(void) {
MachOSegment *segment;
MachOSection *section;
MachOReloc *reloc;
enum reloc_type_ppc pairType;
UInt32 pairValue;
SInt32 scatterFlag;
UInt32 combo;
static char length_code[] = {
0, 0, 1, 1, 2
};
pairType = 0;
pairValue = 0;
scatterFlag = 0;
for (segment = FirstSeg; segment; segment = segment->next) {
for (section = segment->firstSection; section; section = section->next) {
for (reloc = section->firstReloc; reloc; reloc = reloc->next) {
if (reloc->is_extern)
reloc->value += NumStabs;
switch (reloc->reltype) {
case PPC_RELOC_LO16:
case PPC_RELOC_HA16:
case PPC_RELOC_LO14:
pairType = reloc->reltype;
if (reloc->is_extern) {
pairValue = 0;
} else {
pairValue = reloc->next->address + GetSectVMAddr(reloc->value);
}
case PPC_RELOC_VANILLA:
case PPC_RELOC_BR14:
case PPC_RELOC_BR24:
case PPC_RELOC_HI16:
case PPC_RELOC_PB_LA_PTR:
AppendGListLong(&ObjFile, CTool_EndianConvertWord32(reloc->address));
2022-12-29 12:32:55 +00:00
AppendGListLong(&ObjFile,
CTool_EndianConvertWord32((reloc->value << 8) |
2022-12-29 12:32:55 +00:00
(reloc->is_pcrel << 7) |
(length_code[reloc->length] << 5) |
(reloc->is_extern << 4) |
reloc->reltype)
2022-12-29 12:32:55 +00:00
);
break;
case PPC_RELOC_PAIR:
switch (pairType) {
case PPC_RELOC_HI16:
case PPC_RELOC_HA16:
scatterFlag = 0;
reloc->address = pairValue & 0xFFFF;
break;
case PPC_RELOC_LO16:
scatterFlag = 0;
reloc->address = pairValue >> 16;
break;
case PPC_RELOC_HI16_SECTDIFF:
case PPC_RELOC_HA16_SECTDIFF:
scatterFlag = R_SCATTERED;
reloc->value += section->section.addr;
pairValue -= reloc->value;
reloc->address = pairValue & 0xFFFF;
break;
case PPC_RELOC_LO16_SECTDIFF:
scatterFlag = R_SCATTERED;
reloc->value += section->section.addr;
pairValue -= reloc->value;
reloc->address = pairValue >> 16;
break;
default:
CError_FATAL(891);
reloc->address = 0;
break;
}
pairValue = 0;
pairType = 0;
if (scatterFlag) {
AppendGListLong(&ObjFile,
CTool_EndianConvertWord32(scatterFlag |
2022-12-29 12:32:55 +00:00
(reloc->is_pcrel << 30) |
(length_code[reloc->length] << 28) |
(reloc->reltype << 24) |
reloc->address)
2022-12-29 12:32:55 +00:00
);
AppendGListLong(&ObjFile, CTool_EndianConvertWord32(reloc->value));
2022-12-29 12:32:55 +00:00
} else {
combo =
(reloc->value << 8) |
(reloc->is_pcrel << 7) |
(length_code[reloc->length] << 5) |
reloc->reltype;
AppendGListLong(&ObjFile, CTool_EndianConvertWord32(reloc->address));
AppendGListLong(&ObjFile, CTool_EndianConvertWord32(combo));
2022-12-29 12:32:55 +00:00
}
break;
case PPC_RELOC_SECTDIFF:
case PPC_RELOC_HI16_SECTDIFF:
case PPC_RELOC_LO16_SECTDIFF:
case PPC_RELOC_HA16_SECTDIFF:
// build scattered relocation
reloc->value = reloc->next->address + GetSectVMAddr(reloc->value);
pairType = reloc->reltype;
pairValue = reloc->value;
AppendGListLong(&ObjFile,
CTool_EndianConvertWord32(R_SCATTERED |
2022-12-29 12:32:55 +00:00
(reloc->is_pcrel << 30) |
(length_code[reloc->length] << 28) |
(reloc->reltype << 24) |
reloc->address)
2022-12-29 12:32:55 +00:00
);
AppendGListLong(&ObjFile, CTool_EndianConvertWord32(reloc->value));
2022-12-29 12:32:55 +00:00
break;
default:
CError_FATAL(930);
}
}
}
}
}
static void WriteIndirectSymbolTable(void) {
UInt32 i;
UInt32 *ptr;
while (SymPad) {
AppendGListByte(&ObjFile, 0);
SymPad--;
}
COS_LockHandle(IndirectSymbolTable.data);
ptr = (UInt32 *) *IndirectSymbolTable.data;
for (i = 0; i < MachO_NumIndirectSym(); ptr++, i++) {
2022-12-29 12:32:55 +00:00
*ptr += NumStabs;
*ptr = CTool_EndianConvertWord32(*ptr);
}
2022-12-29 12:32:55 +00:00
AppendGListData(&ObjFile, *IndirectSymbolTable.data, IndirectSymbolTable.size);
COS_UnlockHandle(IndirectSymbolTable.data);
FreeGList(&IndirectSymbolTable);
}
static void WriteSymbolTable(void) {
MachOSymbol *symbol;
struct nlist nlist;
if (FirstStab) {
LastStab->next = FirstSym;
FirstSym = FirstStab;
}
for (symbol = FirstSym; symbol; symbol = symbol->next) {
nlist.n_strx = CTool_EndianConvertWord32(symbol->data.u.strx);
2022-12-29 12:32:55 +00:00
nlist.n_type = symbol->data.type;
if (symbol->data.section)
nlist.n_sect = symbol->data.section->num;
else
nlist.n_sect = 0;
nlist.n_desc = CTool_EndianConvertWord16(symbol->data.desc);
2022-12-29 12:32:55 +00:00
if (
symbol->data.type == N_STSYM ||
symbol->data.type == N_FUN ||
symbol->data.type == N_LCSYM ||
symbol->data.type == N_SLINE ||
symbol->data.type == N_SO ||
symbol->data.type == N_SOL ||
symbol->data.type == N_ENTRY ||
symbol->data.type == N_ECOML ||
(symbol->data.type & N_TYPE) == N_SECT
)
{
if (symbol->data.section)
symbol->data.value += symbol->data.section->section.addr;
else
CError_FATAL(1010);
}
nlist.n_value = CTool_EndianConvertWord32(symbol->data.value);
2022-12-29 12:32:55 +00:00
AppendGListData(&ObjFile, &nlist, sizeof(nlist));
}
}
static void WriteStringTable(void) {
COS_LockHandle(StringTable.data);
AppendGListData(&ObjFile, *StringTable.data, StringTable.size);
COS_UnlockHandle(StringTable.data);
}
void MachO_Finish(void) {
struct mach_header hdr;
CodeSize = 0;
IdataSize = UdataSize = 0;
VmAddr = 0;
FileOffset = sizeof(hdr);
hdr.ncmds = AllocateForLoadCommands();
FileOffset += 24; // what am I?
hdr.ncmds++;
if (copts.codegen_dynamic) {
FileOffset += 80; // what am I?
hdr.ncmds++;
}
hdr.ncmds = CTool_EndianConvertWord32(hdr.ncmds);
hdr.sizeofcmds = CTool_EndianConvertWord32(FileOffset - sizeof(hdr));
2022-12-29 12:32:55 +00:00
AllocateAddresses();
ApplyRelocs();
AllocForRelocs();
SymPad = (4 - (FileOffset & 3)) & 3;
FileOffset += SymPad;
IndirectSymbolTableOffset = 0;
if (IndirectSymbolTable.size > 0) {
IndirectSymbolTableOffset = FileOffset;
FileOffset += IndirectSymbolTable.size;
}
InitGList(&ObjFile, 4096);
hdr.magic = CTool_EndianConvertWord32(MH_MAGIC);
hdr.cputype = CTool_EndianConvertWord32(CPU_TYPE_POWERPC);
hdr.cpusubtype = CTool_EndianConvertWord32(CPU_SUBTYPE_MC98000_ALL);
hdr.filetype = CTool_EndianConvertWord32(MH_OBJECT);
2022-12-29 12:32:55 +00:00
hdr.flags = 0;
AppendGListData(&ObjFile, &hdr, sizeof(hdr));
WriteSegLoadCommands();
WriteSymtabLoadCommand();
if (copts.codegen_dynamic)
WriteDynamicSymtabLoadCommand();
WriteSectionData();
WriteRelocs();
WriteIndirectSymbolTable();
WriteSymbolTable();
WriteStringTable();
COS_ResizeHandle(ObjFile.data, ObjFile.size);
cparamblkptr->objectdata = ObjFile.data;
cparamblkptr->object.codesize = CodeSize;
cparamblkptr->object.udatasize = UdataSize;
cparamblkptr->object.idatasize = IdataSize;
2022-12-29 12:32:55 +00:00
}
void MachO_Cleanup(void) {
if (StringTable.data)
FreeGList(&StringTable);
if (IndirectSymbolTable.data)
FreeGList(&IndirectSymbolTable);
}
MachOSegment *MachO_CreateSegment(char *segname, int maxprot, int initprot, UInt32 flags) {
MachOSegment *segment = galloc(sizeof(MachOSegment));
memset(&segment->cmd, 0, sizeof(segment->cmd));
segment->cmd.cmd = LC_SEGMENT;
strncpy(segment->cmd.segname, segname, sizeof(segment->cmd.segname));
segment->cmd.maxprot = maxprot;
segment->cmd.initprot = initprot;
segment->cmd.flags = flags;
segment->firstSection = segment->lastSection = NULL;
segment->next = NULL;
if (FirstSeg == NULL)
FirstSeg = segment;
else
LastSeg->next = segment;
LastSeg = segment;
return segment;
}
MachOSection *MachO_CreateSection(MachOSegment *segment, char *segname, char *sectname, UInt32 align, UInt32 flags, UInt32 sectionID) {
MachOSection *section;
UInt32 alignConv;
alignConv = 0;
while (!(align & 1)) {
align >>= 1;
alignConv++;
}
section = galloc(sizeof(MachOSection));
memset(section, 0, sizeof(MachOSection));
strncpy(section->section.segname, segname, sizeof(section->section.segname));
strncpy(section->section.sectname, sectname, sizeof(section->section.sectname));
section->section.align = alignConv;
section->section.flags = flags;
section->num = ++SectNum;
section->id = sectionID;
section->next = NULL;
if (segment->firstSection == NULL)
segment->firstSection = section;
else
segment->lastSection->next = section;
segment->lastSection = section;
segment->cmd.nsects++;
return section;
}
GList *MachO_GetGList(MachOSection *section) {
if (!section->glist.data)
InitGList(&section->glist, 256);
return &section->glist;
}
void MachO_SetSectionSize(void) {
// empty, unused, unknown args
}
void MachO_Relocate(MachOSection *section, UInt32 address, UInt32 value, char length, char is_pcrel, Boolean is_extern, int reltype) {
MachOReloc *reloc;
reloc = galloc(sizeof(MachOReloc));
reloc->address = address;
reloc->value = value;
reloc->length = length;
reloc->is_pcrel = is_pcrel;
reloc->is_extern = is_extern;
reloc->reltype = reltype;
reloc->next = NULL;
if (section->firstReloc == NULL)
section->firstReloc = reloc;
else
section->lastReloc->next = reloc;
section->lastReloc = reloc;
section->section.nreloc++;
}
static SInt32 DeclareString(char *str) {
SInt32 offset;
if (str) {
offset = StringTable.size;
AppendGListID(&StringTable, str);
} else {
offset = 0;
}
return offset;
}
UInt32 MachO_DeclareSymbol(char *name, MachOSection *section, UInt32 value, Boolean isAbsolute, short type, short desc) {
MachOSymbol *symbol;
symbol = galloc(sizeof(MachOSymbol));
memset(symbol, 0, sizeof(MachOSymbol));
if (section) {
if (type) {
if (nextdefsym == 0)
iextdefsym = SymNum;
nextdefsym++;
} else {
if (nlocalsym == 0)
ilocalsym = SymNum;
nlocalsym++;
}
symbol->data.type = type | N_SECT;
symbol->data.section = section;
} else if (isAbsolute) {
symbol->data.type = type | N_ABS;
} else {
if (nundefsym == 0)
iundefsym = SymNum;
nundefsym++;
symbol->data.type = type & ~N_PEXT;
}
symbol->data.value = value;
symbol->data.u.strx = DeclareString(name);
symbol->data.desc = desc;
symbol->index = SymNum++;
if (FirstSym == NULL)
FirstSym = symbol;
else
LastSym->next = symbol;
LastSym = symbol;
return symbol->index;
}
void MachO_ReOrderSections(void) {
MachOSection *section;
MachOSegment *segment;
MachOSection *prev;
MachOSection *firstRemoved;
MachOSection *lastRemoved;
UInt32 counter;
counter = 0;
for (segment = FirstSeg; segment; segment = segment->next) {
prev = NULL;
section = segment->firstSection;
firstRemoved = lastRemoved = NULL;
while (section) {
if (section->section.size && section->glist.data == NULL && section != segment->firstSection) {
// detach this section
if (prev)
prev->next = section->next;
else
segment->firstSection = section->next;
if (section == segment->lastSection)
segment->lastSection = prev;
section->next = NULL;
// add it to the list to be pushed to the end
if (firstRemoved == NULL)
firstRemoved = section;
else
lastRemoved->next = section;
lastRemoved = section;
// continue iterating
if (prev)
section = prev->next;
else
section = segment->firstSection;
} else {
prev = section;
section = section->next;
}
}
// attach the other sections
if (firstRemoved) {
if (segment->firstSection == NULL)
segment->firstSection = firstRemoved;
else
segment->lastSection->next = firstRemoved;
segment->lastSection = lastRemoved;
}
// renumber them all
for (section = segment->firstSection; section; section = section->next)
section->num = ++counter;
}
}
void MachO_AddIndirectSymbol(SInt32 symbol) {
CError_ASSERT(1577, symbol >= 0);
AppendGListLong(&IndirectSymbolTable, symbol);
}
UInt32 MachO_NumIndirectSym(void) {
return IndirectSymbolTable.size / 4;
}
SInt32 MachO_OutputStab(SymbolData *data, SInt32 strIndex) {
MachOSymbol *symbol;
symbol = galloc(sizeof(MachOSymbol));
memset(symbol, 0, sizeof(MachOSymbol));
if (strIndex == -1)
data->u.strx = DeclareString(data->u.name);
else
data->u.strx = strIndex;
memcpy(&symbol->data, data, sizeof(SymbolData));
if (FirstStab == NULL)
FirstStab = symbol;
else
LastStab->next = symbol;
LastStab = symbol;
NumStabs++;
return data->u.strx;
}