]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/MachOWriterExecutable.hpp
ld64-97.17.tar.gz
[apple/ld64.git] / src / ld / MachOWriterExecutable.hpp
index 95967330007943befbe6f986607b791d04d99cf3..5313669aa40c3ba33052c53034c4d8ef9a66dc00 100644 (file)
@@ -1706,14 +1706,15 @@ class ObjCInfoAtom : public WriterAtom<A>
 {
 public:
                                                                                        ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcContraint,
-                                                                                                               bool objcReplacementClasses);
+                                                                                                               bool objcReplacementClasses, bool abi2override);
        virtual const char*                                             getName() const                         { return "objc$info"; }
        virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
        virtual uint64_t                                                getSize() const                         { return 8; }
        virtual const char*                                             getSectionName() const;
        virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 private:
-       Segment&                                                                getInfoSegment() const;
+       Segment&                                                                getInfoSegment(bool abi2override) const;
+       bool                                                                    fAbi2override;
        uint32_t                                                                fContent[2];
 };
 
@@ -3280,7 +3281,8 @@ int Writer<A>::compressedOrdinalForImortedAtom(ObjectFile::Atom* target)
 template <typename A>
 ObjectFile::Atom& Writer<A>::makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, bool objcReplacementClasses)
 {
-       return *(new ObjCInfoAtom<A>(*this, objcContraint, objcReplacementClasses));
+       
+       return *(new ObjCInfoAtom<A>(*this, objcContraint, objcReplacementClasses, fOptions.objCABIVersion2POverride()));
 }
 
 template <typename A>
@@ -4350,14 +4352,23 @@ uint32_t Writer<arm>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Refere
                                else
                                        sreloc1->set_r_type(ARM_RELOC_SECTDIFF);
                                sreloc1->set_r_address(address);
-                               sreloc1->set_r_value(target.getAddress());
+                               if ( ref->getTargetOffset() >= target.getSize() )
+                                       sreloc1->set_r_value(target.getAddress());
+                               else
+                                       sreloc1->set_r_value(target.getAddress()+ref->getTargetOffset());
                                sreloc2->set_r_scattered(true);
                                sreloc2->set_r_pcrel(false);
                                sreloc2->set_r_length(2);
                                sreloc2->set_r_type(ARM_RELOC_PAIR);
                                sreloc2->set_r_address(0);
-                               if ( &ref->getFromTarget() == atom )
-                                       sreloc2->set_r_value(ref->getFromTarget().getAddress()+ref->getFromTargetOffset());
+                               if ( &ref->getFromTarget() == atom ) {
+                                       unsigned int pcBaseOffset = atom->isThumb() ? 4 : 8;
+                                       if ( (ref->getFromTargetOffset() > pcBaseOffset) && (strncmp(atom->getSectionName(), "__text", 6) == 0) ) {
+                                               sreloc2->set_r_value(ref->getFromTarget().getAddress()+ref->getFromTargetOffset()-pcBaseOffset);
+                                       }
+                                       else
+                                               sreloc2->set_r_value(ref->getFromTarget().getAddress()+ref->getFromTargetOffset());
+                               }
                                else
                                        sreloc2->set_r_value(ref->getFromTarget().getAddress());
                                fSectionRelocs.push_back(reloc2);
@@ -6250,6 +6261,7 @@ void Writer<arm>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const Ob
        uint32_t        firstDisp;
        uint32_t        nextDisp;
        uint32_t        opcode = 0;
+       int32_t         diff;
        bool            relocateableExternal = false;
        bool            is_bl;
        bool            is_blx;
@@ -6330,8 +6342,10 @@ void Writer<arm>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const Ob
                        }
                        break;
                case arm::kPointerDiff:
-                       LittleEndian::set32(*fixUp,
-                               (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
+                       diff = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
+                       if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0) )
+                               diff |= 1;
+                       LittleEndian::set32(*fixUp, diff);
                        break;
                case arm::kReadOnlyPointer:
                        if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0))
@@ -6552,6 +6566,7 @@ void Writer<arm>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, co
        uint32_t        firstDisp;
        uint32_t        nextDisp;
        uint32_t        opcode = 0;
+       int32_t         diff;
        bool            relocateableExternal = false;
        bool            is_bl;
        bool            is_blx;
@@ -6572,7 +6587,6 @@ void Writer<arm>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, co
                case arm::kPointer:
                case arm::kReadOnlyPointer:
                case arm::kPointerWeakImport:
-                       {
                        if ( ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
                                // indirect symbol table has INDIRECT_SYMBOL_LOCAL, so we must put address in content
                                if ( this->indirectSymbolInRelocatableIsLocal(ref) ) 
@@ -6600,23 +6614,17 @@ void Writer<arm>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, co
                                }
                        }
                        else {
-                               // internal relocation
-                               if ( ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition ) {
-                                       // pointer contains target address
-                                       if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0))
+                               // internal relocation =>  pointer contains target address
+                               if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0) )
                                                targetAddr |= 1;
-                                               LittleEndian::set32(*fixUp, targetAddr);
-                                       }
-                                       else {
-                                               // pointer contains addend
-                                               LittleEndian::set32(*fixUp, ref->getTargetOffset());
-                                       }
-                               }
+                               LittleEndian::set32(*fixUp, targetAddr);
                        }
                        break;
                case arm::kPointerDiff:
-                               LittleEndian::set32(*fixUp,
-                                       (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
+                       diff = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
+                       if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0) )
+                               diff |= 1;
+                       LittleEndian::set32(*fixUp, diff);
                        break;
                case arm::kDtraceProbeSite:
                case arm::kDtraceIsEnabledSite:
@@ -9624,7 +9632,10 @@ void SegmentLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
                                                cmd->set_vmaddr(sectInfo->getBaseAddress());
                                                cmd->set_fileoff(sectInfo->fFileOffset);
                                        }
-                                       cmd->set_filesize((sectInfo->fFileOffset+sectInfo->fSize)-cmd->fileoff());
+                                       // <rdar://problem/7712869> if last section is zero-fill don't add size to filesize total
+                                       if ( !sectInfo->fAllZeroFill ) {
+                                               cmd->set_filesize((sectInfo->fFileOffset+sectInfo->fSize)-cmd->fileoff());
+                                       }
                                        cmd->set_vmsize(sectInfo->getBaseAddress() + sectInfo->fSize);
                                }
                                sect->set_sectname(sectInfo->fSectionName);
@@ -11269,8 +11280,9 @@ void SegmentSplitInfoContentAtom<A>::encode()
 
 
 template <typename A>
-ObjCInfoAtom<A>::ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcConstraint, bool objcReplacementClasses)
-       : WriterAtom<A>(writer, getInfoSegment())
+ObjCInfoAtom<A>::ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcConstraint, 
+                                                                       bool objcReplacementClasses, bool abi2override)
+       : WriterAtom<A>(writer, getInfoSegment(abi2override)), fAbi2override(abi2override)
 {
        fContent[0] = 0;
        uint32_t value = 0;
@@ -11306,16 +11318,16 @@ void ObjCInfoAtom<A>::copyRawContent(uint8_t buffer[]) const
 
 // objc info section is in a different segment and section for 32 vs 64 bit runtimes
 template <> const char* ObjCInfoAtom<ppc>::getSectionName()    const { return "__image_info"; }
-template <> const char* ObjCInfoAtom<x86>::getSectionName()    const { return "__image_info"; }
+template <> const char* ObjCInfoAtom<x86>::getSectionName()    const { return fAbi2override ? "__objc_imageinfo" : "__image_info"; }
 template <> const char* ObjCInfoAtom<arm>::getSectionName()    const { return "__objc_imageinfo"; }
 template <> const char* ObjCInfoAtom<ppc64>::getSectionName()  const { return "__objc_imageinfo"; }
 template <> const char* ObjCInfoAtom<x86_64>::getSectionName() const { return "__objc_imageinfo"; }
 
-template <> Segment& ObjCInfoAtom<ppc>::getInfoSegment()    const { return Segment::fgObjCSegment; }
-template <> Segment& ObjCInfoAtom<x86>::getInfoSegment()    const { return Segment::fgObjCSegment; }
-template <> Segment& ObjCInfoAtom<ppc64>::getInfoSegment()  const { return Segment::fgDataSegment; }
-template <> Segment& ObjCInfoAtom<x86_64>::getInfoSegment() const { return Segment::fgDataSegment; }
-template <> Segment& ObjCInfoAtom<arm>::getInfoSegment()    const { return Segment::fgDataSegment; }
+template <> Segment& ObjCInfoAtom<ppc>::getInfoSegment(bool abi2override)    const { return Segment::fgObjCSegment; }
+template <> Segment& ObjCInfoAtom<x86>::getInfoSegment(bool abi2override)    const { return abi2override ? Segment::fgDataSegment : Segment::fgObjCSegment; }
+template <> Segment& ObjCInfoAtom<ppc64>::getInfoSegment(bool abi2override)  const { return Segment::fgDataSegment; }
+template <> Segment& ObjCInfoAtom<x86_64>::getInfoSegment(bool abi2override) const { return Segment::fgDataSegment; }
+template <> Segment& ObjCInfoAtom<arm>::getInfoSegment(bool abi2override)    const { return Segment::fgDataSegment; }