- if ( strcmp(sect->sectionName(), "__text") == 0 )
- textSection = sect;
- }
- if ( textSection == NULL )
- return;
-
- // scan __text section for branch instructions that need to switch mode
- for (std::vector<const ld::Atom*>::iterator ait=textSection->atoms.begin(); ait != textSection->atoms.end(); ++ait) {
- const ld::Atom* atom = *ait;
- const ld::Atom* target;
- for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
- switch ( fit->kind ) {
- case ld::Fixup::kindStoreTargetAddressThumbBranch22:
- extractTarget(fit, state, &target);
- if ( ! target->isThumb() ) {
- const uint8_t* fixUpLocation = atom->rawContentPointer() + fit->offsetInAtom;
- uint32_t instruction = *((uint32_t*)fixUpLocation);
- bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
- if ( is_b ) {
- fprintf(stderr, "need to add thumb->arm instr=0x%08X shim to %s for %s\n", instruction, target->name(), atom->name());
- const Atom* shim = NULL;
- std::map<const Atom*, const Atom*>::iterator pos = thumbToAtomMap.find(target);
- if ( pos == thumbToAtomMap.end() ) {
- if ( opts.subArchitecture() == CPU_SUBTYPE_ARM_V7 )
- shim = new Thumb2ToArmShimAtom(target);
- else
- shim = new Thumb1ToArmShimAtom(target);
- shims.push_back(shim);
- thumbToAtomMap[target] = shim;
- }
- else {
- shim = pos->second;
+ std::map<const Atom*, const Atom*> atomToThumbMap;
+ std::map<const Atom*, const Atom*> thumbToAtomMap;
+ std::vector<const Atom*> shims;
+ // scan section for branch instructions that need to switch mode
+ for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
+ const ld::Atom* atom = *ait;
+ const ld::Atom* target = NULL;
+ bool targetIsProxy;
+ for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
+ switch ( fit->kind ) {
+ case ld::Fixup::kindStoreTargetAddressThumbBranch22:
+ extractTarget(fit, state, &target);
+ targetIsProxy = (target->definition() == ld::Atom::definitionProxy);
+ if ( ! target->isThumb() ) {
+ const uint8_t* fixUpLocation = atom->rawContentPointer();
+ // <rdar://problem/9544194> don't try to scan atom for branches if atom unwilling to supply raw content
+ if ( fixUpLocation == NULL )
+ break;
+ fixUpLocation += fit->offsetInAtom;
+ uint32_t instruction = *((uint32_t*)fixUpLocation);
+ bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
+ // need shim for branch from thumb to arm, or for call to function outside kext
+ if ( is_b || (targetIsProxy && makingKextBundle) ) {
+ if ( _s_log ) fprintf(stderr, "need to add thumb->arm instr=0x%08X shim to %s for %s\n", instruction, target->name(), atom->name());
+ const Atom* shim = NULL;
+ std::map<const Atom*, const Atom*>::iterator pos = thumbToAtomMap.find(target);
+ if ( pos == thumbToAtomMap.end() ) {
+ if ( opts.archSupportsThumb2() ) {
+ // <rdar://problem/9116044> make long-branch style shims for arm kexts
+ if ( makingKextBundle && opts.allowTextRelocs() )
+ shim = new NoPICThumb2ToArmShimAtom(target, *sect);
+ else
+ shim = new Thumb2ToArmShimAtom(target, *sect);
+ }
+ else {
+ shim = new Thumb1ToArmShimAtom(target, *sect);
+ }
+ shims.push_back(shim);
+ thumbToAtomMap[target] = shim;
+ }
+ else {
+ shim = pos->second;
+ }
+ fit->binding = ld::Fixup::bindingDirectlyBound;
+ fit->u.target = shim;