]>
git.saurik.com Git - apple/ld64.git/blob - src/ld/passes/huge.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2009 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>
45 bool operator()(const ld::Atom
* atom
) const {
46 return (atom
== NULL
);
50 class DataPadAtom
: public ld::Atom
{
52 DataPadAtom(ld::Internal
& state
)
53 : ld::Atom(_s_section
, ld::Atom::definitionRegular
, ld::Atom::combineNever
,
54 ld::Atom::scopeTranslationUnit
, ld::Atom::typeUnclassified
,
55 symbolTableNotIn
, false, false, false, ld::Atom::Alignment(3))
56 { state
.addAtom(*this); }
59 virtual const ld::File
* file() const { return NULL
; }
60 virtual const char* name() const { return "padding"; }
61 virtual uint64_t size() const { return 8; }
62 virtual uint64_t objectAddress() const { return 0; }
63 virtual void copyRawContent(uint8_t buffer
[]) const { }
66 virtual ~DataPadAtom() {}
68 static ld::Section _s_section
;
71 ld::Section
DataPadAtom::_s_section("__DATA", "__data", ld::Section::typeUnclassified
);
74 void doPass(const Options
& opts
, ld::Internal
& state
)
76 const bool log
= false;
78 // <rdar://problem/26015603> add __data section if __DATA segment was gutted by dirty data removal
79 if ( (opts
.outputKind() == Options::kDynamicLibrary
) && opts
.useDataConstSegment() && opts
.hasDataSymbolMoves() ) {
80 uint64_t dataAtomsSize
= 0;
81 bool foundSegmentDATA_DIRTY
= false;
82 for (ld::Internal::FinalSection
* sect
: state
.sections
) {
83 if ( strcmp(sect
->segmentName(), "__DATA") == 0 ) {
84 for (const ld::Atom
* atom
: sect
->atoms
) {
85 dataAtomsSize
+= atom
->size();
88 else if ( strcmp(sect
->segmentName(), "__DATA_DIRTY") == 0 ) {
89 foundSegmentDATA_DIRTY
= true;
92 if ( foundSegmentDATA_DIRTY
&& (dataAtomsSize
== 0) ) {
93 new DataPadAtom(state
);
97 // only make make __huge section in final linked images
98 if ( opts
.outputKind() == Options::kObjectFile
)
101 // only make make __huge section for x86_64
102 if ( opts
.architecture() != CPU_TYPE_X86_64
)
105 // only needed if some (non-linkedit) atoms have an addresss >2GB from base address
106 state
.usingHugeSections
= false;
107 uint64_t address
= 0;
108 for (std::vector
<ld::Internal::FinalSection
*>::iterator sit
=state
.sections
.begin(); sit
!= state
.sections
.end(); ++sit
) {
109 ld::Internal::FinalSection
* sect
= *sit
;
110 if ( sect
->type() == ld::Section::typePageZero
)
112 if ( sect
->type() == ld::Section::typeStack
)
114 for (std::vector
<const ld::Atom
*>::iterator ait
=sect
->atoms
.begin(); ait
!= sect
->atoms
.end(); ++ait
) {
115 const ld::Atom
* atom
= *ait
;
116 if ( (address
> 0x7FFFFFFFLL
) && !sect
->isSectionHidden() ) {
117 state
.usingHugeSections
= true;
118 if (log
) fprintf(stderr
, "atom: %s is >2GB (0x%09llX), so enabling huge mode\n", atom
->name(), address
);
121 address
+= atom
->size();
123 if ( state
.usingHugeSections
)
126 if ( !state
.usingHugeSections
)
129 // move all zero fill atoms that >1MB in size to a new __huge section
130 ld::Internal::FinalSection
* hugeSection
= state
.getFinalSection(*new ld::Section("__DATA", "__huge", ld::Section::typeZeroFill
));
131 for (std::vector
<ld::Internal::FinalSection
*>::iterator sit
=state
.sections
.begin(); sit
!= state
.sections
.end(); ++sit
) {
132 ld::Internal::FinalSection
* sect
= *sit
;
133 if ( sect
== hugeSection
)
135 if ( sect
->type() == ld::Section::typeZeroFill
) {
136 bool movedSome
= false;
137 for (std::vector
<const ld::Atom
*>::iterator ait
=sect
->atoms
.begin(); ait
!= sect
->atoms
.end(); ++ait
) {
138 const ld::Atom
* atom
= *ait
;
139 if ( atom
->size() > 1024*1024 ) {
140 hugeSection
->atoms
.push_back(atom
);
141 state
.atomToSection
[atom
] = hugeSection
;
142 if (log
) fprintf(stderr
, "moved to __huge: %s, size=%llu\n", atom
->name(), atom
->size());
143 *ait
= NULL
; // change atom to NULL for later bulk removal
148 sect
->atoms
.erase(std::remove_if(sect
->atoms
.begin(), sect
->atoms
.end(), NullAtom()), sect
->atoms
.end());
157 } // namespace passes