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@
25 #ifndef __OUTPUT_FILE_H__
26 #define __OUTPUT_FILE_H__
29 #include <sys/types.h>
32 #include <sys/sysctl.h>
37 #include <mach/mach_time.h>
38 #include <mach/vm_statistics.h>
39 #include <mach/mach_init.h>
40 #include <mach/mach_host.h>
42 #include <mach-o/dyld.h>
55 OutputFile(const Options
& opts
);
58 // iterates all atoms in initial files
59 void write(ld::Internal
&);
60 bool findSegment(ld::Internal
& state
, uint64_t addr
, uint64_t* start
, uint64_t* end
, uint32_t* index
);
61 void setLazyBindingInfoOffset(uint64_t lpAddress
, uint32_t lpInfoOffset
);
62 uint32_t dylibCount();
63 const ld::dylib::File
* dylibByOrdinal(unsigned int ordinal
);
64 uint32_t dylibToOrdinal(const ld::dylib::File
*);
65 uint32_t encryptedTextStartOffset() { return _encryptedTEXTstartOffset
; }
66 uint32_t encryptedTextEndOffset() { return _encryptedTEXTendOffset
; }
67 int compressedOrdinalForAtom(const ld::Atom
* target
);
68 uint64_t fileSize() const { return _fileSize
; }
71 bool usesWeakExternalSymbols
;
72 bool overridesWeakExternalSymbols
;
73 bool _noReExportedDylibs
;
76 ld::Internal::FinalSection
* headerAndLoadCommandsSection
;
77 ld::Internal::FinalSection
* rebaseSection
;
78 ld::Internal::FinalSection
* bindingSection
;
79 ld::Internal::FinalSection
* weakBindingSection
;
80 ld::Internal::FinalSection
* lazyBindingSection
;
81 ld::Internal::FinalSection
* exportSection
;
82 ld::Internal::FinalSection
* splitSegInfoSection
;
83 ld::Internal::FinalSection
* functionStartsSection
;
84 ld::Internal::FinalSection
* dataInCodeSection
;
85 ld::Internal::FinalSection
* optimizationHintsSection
;
86 ld::Internal::FinalSection
* symbolTableSection
;
87 ld::Internal::FinalSection
* stringPoolSection
;
88 ld::Internal::FinalSection
* localRelocationsSection
;
89 ld::Internal::FinalSection
* externalRelocationsSection
;
90 ld::Internal::FinalSection
* sectionRelocationsSection
;
91 ld::Internal::FinalSection
* indirectSymbolTableSection
;
94 RebaseInfo(uint8_t t
, uint64_t addr
) : _type(t
), _address(addr
) {}
98 int operator<(const RebaseInfo
& rhs
) const {
99 // sort by type, then address
100 if ( this->_type
!= rhs
._type
)
101 return (this->_type
< rhs
._type
);
102 return (this->_address
< rhs
._address
);
107 BindingInfo(uint8_t t
, int ord
, const char* sym
, bool weak_import
, uint64_t addr
, int64_t add
)
108 : _type(t
), _flags(weak_import
? BIND_SYMBOL_FLAGS_WEAK_IMPORT
: 0 ), _libraryOrdinal(ord
),
109 _symbolName(sym
), _address(addr
), _addend(add
) {}
110 BindingInfo(uint8_t t
, const char* sym
, bool non_weak_definition
, uint64_t addr
, int64_t add
)
111 : _type(t
), _flags(non_weak_definition
? BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION
: 0 ),
112 _libraryOrdinal(0), _symbolName(sym
), _address(addr
), _addend(add
) {}
116 const char* _symbolName
;
121 int operator<(const BindingInfo
& rhs
) const {
122 // sort by library, symbol, type, then address
123 if ( this->_libraryOrdinal
!= rhs
._libraryOrdinal
)
124 return (this->_libraryOrdinal
< rhs
._libraryOrdinal
);
125 if ( this->_symbolName
!= rhs
._symbolName
)
126 return ( strcmp(this->_symbolName
, rhs
._symbolName
) < 0 );
127 if ( this->_type
!= rhs
._type
)
128 return (this->_type
< rhs
._type
);
129 return (this->_address
< rhs
._address
);
133 struct SplitSegInfoEntry
{
134 SplitSegInfoEntry(uint64_t a
, ld::Fixup::Kind k
, uint32_t e
=0)
135 : fixupAddress(a
), kind(k
), extra(e
) {}
136 uint64_t fixupAddress
;
137 ld::Fixup::Kind kind
;
141 struct SplitSegInfoV2Entry
{
142 SplitSegInfoV2Entry(uint8_t fi
, uint64_t fo
, uint8_t ti
, uint64_t to
, uint8_t k
)
143 : fixupSectionOffset(fo
), targetSectionOffset(to
), fixupSectionIndex(fi
), targetSectionIndex(ti
), referenceKind(k
) {}
144 uint64_t fixupSectionOffset
;
145 uint64_t targetSectionOffset
;
146 uint8_t fixupSectionIndex
;
147 uint8_t targetSectionIndex
;
148 uint8_t referenceKind
;
150 static void dumpAtomsBySection(ld::Internal
& state
, bool);
153 void writeAtoms(ld::Internal
& state
, uint8_t* wholeBuffer
);
154 void computeContentUUID(ld::Internal
& state
, uint8_t* wholeBuffer
);
155 void buildDylibOrdinalMapping(ld::Internal
&);
156 bool hasOrdinalForInstallPath(const char* path
, int* ordinal
);
157 void addLoadCommands(ld::Internal
& state
);
158 void addLinkEdit(ld::Internal
& state
);
159 void addPreloadLinkEdit(ld::Internal
& state
);
160 void generateLinkEditInfo(ld::Internal
& state
);
161 void buildSymbolTable(ld::Internal
& state
);
162 void writeOutputFile(ld::Internal
& state
);
163 void addSectionRelocs(ld::Internal
& state
, ld::Internal::FinalSection
* sect
,
164 const ld::Atom
* atom
, ld::Fixup
* fixupWithTarget
,
165 ld::Fixup
* fixupWithMinusTarget
, ld::Fixup
* fixupWithAddend
,
166 ld::Fixup
* fixupWithStore
,
167 const ld::Atom
* target
, const ld::Atom
* minusTarget
,
168 uint64_t targetAddend
, uint64_t minusTargetAddend
);
169 void addDyldInfo(ld::Internal
& state
, ld::Internal::FinalSection
* sect
,
170 const ld::Atom
* atom
, ld::Fixup
* fixupWithTarget
,
171 ld::Fixup
* fixupWithMinusTarget
, ld::Fixup
* fixupWithStore
,
172 const ld::Atom
* target
, const ld::Atom
* minusTarget
,
173 uint64_t targetAddend
, uint64_t minusTargetAddend
);
174 void addClassicRelocs(ld::Internal
& state
, ld::Internal::FinalSection
* sect
,
175 const ld::Atom
* atom
, ld::Fixup
* fixupWithTarget
,
176 ld::Fixup
* fixupWithMinusTarget
, ld::Fixup
* fixupWithStore
,
177 const ld::Atom
* target
, const ld::Atom
* minusTarget
,
178 uint64_t targetAddend
, uint64_t minusTargetAddend
);
179 bool useExternalSectionReloc(const ld::Atom
* atom
, const ld::Atom
* target
,
180 ld::Fixup
* fixupWithTarget
);
181 bool useSectionRelocAddend(ld::Fixup
* fixupWithTarget
);
182 uint64_t pageAlign(uint64_t addr
);
183 uint64_t pageAlign(uint64_t addr
, uint64_t pageSize
);
184 void setLoadCommandsPadding(ld::Internal
& state
);
185 void assignAtomAddresses(ld::Internal
& state
);
186 void addRebaseInfo(const ld::Atom
* atom
, const ld::Fixup
* fixup
, const ld::Atom
* target
);
187 void makeRebasingInfo(ld::Internal
& state
);
188 void makeBindingInfo(ld::Internal
& state
);
189 void updateLINKEDITAddresses(ld::Internal
& state
);
190 void applyFixUps(ld::Internal
& state
, uint64_t mhAddress
, const ld::Atom
* atom
, uint8_t* buffer
);
191 uint64_t addressOf(const ld::Internal
& state
, const ld::Fixup
* fixup
, const ld::Atom
** target
);
192 uint64_t addressAndTarget(const ld::Internal
& state
, const ld::Fixup
* fixup
, const ld::Atom
** target
);
193 bool targetIsThumb(ld::Internal
& state
, const ld::Fixup
* fixup
);
194 uint32_t lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress
);
195 void copyNoOps(uint8_t* from
, uint8_t* to
, bool thumb
);
196 bool isPointerToTarget(ld::Fixup::Kind kind
);
197 bool isPointerFromTarget(ld::Fixup::Kind kind
);
198 bool isPcRelStore(ld::Fixup::Kind kind
);
199 bool isStore(ld::Fixup::Kind kind
);
200 bool storeAddendOnly(const ld::Atom
* inAtom
, const ld::Atom
* target
, bool pcRel
=false);
201 bool setsTarget(ld::Fixup::Kind kind
);
202 void addFixupOutInfo(ld::Internal
& state
);
203 void makeRelocations(ld::Internal
& state
);
204 void makeSectionRelocations(ld::Internal
& state
);
205 void makeDyldInfo(ld::Internal
& state
);
206 void makeSplitSegInfo(ld::Internal
& state
);
207 void makeSplitSegInfoV2(ld::Internal
& state
);
208 void writeMapFile(ld::Internal
& state
);
209 void writeJSONEntry(ld::Internal
& state
);
210 uint64_t lookBackAddend(ld::Fixup::iterator fit
);
211 bool takesNoDiskSpace(const ld::Section
* sect
);
212 bool hasZeroForFileOffset(const ld::Section
* sect
);
214 void printSectionLayout(ld::Internal
& state
);
216 bool checkThumbBranch22Displacement(int64_t displacement
);
217 bool checkArmBranch24Displacement(int64_t displacement
);
219 void rangeCheck8(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
220 const ld::Fixup
* fixup
);
221 void rangeCheck16(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
222 const ld::Fixup
* fixup
);
223 void rangeCheckBranch32(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
224 const ld::Fixup
* fixup
);
225 void rangeCheckAbsolute32(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
226 const ld::Fixup
* fixup
);
227 void rangeCheckRIP32(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
228 const ld::Fixup
* fixup
);
229 void rangeCheckARM12(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
230 const ld::Fixup
* fixup
);
231 void rangeCheckARMBranch24(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
232 const ld::Fixup
* fixup
);
233 void rangeCheckThumbBranch22(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
234 const ld::Fixup
* fixup
);
235 void rangeCheckARM64Branch26(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
236 const ld::Fixup
* fixup
);
237 void rangeCheckARM64Page21(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,
238 const ld::Fixup
* fixup
);
241 uint64_t sectionOffsetOf(const ld::Internal
& state
, const ld::Fixup
* fixup
);
242 uint64_t tlvTemplateOffsetOf(const ld::Internal
& state
, const ld::Fixup
* fixup
);
243 void synthesizeDebugNotes(ld::Internal
& state
);
244 const char* assureFullPath(const char* path
);
245 void noteTextReloc(const ld::Atom
* atom
, const ld::Atom
* target
);
248 struct InstructionInfo
{
249 uint32_t offsetInAtom
;
250 const ld::Fixup
* fixup
;
251 const ld::Atom
* target
;
252 uint64_t targetAddress
;
253 uint8_t* instructionContent
;
254 uint64_t instructionAddress
;
255 uint32_t instruction
;
258 void setInfo(ld::Internal
& state
, const ld::Atom
* atom
, uint8_t* buffer
, const std::map
<uint32_t, const Fixup
*>& usedHints
,
259 uint32_t offsetInAtom
, uint32_t delta
, InstructionInfo
* info
);
261 static uint16_t get16LE(uint8_t* loc
);
262 static void set16LE(uint8_t* loc
, uint16_t value
);
263 static uint32_t get32LE(uint8_t* loc
);
264 static void set32LE(uint8_t* loc
, uint32_t value
);
265 static uint64_t get64LE(uint8_t* loc
);
266 static void set64LE(uint8_t* loc
, uint64_t value
);
268 static uint16_t get16BE(uint8_t* loc
);
269 static void set16BE(uint8_t* loc
, uint16_t value
);
270 static uint32_t get32BE(uint8_t* loc
);
271 static void set32BE(uint8_t* loc
, uint32_t value
);
272 static uint64_t get64BE(uint8_t* loc
);
273 static void set64BE(uint8_t* loc
, uint64_t value
);
277 const Options
& _options
;
278 std::map
<const ld::dylib::File
*, int> _dylibToOrdinal
;
279 std::vector
<const ld::dylib::File
*> _dylibsToLoad
;
280 std::vector
<const char*> _dylibOrdinalPaths
;
281 const bool _hasDyldInfo
;
282 const bool _hasSymbolTable
;
283 const bool _hasSectionRelocations
;
284 const bool _hasSplitSegInfo
;
285 const bool _hasFunctionStartsInfo
;
286 const bool _hasDataInCodeInfo
;
287 bool _hasDynamicSymbolTable
;
288 bool _hasLocalRelocations
;
289 bool _hasExternalRelocations
;
290 bool _hasOptimizationHints
;
292 std::map
<uint64_t, uint32_t> _lazyPointerAddressToInfoOffset
;
293 uint32_t _encryptedTEXTstartOffset
;
294 uint32_t _encryptedTEXTendOffset
;
296 std::vector
<const ld::Atom
*> _localAtoms
;
297 std::vector
<const ld::Atom
*> _exportedAtoms
;
298 std::vector
<const ld::Atom
*> _importedAtoms
;
299 uint32_t _localSymbolsStartIndex
;
300 uint32_t _localSymbolsCount
;
301 uint32_t _globalSymbolsStartIndex
;
302 uint32_t _globalSymbolsCount
;
303 uint32_t _importSymbolsStartIndex
;
304 uint32_t _importSymbolsCount
;
305 std::map
<const ld::Atom
*, uint32_t> _atomToSymbolIndex
;
306 std::vector
<RebaseInfo
> _rebaseInfo
;
307 std::vector
<BindingInfo
> _bindingInfo
;
308 std::vector
<BindingInfo
> _lazyBindingInfo
;
309 std::vector
<BindingInfo
> _weakBindingInfo
;
310 std::vector
<SplitSegInfoEntry
> _splitSegInfos
;
311 std::vector
<SplitSegInfoV2Entry
> _splitSegV2Infos
;
312 class HeaderAndLoadCommandsAbtract
* _headersAndLoadCommandAtom
;
313 class RelocationsAtomAbstract
* _sectionsRelocationsAtom
;
314 class RelocationsAtomAbstract
* _localRelocsAtom
;
315 class RelocationsAtomAbstract
* _externalRelocsAtom
;
316 class ClassicLinkEditAtom
* _symbolTableAtom
;
317 class ClassicLinkEditAtom
* _indirectSymbolTableAtom
;
318 class StringPoolAtom
* _stringPoolAtom
;
319 class LinkEditAtom
* _rebasingInfoAtom
;
320 class LinkEditAtom
* _bindingInfoAtom
;
321 class LinkEditAtom
* _lazyBindingInfoAtom
;
322 class LinkEditAtom
* _weakBindingInfoAtom
;
323 class LinkEditAtom
* _exportInfoAtom
;
324 class LinkEditAtom
* _splitSegInfoAtom
;
325 class LinkEditAtom
* _functionStartsAtom
;
326 class LinkEditAtom
* _dataInCodeAtom
;
327 class LinkEditAtom
* _optimizationHintsAtom
;
333 #endif // __OUTPUT_FILE_H__