Collapse OBJC_CLASSLIST_REFERENCES globals in llvm-link?

Hello list,

I’m wondering about the feasibility of collapsing the following two globals within llvm-link:

@“OBJC_CLASSLIST_REFERENCES_$_2” = private global %struct.objc_class* bitcast (%struct.class_t* @"OBJC_CLASS$_NSString" to %struct.objc_class*), section “__DATA, _objc_classrefs, regular, no_dead_strip", align 4
@"OBJC_CLASSLIST_REFERENCES
$_8” = private global %struct.objc_class* bitcast (%struct.class_t* @"OBJC_CLASS$_NSString" to %struct.objc_class*), section “__DATA, __objc_classrefs, regular, no_dead_strip”, align 4

The reason we’d like to do it in llvm-link is because the Mach-O linker isn’t doing it for us, and instead giving us the following error when we try to link:

ld: in /var/folders/q7/q7f3KCNoGkOtsKthZvb6LJWOlJU/-Tmp-//ccjnT818.o, __objc_classrefs element missing reloc (count=2) for target class in /var/folders/q7/q7f3KCNoGkOtsKthZvb6LJWOlJU/-Tmp-//ccjnT818.o

collect2: ld returned 1 exit status

The code that generates this error (from ld.cpp) is here:

template
void AnonymousAtom::resolveName()
{
/some code omitted/
else if ( (strncmp(fSection->sectname(), “__objc_classrefs”, 16) == 0) && (strcmp(fSection->segname(), “__DATA”) == 0) ) {

std::vectorObjectFile::Reference*& references = this->getReferences();
if ( references.size() != 1 )
throwf(“__objc_classrefs element missing reloc (count=%ld) for target class in %s”, references.size(), fOwner.getPath());
const char* targetName = references[0]->getTargetName();
if ( strncmp(targetName, “OBJC_CLASS$_”, 14) == 0 )
asprintf((char**)&fSynthesizedName, “objc-class-ref-to-%s”, &targetName[14]);
else
asprintf((char**)&fSynthesizedName, “objc-class-ref-to-%s”, targetName);
}

}

The Mach-O linker knows how to do the collapsing, but does not do it. It doesn’t do it (seemingly) because we remove the .subsections_via_symbols assembly directive from the .s file generated by llc. We removed this directive at the recommendation of Apple support, because the linker was shuffling our code in a way that broke it. (We insert labels in the middle of instruction streams, that aren’t referenced by anything else). I can’t for the life of me find the code in the linker that does the collapsing; all I know is that it isn’t doing it.

I’m also open to other suggestions from the list on how to work around this issue. Basically, it seems like I need to collapse these two references somewhere, either in llvm-link or by hand-editting the assembly file. Does anyone have any insight or advice on how to work around this linker limitation? Thanks in advance.

Nathan McCauley
Arxan Technologies