MWCC/compiler_and_linker/unsorted/ObjGenMachO.c

1838 lines
56 KiB
C

#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"
#ifndef CW_TARGET_MACH
#error "Wrong configuration for ObjGenMachO"
#endif
#ifdef __MWERKS__
#pragma options align=mac68k
#endif
typedef struct Reloc {
MachOSection *section;
SInt32 offset;
SInt32 relocID;
SInt32 picOffset;
struct Reloc *next;
char 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)])
enum { ForceCreateCount = 1 };
static Section SegmentForceCreate[ForceCreateCount] = { 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_WEAK)) &&
(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_USED) &&
(objectFlags & OBJECT_FLAGS_2) &&
!(objectFlags & OBJECT_DEFINED)
)
return 0;
return 1;
case 3:
case 4:
if ((objectFlags & OBJECT_INTERNAL) == OBJECT_INTERNAL)
return 1;
if ((objectFlags & OBJECT_EXPORT) == OBJECT_EXPORT)
return 0;
if (
(objectFlags & OBJECT_USED) &&
(objectFlags & OBJECT_FLAGS_2) &&
!(objectFlags & OBJECT_DEFINED)
)
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_WEAK)) > 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_WEAK))) {
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_WEAK)))
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(&section->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.filesyminfo)
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 & 0xFFFF0000) >> 16;
nextRelType = PPC_RELOC_HA16_SECTDIFF;
break;
case MW_RELOC_6_HI16:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
value = (value & 0xFFFF0000) >> 16;
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 & 0xFFFF0000) >> 16;
nextRelType = PPC_RELOC_HA16;
break;
case MW_RELOC_6_HI16:
opMask = 0xFFFF0000;
argMask = 0xFFFF;
value = (value & 0xFFFF0000) >> 16;
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) {
int i;
TheSegment = MachO_CreateSegment("", 7, 7, 0);
for (i = 0; i < ForceCreateCount; i++)
Sections[SegmentForceCreate[i]] = ObjGen_GetSection(SegmentForceCreate[i]);
}
static void patchuplazyptr(Object *object) {
RelocDataT *rd;
Object *toc;
if (CParser_HasInternalLinkage(object) || !(object->qual & (Q_20000 | Q_WEAK))) {
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.filesyminfo)
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) != 0) {
// issue here
int 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.filesyminfo) {
if (name)
strncpy(buf1, name->name, sizeof(buf1));
else
COS_FileGetPathName(buf1, &cparamblkptr->sourcefile, &fileModDate);
if (name && copts.absolutepath)
ptr = buf1 + strlen(buf1);
else
ptr = strrchr(buf1, OS_PATHSEP);
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) {
#ifdef CW_HOST_MAC_CLASSIC
if (*ptr3 == '/')
*ptr2 = ':';
else if (*ptr3 == ':')
*ptr2 = '/';
else
*ptr2 = *ptr3;
#else
*ptr2 = *ptr3;
#endif
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, SInt32 size) {
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(char *segname, char *sectname, UInt32 align, UInt32 flags) {
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)) >> 3) & 1) {
*((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.filesyminfo)
SymContainedVars();
}
void ObjGen_Line(UInt32 line, UInt32 offset) {
if (copts.filesyminfo && line)
GenStab_Line(line, offset + last_base_offset[last_function_sect_id]);
}
void ObjGen_OutputDebugInfo(Object *funcobj) {
if (copts.filesyminfo)
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);
}