1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2010 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
30 #include <mach/machine.h>
32 #include <algorithm> // std::remove_if
47 bool operator()(ld::dylib::File
* dylib
) const {
48 return dylib
->willRemoved();
53 void doPass(const Options
& opts
, ld::Internal
& state
)
55 // const bool log = false;
57 // clear "willRemoved" bit on all dylibs
58 for (std::vector
<ld::dylib::File
*>::iterator it
= state
.dylibs
.begin(); it
!= state
.dylibs
.end(); ++it
) {
59 ld::dylib::File
* aDylib
= *it
;
60 aDylib
->setWillBeRemoved(false);
62 for (std::vector
<ld::dylib::File
*>::iterator it
= state
.dylibs
.begin(); it
!= state
.dylibs
.end(); ++it
) {
63 ld::dylib::File
* aDylib
= *it
;
64 // set "willRemoved" bit on implicit dylibs that did not provide any exports
65 if ( aDylib
->implicitlyLinked() && !aDylib
->explicitlyLinked() && !aDylib
->providedExportAtom() )
66 aDylib
->setWillBeRemoved(true);
67 // set "willRemoved" bit on dead strippable explicit dylibs that did not provide any exports
68 if ( aDylib
->explicitlyLinked() && aDylib
->deadStrippable() && !aDylib
->providedExportAtom() )
69 aDylib
->setWillBeRemoved(true);
70 // set "willRemoved" bit on any unused explicit when -dead_strip_dylibs is used
71 if ( opts
.deadStripDylibs() && !aDylib
->providedExportAtom() )
72 aDylib
->setWillBeRemoved(true);
74 // remove unused dylibs
75 state
.dylibs
.erase(std::remove_if(state
.dylibs
.begin(), state
.dylibs
.end(), WillBeUsed()), state
.dylibs
.end());
78 // <rdar://problem/9441273> automatically weak-import dylibs when all symbols from it are weak-imported
79 for (std::vector
<ld::Internal::FinalSection
*>::iterator sit
=state
.sections
.begin(); sit
!= state
.sections
.end(); ++sit
) {
80 ld::Internal::FinalSection
* sect
= *sit
;
81 for (std::vector
<const ld::Atom
*>::iterator ait
=sect
->atoms
.begin(); ait
!= sect
->atoms
.end(); ++ait
) {
82 const ld::Atom
* atom
= *ait
;
83 const ld::Atom
* target
= NULL
;
84 bool targetIsWeakImport
= false;
85 for (ld::Fixup::iterator fit
= atom
->fixupsBegin(), end
=atom
->fixupsEnd(); fit
!= end
; ++fit
) {
86 if ( fit
->firstInCluster() )
88 switch ( fit
->binding
) {
89 case ld::Fixup::bindingsIndirectlyBound
:
90 target
= state
.indirectBindingTable
[fit
->u
.bindingIndex
];
91 targetIsWeakImport
= fit
->weakImport
;
93 case ld::Fixup::bindingDirectlyBound
:
94 target
= fit
->u
.target
;
95 targetIsWeakImport
= fit
->weakImport
;
100 if ( (target
!= NULL
) && (target
->definition() == ld::Atom::definitionProxy
) ) {
101 if ( targetIsWeakImport
&& !opts
.allowWeakImports() )
102 throwf("weak import of symbol '%s' not supported because of option: -no_weak_imports", target
->name());
103 ld::Atom::WeakImportState curWI
= target
->weakImportState();
104 if ( curWI
== ld::Atom::weakImportUnset
) {
105 // first use of this proxy, set weak-import based on this usage
106 (const_cast<ld::Atom
*>(target
))->setWeakImportState(targetIsWeakImport
);
109 // proxy already has weak-importness set, check for weakness mismatch
110 bool curIsWeakImport
= (curWI
== ld::Atom::weakImportTrue
);
111 if ( curIsWeakImport
!= targetIsWeakImport
) {
113 switch ( opts
.weakReferenceMismatchTreatment() ) {
114 case Options::kWeakReferenceMismatchError
:
115 throwf("mismatching weak references for symbol: %s", target
->name());
116 case Options::kWeakReferenceMismatchWeak
:
117 (const_cast<ld::Atom
*>(target
))->setWeakImportState(true);
119 case Options::kWeakReferenceMismatchNonWeak
:
120 (const_cast<ld::Atom
*>(target
))->setWeakImportState(false);
133 } // namespace dylibs
134 } // namespace passes