]> git.saurik.com Git - apple/ld64.git/blame - src/ld/OutputFile.h
ld64-242.2.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;
ebf6f434 86 ld::Internal::FinalSection* dependentDRsSection;
a645023d
A
87 ld::Internal::FinalSection* symbolTableSection;
88 ld::Internal::FinalSection* stringPoolSection;
89 ld::Internal::FinalSection* localRelocationsSection;
90 ld::Internal::FinalSection* externalRelocationsSection;
91 ld::Internal::FinalSection* sectionRelocationsSection;
92 ld::Internal::FinalSection* indirectSymbolTableSection;
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)
109 : _type(t), _flags(weak_import ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0 ), _libraryOrdinal(ord),
110 _symbolName(sym), _address(addr), _addend(add) {}
111 BindingInfo(uint8_t t, const char* sym, bool non_weak_definition, uint64_t addr, int64_t add)
112 : _type(t), _flags(non_weak_definition ? BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION : 0 ),
113 _libraryOrdinal(0), _symbolName(sym), _address(addr), _addend(add) {}
114 uint8_t _type;
115 uint8_t _flags;
116 int _libraryOrdinal;
117 const char* _symbolName;
118 uint64_t _address;
119 int64_t _addend;
120
121 // for sorting
122 int operator<(const BindingInfo& rhs) const {
123 // sort by library, symbol, type, then address
124 if ( this->_libraryOrdinal != rhs._libraryOrdinal )
125 return (this->_libraryOrdinal < rhs._libraryOrdinal );
126 if ( this->_symbolName != rhs._symbolName )
127 return ( strcmp(this->_symbolName, rhs._symbolName) < 0 );
128 if ( this->_type != rhs._type )
129 return (this->_type < rhs._type );
130 return (this->_address < rhs._address );
131 }
132 };
133
134 struct SplitSegInfoEntry {
afe874b1 135 SplitSegInfoEntry(uint64_t a, ld::Fixup::Kind k, uint32_t e=0) : address(a), kind(k), extra(e) {}
a645023d
A
136 uint64_t address;
137 ld::Fixup::Kind kind;
afe874b1 138 uint32_t extra;
a645023d
A
139 };
140
141private:
ebf6f434
A
142 void writeAtoms(ld::Internal& state, uint8_t* wholeBuffer);
143 void computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer);
a645023d
A
144 void buildDylibOrdinalMapping(ld::Internal&);
145 bool hasOrdinalForInstallPath(const char* path, int* ordinal);
146 void addLoadCommands(ld::Internal& state);
147 void addLinkEdit(ld::Internal& state);
148 void addPreloadLinkEdit(ld::Internal& state);
149 void generateLinkEditInfo(ld::Internal& state);
150 void buildSymbolTable(ld::Internal& state);
151 void writeOutputFile(ld::Internal& state);
a645023d
A
152 void addSectionRelocs(ld::Internal& state, ld::Internal::FinalSection* sect,
153 const ld::Atom* atom, ld::Fixup* fixupWithTarget,
f80fe69f
A
154 ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithAddend,
155 ld::Fixup* fixupWithStore,
a645023d
A
156 const ld::Atom* target, const ld::Atom* minusTarget,
157 uint64_t targetAddend, uint64_t minusTargetAddend);
158 void addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* sect,
159 const ld::Atom* atom, ld::Fixup* fixupWithTarget,
160 ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
161 const ld::Atom* target, const ld::Atom* minusTarget,
162 uint64_t targetAddend, uint64_t minusTargetAddend);
163 void addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect,
164 const ld::Atom* atom, ld::Fixup* fixupWithTarget,
165 ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
166 const ld::Atom* target, const ld::Atom* minusTarget,
167 uint64_t targetAddend, uint64_t minusTargetAddend);
168 bool useExternalSectionReloc(const ld::Atom* atom, const ld::Atom* target,
169 ld::Fixup* fixupWithTarget);
f80fe69f 170 bool useSectionRelocAddend(ld::Fixup* fixupWithTarget);
a645023d
A
171 uint64_t pageAlign(uint64_t addr);
172 uint64_t pageAlign(uint64_t addr, uint64_t pageSize);
173 void setLoadCommandsPadding(ld::Internal& state);
174 void assignAtomAddresses(ld::Internal& state);
175 void addRebaseInfo(const ld::Atom* atom, const ld::Fixup* fixup, const ld::Atom* target);
176 void makeRebasingInfo(ld::Internal& state);
177 void makeBindingInfo(ld::Internal& state);
178 void updateLINKEDITAddresses(ld::Internal& state);
179 void applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer);
180 uint64_t addressOf(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target);
181 bool targetIsThumb(ld::Internal& state, const ld::Fixup* fixup);
182 uint32_t lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress);
afe874b1 183 void copyNoOps(uint8_t* from, uint8_t* to, bool thumb);
a645023d
A
184 bool isPointerToTarget(ld::Fixup::Kind kind);
185 bool isPointerFromTarget(ld::Fixup::Kind kind);
186 bool isPcRelStore(ld::Fixup::Kind kind);
187 bool isStore(ld::Fixup::Kind kind);
188 bool storeAddendOnly(const ld::Atom* inAtom, const ld::Atom* target, bool pcRel=false);
189 bool setsTarget(ld::Fixup::Kind kind);
190 void addFixupOutInfo(ld::Internal& state);
191 void makeRelocations(ld::Internal& state);
192 void makeSectionRelocations(ld::Internal& state);
193 void makeDyldInfo(ld::Internal& state);
194 void makeSplitSegInfo(ld::Internal& state);
195 void writeMapFile(ld::Internal& state);
196 uint64_t lookBackAddend(ld::Fixup::iterator fit);
197 bool takesNoDiskSpace(const ld::Section* sect);
198 bool hasZeroForFileOffset(const ld::Section* sect);
199
200 void printSectionLayout(ld::Internal& state);
9543cb2f
A
201
202 bool checkThumbBranch22Displacement(int64_t displacement);
203 bool checkArmBranch24Displacement(int64_t displacement);
204
a645023d
A
205 void rangeCheck8(int64_t delta, ld::Internal& state, const ld::Atom* atom,
206 const ld::Fixup* fixup);
207 void rangeCheck16(int64_t delta, ld::Internal& state, const ld::Atom* atom,
208 const ld::Fixup* fixup);
209 void rangeCheckBranch32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
210 const ld::Fixup* fixup);
afe874b1
A
211 void rangeCheckAbsolute32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
212 const ld::Fixup* fixup);
a645023d
A
213 void rangeCheckRIP32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
214 const ld::Fixup* fixup);
215 void rangeCheckARM12(int64_t delta, ld::Internal& state, const ld::Atom* atom,
216 const ld::Fixup* fixup);
217 void rangeCheckARMBranch24(int64_t delta, ld::Internal& state, const ld::Atom* atom,
218 const ld::Fixup* fixup);
219 void rangeCheckThumbBranch22(int64_t delta, ld::Internal& state, const ld::Atom* atom,
220 const ld::Fixup* fixup);
f80fe69f
A
221 void rangeCheckARM64Branch26(int64_t delta, ld::Internal& state, const ld::Atom* atom,
222 const ld::Fixup* fixup);
223 void rangeCheckARM64Page21(int64_t delta, ld::Internal& state, const ld::Atom* atom,
224 const ld::Fixup* fixup);
225
226
a645023d
A
227 uint64_t sectionOffsetOf(const ld::Internal& state, const ld::Fixup* fixup);
228 uint64_t tlvTemplateOffsetOf(const ld::Internal& state, const ld::Fixup* fixup);
229 void dumpAtomsBySection(ld::Internal& state, bool);
230 void synthesizeDebugNotes(ld::Internal& state);
231 const char* assureFullPath(const char* path);
232 void noteTextReloc(const ld::Atom* atom, const ld::Atom* target);
233
234
9543cb2f
A
235 struct InstructionInfo {
236 uint32_t offsetInAtom;
237 const ld::Fixup* fixup;
238 const ld::Atom* target;
239 uint64_t targetAddress;
240 uint8_t* instructionContent;
241 uint64_t instructionAddress;
242 uint32_t instruction;
243 };
244
245 void setInfo(ld::Internal& state, const ld::Atom* atom, uint8_t* buffer, const std::map<uint32_t, const Fixup*>& usedHints,
246 uint32_t offsetInAtom, uint32_t delta, InstructionInfo* info);
247
a645023d
A
248 static uint16_t get16LE(uint8_t* loc);
249 static void set16LE(uint8_t* loc, uint16_t value);
250 static uint32_t get32LE(uint8_t* loc);
251 static void set32LE(uint8_t* loc, uint32_t value);
252 static uint64_t get64LE(uint8_t* loc);
253 static void set64LE(uint8_t* loc, uint64_t value);
254
255 static uint16_t get16BE(uint8_t* loc);
256 static void set16BE(uint8_t* loc, uint16_t value);
257 static uint32_t get32BE(uint8_t* loc);
258 static void set32BE(uint8_t* loc, uint32_t value);
259 static uint64_t get64BE(uint8_t* loc);
260 static void set64BE(uint8_t* loc, uint64_t value);
261
262
263
264 const Options& _options;
265 std::map<const ld::dylib::File*, int> _dylibToOrdinal;
266 std::vector<const ld::dylib::File*> _dylibsToLoad;
267 std::vector<const char*> _dylibOrdinalPaths;
268 const bool _hasDyldInfo;
269 const bool _hasSymbolTable;
270 const bool _hasSectionRelocations;
271 const bool _hasSplitSegInfo;
272 const bool _hasFunctionStartsInfo;
ebf6f434
A
273 const bool _hasDataInCodeInfo;
274 const bool _hasDependentDRInfo;
a645023d
A
275 bool _hasDynamicSymbolTable;
276 bool _hasLocalRelocations;
277 bool _hasExternalRelocations;
9543cb2f 278 bool _hasOptimizationHints;
a645023d
A
279 uint64_t _fileSize;
280 std::map<uint64_t, uint32_t> _lazyPointerAddressToInfoOffset;
281 uint32_t _encryptedTEXTstartOffset;
282 uint32_t _encryptedTEXTendOffset;
283public:
284 std::vector<const ld::Atom*> _localAtoms;
285 std::vector<const ld::Atom*> _exportedAtoms;
286 std::vector<const ld::Atom*> _importedAtoms;
287 uint32_t _localSymbolsStartIndex;
288 uint32_t _localSymbolsCount;
289 uint32_t _globalSymbolsStartIndex;
290 uint32_t _globalSymbolsCount;
291 uint32_t _importSymbolsStartIndex;
292 uint32_t _importSymbolsCount;
293 std::map<const ld::Atom*, uint32_t> _atomToSymbolIndex;
294 std::vector<RebaseInfo> _rebaseInfo;
295 std::vector<BindingInfo> _bindingInfo;
296 std::vector<BindingInfo> _lazyBindingInfo;
297 std::vector<BindingInfo> _weakBindingInfo;
298 std::vector<SplitSegInfoEntry> _splitSegInfos;
299 class HeaderAndLoadCommandsAbtract* _headersAndLoadCommandAtom;
300 class RelocationsAtomAbstract* _sectionsRelocationsAtom;
301 class RelocationsAtomAbstract* _localRelocsAtom;
302 class RelocationsAtomAbstract* _externalRelocsAtom;
303 class ClassicLinkEditAtom* _symbolTableAtom;
304 class ClassicLinkEditAtom* _indirectSymbolTableAtom;
305 class StringPoolAtom* _stringPoolAtom;
306 class LinkEditAtom* _rebasingInfoAtom;
307 class LinkEditAtom* _bindingInfoAtom;
308 class LinkEditAtom* _lazyBindingInfoAtom;
309 class LinkEditAtom* _weakBindingInfoAtom;
310 class LinkEditAtom* _exportInfoAtom;
311 class LinkEditAtom* _splitSegInfoAtom;
312 class LinkEditAtom* _functionStartsAtom;
ebf6f434
A
313 class LinkEditAtom* _dataInCodeAtom;
314 class LinkEditAtom* _dependentDRInfoAtom;
9543cb2f 315 class LinkEditAtom* _optimizationHintsAtom;
a645023d
A
316};
317
318} // namespace tool
319} // namespace ld
320
321#endif // __OUTPUT_FILE_H__