#include "compiler/ObjGenMachO.h" #include "compiler/CError.h" #include "compiler/CInit.h" #include "compiler/CFunc.h" #include "compiler/CMachine.h" #include "compiler/CMangler.h" #include "compiler/CParser.h" #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" #include "compiler/uDump.h" #include "compiler/GenStabs.h" #include "compiler/IrOptimizer.h" #include "compiler/MachO.h" #include "compiler/PCodeListing.h" #include "compiler/TOC.h" #include "compiler/objects.h" #include "cos.h" #ifdef __MWERKS__ #pragma options align=mac68k #endif typedef struct Reloc { MachOSection *section; SInt32 offset; SInt32 relocID; SInt32 picOffset; struct Reloc *next; RelocType relocType; MWReloc mwRelType; } Reloc; typedef struct { Section x0; Section x1; char *segname; char *sectname; UInt32 align; UInt32 flags; } DefSectionInfo; static DefSectionInfo def_section_info[] = { SECT_DEFAULT, SECT_DEFAULT, "", "", 1, S_REGULAR, SECT_TEXT, SECT_TEXT_COALESCE, "__TEXT", "__text", 4, S_ATTR_SOME_INSTRUCTIONS, SECT_DATA, SECT_DATA_COALESCE, "__DATA", "__data", 8, S_REGULAR, SECT_UDATA, SECT_UDATA_COALESCE, "__DATA", "__bss", 8, S_ZEROFILL, SECT_DATA_FAR, 0, "__DATA", "__fdata", 8, S_REGULAR, SECT_DATA_NEAR, 0, "__DATA", "__ndata", 8, S_REGULAR, SECT_INIT, 0, "__INIT", "__init", 4, S_REGULAR, SECT_OBJC_CAT_CLS_METH, 0, "__OBJC", "__cat_cls_meth", 4, S_REGULAR, SECT_OBJC_CAT_INST_METH, 0, "__OBJC", "__cat_inst_meth", 4, S_REGULAR, SECT_OBJC_STRING_OBJECT, 0, "__OBJC", "__string_object", 1, S_REGULAR, SECT_OBJC_CSTRING_OBJECT, 0, "__OBJC", "__cstring_object", 1, S_REGULAR, SECT_OBJC_MESSAGE_REFS, 0, "__OBJC", "__message_refs", 4, S_LITERAL_POINTERS, SECT_OBJC_SEL_FIXUP, 0, "__OBJC", "__sel_fixup", 4, S_REGULAR, SECT_OBJC_CLS_REFS, 0, "__OBJC", "__cls_refs", 4, S_LITERAL_POINTERS, SECT_OBJC_CLASS, 0, "__OBJC", "__class", 4, S_REGULAR, SECT_OBJC_META_CLASS, 0, "__OBJC", "__meta_class", 4, S_REGULAR, SECT_OBJC_CLS_METH, 0, "__OBJC", "__cls_meth", 4, S_REGULAR, SECT_OBJC_INST_METH, 0, "__OBJC", "__inst_meth", 4, S_REGULAR, SECT_OBJC_PROTOCOL, 0, "__OBJC", "__protocol", 4, S_REGULAR, SECT_OBJC_CLASS_NAMES, 0, "__OBJC", "__class_names", 4, S_CSTRING_LITERALS, SECT_OBJC_METH_VAR_TYPES, 0, "__OBJC", "__meth_var_types", 4, S_CSTRING_LITERALS, SECT_OBJC_METH_VAR_NAMES, 0, "__OBJC", "__meth_var_names", 4, S_CSTRING_LITERALS, SECT_OBJC_CATEGORY, 0, "__OBJC", "__category", 4, S_REGULAR, SECT_OBJC_CLASS_VARS, 0, "__OBJC", "__class_vars", 4, S_REGULAR, SECT_OBJC_INSTANCE_VARS, 0, "__OBJC", "__instance_vars", 4, S_REGULAR, SECT_OBJC_MODULE_INFO, 0, "__OBJC", "__module_info", 4, S_REGULAR, SECT_OBJC_MSYMBOLS, 0, "__OBJC", "__symbols", 4, S_REGULAR, SECT_TEXT_CSTRING, SECT_TEXT_CSTRING, "__TEXT", "__cstring", 4, S_CSTRING_LITERALS, SECT_MW_EX_TABLE, SECT_MW_EX_TABLE, "__DATA", "__coalsc_MXCPTTB", 4, S_COALESCED | S_ATTR_NO_TOC, SECT_MW_EX_TABLE_INDEX, SECT_MW_EX_TABLE_INDEX, "__DATA", "__mwexceptionidx", 4, S_COALESCED | S_ATTR_NO_TOC, SECT_MW_SWITCH, SECT_MW_SWITCH, "__DATA", "__mwswitch", 4, S_REGULAR, SECT_8BYTE_LITERALS, SECT_8BYTE_LITERALS, "__TEXT", "__literal8", 8, S_8BYTE_LITERALS, SECT_4BYTE_LITERALS, SECT_4BYTE_LITERALS, "__TEXT", "__literal4", 4, S_4BYTE_LITERALS, SECT_MOD_INIT_FUNC, SECT_MOD_INIT_FUNC, "__DATA", "__mod_init_func", 4, S_MOD_INIT_FUNC_POINTERS, SECT_CONST, SECT_CONST, "__TEXT", "__const", 4, S_REGULAR, SECT_CONST_PTR, SECT_CONST_PTR, "__DATA", "__const", 4, S_REGULAR, SECT_NONLAZY_PTRS, SECT_NONLAZY_PTRS, "__DATA", "__nl_symbol_ptr", 4, S_NON_LAZY_SYMBOL_POINTERS, SECT_COMMON_VARS, SECT_COMMON_VARS, NULL, NULL, 0, S_REGULAR, SECT_16BYTE_LITERALS, SECT_16BYTE_LITERALS, "__DATA", "__literal16", 16, S_REGULAR, SECT_TEXT_COALESCE, SECT_TEXT_COALESCE, "__TEXT", "__coalesced_text", 4, S_COALESCED | S_ATTR_SOME_INSTRUCTIONS, SECT_DATA_COALESCE, SECT_DATA_COALESCE, "__DATA", "__coalesced_data", 8, S_COALESCED, SECT_UDATA_COALESCE, SECT_UDATA_COALESCE, "__DATA", "__coalesced_bss", 8, S_COALESCED, SECT_CONST_COALESCE, SECT_CONST_COALESCE, "__TEXT", "__coalesce_const", 4, S_COALESCED, SECT_CONST_PTR_COALESCE, SECT_CONST_PTR_COALESCE, "__DATA", "__coalesce_const", 4, S_COALESCED }; #ifdef __MWERKS__ #pragma options align=reset #endif Boolean declare_readonly; SInt32 symdeclend; SInt32 symdecloffset; SInt32 nexttypeid; GList symtypemodule; SInt32 last_base_offset[N_SECTIONS]; static SInt32 RelocIndex; static MachOSegment *TheSegment; MachOSection *Sections[N_SECTIONS]; static MachOSection *StubSect; static MachOSection *LazySymbolSect; static MachOSection *NonLazySymbolSect; static GList RelocData; static Reloc *FirstReloc; static Reloc *LastReloc; Section last_function_sect_id; MachOSection *last_function_sect; SInt32 pic_base_offset; #define RELOC_DATA(_id) (((RelocDataT *) (*RelocData.data))[(_id)]) static Section SegmentForceCreate = SECT_TEXT; // forward decls static void CreateTheSegment(void); static void SymContainedVars(void); static void AppendGListZeros(GList *glist, SInt32 size); static Section ObjGen_CheckCoalesceSection(Object *object) { Section s; if ( !CParser_HasInternalLinkage(object) && (object->qual & (Q_20000 | Q_OVERLOAD)) && (s = def_section_info[object->section].x1) != SECT_DEFAULT ) return s; else return object->section; } static MachOSection *ObjGen_GetSection(Section section) { CError_ASSERT(360, section != SECT_COMMON_VARS); if (!Sections[section]) { DefSectionInfo *info = def_section_info + section; Sections[section] = MachO_CreateSection( TheSegment, info->segname, info->sectname, info->align, info->flags, section); } return Sections[section]; } static UInt32 AlignTo_Section(MachOSection *section, UInt32 value) { UInt32 conv; UInt32 work; if (value < (1 << section->section.align)) return 1 << section->section.align; conv = 0; work = 1; while (work < value) { work = work * 2; conv++; } section->section.align = conv; return work; } static void updatesectreloc(RelocDataT *r, MachOSection *section, UInt32 a) { CError_ASSERT(396, r->x3 == 0); r->type = RT_0; r->section = section; r->x4 = a; } SInt32 ObjGen_MakeSectReloc(MachOSection *section) { RelocDataT r = {0}; r.x18 = -1; updatesectreloc(&r, section, section->glist.data ? section->glist.size : section->section.size); AppendGListData(&RelocData, &r, sizeof(r)); return RelocIndex++; } static char ObjGen_ComputePrivFlag(UInt8 objectFlags) { switch (copts.x06) { case 0: case 1: if ( (objectFlags & OBJECT_FLAGS_1) && (objectFlags & OBJECT_FLAGS_2) && !(objectFlags & OBJECT_FLAGS_4) ) return 0; return 1; case 3: case 4: if ((objectFlags & OBJECT_FLAGS_10) == OBJECT_FLAGS_10) return 1; if ((objectFlags & OBJECT_FLAGS_40) == OBJECT_FLAGS_40) return 0; if ( (objectFlags & OBJECT_FLAGS_1) && (objectFlags & OBJECT_FLAGS_2) && !(objectFlags & OBJECT_FLAGS_4) ) return 0; return 1; case 2: return 0; default: return 1; } } SInt32 ObjGen_GetHashNodeRelocID(Object *object, MachOSection *section, SInt32 value) { HashNameNode *name; HashNameNode *name2; RelocDataT r; RelocDataT *other_rd; ObjectList *list; SInt32 tmp; memclrw(&r, sizeof(r)); r.x18 = -1; if (object->datatype == DNONLAZYPTR) name = object->name; else name = CMangler_GetLinkName(object); if (value < 0) return name->id; if (name->id < 0) { if (section) { if (Sections[SECT_COMMON_VARS] && section == Sections[SECT_COMMON_VARS]) { CError_FATAL(489); } else { name->id = ObjGen_MakeSectReloc(section); } } else if (object->datatype == DNONLAZYPTR) { CError_ASSERT(497, object->u.var.realObj != NULL); name->id = RelocIndex; r.type = RT_3; r.privFlag = ObjGen_ComputePrivFlag(object->flags); r.name = name->name; AppendGListData(&RelocData, &r, sizeof(r)); RelocIndex++; ObjGen_GetHashNodeRelocID(object->u.var.realObj, NULL, 0); } else if (value) { object->section = SECT_COMMON_VARS; name->id = RelocIndex; r.type = RT_4; r.privFlag = ObjGen_ComputePrivFlag(object->flags); r.name = name->name; r.x4 = value; AppendGListData(&RelocData, &r, sizeof(r)); RelocIndex++; } else { name->id = RelocIndex; r.type = (object->datatype == DFUNC || object->datatype == DVFUNC) ? RT_1 : RT_2; r.x2 = 1; r.privFlag = ObjGen_ComputePrivFlag(object->flags); if (!CParser_HasInternalLinkage(object)) r.x3 = (object->qual & (Q_20000 | Q_OVERLOAD)) > 0; r.name = name->name; r.x4 = value; AppendGListData(&RelocData, &r, sizeof(r)); RelocIndex++; } } else if (section) { other_rd = &RELOC_DATA(name->id); other_rd->privFlag = ObjGen_ComputePrivFlag(object->flags); if (!CParser_HasInternalLinkage(object) && (object->qual & (Q_20000 | Q_OVERLOAD))) { other_rd->x3 = 1; switch (other_rd->type) { case RT_0: CError_FATAL(548); other_rd->type = (object->datatype == DFUNC || object->datatype == DVFUNC) ? RT_1 : RT_2; other_rd->x2 = 1; other_rd->privFlag = ObjGen_ComputePrivFlag(object->flags); other_rd->x18 = -1; other_rd->name = name->name; break; case RT_1: case RT_2: case RT_5: tmp = ObjGen_GetSectSize(section); other_rd = &RELOC_DATA(name->id); other_rd->section = section; other_rd->x4 = tmp; break; default: CError_FATAL(571); break; } } else { switch (other_rd->type) { case RT_0: CError_ASSERT(577, other_rd->section == section); break; case RT_2: name2 = CMangler_GetLinkName(object); for (list = toclist; list; list = list->next) { if (name2->id == CMangler_GetLinkName(list->object)->id) { SInt32 id = list->object->name->id; list->object->section = SECT_CONST_PTR; list->object->u.var.realObj = object; other_rd = &RELOC_DATA(id); if (other_rd->type == RT_3) { other_rd->type = RT_6; other_rd->x18 = name2->id; } else if (other_rd->type != RT_6) { CError_FATAL(602); } } } for (tmp = 0; tmp < RelocIndex; tmp++) { other_rd = &RELOC_DATA(tmp); if (other_rd->type == RT_2 && !strcmp(name->name, other_rd->name)) { name->id = tmp; break; } } case RT_1: case RT_5: tmp = ObjGen_GetSectSize(section); other_rd = &RELOC_DATA(name->id); updatesectreloc(other_rd, section, tmp); break; default: CError_FATAL(626); } } } else if (value) { other_rd = &RELOC_DATA(name->id); other_rd->privFlag = ObjGen_ComputePrivFlag(object->flags); if (other_rd->type == RT_4) { CError_ASSERT(635, value == other_rd->x4); } else { CError_ASSERT(639, other_rd->type == RT_2); other_rd->type = RT_4; other_rd->x4 = value; } } return name->id; } static Boolean ObjGen_DeclareSymbol(Object *object, MachOSection *section, SInt32 value) { HashNameNode *name; RelocDataT r; if (object->name->name[0] == '@') return 0; if (object->sclass == TK_STATIC) { if (!strncmp(object->name->name, "L_OBJC_", 7) || !strncmp(object->name->name, "L_NSConst", 9)) return 0; } name = CMangler_GetLinkName(object); memclrw(&r, sizeof(r)); r.x18 = -1; r.type = RT_7; if (!CParser_HasInternalLinkage(object)) { if (object->datatype == DFUNC || object->datatype == DVFUNC) { if (ObjGen_ComputePrivFlag(object->flags)) { r.privFlag = 1; r.x2 = 1; } else { r.privFlag = 0; r.x2 = 1; } } else { if (object->qual & Q_INLINE) { r.privFlag = 1; r.x2 = 1; } else { r.privFlag = 0; r.x2 = 1; } } } if (!CParser_HasInternalLinkage(object) && (object->qual & (Q_20000 | Q_OVERLOAD))) r.x3 = 1; r.x4 = value; r.section = section; r.name = name->name; if (r.x3) { r.type = (object->datatype == DFUNC || object->datatype == DVFUNC) ? RT_1 : RT_2; if (name->id >= 0) { RELOC_DATA(name->id) = r; return 1; } } if (r.type == RT_7) { AppendGListData(&RelocData, &r, sizeof(r)); RelocIndex++; r.type = RT_0; } if (name->id < 0) name->id = RelocIndex; AppendGListData(&RelocData, &r, sizeof(r)); RelocIndex++; return 1; } void ObjGen_Setup(void) { int i; MachO_Setup(); GenStab_Setup(); declare_readonly = 0; symtypemodule.data = NULL; if (InitGList(&symtypemodule, 5000)) CError_NoMem(); nexttypeid = -1; pic_base_offset = 0; last_function_sect = 0; last_function_sect_id = SECT_DEFAULT; setupaddressing(); TheSegment = NULL; for (i = 0; i < N_SECTIONS; i++) { Sections[i] = NULL; last_base_offset[i] = 0; CError_ASSERT(769, i == def_section_info[i].x0); } RelocIndex = 0; FirstReloc = NULL; StubSect = NULL; LazySymbolSect = NULL; NonLazySymbolSect = NULL; LastReloc = NULL; InitGList(&RelocData, 2800); CreateTheSegment(); ObjGen_SrcBreakName(NULL, 0, 1); IRO_Setup(); } static void GenStubs(void) { SInt32 i; SInt32 rdCount; SInt32 offset; RelocDataT *rd; rdCount = RelocData.size / sizeof(RelocDataT); for (i = 0; i < rdCount; i++) { if (RELOC_DATA(i).type == RT_1 && RELOC_DATA(i).x3) { if (StubSect == NULL) { StubSect = MachO_CreateSection( TheSegment, "__TEXT", copts.codegen_pic ? "__picsymbol_stub" : "__symbol_stub", 4, S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS, -1); MachO_GetGList(StubSect); } if (LazySymbolSect == NULL) { LazySymbolSect = MachO_CreateSection( TheSegment, "__DATA", "__la_symbol_ptr", 4, S_LAZY_SYMBOL_POINTERS, -2); } offset = StubSect->glist.size; rd = &RELOC_DATA(i); rd->gapC = offset; rd->sect10 = StubSect; CodeGen_GenDynLinkStub(StubSect, LazySymbolSect, ObjGen_MakeSectReloc(LazySymbolSect)); StubSect->section.reserved2 = StubSect->glist.size - offset; } } for (i = 0; i < rdCount; i++) { if (RELOC_DATA(i).type == RT_1 && !RELOC_DATA(i).x3) { if (StubSect == NULL) { StubSect = MachO_CreateSection( TheSegment, "__TEXT", copts.codegen_pic ? "__picsymbol_stub" : "__symbol_stub", 4, S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS, -1); MachO_GetGList(StubSect); } if (LazySymbolSect == NULL) { LazySymbolSect = MachO_CreateSection( TheSegment, "__DATA", "__la_symbol_ptr", 4, S_LAZY_SYMBOL_POINTERS, -2); } offset = StubSect->glist.size; rd = &RELOC_DATA(i); rd->gapC = offset; rd->sect10 = StubSect; CodeGen_GenDynLinkStub(StubSect, LazySymbolSect, ObjGen_MakeSectReloc(LazySymbolSect)); StubSect->section.reserved2 = StubSect->glist.size - offset; } } } static void GenNonLazyPointers(void) { ObjectList *list; // r31 Object *object; // r30 MachOSection *section; // r29 SInt32 id; // r29, r27? UInt32 offset; // r26 RelocDataT *rd; // r26 GList *gl; // r25 SInt32 align; SInt32 i; for (list = toclist; list; list = list->next) { object = list->object; if (object->section == SECT_NONLAZY_PTRS) { id = ObjGen_GetHashNodeRelocID(object, NULL, 0); CError_ASSERT(877, RELOC_DATA(id).type == RT_3); if (NonLazySymbolSect == NULL) { NonLazySymbolSect = ObjGen_GetSection(SECT_NONLAZY_PTRS); MachO_GetGList(NonLazySymbolSect); } updatesectreloc(&RELOC_DATA(id), NonLazySymbolSect, NonLazySymbolSect->glist.size); AppendGListLong(&NonLazySymbolSect->glist, 0); } else if (object->section == SECT_CONST_PTR) { id = ObjGen_GetHashNodeRelocID(object, NULL, 0); CError_ASSERT(901, RELOC_DATA(id).type == RT_6 || RELOC_DATA(id).type == RT_3); section = ObjGen_GetSection(object->section); gl = MachO_GetGList(section); offset = gl->size; align = AlignTo_Section(section, 4); if ((offset % align) != 0) { for (i = 0; i < (align - (offset % align)); i++) AppendGListByte(gl, 0); } rd = &RELOC_DATA(id); updatesectreloc(rd, section, section->glist.size); AppendGListLong(§ion->glist, 0); id = CMangler_GetLinkName(object)->id; CError_ASSERT(940, RELOC_DATA(id).type == RT_0); ObjGen_Relocate(section, rd->x4, id, RT_4, MW_RELOC_0); } else { CError_FATAL(944); } } } void ObjGen_DeclareFloatConst(Object *object) { Section sectionID; GList *gl; if (!TheSegment) CreateTheSegment(); sectionID = object->section; if (sectionID == SECT_DEFAULT) { if (object->type->size == 4) sectionID = SECT_4BYTE_LITERALS; else sectionID = SECT_8BYTE_LITERALS; } ObjGen_GetHashNodeRelocID(object, ObjGen_GetSection(sectionID), 0); gl = MachO_GetGList(Sections[sectionID]); if (object->type->size == 4) { float f = object->u.data.u.floatconst->value; CTool_EndianConvertMem(&f, 4); AppendGListData(gl, &f, 4); } else if (object->type->size == 8) { double f = object->u.data.u.floatconst->value; CTool_EndianConvertMem(&f, 8); AppendGListData(gl, &f, 8); } else { CError_FATAL(998); } } void ObjGen_DeclareVectorConst(Object *object) { Section sectionID; GList *gl; if (!TheSegment) CreateTheSegment(); sectionID = SECT_16BYTE_LITERALS; ObjGen_GetHashNodeRelocID(object, ObjGen_GetSection(sectionID), 0); gl = MachO_GetGList(Sections[sectionID]); if (object->type->size == 16) { MWVector128 vec = *object->u.data.u.vector128const; AppendGListData(gl, &vec, 16); } else { CError_FATAL(1034); } } void ObjGen_Finish(void) { UInt32 symIndex; SInt32 rdCount; RelocDataT *rdArray; SInt32 rdIndex; RelocDataT *rd; Reloc *reloc; ObjectList *objlist; SInt32 value; int flags; int desc; enum reloc_type_ppc nextRelType; UInt32 opMask; UInt32 argMask; if (copts.isGeneratingDebugInfo) GenStab_SourceFile(""); CInit_DeclarePooledStrings(); DeclarePooledConstants(); if (copts.codegen_dynamic) { GenStubs(); GenNonLazyPointers(); } MachO_ReOrderSections(); COS_LockHandle(RelocData.data); rdCount = RelocData.size / sizeof(RelocDataT); rdArray = &RELOC_DATA(0); for (rdIndex = 0; rdIndex < (RelocData.size / sizeof(RelocDataT)); rdIndex++) { rd = rdArray + rdIndex; if (rd->type == RT_7 && rd->x2 == 0) { symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, 0, 0); rd->type = RT_5; rd->x18 = symIndex; } } rdArray = &RELOC_DATA(0); for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = rdArray + rdIndex; if (rd->type == RT_7 && rd->x2 != 0) { flags = N_EXT; desc = 0; if (rd->privFlag != 0) { flags |= N_PEXT; desc = 0; } symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, flags, desc); rd->type = RT_5; rd->x18 = symIndex; } } if (copts.codegen_dynamic && StubSect) StubSect->section.reserved1 = MachO_NumIndirectSym(); for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = &RELOC_DATA(rdIndex); if (rd->type == RT_1 && rd->x3 != 0) { flags = N_EXT; desc = 0; if (rd->privFlag != 0) { flags |= N_PEXT; desc = 0; } symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, flags, desc); rd->x18 = symIndex; if (copts.codegen_dynamic && rd->sect10 == StubSect) { MachOSection *tmpSection; UInt32 tmpValue; MachO_AddIndirectSymbol(symIndex); tmpSection = rd->section; tmpValue = rd->x4; rd->section = rd->sect10; rd->x4 = rd->gapC; rd->sect10 = tmpSection; rd->gapC = tmpValue; } else { rd->x2 = 1; rd->type = RT_5; } } } for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = rdArray + rdIndex; if (rd->type == RT_2 && rd->x3 != 0) { flags = N_EXT; desc = 0; if (rd->privFlag != 0) { flags |= N_PEXT; desc = 0; } symIndex = MachO_DeclareSymbol(rd->name, rd->section, rd->x4, 0, flags, desc); rd->type = RT_5; rd->x18 = symIndex; } } for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = rdArray + rdIndex; if (rd->type == RT_4) { flags = N_EXT; desc = 0; if (rd->privFlag != 0) { flags |= N_PEXT; desc = 4; // REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY? } symIndex = MachO_DeclareSymbol(rd->name, NULL, rd->x4, 0, flags, desc); rd->type = RT_5; rd->x18 = symIndex; } } for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = rdArray + rdIndex; if (rd->type == RT_2 & rd->x3 == 0) { // typo alert flags = N_EXT; desc = 0; if (rd->privFlag != 0) { flags |= N_PEXT; desc = 4; // REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY? } symIndex = MachO_DeclareSymbol(rd->name, NULL, rd->x4, 0, flags, desc); rd->type = RT_5; rd->x18 = symIndex; } } for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = &RELOC_DATA(rdIndex); if (rd->type == RT_1 && rd->x3 == 0) { flags = N_EXT; desc = 1; // REFERENCE_FLAG_UNDEFINED_LAZY? if (rd->privFlag != 0) { flags |= N_PEXT; desc = 5; // REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY? } symIndex = MachO_DeclareSymbol(rd->name, NULL, 0, 0, flags, desc); rd = &RELOC_DATA(rdIndex); rd->x18 = symIndex; if (copts.codegen_dynamic && rd->sect10 == StubSect) { MachO_AddIndirectSymbol(symIndex); rd->section = rd->sect10; rd->x4 = rd->gapC; } else { rd->x2 = 1; rd->type = RT_5; } } } if (copts.codegen_dynamic) { if (LazySymbolSect) LazySymbolSect->section.reserved1 = MachO_NumIndirectSym(); for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = &RELOC_DATA(rdIndex); if (rd->type == RT_1 && rd->x3 != 0 && rd->section == StubSect) { MachO_AddIndirectSymbol(rd->x18); rd = &RELOC_DATA(rdIndex); rd->x3 = 0; updatesectreloc(rd, rd->section, rd->x4); } } for (rdIndex = 0; rdIndex < rdCount; rdIndex++) { rd = &RELOC_DATA(rdIndex); if (rd->type == RT_1 && rd->x3 == 0 && rd->section == StubSect) { MachO_AddIndirectSymbol(rd->x18); rd = &RELOC_DATA(rdIndex); rd->x3 = 0; updatesectreloc(rd, rd->section, rd->x4); } } } if (copts.codegen_dynamic) { if (NonLazySymbolSect) NonLazySymbolSect->section.reserved1 = MachO_NumIndirectSym(); for (objlist = toclist; objlist; objlist = objlist->next) { if (objlist->object->section == SECT_NONLAZY_PTRS) { SInt32 id = CMangler_GetLinkName(objlist->object)->id; MachO_AddIndirectSymbol(RELOC_DATA(id).x18); } } } for (reloc = FirstReloc; reloc; reloc = reloc->next) { rd = rdArray + reloc->relocID; value = 0; switch (rd->type) { case RT_0: if (rd->section == StubSect && reloc->mwRelType == MW_RELOC_9) { symIndex = rd->sect10->num; value = rd->gapC; } else { symIndex = rd->section->num; value = rd->x4; flags = 0; } break; case RT_5: symIndex = rd->x18; flags = N_EXT; break; default: CError_FATAL(1341); } if (copts.codegen_pic) { switch (reloc->mwRelType) { case MW_RELOC_5_LO16: opMask = 0xFFFF0000; argMask = 0xFFFF; value = value & 0xFFFF; nextRelType = PPC_RELOC_LO16_SECTDIFF; break; case MW_RELOC_7_HA16: opMask = 0xFFFF0000; argMask = 0xFFFF; if (value & 0x8000) value += 0x10000; value = (value >> 16) & 0xFFFF; nextRelType = PPC_RELOC_HA16_SECTDIFF; break; case MW_RELOC_6_HI16: opMask = 0xFFFF0000; argMask = 0xFFFF; value = (value >> 16) & 0xFFFF; nextRelType = PPC_RELOC_HI16_SECTDIFF; break; case MW_RELOC_8: CError_FATAL(1367); nextRelType = PPC_RELOC_HI16_SECTDIFF; break; case MW_RELOC_0: case MW_RELOC_9: opMask = 0; argMask = 0xFFFFFFFF; nextRelType = PPC_RELOC_VANILLA; break; case MW_RELOC_2_BR24: opMask = 0xFC000003; argMask = 0x3FFFFFC; value = value & 0x3FFFFFC; nextRelType = PPC_RELOC_BR24; break; default: CError_FATAL(1383); } if (nextRelType == PPC_RELOC_BR24) { MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 1, flags, nextRelType); } else if (nextRelType == PPC_RELOC_VANILLA) { MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 0, flags, nextRelType); } else { CError_ASSERT(1391, rd->type == RT_0); MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 0, flags, nextRelType); MachO_Relocate(reloc->section, rd->x4, reloc->picOffset, 4, 0, flags, PPC_RELOC_PAIR); value = 0; } if (value) { UInt32 *ptr = (UInt32 *) (*reloc->section->glist.data + reloc->offset); *ptr = CTool_EndianConvertWord32( (CTool_EndianConvertWord32(*ptr) & opMask) | (argMask & (value + (CTool_EndianConvertWord32(*ptr) & argMask))) ); } } else { switch (reloc->mwRelType) { case MW_RELOC_5_LO16: opMask = 0xFFFF0000; argMask = 0xFFFF; value = value & 0xFFFF; nextRelType = PPC_RELOC_LO16; break; case MW_RELOC_7_HA16: opMask = 0xFFFF0000; argMask = 0xFFFF; if (value & 0x8000) value += 0x10000; value = (value >> 16) & 0xFFFF; nextRelType = PPC_RELOC_HA16; break; case MW_RELOC_6_HI16: opMask = 0xFFFF0000; argMask = 0xFFFF; value = (value >> 16) & 0xFFFF; nextRelType = PPC_RELOC_HI16; break; case MW_RELOC_8: CError_FATAL(1434); opMask = 0xFFFF0000; argMask = 0xFFFF; nextRelType = PPC_RELOC_HI16; break; case MW_RELOC_2_BR24: opMask = 0xFC000003; argMask = 0x3FFFFFC; value = value & 0x3FFFFFC; nextRelType = PPC_RELOC_BR24; break; case MW_RELOC_0: case MW_RELOC_9: opMask = 0; argMask = 0xFFFFFFFF; nextRelType = PPC_RELOC_VANILLA; break; default: CError_FATAL(1452); } if (value != 0) { UInt32 *ptr = (UInt32 *) (*reloc->section->glist.data + reloc->offset); *ptr = CTool_EndianConvertWord32( (CTool_EndianConvertWord32(*ptr) & opMask) | (argMask & (value + (CTool_EndianConvertWord32(*ptr) & argMask))) ); } if (nextRelType == PPC_RELOC_BR24) { MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 1, flags, nextRelType); } else { MachO_Relocate(reloc->section, reloc->offset, symIndex, 4, 0, flags, nextRelType); if (nextRelType == PPC_RELOC_HI16 || nextRelType == PPC_RELOC_HA16 || nextRelType == PPC_RELOC_LO16) MachO_Relocate(reloc->section, rd->x4, 0xFFFFFF, 4, 0, 0, PPC_RELOC_PAIR); } } } COS_UnlockHandle(RelocData.data); MachO_Finish(); } void ObjGen_Cleanup(void) { MachO_Cleanup(); if (RelocData.data) FreeGList(&RelocData); CleanupDumpIR(); pccleanuplisting(); } void ObjGen_SetupSym(void) { } static void CreateTheSegment(void) { TheSegment = MachO_CreateSegment("", 7, 7, 0); Sections[SegmentForceCreate] = ObjGen_GetSection(SegmentForceCreate); } static void patchuplazyptr(Object *object) { RelocDataT *rd; Object *toc; if (CParser_HasInternalLinkage(object) || !(object->qual & (Q_20000 | Q_OVERLOAD))) { toc = object->toc; if (toc->section == SECT_NONLAZY_PTRS) { toc->section = SECT_CONST_PTR; rd = &RELOC_DATA(ObjGen_GetHashNodeRelocID(toc, NULL, 0)); if (rd->type == RT_3) { rd->type = RT_6; rd->x18 = ObjGen_GetHashNodeRelocID(object, NULL, 0); } else { CError_FATAL(1592); } } } } static void definedatasymbol(Object *object, MachOSection *section, SInt32 value) { Boolean flag; flag = ObjGen_DeclareSymbol(object, section, value); ObjGen_GetHashNodeRelocID(object, section, 0); if (flag && copts.isGeneratingDebugInfo) GenStab_Var(object); if (object->toc) patchuplazyptr(object); } static void declaredata(Object *object, char *data, OLinkList *olinklist, UInt32 size, Boolean isConst) { Section sectionID; // r30 MachOSection *section; // r24 SInt32 offset; // r23 GList *gl; // r22 UInt32 align; OLinkList *scan; if (!TheSegment) CreateTheSegment(); if (data) { if (object->section == SECT_COMMON_VARS) object->section = SECT_DEFAULT; if (object->section == SECT_DEFAULT) { if (isConst) object->section = SECT_CONST; else object->section = SECT_DATA; } if (object->section == SECT_CONST && olinklist) object->section = SECT_CONST_PTR; object->section = ObjGen_CheckCoalesceSection(object); sectionID = object->section; section = Sections[sectionID]; if (!section) section = ObjGen_GetSection(sectionID); gl = MachO_GetGList(section); offset = gl->size; align = CMach_AllocationAlignment(object->type, object->qual); if (!align) align = 1; align = AlignTo_Section(section, align); if (offset % align) { SInt32 adjust = align - (offset % align); AppendGListZeros(gl, adjust); offset += adjust; } definedatasymbol(object, Sections[sectionID], offset); for (scan = olinklist; scan; scan = scan->next) { if (scan->somevalue) *((SInt32 *) (data + scan->offset)) = CTool_EndianConvertWord32(scan->somevalue); } if (sectionID == SECT_8BYTE_LITERALS) AppendGListData(gl, data, 8); else if (sectionID == SECT_4BYTE_LITERALS) AppendGListData(gl, data, 4); else AppendGListData(gl, data, size); while (olinklist) { SInt32 extflag; SInt32 id; extflag = ObjGen_IsExternalVar(ObjGen_GetHashNodeRelocID(olinklist->obj, NULL, 0)); id = CMangler_GetLinkName(olinklist->obj)->id; ObjGen_Relocate(Sections[sectionID], offset + olinklist->offset, extflag + id, RT_4, MW_RELOC_0); olinklist = olinklist->next; } } else { if ( CParser_HasInternalLinkage(object) || (copts.no_common && !(object->qual & Q_20000)) || !object->qual & Q_1000000 // typo alert ) { if (object->section == SECT_DEFAULT) { if (isConst) object->section = SECT_CONST; else object->section = SECT_UDATA; } if (object->section == SECT_CONST && olinklist) object->section = SECT_CONST_PTR; object->section = ObjGen_CheckCoalesceSection(object); section = ObjGen_GetSection(object->section); sectionID = object->section; if (sectionID == SECT_UDATA) { align = CMach_AllocationAlignment(object->type, object->qual); AlignTo_Section(section, align); offset = section->section.size; if (!align) align = 1; if (offset % align) { // issue here SInt32 adjust = align - (offset % align); offset = offset + adjust; } section->section.size = offset; definedatasymbol(object, Sections[sectionID], offset); offset += size; section->section.size = offset; } else { gl = MachO_GetGList(section); offset = gl->size; align = CMach_AllocationAlignment(object->type, object->qual); if (!align) align = 1; align = AlignTo_Section(section, align); if (offset % align) { SInt32 adjust = align - (offset % align); AppendGListZeros(gl, adjust); offset += adjust; } definedatasymbol(object, Sections[sectionID], offset); AppendGListZeros(gl, size); } } else { object->qual |= Q_1000000; object->section = SECT_COMMON_VARS; ObjGen_GetHashNodeRelocID(object, NULL, size); } } } void ObjGen_DeclareData(Object *object, char *data, OLinkList *olinklist, UInt32 size) { declaredata(object, data, olinklist, size, 0); } void ObjGen_DeclareReadOnlyData(Object *object, char *data, OLinkList *olinklist, UInt32 size) { declaredata(object, data, olinklist, size, 1); } void ObjGen_SegmentName(void) { } void ObjGen_SymFunc(Object *function) { GenStab_Function(function, ObjGen_GetHashNodeRelocID(function, NULL, 0)); } void ObjGenMach_SymFuncEnd(Object *function, UInt32 offset) { GenStab_FunctionEnd(function, ObjGen_GetHashNodeRelocID(function, NULL, 0), offset); } void ObjGen_CodeSetup(void) { // empty/unknown args } void ObjGen_CodeCleanup(void) { } void ObjGen_SrcBreakName(HashNameNode *name, SInt32 fileModDate, Boolean flag) { char *ptr; char *ptr2; char *ptr3; char buf1[1024]; char buf2[1024]; if (copts.isGeneratingDebugInfo) { if (name) strncpy(buf1, name->name, sizeof(buf1)); else COS_FileGetPathName(buf1, &cparamblkptr->mainFileSpec, &fileModDate); if (name && copts.absolutepath) ptr = buf1 + strlen(buf1); else ptr = strrchr(buf1, '/'); if ((flag || name) && ptr && copts.absolutepath) { if (!strncmp(buf1, "Mac OS X:", strlen("Mac OS X:"))) { strcpy(buf2, "/"); ptr2 = buf2 + 1; ptr3 = buf1 + strlen("Mac OS X:"); } else { strcpy(buf2, "/Volumes/"); ptr2 = buf2 + strlen("/Volumes/"); ptr3 = buf1; } while (ptr3 <= ptr) *(ptr2++) = *(ptr3++); *ptr2 = 0; if (flag && !name) { GenStab_SourceFile(buf2); } else { GenStab_IncludeFile(buf2); return; } } if (ptr) ptr++; else ptr = buf1; if (flag && !name) GenStab_SourceFile(ptr); else GenStab_IncludeFile(ptr); } } GList *ObjGen_GetSectionGList(MachOSection *section) { return MachO_GetGList(section); } MachOSection *ObjGen_DeclareFunction(Object *object) { MachOSection *section; if (!TheSegment) CreateTheSegment(); if (object->section == SECT_DEFAULT) object->section = SECT_TEXT; object->section = ObjGen_CheckCoalesceSection(object); section = ObjGen_GetSection(object->section); if (object) { ObjGen_DeclareSymbol(object, section, section->glist.size); if (CMangler_GetLinkName(object)->id == -1) { CMangler_GetLinkName(object)->id = ObjGen_MakeSectReloc(section); } else { RelocDataT *rd = &RELOC_DATA(CMangler_GetLinkName(object)->id); if (rd->x3 == 0) { updatesectreloc(rd, section, section->glist.size); } else { rd->section = section; rd->x4 = section->glist.size; } } } return section; } MachOSection *ObjGen_DeclareCode(Object *object) { MachOSection *section; section = ObjGen_DeclareFunction(object); last_base_offset[object->section] = ObjGen_GetSectionGList(section)->size; last_function_sect = section; last_function_sect_id = object->section; return section; } MachOSection *ObjGen_DeclareMachSection() { // unknown args CError_FATAL(2020); return NULL; } void ObjGen_Relocate(MachOSection *section, SInt32 offset, SInt32 relocID, RelocType relocType, MWReloc mwRelType) { Reloc *reloc; reloc = galloc(sizeof(Reloc)); reloc->section = section; reloc->offset = offset; reloc->relocID = relocID; reloc->relocType = relocType; reloc->mwRelType = mwRelType; if (copts.codegen_pic) reloc->picOffset = pic_base_offset; else reloc->picOffset = 0; reloc->next = NULL; if (FirstReloc == NULL) FirstReloc = reloc; else LastReloc->next = reloc; LastReloc = reloc; } void ObjGen_RelocateObj(MachOSection *section, SInt32 offset, Object *object, MWReloc mwRelType) { Reloc *reloc; if (section == last_function_sect) offset += last_base_offset[last_function_sect_id]; if (object) { reloc = galloc(sizeof(Reloc)); reloc->section = section; reloc->offset = offset; reloc->relocID = ObjGen_GetHashNodeRelocID(object, NULL, 0); switch (mwRelType) { case MW_RELOC_0: case MW_RELOC_2_BR24: case MW_RELOC_9: reloc->picOffset = 0; break; case MW_RELOC_5_LO16: case MW_RELOC_6_HI16: case MW_RELOC_7_HA16: reloc->picOffset = pic_base_offset; break; default: CError_FATAL(2115); } reloc->relocType = RT_4; reloc->mwRelType = mwRelType; reloc->next = NULL; if (FirstReloc == NULL) FirstReloc = reloc; else LastReloc->next = reloc; LastReloc = reloc; } } SInt32 ObjGen_DeclareLiteralString(UInt32 len, char *data, SInt32 align) { SInt32 offset; SInt32 relocID; GList *gl; MachOSection *section; UInt32 align2; SInt32 pad; SInt32 i; if (!TheSegment) CreateTheSegment(); section = ObjGen_GetSection(SECT_TEXT_CSTRING); gl = MachO_GetGList(section); offset = gl->size; if (!align) align = 1; align2 = AlignTo_Section(section, align); if (offset % align2) { pad = align2 - (offset % align2); for (i = 0; i < pad; i++) AppendGListByte(gl, 0); } relocID = ObjGen_MakeSectReloc(section); AppendGListData(gl, data, len); return relocID; } UInt32 ObjGen_GetSectSize(MachOSection *section) { if (section->glist.data) return section->glist.size; else return section->section.size; } void ObjGen_GetExtName(SInt32 id, char *buf) { switch (RELOC_DATA(id).type) { case RT_0: sprintf(buf, "%s+%08x", RELOC_DATA(id).section->section.sectname, RELOC_DATA(id).x4); break; case RT_1: case RT_2: case RT_3: case RT_4: strcpy(buf, RELOC_DATA(id).name); break; case RT_5: sprintf(buf, "id(%d)", RELOC_DATA(id).x18); break; } } void ObjGen_PicRelocate(MachOSection *section, SInt32 offset, SInt32 relocID, SInt32 picOffset) { Reloc *reloc; reloc = galloc(sizeof(Reloc)); reloc->section = section; reloc->offset = offset; reloc->relocID = relocID; reloc->relocType = RT_4; reloc->mwRelType = MW_RELOC_0; reloc->picOffset = picOffset; reloc->next = NULL; if (FirstReloc == NULL) FirstReloc = reloc; else LastReloc->next = reloc; LastReloc = reloc; } SInt32 ObjGen_GetRelocOffset(SInt32 id) { switch (RELOC_DATA(id).type) { case RT_0: break; case RT_1: case RT_2: if (RELOC_DATA(id).x3) break; default: return 0; } return RELOC_DATA(id).x4; } Boolean ObjGen_IsExternalVar(SInt32 id) { return RELOC_DATA(id).type == RT_3; } SInt32 ObjGen_DeclareInit(UInt32 len, char *data, SInt32 align) { SInt32 offset; SInt32 relocID; GList *gl; MachOSection *section; UInt32 align2; SInt32 pad; SInt32 i; section = ObjGen_GetSection(SECT_DATA); gl = MachO_GetGList(section); offset = gl->size; if (!align) align = 1; align2 = AlignTo_Section(section, align); if (offset % align2) { pad = align2 - (offset % align2); for (i = 0; i < pad; i++) AppendGListByte(gl, 0); } relocID = ObjGen_MakeSectReloc(section); AppendGListData(gl, data, len); return relocID; } static UInt32 pic_stub[] = { 0x7C0802A6, 0x429F0005, 0x7D6802A6, 0x7C0803A6, 0x3D6B0000, 0x818B0000, 0x7D8903A6, 0x396B0000, 0x4E800420, 0 }; static UInt32 abs_stub[] = { 0x3D600000, 0x818B0000, 0x7D8903A6, 0x396B0000, 0x4E800420, 0 }; void CodeGen_GenDynLinkStub(MachOSection *a, MachOSection *b, SInt32 relocID) { SInt32 offset; GList *gl; SInt32 id; id = ObjGen_GetHashNodeRelocID(dyld_stub_binding_helper, NULL, 0); offset = ObjGen_GetSectSize(a); gl = ObjGen_GetSectionGList(a); if (copts.codegen_pic) { UInt32 i; for (i = 0; i < 9; i++) AppendGListLong(gl, CTool_EndianConvertWord32(pic_stub[i])); pic_base_offset = offset + 8; ObjGen_Relocate(a, offset + 16, relocID, RT_4, MW_RELOC_7_HA16); ObjGen_Relocate(a, offset + 20, relocID, RT_4, MW_RELOC_5_LO16); ObjGen_Relocate(a, offset + 28, relocID, RT_4, MW_RELOC_5_LO16); } else { UInt32 i; for (i = 0; i < 5; i++) AppendGListLong(gl, CTool_EndianConvertWord32(abs_stub[i])); ObjGen_Relocate(a, offset, relocID, RT_4, MW_RELOC_7_HA16); ObjGen_Relocate(a, offset + 4, relocID, RT_4, MW_RELOC_5_LO16); ObjGen_Relocate(a, offset + 12, relocID, RT_4, MW_RELOC_5_LO16); } offset = ObjGen_GetSectSize(b); gl = ObjGen_GetSectionGList(b); AppendGListLong(gl, 0); ObjGen_Relocate(b, offset, id, RT_4, MW_RELOC_0); } void ObjGen_DeclarePICBase(Object *object, SInt32 offset) { pic_base_offset = offset + ObjGen_GetRelocOffset(CMangler_GetLinkName(object)->id); } void ObjGen_DeclareEntry(Object *object, SInt32 offset) { RelocDataT r = {0}; CError_ASSERT(2415, last_function_sect_id != SECT_DEFAULT); ObjGen_DeclareSymbol( object, Sections[last_function_sect_id], offset + last_base_offset[last_function_sect_id]); r.privFlag = ObjGen_ComputePrivFlag(object->flags); updatesectreloc( &r, Sections[last_function_sect_id], offset + last_base_offset[last_function_sect_id]); AppendGListData(&RelocData, &r, sizeof(r)); CMangler_GetLinkName(object)->id = RelocIndex; RelocIndex++; } void ObjGen_DeclareExceptionTables(Object *object, SInt32 codesize, char *data, SInt32 len, OLinkList *refs) { UInt32 offset; MachOSection *section; GList *gl; SInt32 relocID; Boolean flag22; char *buf; char *tmp; UInt32 zero; RelocDataT rd; UInt32 stuff[3]; zero = 0; flag22 = 1; if (CParser_HasInternalLinkage(object)) flag22 = 0; if (len == 8) { if (CTool_EndianConvertWord16(*((UInt16 *) data) & 8) >> 3) { *((UInt16 *) data) = CTool_EndianConvertWord16(CTool_EndianConvertWord16(*((UInt16 *) data)) & ~8); len = 4; } } if (len != 4) { section = ObjGen_GetSection(SECT_MW_EX_TABLE); offset = ObjGen_GetSectSize(section); memclrw(&rd, sizeof(rd)); rd.type = RT_7; rd.x2 = flag22; rd.privFlag = 1; rd.x3 = 1; rd.x4 = offset; rd.section = section; tmp = CMangler_GetLinkName(object)->name; buf = galloc(1 + strlen(tmp) + strlen("mwEXTBL@")); sprintf(buf, "mwEXTBL.%s", tmp); rd.name = buf; rd.x18 = -1; AppendGListData(&RelocData, &rd, sizeof(rd)); RelocIndex++; gl = ObjGen_GetSectionGList(section); relocID = ObjGen_MakeSectReloc(section); AppendGListData(gl, data, len); if ((len & 3) != 0) AppendGListData(gl, &zero, 4 - (len & 3)); while (refs) { ObjGen_RelocateObj(section, offset + refs->offset, refs->obj, MW_RELOC_9); refs = refs->next; } } section = ObjGen_GetSection(SECT_MW_EX_TABLE_INDEX); gl = ObjGen_GetSectionGList(section); offset = ObjGen_GetSectSize(section); memclrw(&rd, sizeof(rd)); rd.type = RT_7; rd.x2 = flag22; rd.privFlag = 1; rd.x3 = 1; rd.x4 = offset; rd.section = section; tmp = CMangler_GetLinkName(object)->name; buf = galloc(1 + strlen(tmp) + strlen("mwEXTBL@")); sprintf(buf, "mwEXIDX.%s", tmp); rd.name = buf; rd.x18 = -1; AppendGListData(&RelocData, &rd, sizeof(rd)); RelocIndex++; stuff[0] = 0; stuff[1] = CTool_EndianConvertWord32(((len == 4) << 31) | (codesize & 0x7FFFFFFF)); stuff[2] = CTool_EndianConvertWord32((len == 4) ? CTool_EndianConvertWord32(*((UInt32 *) data)) : 0); AppendGListData(gl, stuff, sizeof(stuff)); ObjGen_RelocateObj(section, offset, object, MW_RELOC_9); if (len != 4) ObjGen_Relocate(section, offset + 8, relocID, RT_4, MW_RELOC_9); } void ObjGen_DeclareCodeLabel(Object *labelobj, SInt32 offset, Object *funcobj) { SInt32 relocOffset; GList *gl; MachOSection *section; section = ObjGen_GetSection(SECT_DATA); gl = MachO_GetGList(section); relocOffset = ObjGen_GetSectSize(section); ObjGen_GetHashNodeRelocID(labelobj, section, 0); AppendGListData(gl, &offset, 4); ObjGen_RelocateObj(section, relocOffset, funcobj, MW_RELOC_9); } void ObjGen_DeclareSwitchTable(Object *tableobj, Object *funcobj) { SInt32 relocOffset; GList *gl; int i; MachOSection *section; section = ObjGen_GetSection(SECT_MW_SWITCH); gl = MachO_GetGList(section); relocOffset = ObjGen_GetSectSize(section); ObjGen_GetHashNodeRelocID(tableobj, section, 0); AppendGListData(gl, tableobj->u.data.u.switchtable.data, 4 * tableobj->u.data.u.switchtable.size); for (i = tableobj->u.data.u.switchtable.size; i; i--) { ObjGen_RelocateObj(section, relocOffset, funcobj, MW_RELOC_9); relocOffset += 4; } } void ObjGen_DeclareTracebackTable(Object *tableobj, void *data, SInt32 size) { MachOSection *section; GList *gl; section = ObjGen_GetSection(SECT_MW_SWITCH); gl = MachO_GetGList(section); ObjGen_GetHashNodeRelocID(tableobj, section, 0); if (CMangler_GetLinkName(tableobj)->id < 0) { CMangler_GetLinkName(tableobj)->id = ObjGen_MakeSectReloc(section); } else { RelocDataT *rd = &RELOC_DATA(CMangler_GetLinkName(tableobj)->id); switch (rd->type) { case RT_2: updatesectreloc(rd, section, section->glist.size); break; default: CError_FATAL(2628); } } AppendGListData(gl, data, size); } void ObjGen_DeclareSymInfo(void) { if (copts.isGeneratingDebugInfo) SymContainedVars(); } void ObjGen_Line(UInt32 line, UInt32 offset) { if (copts.isGeneratingDebugInfo && line) GenStab_Line(line, offset + last_base_offset[last_function_sect_id]); } void ObjGen_OutputDebugInfo(Object *funcobj) { if (copts.isGeneratingDebugInfo) GenStab_Function(funcobj, CMangler_GetLinkName(funcobj)->id); } SInt32 ObjGen_OutputStab(SymbolData *symbol, SInt32 strIdx) { Section sectionID; RelocDataT *rd; sectionID = last_function_sect_id; if (sectionID == SECT_DEFAULT) sectionID = SECT_TEXT; if (symbol->type == N_FUN) { if (symbol->u.name[0] == 0) { if (Sections[sectionID]) { symbol->section = Sections[sectionID]; symbol->value = ObjGen_GetSectSize(Sections[sectionID]); } else { symbol->section = NULL; symbol->value = 0; } } else { rd = &RELOC_DATA(symbol->value); symbol->section = rd->section; symbol->value = rd->x4; } } else if (symbol->type == N_SLINE) { symbol->u.strx = 0; if (Sections[sectionID]) symbol->section = Sections[sectionID]; else symbol->section = NULL; } else if (symbol->type == N_STSYM) { rd = &RELOC_DATA(symbol->value); symbol->section = rd->section; symbol->value = rd->x4; if (symbol->section && (symbol->section->section.flags & S_ZEROFILL)) symbol->type = N_LCSYM; } else if (symbol->type == N_SO || symbol->type == N_SOL) { if (Sections[sectionID]) { symbol->section = Sections[sectionID]; symbol->value = ObjGen_GetSectSize(Sections[sectionID]); } else { symbol->section = NULL; symbol->value = 0; } } return MachO_OutputStab(symbol, strIdx); } void ObjGen_SetSectName() { // empty, unknown args } void ObjGen_DeclareInitFunction(Object *funcobj) { SInt32 offset; MachOSection *section; GList *gl; section = ObjGen_GetSection(SECT_MOD_INIT_FUNC); offset = ObjGen_GetSectSize(section); gl = ObjGen_GetSectionGList(section); AppendGListLong(gl, 0); ObjGen_Relocate(section, offset, ObjGen_GetHashNodeRelocID(funcobj, NULL, 0), RT_4, MW_RELOC_0); } static void SymContainedVars(void) { ObjectList *list; for (list = arguments; list; list = list->next) { if (list->object->u.var.info->used && list->object->name->name[0] != '@') GenStab_Parameter(list->object); } for (list = locals; list; list = list->next) { if (list->object->u.var.info->used && list->object->name->name[0] != '@') GenStab_Var(list->object); } } Boolean ObjGen_IsExported(Object *object) { SInt32 id = ObjGen_GetHashNodeRelocID(object, NULL, -1); if (id >= 0 && RELOC_DATA(id).type == RT_0) return 1; return 0; } static void AppendGListZeros(GList *glist, SInt32 size) { SInt32 pos = glist->size; AppendGListNoData(glist, size); memclr(*glist->data + pos, size); }