]> git.saurik.com Git - apple/ld64.git/blame - src/ld/OutputFile.h
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / OutputFile.h
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 *
3 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#ifndef __OUTPUT_FILE_H__
26#define __OUTPUT_FILE_H__
27
28#include <stdlib.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/mman.h>
32#include <sys/sysctl.h>
33#include <fcntl.h>
34#include <errno.h>
35#include <limits.h>
36#include <unistd.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>
41#include <dlfcn.h>
42#include <mach-o/dyld.h>
43
44#include <vector>
45
46#include "Options.h"
47#include "ld.hpp"
48
49namespace ld {
50namespace tool {
51
52class OutputFile
53{
54public:
55 OutputFile(const Options& opts);
56
57
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);
b2fa67a8 68 uint64_t fileSize() const { return _fileSize; }
a645023d
A
69
70
a645023d
A
71 bool usesWeakExternalSymbols;
72 bool overridesWeakExternalSymbols;
73 bool _noReExportedDylibs;
a645023d 74 bool pieDisabled;
ebf6f434 75 bool hasDataInCode;
a645023d
A
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;
ebf6f434 84 ld::Internal::FinalSection* dataInCodeSection;
9543cb2f 85 ld::Internal::FinalSection* optimizationHintsSection;
a645023d
A
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;
e456bf10 92 ld::Internal::FinalSection* threadedPageStartsSection;
a645023d
A
93
94 struct RebaseInfo {
95 RebaseInfo(uint8_t t, uint64_t addr) : _type(t), _address(addr) {}
96 uint8_t _type;
97 uint64_t _address;
98 // for sorting
99 int operator<(const RebaseInfo& rhs) const {
100 // sort by type, then address
101 if ( this->_type != rhs._type )
102 return (this->_type < rhs._type );
103 return (this->_address < rhs._address );
104 }
105 };
106
107 struct BindingInfo {
108 BindingInfo(uint8_t t, int ord, const char* sym, bool weak_import, uint64_t addr, int64_t add)
e456bf10
A
109 : _type(t), _flags(weak_import ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0 ),
110 _threadedBindOrdinal(0), _libraryOrdinal(ord),
a645023d
A
111 _symbolName(sym), _address(addr), _addend(add) {}
112 BindingInfo(uint8_t t, const char* sym, bool non_weak_definition, uint64_t addr, int64_t add)
113 : _type(t), _flags(non_weak_definition ? BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION : 0 ),
e456bf10 114 _threadedBindOrdinal(0), _libraryOrdinal(0), _symbolName(sym), _address(addr), _addend(add) {}
a645023d
A
115 uint8_t _type;
116 uint8_t _flags;
e456bf10 117 uint16_t _threadedBindOrdinal;
a645023d
A
118 int _libraryOrdinal;
119 const char* _symbolName;
120 uint64_t _address;
121 int64_t _addend;
122
123 // for sorting
124 int operator<(const BindingInfo& rhs) const {
125 // sort by library, symbol, type, then address
126 if ( this->_libraryOrdinal != rhs._libraryOrdinal )
127 return (this->_libraryOrdinal < rhs._libraryOrdinal );
128 if ( this->_symbolName != rhs._symbolName )
129 return ( strcmp(this->_symbolName, rhs._symbolName) < 0 );
130 if ( this->_type != rhs._type )
131 return (this->_type < rhs._type );
132 return (this->_address < rhs._address );
133 }
134 };
135
136 struct SplitSegInfoEntry {
eaf282aa
A
137 SplitSegInfoEntry(uint64_t a, ld::Fixup::Kind k, uint32_t e=0)
138 : fixupAddress(a), kind(k), extra(e) {}
139 uint64_t fixupAddress;
a645023d 140 ld::Fixup::Kind kind;
afe874b1 141 uint32_t extra;
a645023d
A
142 };
143
eaf282aa
A
144 struct SplitSegInfoV2Entry {
145 SplitSegInfoV2Entry(uint8_t fi, uint64_t fo, uint8_t ti, uint64_t to, uint8_t k)
146 : fixupSectionOffset(fo), targetSectionOffset(to), fixupSectionIndex(fi), targetSectionIndex(ti), referenceKind(k) {}
147 uint64_t fixupSectionOffset;
148 uint64_t targetSectionOffset;
149 uint8_t fixupSectionIndex;
150 uint8_t targetSectionIndex;
151 uint8_t referenceKind;
152 };
ec29ba20 153 static void dumpAtomsBySection(ld::Internal& state, bool);
eaf282aa 154
a645023d 155private:
ebf6f434
A
156 void writeAtoms(ld::Internal& state, uint8_t* wholeBuffer);
157 void computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer);
a645023d
A
158 void buildDylibOrdinalMapping(ld::Internal&);
159 bool hasOrdinalForInstallPath(const char* path, int* ordinal);
160 void addLoadCommands(ld::Internal& state);
161 void addLinkEdit(ld::Internal& state);
162 void addPreloadLinkEdit(ld::Internal& state);
163 void generateLinkEditInfo(ld::Internal& state);
164 void buildSymbolTable(ld::Internal& state);
165 void writeOutputFile(ld::Internal& state);
a645023d
A
166 void addSectionRelocs(ld::Internal& state, ld::Internal::FinalSection* sect,
167 const ld::Atom* atom, ld::Fixup* fixupWithTarget,
f80fe69f
A
168 ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithAddend,
169 ld::Fixup* fixupWithStore,
e456bf10
A
170#if SUPPORT_ARCH_arm64e
171 ld::Fixup* fixupWithAuthData,
172#endif
a645023d
A
173 const ld::Atom* target, const ld::Atom* minusTarget,
174 uint64_t targetAddend, uint64_t minusTargetAddend);
175 void addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* sect,
176 const ld::Atom* atom, ld::Fixup* fixupWithTarget,
177 ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
178 const ld::Atom* target, const ld::Atom* minusTarget,
179 uint64_t targetAddend, uint64_t minusTargetAddend);
e456bf10
A
180 void addThreadedRebaseInfo(ld::Internal& state, ld::Internal::FinalSection* sect,
181 const ld::Atom* atom, ld::Fixup* fixupWithTarget,
182 ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
183 const ld::Atom* target, const ld::Atom* minusTarget,
184 uint64_t targetAddend, uint64_t minusTargetAddend);
a645023d
A
185 void addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect,
186 const ld::Atom* atom, ld::Fixup* fixupWithTarget,
187 ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
188 const ld::Atom* target, const ld::Atom* minusTarget,
189 uint64_t targetAddend, uint64_t minusTargetAddend);
190 bool useExternalSectionReloc(const ld::Atom* atom, const ld::Atom* target,
191 ld::Fixup* fixupWithTarget);
f80fe69f 192 bool useSectionRelocAddend(ld::Fixup* fixupWithTarget);
a645023d
A
193 uint64_t pageAlign(uint64_t addr);
194 uint64_t pageAlign(uint64_t addr, uint64_t pageSize);
195 void setLoadCommandsPadding(ld::Internal& state);
196 void assignAtomAddresses(ld::Internal& state);
197 void addRebaseInfo(const ld::Atom* atom, const ld::Fixup* fixup, const ld::Atom* target);
198 void makeRebasingInfo(ld::Internal& state);
199 void makeBindingInfo(ld::Internal& state);
200 void updateLINKEDITAddresses(ld::Internal& state);
201 void applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer);
202 uint64_t addressOf(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target);
0a8dc3df 203 uint64_t addressAndTarget(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target);
a645023d
A
204 bool targetIsThumb(ld::Internal& state, const ld::Fixup* fixup);
205 uint32_t lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress);
afe874b1 206 void copyNoOps(uint8_t* from, uint8_t* to, bool thumb);
a645023d
A
207 bool isPointerToTarget(ld::Fixup::Kind kind);
208 bool isPointerFromTarget(ld::Fixup::Kind kind);
e456bf10 209 bool isPcRelStore(const ld::Fixup* fixup);
a645023d
A
210 bool isStore(ld::Fixup::Kind kind);
211 bool storeAddendOnly(const ld::Atom* inAtom, const ld::Atom* target, bool pcRel=false);
e456bf10 212 bool setsTarget(const ld::Fixup &fixup);
a645023d
A
213 void addFixupOutInfo(ld::Internal& state);
214 void makeRelocations(ld::Internal& state);
215 void makeSectionRelocations(ld::Internal& state);
216 void makeDyldInfo(ld::Internal& state);
217 void makeSplitSegInfo(ld::Internal& state);
eaf282aa 218 void makeSplitSegInfoV2(ld::Internal& state);
a645023d 219 void writeMapFile(ld::Internal& state);
0a8dc3df 220 void writeJSONEntry(ld::Internal& state);
a645023d
A
221 uint64_t lookBackAddend(ld::Fixup::iterator fit);
222 bool takesNoDiskSpace(const ld::Section* sect);
223 bool hasZeroForFileOffset(const ld::Section* sect);
224
225 void printSectionLayout(ld::Internal& state);
9543cb2f
A
226
227 bool checkThumbBranch22Displacement(int64_t displacement);
228 bool checkArmBranch24Displacement(int64_t displacement);
229
a645023d
A
230 void rangeCheck8(int64_t delta, ld::Internal& state, const ld::Atom* atom,
231 const ld::Fixup* fixup);
232 void rangeCheck16(int64_t delta, ld::Internal& state, const ld::Atom* atom,
233 const ld::Fixup* fixup);
234 void rangeCheckBranch32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
235 const ld::Fixup* fixup);
afe874b1
A
236 void rangeCheckAbsolute32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
237 const ld::Fixup* fixup);
a645023d
A
238 void rangeCheckRIP32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
239 const ld::Fixup* fixup);
240 void rangeCheckARM12(int64_t delta, ld::Internal& state, const ld::Atom* atom,
241 const ld::Fixup* fixup);
242 void rangeCheckARMBranch24(int64_t delta, ld::Internal& state, const ld::Atom* atom,
243 const ld::Fixup* fixup);
244 void rangeCheckThumbBranch22(int64_t delta, ld::Internal& state, const ld::Atom* atom,
245 const ld::Fixup* fixup);
f80fe69f
A
246 void rangeCheckARM64Branch26(int64_t delta, ld::Internal& state, const ld::Atom* atom,
247 const ld::Fixup* fixup);
248 void rangeCheckARM64Page21(int64_t delta, ld::Internal& state, const ld::Atom* atom,
249 const ld::Fixup* fixup);
250
251
a645023d
A
252 uint64_t sectionOffsetOf(const ld::Internal& state, const ld::Fixup* fixup);
253 uint64_t tlvTemplateOffsetOf(const ld::Internal& state, const ld::Fixup* fixup);
a645023d
A
254 void synthesizeDebugNotes(ld::Internal& state);
255 const char* assureFullPath(const char* path);
256 void noteTextReloc(const ld::Atom* atom, const ld::Atom* target);
257
258
9543cb2f
A
259 struct InstructionInfo {
260 uint32_t offsetInAtom;
261 const ld::Fixup* fixup;
262 const ld::Atom* target;
263 uint64_t targetAddress;
264 uint8_t* instructionContent;
265 uint64_t instructionAddress;
266 uint32_t instruction;
267 };
268
269 void setInfo(ld::Internal& state, const ld::Atom* atom, uint8_t* buffer, const std::map<uint32_t, const Fixup*>& usedHints,
270 uint32_t offsetInAtom, uint32_t delta, InstructionInfo* info);
271
a645023d
A
272 static uint16_t get16LE(uint8_t* loc);
273 static void set16LE(uint8_t* loc, uint16_t value);
274 static uint32_t get32LE(uint8_t* loc);
275 static void set32LE(uint8_t* loc, uint32_t value);
276 static uint64_t get64LE(uint8_t* loc);
277 static void set64LE(uint8_t* loc, uint64_t value);
278
279 static uint16_t get16BE(uint8_t* loc);
280 static void set16BE(uint8_t* loc, uint16_t value);
281 static uint32_t get32BE(uint8_t* loc);
282 static void set32BE(uint8_t* loc, uint32_t value);
283 static uint64_t get64BE(uint8_t* loc);
284 static void set64BE(uint8_t* loc, uint64_t value);
285
286
287
288 const Options& _options;
289 std::map<const ld::dylib::File*, int> _dylibToOrdinal;
290 std::vector<const ld::dylib::File*> _dylibsToLoad;
291 std::vector<const char*> _dylibOrdinalPaths;
292 const bool _hasDyldInfo;
e456bf10 293 const bool _hasThreadedPageStarts;
a645023d
A
294 const bool _hasSymbolTable;
295 const bool _hasSectionRelocations;
296 const bool _hasSplitSegInfo;
297 const bool _hasFunctionStartsInfo;
ebf6f434 298 const bool _hasDataInCodeInfo;
a645023d
A
299 bool _hasDynamicSymbolTable;
300 bool _hasLocalRelocations;
301 bool _hasExternalRelocations;
9543cb2f 302 bool _hasOptimizationHints;
a645023d
A
303 uint64_t _fileSize;
304 std::map<uint64_t, uint32_t> _lazyPointerAddressToInfoOffset;
305 uint32_t _encryptedTEXTstartOffset;
306 uint32_t _encryptedTEXTendOffset;
307public:
308 std::vector<const ld::Atom*> _localAtoms;
309 std::vector<const ld::Atom*> _exportedAtoms;
310 std::vector<const ld::Atom*> _importedAtoms;
311 uint32_t _localSymbolsStartIndex;
312 uint32_t _localSymbolsCount;
313 uint32_t _globalSymbolsStartIndex;
314 uint32_t _globalSymbolsCount;
315 uint32_t _importSymbolsStartIndex;
316 uint32_t _importSymbolsCount;
317 std::map<const ld::Atom*, uint32_t> _atomToSymbolIndex;
318 std::vector<RebaseInfo> _rebaseInfo;
319 std::vector<BindingInfo> _bindingInfo;
320 std::vector<BindingInfo> _lazyBindingInfo;
321 std::vector<BindingInfo> _weakBindingInfo;
e456bf10
A
322 bool _hasUnalignedFixup = false;
323 // Note, <= 0 values are indices in to rebases, > 0 are binds.
324 std::vector<int64_t> _threadedRebaseBindIndices;
325#if SUPPORT_ARCH_arm64e
326 std::map<uintptr_t, std::pair<Fixup::AuthData, uint64_t>> _authenticatedFixupData;
327#endif
a645023d 328 std::vector<SplitSegInfoEntry> _splitSegInfos;
eaf282aa 329 std::vector<SplitSegInfoV2Entry> _splitSegV2Infos;
a645023d
A
330 class HeaderAndLoadCommandsAbtract* _headersAndLoadCommandAtom;
331 class RelocationsAtomAbstract* _sectionsRelocationsAtom;
332 class RelocationsAtomAbstract* _localRelocsAtom;
333 class RelocationsAtomAbstract* _externalRelocsAtom;
334 class ClassicLinkEditAtom* _symbolTableAtom;
335 class ClassicLinkEditAtom* _indirectSymbolTableAtom;
336 class StringPoolAtom* _stringPoolAtom;
337 class LinkEditAtom* _rebasingInfoAtom;
338 class LinkEditAtom* _bindingInfoAtom;
339 class LinkEditAtom* _lazyBindingInfoAtom;
340 class LinkEditAtom* _weakBindingInfoAtom;
341 class LinkEditAtom* _exportInfoAtom;
342 class LinkEditAtom* _splitSegInfoAtom;
343 class LinkEditAtom* _functionStartsAtom;
ebf6f434 344 class LinkEditAtom* _dataInCodeAtom;
9543cb2f 345 class LinkEditAtom* _optimizationHintsAtom;
a645023d
A
346};
347
348} // namespace tool
349} // namespace ld
350
351#endif // __OUTPUT_FILE_H__