]> git.saurik.com Git - apple/ld64.git/commitdiff
ld64-97.14.tar.gz developer-tools-323 developer-tools-324 ios-40 ios-41 v97.14
authorApple <opensource@apple.com>
Tue, 27 Jul 2010 02:16:02 +0000 (02:16 +0000)
committerApple <opensource@apple.com>
Tue, 27 Jul 2010 02:16:02 +0000 (02:16 +0000)
14 files changed:
ChangeLog
doc/man/man1/ld.1
ld64.xcodeproj/project.pbxproj
src/ld/MachOReaderRelocatable.hpp
src/ld/MachOWriterExecutable.hpp
src/ld/ObjectFile.h
src/ld/Options.cpp
src/ld/Options.h
src/ld/ld.cpp
unit-tests/test-cases/relocs-asm/relocs-asm.s
unit-tests/test-cases/tentative-to-real-r/Makefile [new file with mode: 0644]
unit-tests/test-cases/tentative-to-real-r/test.c [new file with mode: 0644]
unit-tests/test-cases/weak-def-flag/Makefile
unit-tests/test-cases/weak-def-flag/main-strip-weak.c [new file with mode: 0644]

index ffe419096e330f8a24ef6b10d724e2b3a96870d0..38543bce9ba1927727e5ac77ca30a0d6a1bea6f8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,116 @@
 
+----- Tagged ld64-97.14
+
+2010-04-20    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7712869> if last section is zero-fill don't add size to filesize total in -r mode
+
+----- Tagged ld64-97.13
+
+2010-03-17    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7824112> Support for iPhoneSimulator with OBJC 2.0 ABI
+
+
+----- Tagged ld64-97.12
+
+2010-03-17    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7712869> if last section is zero-fill don't add size to filesize total in -r mode
+
+----- Tagged ld64-97.11
+
+2010-01-26    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7622634> Libc-624.1 causes latent ld bug
+       * build linker -no_pie
+       
+
+----- Tagged ld64-97.10
+
+2010-01-26    Nick Kledzik    <kledzik@apple.com>
+       
+       <rdar://problem/7556912> LC_SEGMENT command 0 filesize field greater than vmsize field
+       * Move __DATA to end in -r mode
+       
+
+2010-01-26    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7516793> symboled __ustring strings of just 0x0000 mis-parsed
+       * Parse __ustring section based on content - not just labels
+
+
+----- Tagged ld64-97.9
+
+2010-01-14    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7532743> LC_SEGMENT command 0 filesize field greater than vmsize field
+       * for i386 -r mode sort __IMPORT segment before __DATA segment
+
+
+2010-01-11    Nick Kledzik    <kledzik@apple.com>
+
+       * fix ARM -r -d references to tentative definitions
+
+----- Tagged ld64-97.8
+
+2009-12-08    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7455147> many mach-o images in Barolo have MH_WEAK_DEFINES bit incorrectly set
+       * don't let auto-strip weak symbols set MH_WEAK_DEFINES
+       
+
+----- Tagged ld64-97.7
+
+2009-11-30    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7429384> llvmgcc now puts const short arrays in __ustring section, linker does not handle that
+       * Only auto-coalesce UTF16 strings that are labeled with "___utf16_string*"
+
+
+----- Tagged ld64-97.6
+2009-11-06    Nick Kledzik    <kledzik@apple.com>
+       <rdar://problem/7332627> make -pie default for x86_64 for 10.7 and later
+
+
+2009-10-28    Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7331635> Add a -no_pie flag
+       * support -no_pie and LD_NO_PIE
+
+
+----- Tagged ld64-97.5
+
+2009-10-27     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7341117> crash when __ustring section has zero length string
+       * stop trying to suppress tailing 0x0000 from synthesized string used to coalese utf16 strings
+       
+
+----- Tagged ld64-97.4
+
+2009-10-21     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7320293> missing thumb bit when thumb function takes address of itself
+       * move toao.atom == srcao.atom test to after fromao.atom == srcao.atom test
+       
+
+----- Tagged ld64-97.3
+
+2009-10-06     Nick Kledzik    <kledzik@apple.com>
+
+       * Add missing LittleEndian::set32() in arm::kPointerDiff
+
+2009-10-05     Nick Kledzik    <kledzik@apple.com>
+
+       <rdar://problem/7268427> ARM: handle pointer-diff to weak thumb that is overridden by non-weak ARM
+       * When parsing ARM relocations, if target is a thumb function, remove one from addend
+       * When writing out content for arm::kPointerDiff, add one if target is thumb
+       * When writing ARM_RELOC_SECTDIFF, use target offsets if they fit in function
+
+
 ----- Tagged ld64-97.2
 
 2009-09-25     Nick Kledzik    <kledzik@apple.com>
index 3a84e0a66eec5dbb7704475af3b00ffb8d955402..b6363fc8fe012972ec40050a511488a1ee4dd665 100644 (file)
@@ -308,10 +308,12 @@ This option is also called -dylib_current_version for compatibility.
 .Ss Options when creating a main executable
 .Bl -tag
 .It Fl pie
-This makes a special kind of main executable that is position independent (PIE).  On Mac OS X 10.5, the OS
-will load a PIE at a random address each time it is executed.  You cannot create a PIE from .o files compiled 
+This makes a special kind of main executable that is position independent (PIE).  On Mac OS X 10.5 and later, the OS
+the OS will load a PIE at a random address each time it is executed.  You cannot create a PIE from .o files compiled 
 with -mdynamic-no-pic.  That means the codegen is less optimal, but the address randomization adds some 
-security. 
+security. When targeting Mac OS X 10.7 or later PIE is the default for x86_64 main executables.
+.It Fl no_pie
+Do not make a position independent executable (PIE).  This is the default, except for x86_64 for 10.7 or later.
 .It Fl pagezero_size Ar size
 By default the linker creates an unreadable segment starting at address zero named __PAGEZERO.  Its existence
 will cause a bus error if a NULL pointer is dereferenced.  The argument
index 55fd5ea719b59b5fb3ff8d1908f6fc706c5fec4a..9c5493ce42417c0a7b9242cf21a165103b07f840 100644 (file)
                                INSTALL_PATH = /usr/bin;
                                OTHER_CPLUSPLUSFLAGS = "$(OTHER_CPLUSPLUSFLAGS)";
                                OTHER_LDFLAGS = (
+                                       "-Wl,-no_pie",
                                        "@$(DERIVED_FILE_DIR)/linker_opts",
                                        "-Wl,-exported_symbol,__mh_execute_header",
                                );
index 0792f51f9ccc4dce5efd95b6383cdbb2e0e4efb2..2aa7926e283301943029e3ad4e655d676ee92a07 100644 (file)
@@ -1075,9 +1075,6 @@ AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* sectio
                                        char* s = &name[13];
                                        const uint16_t* words = (uint16_t*)((char*)(owner.fHeader) + section->offset() + addr - section->addr());
                                        unsigned int wordCount = size/2;
-                                       // note, the compiler sometimes puts trailing zeros on the end of the data
-                                       if ( E::get32(words[wordCount-1]) == 0 )
-                                               --wordCount;
                                        bool needSeperator = false;
                                        for(unsigned int i=0; i < wordCount; ++i) {
                                                if ( needSeperator )
@@ -2044,28 +2041,76 @@ Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime,
                                }
                        }
                }
-               else if ( (strcmp(sect->sectname(), "__ustring") == 0) && (strcmp(sect->segname(), "__TEXT") == 0) ) {
-                       // if there is a __ustring section parse it into AnonymousAtoms based on labels
+               else if ( (strcmp(sect->sectname(), "__ustring") == 0) && (strcmp(sect->segname(), "__TEXT") == 0) && (sect->size() != 0) ) {
+                       // if there is a __ustring section parse it into atoms
                        fUTF16Section = sect;
+                       // first find all cleave points 
+                       const uint16_t* words = (uint16_t*)((char*)(fHeader) + fUTF16Section->offset());
+                       unsigned int wordCount = fUTF16Section->size()/2;
                        std::vector<pint_t> utf16Addreses;
+                       bool inString = false;
+                       for (unsigned int i=0; i < wordCount; ++i) {
+                               if ( inString ) {
+                                       if ( words[i] == 0x0000 ) {
+                                               inString = false;
+                                       }
+                               }
+                               else {
+                                       if ( words[i] == 0x0000 ) {
+                                               // skip over zero padding
+                                       }
+                                       else {
+                                               inString = true;
+                                               utf16Addreses.push_back(fUTF16Section->addr() + i*2);
+                                       }
+                               }
+                       }
+                       utf16Addreses.push_back(fUTF16Section->addr() + sect->size());
+                       // build map of symbols
+                       std::map<pint_t, const macho_nlist<P>* > symbolMap;
                        for (int i=fSymbolCount-1; i >= 0 ; --i) {
                                const macho_nlist<P>& sym = fSymbols[i];
                                if ( (sym.n_type() & N_STAB) == 0 ) {
                                        uint8_t type =  (sym.n_type() & N_TYPE);
                                        if ( type == N_SECT ) {
                                                if ( &fSectionsStart[sym.n_sect()-1] == fUTF16Section ) {
-                                                       utf16Addreses.push_back(sym.n_value());
+                                                       // rdar://problem/7429384 don't coalesce UTF16 strings unless label starts with ___utf16_string
+                                                       if ( strncmp(&fStrings[sym.n_strx()], "___utf16_string", 15) != 0 ) {
+                                                               symbolMap[sym.n_value()] = &sym;
+                                                               // <rdar://problem/7516793> if this symbol is a string of just 0x0000, it may not be in utf16Addreses
+                                                               if ( words[(sym.n_value() - sect->addr())/2] == 0x0000 ) {
+                                                                       for(typename std::vector<pint_t>::iterator sit=utf16Addreses.begin(); sit != utf16Addreses.end(); ++sit) {
+                                                                               if ( *sit == sym.n_value() ) {
+                                                                                       // already in utf16Addreses
+                                                                                       break;
+                                                                               }
+                                                                               if ( *sit > sym.n_value() ) {
+                                                                                       // need to insert
+                                                                                       utf16Addreses.insert(sit, sym.n_value());
+                                                                                       break;
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
                                                }
                                        }
                                }
                        }
-                       utf16Addreses.push_back(fUTF16Section->addr()+fUTF16Section->size());
-                       std::sort(utf16Addreses.begin(), utf16Addreses.end());
+                       // make atom for each string
                        for(int i=utf16Addreses.size()-2; i >=0 ; --i) {
                                pint_t size = utf16Addreses[i+1] - utf16Addreses[i];
-                               AnonymousAtom<A>* strAtom = new AnonymousAtom<A>(*this, fUTF16Section, utf16Addreses[i], size);
-                               fAtoms.push_back(strAtom);
-                               fAddrToAtom[utf16Addreses[i]] = strAtom;
+                               typename std::map<pint_t, const macho_nlist<P>* >::iterator pos = symbolMap.find(utf16Addreses[i]);
+                               if ( pos == symbolMap.end() ) {
+                                       AnonymousAtom<A>* strAtom = new AnonymousAtom<A>(*this, fUTF16Section, utf16Addreses[i], size);
+                                       fAtoms.push_back(strAtom);
+                                       fAddrToAtom[utf16Addreses[i]] = strAtom;
+                               }
+                               else {
+                                       SymbolAtom<A>* newAtom = new SymbolAtom<A>(*this, pos->second, fUTF16Section);
+                                       fAtoms.push_back(newAtom);
+                                       fAddrToAtom[utf16Addreses[i]] = newAtom;
+                                       newAtom->setSize(size);
+                               }
                        }
                }
        }
@@ -5322,6 +5367,9 @@ bool Reader<arm>::addRelocReference(const macho_section<arm::P>* sect,
                                if ( weakImport )
                                        kind = arm::kPointerWeakImport;
                                if ( reloc->r_extern() ) {
+                                       const macho_nlist<P>* targetSymbol = &fSymbols[reloc->r_symbolnum()];
+                                       if ( (targetSymbol->n_desc() &  N_ARM_THUMB_DEF) && (pointerValue == 1) )
+                                               pointerValue = 0;
                                        makeByNameReference(kind, srcAddr, targetName, pointerValue);
                                }
                                else {
@@ -5345,6 +5393,7 @@ bool Reader<arm>::addRelocReference(const macho_section<arm::P>* sect,
        else {
                const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
                const macho_scattered_relocation_info<P>* nextSReloc = &sreloc[1];
+               int32_t addend;
                srcAddr = sect->addr() + sreloc->r_address();
                dstAddr = sreloc->r_value();
                uint32_t betterDstAddr;
@@ -5429,13 +5478,28 @@ bool Reader<arm>::addRelocReference(const macho_section<arm::P>* sect,
                                AtomAndOffset toao   = findAtomAndOffset(dstAddr);
                                // check for addend encoded in the section content
                                pointerValue = LittleEndian::get32(*fixUpPtr);
+                               addend = pointerValue - (dstAddr - nextRelocValue);
+                               if ( toao.atom->isThumb() && (addend & 1) )
+                                       addend &= -2; // remove thumb bit 
                                if ( (dstAddr - nextRelocValue) != pointerValue ) {
-                                       if ( toao.atom == srcao.atom )
-                                               toao.offset += (pointerValue + nextRelocValue) - dstAddr;
-                                       else if ( fromao.atom == srcao.atom )
-                                               toao.offset += (pointerValue + nextRelocValue) - dstAddr;
+                                       if ( fromao.atom == srcao.atom ) {
+                                               if ( ((const macho_section<P>*)(((BaseAtom*)(srcao.atom))->getSectionRecord()))->flags() & S_ATTR_PURE_INSTRUCTIONS ) {
+                                                       int pcBaseOffset = srcao.atom->isThumb() ? 4 : 8;
+                                                       if ( addend == -pcBaseOffset ) {
+                                                               fromao.offset -= addend;
+                                                       }
+                                                       else {
+                                                               toao.offset += addend;
+                                                       }
+                                               }
+                                               else {
+                                                       toao.offset += addend;
+                                               }
+                                       }
+                                       else if ( toao.atom == srcao.atom )
+                                               toao.offset += addend;
                                        else
-                                               fromao.offset += (dstAddr - pointerValue) - nextRelocValue;
+                                               fromao.offset -= addend;
                                }
                                new Reference<arm>(arm::kPointerDiff, srcao, fromao, toao);
                                }
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; }
 
 
 
index e3ad601c4847d950b29b0ad3b0765c99b970eb4b..2710bfb572e87521811120f8b714600f991270ad 100644 (file)
@@ -76,7 +76,7 @@ public:
                                                                                fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), 
                                                                                fTraceOutputFile(NULL), fMacVersionMin(kMinMacVersionUnset), fIPhoneVersionMin(kMinIPhoneVersionUnset) {}
        enum DebugInfoStripping { kDebugInfoNone, kDebugInfoMinimal, kDebugInfoFull };
-       enum MacVersionMin { kMinMacVersionUnset, k10_1, k10_2, k10_3, k10_4, k10_5, k10_6 };
+       enum MacVersionMin { kMinMacVersionUnset, k10_1, k10_2, k10_3, k10_4, k10_5, k10_6, k10_7 };
        enum IPhoneVersionMin { kMinIPhoneVersionUnset, k2_0, k2_1, k2_2, k3_0, k3_1, k3_2, k4_0 };
 
        struct AliasPair {
index f63a123351f966e163ee92b0e5b8f496726c8333..01ce10f31027f0279b93e36e87a59072e2d929ba 100644 (file)
@@ -99,12 +99,13 @@ Options::Options(int argc, const char* argv[])
          fVerbose(false), fKeepRelocations(false), fWarnStabs(false),
          fTraceDylibSearching(false), fPause(false), fStatistics(false), fPrintOptions(false),
          fSharedRegionEligible(false), fPrintOrderFileStatistics(false),  
-         fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
+         fReadOnlyx86Stubs(false), fPositionIndependentExecutable(false), 
+         fDisablePositionIndependentExecutable(false), fMaxMinimumHeaderPad(false),
          fDeadStripDylibs(false),  fAllowTextRelocs(false), fWarnTextRelocs(false), 
          fUsingLazyDylibLinking(false), fEncryptable(true), 
          fOrderData(true), fMarkDeadStrippableDylib(false),
          fMakeClassicDyldInfo(true), fMakeCompressedDyldInfo(true), fAllowCpuSubtypeMismatches(false),
-         fUseSimplifiedDylibReExports(false), fSaveTempFiles(false)
+         fUseSimplifiedDylibReExports(false), fObjCABIVersion2POverride(false), fSaveTempFiles(false)
 {
        this->checkForClassic(argc, argv);
        this->parsePreCommandLineEnvironmentSettings();
@@ -1248,8 +1249,11 @@ void Options::setMacOSXVersionMin(const char* version)
                        case 6:
                                fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_6;
                                break;
+                       case 7:
+                               fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_7;
+                               break;
                        default:
-                               fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_6;
+                               fReaderOptions.fMacVersionMin = ObjectFile::ReaderOptions::k10_7;
                                break;
                        }
        }
@@ -2430,6 +2434,9 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-pie") == 0 ) {
                                fPositionIndependentExecutable = true;
                        }
+                       else if ( strcmp(arg, "-no_pie") == 0 ) {
+                               fDisablePositionIndependentExecutable = true;
+                       }
                        else if ( strncmp(arg, "-reexport-l", 11) == 0 ) {
                                FileInfo info = findLibrary(&arg[11], true);
                                info.options.fReExport = true;
@@ -2504,6 +2511,15 @@ void Options::parse(int argc, const char* argv[])
                        else if ( strcmp(arg, "-no_zero_fill_sections") == 0 ) {
                                fReaderOptions.fOptimizeZeroFill = false;
                        }
+                       else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
+                               const char* version = argv[++i];
+                                if ( version == NULL )
+                                       throw "-objc_abi_version missing version number";
+                               if ( strcmp(version, "2") == 0 )
+                                       fObjCABIVersion2POverride = true;
+                               else
+                                       warning("ignoring unrecognized argument (%s) to -objc_abi_version", version);
+                       }
                        else {
                                throwf("unknown option: %s", arg);
                        }
@@ -2752,6 +2768,11 @@ void Options::parsePreCommandLineEnvironmentSettings()
                fMakeCompressedDyldInfo = false;
                fMakeClassicDyldInfo = true;
        }
+       // temporary until projects adopt -no_pie
+       if ( getenv("LD_NO_PIE") != NULL ) {
+               warning("LD_NO_PIE being used to disble building a position independent executable");
+               fDisablePositionIndependentExecutable = true;
+       }
 
        sWarningsSideFilePath = getenv("LD_WARN_FILE");
 }
@@ -3179,6 +3200,12 @@ void Options::reconfigureDefaults()
        // Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
        if ( minOS(ObjectFile::ReaderOptions::k10_5, ObjectFile::ReaderOptions::k2_0) )
                fUseSimplifiedDylibReExports = true;
+               
+       // x86_64 for MacOSX 10.7 defaults to PIE
+       if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable)
+                       && (fReaderOptions.fMacVersionMin >= ObjectFile::ReaderOptions::k10_7) ) {
+               fPositionIndependentExecutable = true;
+       }
 }
 
 void Options::checkIllegalOptionCombinations()
@@ -3375,6 +3402,11 @@ void Options::checkIllegalOptionCombinations()
                if ( strncmp(name, ".objc_class_name_", 17) == 0 ) {
                        // rdar://problem/4718189 map ObjC class names to new runtime names
                        switch (fArchitecture) {
+                               case CPU_TYPE_I386:
+                                       // i386 only uses new symbols when using objc2 ABI
+                                       if ( !fObjCABIVersion2POverride )
+                                               break;
+                                       // when using objc2 ABI to same as archs below
                                case CPU_TYPE_POWERPC64:
                                case CPU_TYPE_X86_64:
                            case CPU_TYPE_ARM:
@@ -3486,6 +3518,10 @@ void Options::checkIllegalOptionCombinations()
        if ( fPositionIndependentExecutable ) {
                switch ( fOutputKind ) {
                        case Options::kDynamicExecutable:
+                               // -no_pie anywhere on command line disable PIE
+                               if ( fDisablePositionIndependentExecutable )
+                                       fPositionIndependentExecutable = false;
+                               break;
                        case Options::kPreload:
                                break;
                        case Options::kDynamicLibrary:
index 2fa364e758c065b62079c1c585bb16e489335bb6..4a06a5e0f975d279220889c3198a2665f7abb20e 100644 (file)
@@ -232,6 +232,7 @@ public:
        bool                                            markAutoDeadStripDylib() { return fMarkDeadStrippableDylib; }
        bool                                            removeEHLabels() { return fReaderOptions.fNoEHLabels; }
        bool                                            useSimplifiedDylibReExports() { return fUseSimplifiedDylibReExports; }
+       bool                                            objCABIVersion2POverride() { return fObjCABIVersion2POverride; }
 
 private:
        class CStringEquals
@@ -369,6 +370,7 @@ private:
        bool                                                            fPrintOrderFileStatistics;
        bool                                                            fReadOnlyx86Stubs;
        bool                                                            fPositionIndependentExecutable;
+       bool                                                            fDisablePositionIndependentExecutable;
        bool                                                            fMaxMinimumHeaderPad;
        bool                                                            fDeadStripDylibs;
        bool                                                            fAllowTextRelocs;
@@ -382,6 +384,7 @@ private:
        bool                                                            fNoEHLabels;
        bool                                                            fAllowCpuSubtypeMismatches;
        bool                                                            fUseSimplifiedDylibReExports;
+       bool                                                            fObjCABIVersion2POverride;
        std::vector<const char*>                        fInitialUndefines;
        NameSet                                                         fAllowedUndefined;
        NameSet                                                         fWhyLive;
index 6b6d1149d1ea7742ee2e9a69e371b9c5a4974e96..48e1e882b73055fd01851fd6a51f3dcef3ca0416 100644 (file)
@@ -87,7 +87,7 @@ class Section : public ObjectFile::Section
 {
 public:
        static Section* find(const char* sectionName, const char* segmentName, bool zeroFill, bool untrustedZeroFill, bool createIfNeeded=true);
-       static void             assignIndexes();
+       static void             assignIndexes(bool objfile);
        const char*             getName() { return fSectionName; }
 private:
                                        Section(const char* sectionName, const char* segmentName, bool zeroFill, bool untrustedZeroFill);
@@ -109,11 +109,13 @@ private:
        static NameToSection                    fgMapping;
        static std::vector<Section*>    fgSections;
        static NameToOrdinal                    fgSegmentDiscoverOrder;
+       static bool                                             fgMakingObjectFile;
 };
 
 Section::NameToSection Section::fgMapping;
 std::vector<Section*>  Section::fgSections;
 Section::NameToOrdinal Section::fgSegmentDiscoverOrder;
+bool                                   Section::fgMakingObjectFile;
 
 Section::Section(const char* sectionName, const char* segmentName, bool zeroFill, bool untrustedZeroFill)
  : fZeroFill(zeroFill), fUntrustedZeroFill(untrustedZeroFill)
@@ -254,10 +256,10 @@ int Section::Sorter::segmentOrdinal(const char* segName)
        if ( strcmp(segName, "__TEXT") == 0 )
                return 2;
        if ( strcmp(segName, "__DATA") == 0 )
-               return 3;
+               return (fgMakingObjectFile ? 6 : 3); // __DATA is last in .o files and here in FLI
        if ( strcmp(segName, "__OBJC") == 0 )
                return 4;
-       if ( strcmp(segName, "__OBJC2") == 0 )
+       if ( strcmp(segName, "__IMPORT") == 0 )
                return 5;
        if ( strcmp(segName, "__LINKEDIT") == 0 )
                return INT_MAX; // linkedit segment should always sort last
@@ -286,7 +288,7 @@ bool Section::Sorter::operator()(Section* left, Section* right)
        return left->fIndex < right->fIndex;
 }
 
-void Section::assignIndexes()
+void Section::assignIndexes(bool objfile)
 {      
        //printf("unsorted sections:\n");
        //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
@@ -294,6 +296,7 @@ void Section::assignIndexes()
        //}
 
        // sort it
+       Section::fgMakingObjectFile = objfile;
        std::sort(fgSections.begin(), fgSections.end(), Section::Sorter());
 
        // assign correct section ordering to each Section object
@@ -793,8 +796,10 @@ void Linker::adjustScope()
                                                //fprintf(stderr, "demote %s to hidden\n", name);
                                        }
                                        else if ( atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) {
-                                               // we do have an exported weak symbol, turn WEAK_DEFINES back on
-                                               fGlobalSymbolTable.setHasExternalWeakDefinitions(true);
+                                               if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableIn ) {
+                                                       // we do have an exported weak symbol, turn WEAK_DEFINES back on
+                                                       fGlobalSymbolTable.setHasExternalWeakDefinitions(true);
+                                               }
                                        }
                                }
                                else if ( scope == ObjectFile::Atom::scopeLinkageUnit ) {
@@ -2152,7 +2157,7 @@ ObjectFile::Atom* Linker::findAtom(const Options::OrderedSymbol& orderedSymbol)
 
 void Linker::sortSections()
 {
-       Section::assignIndexes();
+       Section::assignIndexes(fOptions.outputKind() == Options::kObjectFile);
 }
 
 
@@ -4124,7 +4129,8 @@ bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
                                        ++fRequireCount; // added a tentative definition means loadUndefines() needs to continue
                                        break;
                                case ObjectFile::Atom::kWeakDefinition:
-                                       fHasExternalWeakDefinitions = true;
+                                       if ( newAtom.getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableIn )
+                                               fHasExternalWeakDefinitions = true;
                                        break;
                                case ObjectFile::Atom::kExternalDefinition:
                                case ObjectFile::Atom::kExternalWeakDefinition:
index 73c31eab93b9d431614558697029fc935c477f1f..4d38f2de3b9efaa2c93ef41302ccdc89bab09b89 100644 (file)
        .globl _test_loads
 _test_loads:
     @ PIC load of a
-    ldr r0, L6
+    ldr r0, L100
 L0:
     ldr r0, [pc, r0]
 
     @ PIC load of c
-    ldr r0, L6+4
+    ldr r0, L100+4
 L1:
     ldr r0, [pc, r0]
 
        @ sorta-absolute load of a
-       ldr r0, L6+8
+       ldr r0, L100+8
        ldr r0, [r0, #0]
        
        @ sorta-absolute load of c
-       ldr r0, L6+12
+       ldr r0, L100+12
        ldr r0, [r0, #0]
 
        @ sorta-absolute load of external
-       ldr r0, L6+16
+       ldr r0, L100+16
        ldr r0, [r0, #0]
 
        @ PIC load of a + addend ??
     bx lr
 
-L6:
+L100:
     .long _a-(L0+8)
     .long _c-(L1+8)
     .long _a
@@ -88,10 +88,12 @@ _test_branches:
        @ call external + addend
        bne     _external+16
 
-_pointer_diffs:
        nop
        bl        1f
 1:     nop
+
+       .text
+_pointer_diffs:
        .long _foo-1b
        .long _foo+10-1b
        .long _test_branches-1b
@@ -99,6 +101,98 @@ _pointer_diffs:
        .long (_test_branches - _test_loads) + -2097152
        .long (_test_calls - _test_loads) + -2097152 
 
+       .text
+       .code 32
+_arm1: 
+       bx      lr
+_arm2: 
+       bx      lr
+       .weak_definition _arm3
+       .globl _arm3
+       .private_extern _arm3
+_arm3: 
+       bx      lr
+       .weak_definition _arm4
+       .globl _arm4
+       .private_extern _arm4
+_arm4: 
+       bx      lr
+
+       .code 16
+       .thumb_func _thumb1
+_thumb1: 
+       bx      lr
+       .thumb_func _thumb2
+_thumb2: 
+       bx      lr
+       .weak_definition _thumb3
+       .globl _thumb3
+       .private_extern _thumb3
+       .thumb_func _thumb3
+_thumb3: 
+       bx      lr
+       .weak_definition _thumb4
+       .globl _thumb4
+       .private_extern _thumb4
+       .thumb_func _thumb4
+_thumb4: 
+       bx      lr
+
+       .thumb_func _thumb_func_ref_test
+_thumb_func_ref_test: 
+       push    {r7, lr}
+       add     r7, sp, #0
+       ldr     r3, L6
+L2:    add     r3, pc
+       ldr     r3, L7
+L3:    add     r3, pc
+       ldr     r3, L8
+L4:    add     r3, pc
+       ldr     r3, L9
+L5:    add     r3, pc
+       pop     {r7, pc}
+       .align 2
+L6:    .long   _thumb1-(L2+4)
+L7:    .long   _thumb2-(L3+4)
+L7a:.long      _thumb3-(L3+4)
+L7b:.long      _thumb4-(L3+4)
+L8:    .long   _arm1-(L4+4)
+L9:    .long   _arm2-(L5+4)
+L9a:.long      _arm3-(L5+4)
+L9b:.long      _arm4-(L5+4)
+
+       .code 32
+       .align 2
+_arm_func_ref_test: 
+       push    {r7, lr}
+       add     r7, sp, #0
+       ldr     r3, L16
+L12:add        r3, pc
+       ldr     r3, L17
+L13:add        r3, pc
+       ldr     r3, L18
+L14:add        r3, pc
+       ldr     r3, L19
+L15:add        r3, pc
+       pop     {r7, pc}
+       .align 2
+L16:   .long   _thumb1-(L12+8)
+L17:   .long   _thumb2-(L13+8)
+L17a:  .long   _thumb3-(L3+8)
+L17b:  .long   _thumb4-(L3+8)
+L18:   .long   _arm1-(L14+8)
+L19:   .long   _arm2-(L15+8)
+L19a:  .long   _arm3-(L15+8)
+L19b:  .long   _arm4-(L15+8)
+
+       .section        __DATA,__const
+_myVTable:
+               .long   _thumb1
+               .long   _thumb2
+               .long   _thumb3
+               .long   _arm1
+               .long   _arm2
+       
 #endif
 
 #if __ppc__ || __ppc64__
@@ -410,6 +504,8 @@ Llocal2:
        .long _test_branches - .
        .long _test_branches - . + 8
        .long _test_branches - . - 8
+       .long 0
+       .long 0
 #if __ppc64__
        .quad Llocal2-_test_branches
 #endif
diff --git a/unit-tests/test-cases/tentative-to-real-r/Makefile b/unit-tests/test-cases/tentative-to-real-r/Makefile
new file mode 100644 (file)
index 0000000..df0ae07
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2010 Apple Inc. All rights reserved.
+#
+# @APPLE_LICENSE_HEADER_START@
+#
+# This file contains Original Code and/or Modifications of Original Code
+# as defined in and that are subject to the Apple Public Source License
+# Version 2.0 (the 'License'). You may not use this file except in
+# compliance with the License. Please obtain a copy of the License at
+# http://www.opensource.apple.com/apsl/ and read it before using this
+# file.
+#
+# The Original Code and all software distributed under the License are
+# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+# Please see the License for the specific language governing rights and
+# limitations under the License.
+#
+# @APPLE_LICENSE_HEADER_END@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+#
+# Test that references to commons survive -r -d
+#
+
+run: all
+
+all:
+       ${CC} ${CCFLAGS} test.c -c -o test.${ARCH}.o
+       ${OBJECTDUMP} -no_content test.${ARCH}.o | grep -v kind: | grep -v section: > test.${ARCH}.o.dump
+
+       ${LD} -arch ${ARCH} -r -d test.${ARCH}.o -o test-r-d.${ARCH}.o
+       ${OBJECTDUMP} -no_content test-r-d.${ARCH}.o | grep -v kind: | grep -v section: > test-r-d.${ARCH}.o.dump
+       
+       ${PASS_IFF} diff test.${ARCH}.o.dump  test-r-d.${ARCH}.o.dump
+       
+
+clean:
+       rm -rf *.o *.dump
+       
diff --git a/unit-tests/test-cases/tentative-to-real-r/test.c b/unit-tests/test-cases/tentative-to-real-r/test.c
new file mode 100644 (file)
index 0000000..27d22e7
--- /dev/null
@@ -0,0 +1,13 @@
+
+void foo() {}
+
+int a;
+int b;
+int c;
+
+
+
+int* pa = &a;
+int* pb = &b;
+int* pc = &c;
+
index 71d5db6d43ef90ac023d6fad329bef9882ccea61..e813f498bf1dded9bb43270fc21b9645a362038d 100644 (file)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008 Apple Inc. All rights reserved.
+# Copyright (c) 2008-2009 Apple Inc. All rights reserved.
 #
 # @APPLE_LICENSE_HEADER_START@
 # 
@@ -40,7 +40,9 @@ all:
        otool -hv main | grep WEAK_DEFINES | ${FAIL_IF_STDIN}
        ${CC} ${CCFLAGS} main.c -o main -Wl,-exported_symbol,_my_weak
        otool -hv main | grep WEAK_DEFINES | ${FAIL_IF_EMPTY}
+       ${CC} ${CCFLAGS} main-strip-weak.c -o main-strip-weak
+       otool -hv main-strip-weak | grep WEAK_DEFINES | ${FAIL_IF_STDIN}
        ${PASS_IFF_GOOD_MACHO} main
        
 clean:
-       rm main
+       rm main main-strip-weak
\ No newline at end of file
diff --git a/unit-tests/test-cases/weak-def-flag/main-strip-weak.c b/unit-tests/test-cases/weak-def-flag/main-strip-weak.c
new file mode 100644 (file)
index 0000000..cb40513
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+// the 'l' prefix makes this an auto-strip symbol
+void my_auto_strip_weak() __asm ( "lautostrip" );
+
+void __attribute__((weak)) my_auto_strip_weak()
+{
+
+}
+
+int main()
+{
+       my_auto_strip_weak();
+       return 0;
+}
+