#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)))); } } 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))) ); } } } } } } 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 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 AppendGListData(&ObjFile, §ion->section, sizeof(section->section)); #endif } } } 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); total = SymNum + NumStabs; cmd.nsyms = CTool_EndianConvertWord32(total); FileOffset += total * sizeof(struct nlist); cmd.stroff = CTool_EndianConvertWord32(FileOffset); cmd.strsize = CTool_EndianConvertWord32(StringTable.size); 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)); 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); 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); 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(§ion->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)); AppendGListLong(&ObjFile, CTool_EndianConvertWord32((reloc->value << 8) | (reloc->is_pcrel << 7) | (length_code[reloc->length] << 5) | (reloc->is_extern << 4) | reloc->reltype) ); 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 | (reloc->is_pcrel << 30) | (length_code[reloc->length] << 28) | (reloc->reltype << 24) | reloc->address) ); AppendGListLong(&ObjFile, CTool_EndianConvertWord32(reloc->value)); } 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)); } 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 | (reloc->is_pcrel << 30) | (length_code[reloc->length] << 28) | (reloc->reltype << 24) | reloc->address) ); AppendGListLong(&ObjFile, CTool_EndianConvertWord32(reloc->value)); 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++) { *ptr += NumStabs; *ptr = CTool_EndianConvertWord32(*ptr); } 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); 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); 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); 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)); 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); 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->objectDataHandle = ObjFile.data; cparamblkptr->objectdata.codesize = CodeSize; cparamblkptr->objectdata.udatasize = UdataSize; cparamblkptr->objectdata.idatasize = IdataSize; } 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(§ion->glist, 256); return §ion->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; }