- case PPC_RELOC_BR24:
- assert((instruction & 0x4C000000) == 0x48000000);
- displacement = (instruction & 0x03FFFFFC);
- if ( (displacement & 0x02000000) != 0 )
- displacement |= 0xFC000000;
- if ( reloc->r_extern() ) {
- target.addend = srcAddr + displacement;
- }
- else {
- dstAddr = srcAddr + displacement;
- parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
- }
- // special case "calls" for dtrace
- if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_probe$", 16) == 0) ) {
- parser.addFixup(src, ld::Fixup::k1of1,
- ld::Fixup::kindStorePPCDtraceCallSiteNop, false, target.name);
- parser.addDtraceExtraInfos(src, &target.name[16]);
- }
- else if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_isenabled$", 20) == 0) ) {
- parser.addFixup(src, ld::Fixup::k1of1,
- ld::Fixup::kindStorePPCDtraceIsEnableSiteClear, false, target.name);
- parser.addDtraceExtraInfos(src, &target.name[20]);
- }
- else {
- parser.addFixups(src, ld::Fixup::kindStorePPCBranch24, target);
- }
- break;
- case PPC_RELOC_BR14:
- displacement = (instruction & 0x0000FFFC);
- if ( (displacement & 0x00008000) != 0 )
- displacement |= 0xFFFF0000;
- if ( reloc->r_extern() ) {
- target.addend = srcAddr + displacement;
- }
- else {
- dstAddr = srcAddr + displacement;
- parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
- }
- parser.addFixups(src, ld::Fixup::kindStorePPCBranch14, target);
- break;
- case PPC_RELOC_PAIR:
- // skip, processed by a previous look ahead
- break;
- case PPC_RELOC_LO16:
- if ( nextReloc->r_type() != PPC_RELOC_PAIR )
- throw "PPC_RELOC_LO16 missing following pair";
- result = true;
- lowBits = (instruction & 0x0000FFFF);
- dstAddr = (nextReloc->r_address() << 16) + ((uint32_t)lowBits & 0x0000FFFF);
- if ( reloc->r_extern() ) {
- target.addend = dstAddr;
- }
- else {
- parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
- }
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsLow16, target);
- break;
- case PPC_RELOC_LO14:
- if ( nextReloc->r_type() != PPC_RELOC_PAIR )
- throw "PPC_RELOC_LO14 missing following pair";
- result = true;
- lowBits = (instruction & 0xFFFC);
- dstAddr = (nextReloc->r_address() << 16) + ((uint32_t)lowBits & 0x0000FFFF);
- if ( reloc->r_extern() ) {
- target.addend = dstAddr;
- }
- else {
- parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
- }
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsLow14, target);
- break;
- case PPC_RELOC_HI16:
- if ( nextReloc->r_type() != PPC_RELOC_PAIR )
- throw "PPC_RELOC_HI16 missing following pair";
- result = true;
- lowBits = (nextReloc->r_address() & 0xFFFF);
- dstAddr = ((instruction & 0xFFFF) << 16) | (lowBits & 0x0000FFFF);
- if ( reloc->r_extern() ) {
- target.addend = dstAddr;
- }
- else {
- parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
- }
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsHigh16, target);
- break;
- case PPC_RELOC_HA16:
- if ( nextReloc->r_type() != PPC_RELOC_PAIR )
- throw "PPC_RELOC_HA16 missing following pair";
- result = true;
- lowBits = (nextReloc->r_address() & 0x0000FFFF);
- dstAddr = ((instruction & 0xFFFF) << 16) + (int32_t)lowBits;
- if ( reloc->r_extern() ) {
- target.addend = dstAddr;
- }
- else {
- parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
- }
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsHigh16AddLow, target);
- break;
- case PPC_RELOC_VANILLA:
- contentValue = P::getP(*((pint_t*)fixUpPtr));
- if ( reloc->r_extern() ) {
- target.addend = contentValue;
- }
- else {
- parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
- }
- switch ( reloc->r_length() ) {
- case 0:
- case 1:
- throw "bad r_length in PPC_RELOC_VANILLA";
- case 2:
- parser.addFixups(src, ld::Fixup::kindStoreBigEndian32, target);
- break;
- case 3:
- parser.addFixups(src, ld::Fixup::kindStoreBigEndian64, target);
- break;
- }
- break;
- case PPC_RELOC_JBSR:
- // this is from -mlong-branch codegen. We ignore the jump island and make reference to the real target
- if ( nextReloc->r_type() != PPC_RELOC_PAIR )
- throw "PPC_RELOC_JBSR missing following pair";
- if ( !parser._hasLongBranchStubs )
- warning("object file compiled with -mlong-branch which is no longer needed. "
- "To remove this warning, recompile without -mlong-branch: %s", parser._path);
- parser._hasLongBranchStubs = true;
- result = true;
- if ( reloc->r_extern() ) {
- throw "PPC_RELOC_JBSR should not be using an external relocation";
- }
- parser.findTargetFromAddressAndSectionNum(nextReloc->r_address(), reloc->r_symbolnum(), target);
- parser.addFixups(src, ld::Fixup::kindStorePPCBranch24, target);
- break;
- default:
- warning("unknown relocation type %d", reloc->r_type());
- }
- }
- else {
- const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
- // file format allows pair to be scattered or not
- const macho_scattered_relocation_info<P>* nextSReloc = &sreloc[1];
- const macho_relocation_info<P>* nextReloc = &reloc[1];
- srcAddr = sect->addr() + sreloc->r_address();
- dstAddr = sreloc->r_value();
- fixUpPtr = (uint32_t*)(file().fileContent() + sect->offset() + sreloc->r_address());
- instruction = BigEndian::get32(*fixUpPtr);
- src.atom = this->findAtomByAddress(srcAddr);
- src.offsetInAtom = srcAddr - src.atom->_objAddress;
- typename Parser<A>::TargetDesc picBase;
- bool nextRelocIsPair = false;
- uint32_t nextRelocAddress = 0;
- uint32_t nextRelocValue = 0;
- if ( (nextReloc->r_address() & R_SCATTERED) == 0 ) {
- if ( nextReloc->r_type() == PPC_RELOC_PAIR ) {
- nextRelocIsPair = true;
- nextRelocAddress = nextReloc->r_address();
- result = true;
- }
- }
- else {
- if ( nextSReloc->r_type() == PPC_RELOC_PAIR ) {
- nextRelocIsPair = true;
- nextRelocAddress = nextSReloc->r_address();
- nextRelocValue = nextSReloc->r_value();
- result = true;
- }
- }
- switch ( sreloc->r_type() ) {
- case PPC_RELOC_VANILLA:
- // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
- target.atom = parser.findAtomByAddress(sreloc->r_value());
- switch ( sreloc->r_length() ) {
- case 0:
- case 1:
- throw "unsuppored r_length < 2 for scattered PPC_RELOC_VANILLA";
- case 2:
- contentValue = BigEndian::get32(*(uint32_t*)fixUpPtr);
- target.addend = contentValue - target.atom->_objAddress;
- parser.addFixups(src, ld::Fixup::kindStoreBigEndian32, target);
- break;
- case 3:
- contentValue = BigEndian::get64(*(uint64_t*)fixUpPtr);
- target.addend = contentValue - target.atom->_objAddress;
- parser.addFixups(src, ld::Fixup::kindStoreBigEndian64, target);
- break;
- }
- break;
- case PPC_RELOC_BR14:
- displacement = (instruction & 0x0000FFFC);
- if ( (displacement & 0x00008000) != 0 )
- displacement |= 0xFFFF0000;
- target.atom = parser.findAtomByAddress(sreloc->r_value());
- target.addend = (srcAddr + displacement) - target.atom->_objAddress;
- parser.addFixups(src, ld::Fixup::kindStorePPCBranch14, target);
- break;
- case PPC_RELOC_BR24:
- assert((instruction & 0x4C000000) == 0x48000000);
- displacement = (instruction & 0x03FFFFFC);
- if ( (displacement & 0x02000000) != 0 )
- displacement |= 0xFC000000;
- target.atom = parser.findAtomByAddress(sreloc->r_value());
- target.addend = (srcAddr + displacement) - target.atom->_objAddress;
- parser.addFixups(src, ld::Fixup::kindStorePPCBranch24, target);
- break;
- case PPC_RELOC_LO16_SECTDIFF:
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_LO16_SECTDIFF missing following pair";
- lowBits = (instruction & 0xFFFF);
- dstAddr = nextRelocValue + ((nextRelocAddress << 16) | ((uint32_t)lowBits & 0x0000FFFF));
- parser.findTargetFromAddress(sreloc->r_value(), target);
- if ( target.atom != NULL )
- target.addend = dstAddr - target.atom->_objAddress;
- picBase.atom = parser.findAtomByAddress(nextRelocValue);
- picBase.addend = nextRelocValue - picBase.atom->_objAddress;
- picBase.weakImport = false;
- picBase.name = NULL;
- parser.addFixups(src, ld::Fixup::kindStorePPCPicLow16, target, picBase);
- break;
- case PPC_RELOC_LO14_SECTDIFF:
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_LO14_SECTDIFF missing following pair";
- lowBits = (instruction & 0xFFFC);
- dstAddr = nextRelocValue + ((nextRelocAddress << 16) | ((uint32_t)lowBits & 0x0000FFFF));
- parser.findTargetFromAddress(sreloc->r_value(), target);
- if ( target.atom != NULL )
- target.addend = dstAddr - target.atom->_objAddress;
- picBase.atom = parser.findAtomByAddress(nextRelocValue);
- picBase.addend = nextRelocValue - picBase.atom->_objAddress;
- picBase.weakImport = false;
- picBase.name = NULL;
- parser.addFixups(src, ld::Fixup::kindStorePPCPicLow14, target, picBase);
- break;
- case PPC_RELOC_HA16_SECTDIFF:
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_HA16_SECTDIFF missing following pair";
- lowBits = (nextRelocAddress & 0x0000FFFF);
- dstAddr = nextRelocValue + (((instruction & 0x0000FFFF) << 16) + (int32_t)lowBits);
- parser.findTargetFromAddress(sreloc->r_value(), target);
- if ( target.atom != NULL )
- target.addend = dstAddr - target.atom->_objAddress;
- picBase.atom = parser.findAtomByAddress(nextRelocValue);
- picBase.addend = nextRelocValue - picBase.atom->_objAddress;
- picBase.weakImport = false;
- picBase.name = NULL;
- parser.addFixups(src, ld::Fixup::kindStorePPCPicHigh16AddLow, target, picBase);
- break;
- case PPC_RELOC_LO14:
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_LO14 missing following pair";
- lowBits = (instruction & 0xFFFC);
- dstAddr = ((nextRelocAddress << 16) + ((uint32_t)lowBits & 0x0000FFFF));
- parser.findTargetFromAddress(sreloc->r_value(), dstAddr, target);
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsLow14, target);
- break;
- case PPC_RELOC_LO16:
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_LO16 missing following pair";
- lowBits = (instruction & 0xFFFF);
- dstAddr = ((nextRelocAddress << 16) + ((uint32_t)lowBits & 0x0000FFFF));
- parser.findTargetFromAddress(sreloc->r_value(), dstAddr, target);
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsLow16, target);
- break;
- case PPC_RELOC_HA16:
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_HA16 missing following pair";
- lowBits = (nextRelocAddress & 0xFFFF);
- dstAddr = (((instruction & 0xFFFF) << 16) + (int32_t)lowBits);
- parser.findTargetFromAddress(sreloc->r_value(), dstAddr, target);
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsHigh16AddLow, target);
- break;
- case PPC_RELOC_HI16:
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_HI16 missing following pair";
- lowBits = (nextRelocAddress & 0xFFFF);
- dstAddr = ((instruction & 0xFFFF) << 16) | (lowBits & 0x0000FFFF);
- parser.findTargetFromAddress(sreloc->r_value(), dstAddr, target);
- parser.addFixups(src, ld::Fixup::kindStorePPCAbsHigh16, target);
- break;
- case PPC_RELOC_SECTDIFF:
- case PPC_RELOC_LOCAL_SECTDIFF:
- {
- if ( ! nextRelocIsPair )
- throw "PPC_RELOC_SECTDIFF missing following pair";
- ld::Fixup::Kind kind = ld::Fixup::kindNone;
- switch ( sreloc->r_length() ) {
- case 0:
- throw "bad length for PPC_RELOC_SECTDIFF";
- case 1:
- contentValue = (int32_t)(int16_t)BigEndian::get16(*((uint16_t*)fixUpPtr));
- kind = ld::Fixup::kindStoreBigEndian16;
- break;
- case 2:
- contentValue = BigEndian::get32(*((uint32_t*)fixUpPtr));
- kind = ld::Fixup::kindStoreBigEndian32;
- break;
- case 3:
- contentValue = BigEndian::get64(*((uint64_t*)fixUpPtr));
- kind = ld::Fixup::kindStoreBigEndian64;
- break;
- break;
- }
- Atom<A>* fromAtom = parser.findAtomByAddress(nextRelocValue);
- Atom<A>* targetAtom = parser.findAtomByAddress(sreloc->r_value());
- uint32_t offsetInFrom = nextRelocValue - fromAtom->_objAddress;
- uint32_t offsetInTarget = sreloc->r_value() - targetAtom->_objAddress;
- // check for addend encoded in the section content
- int32_t addend = contentValue - (sreloc->r_value() - nextRelocValue);
- if ( addend < 0 ) {
- if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
- parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
- }
- else if ( (targetAtom->combine() == ld::Atom::combineByNameAndContent) || (targetAtom->combine() == ld::Atom::combineByNameAndReferences) ) {
- parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, targetAtom);
- }
- else {
- parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
- }
- parser.addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, offsetInTarget);
- parser.addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, fromAtom);
- parser.addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, offsetInFrom-addend);
- parser.addFixup(src, ld::Fixup::k5of5, kind);
- }
- else {
- if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
- parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
- }
- else if ( (targetAtom->combine() == ld::Atom::combineByNameAndContent) || (targetAtom->combine() == ld::Atom::combineByNameAndReferences) ) {
- parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, targetAtom);
- }
- else {
- parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
- }
- parser.addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, offsetInTarget+addend);
- parser.addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, fromAtom);
- parser.addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, offsetInFrom);
- parser.addFixup(src, ld::Fixup::k5of5, kind);
- }
- }
- break;
- case PPC_RELOC_PAIR:
- break;
- case PPC_RELOC_HI16_SECTDIFF:
- warning("unexpected scattered relocation type PPC_RELOC_HI16_SECTDIFF");
- break;
- default:
- warning("unknown scattered relocation type %d", sreloc->r_type());
- }
- }
- return result;
-}
-
-
-template <>
-bool Section<ppc>::addRelocFixup(class Parser<ppc>& parser, const macho_relocation_info<P>* reloc)
-{
- return addRelocFixup_powerpc(parser, reloc);
-}
-
-
-template <>
-bool Section<ppc64>::addRelocFixup(class Parser<ppc64>& parser, const macho_relocation_info<P>* reloc)
-{
- return addRelocFixup_powerpc(parser, reloc);
-}
-
-
-
-template <>
-bool Section<arm>::addRelocFixup(class Parser<arm>& parser, const macho_relocation_info<P>* reloc)
-{
- const macho_section<P>* sect = this->machoSection();
- bool result = false;
- uint32_t srcAddr;
- uint32_t dstAddr;
- uint32_t* fixUpPtr;
- int32_t displacement = 0;
- uint32_t instruction = 0;
- pint_t contentValue = 0;
- Parser<arm>::SourceLocation src;
- Parser<arm>::TargetDesc target;
- const macho_relocation_info<P>* nextReloc;
-
- if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
- bool externSymbolIsThumbDef = false;
- srcAddr = sect->addr() + reloc->r_address();
- src.atom = this->findAtomByAddress(srcAddr);
- src.offsetInAtom = srcAddr - src.atom->_objAddress;
- fixUpPtr = (uint32_t*)(file().fileContent() + sect->offset() + reloc->r_address());
- if ( reloc->r_type() != ARM_RELOC_PAIR )
- instruction = LittleEndian::get32(*fixUpPtr);
- if ( reloc->r_extern() ) {
- target.atom = NULL;
- const macho_nlist<P>& targetSymbol = parser.symbolFromIndex(reloc->r_symbolnum());
- target.name = parser.nameFromSymbol(targetSymbol);
- target.weakImport = parser.weakImportFromSymbol(targetSymbol);
- if ( ((targetSymbol.n_type() & N_TYPE) == N_SECT) && (targetSymbol.n_desc() & N_ARM_THUMB_DEF) )
- externSymbolIsThumbDef = true;
- }
- switch ( reloc->r_type() ) {
- case ARM_RELOC_BR24:
- // Sign-extend displacement
- displacement = (instruction & 0x00FFFFFF) << 2;