]> git.saurik.com Git - apple/ld64.git/blob - src/ld/OutputFile.h
5fd27d80592c0d72253598a2df33826e34edbb0c
[apple/ld64.git] / src / ld / OutputFile.h
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
49 namespace ld {
50 namespace tool {
51
52 class OutputFile
53 {
54 public:
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);
68 uint64_t fileSize() const { return _fileSize; }
69
70
71 bool usesWeakExternalSymbols;
72 bool overridesWeakExternalSymbols;
73 bool _noReExportedDylibs;
74 bool pieDisabled;
75 bool hasDataInCode;
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;
92
93 struct RebaseInfo {
94 RebaseInfo(uint8_t t, uint64_t addr) : _type(t), _address(addr) {}
95 uint8_t _type;
96 uint64_t _address;
97 // for sorting
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 );
103 }
104 };
105
106 struct BindingInfo {
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) {}
113 uint8_t _type;
114 uint8_t _flags;
115 int _libraryOrdinal;
116 const char* _symbolName;
117 uint64_t _address;
118 int64_t _addend;
119
120 // for sorting
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 );
130 }
131 };
132
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;
138 uint32_t extra;
139 };
140
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;
149 };
150 static void dumpAtomsBySection(ld::Internal& state, bool);
151
152 private:
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 bool targetIsThumb(ld::Internal& state, const ld::Fixup* fixup);
193 uint32_t lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress);
194 void copyNoOps(uint8_t* from, uint8_t* to, bool thumb);
195 bool isPointerToTarget(ld::Fixup::Kind kind);
196 bool isPointerFromTarget(ld::Fixup::Kind kind);
197 bool isPcRelStore(ld::Fixup::Kind kind);
198 bool isStore(ld::Fixup::Kind kind);
199 bool storeAddendOnly(const ld::Atom* inAtom, const ld::Atom* target, bool pcRel=false);
200 bool setsTarget(ld::Fixup::Kind kind);
201 void addFixupOutInfo(ld::Internal& state);
202 void makeRelocations(ld::Internal& state);
203 void makeSectionRelocations(ld::Internal& state);
204 void makeDyldInfo(ld::Internal& state);
205 void makeSplitSegInfo(ld::Internal& state);
206 void makeSplitSegInfoV2(ld::Internal& state);
207 void writeMapFile(ld::Internal& state);
208 uint64_t lookBackAddend(ld::Fixup::iterator fit);
209 bool takesNoDiskSpace(const ld::Section* sect);
210 bool hasZeroForFileOffset(const ld::Section* sect);
211
212 void printSectionLayout(ld::Internal& state);
213
214 bool checkThumbBranch22Displacement(int64_t displacement);
215 bool checkArmBranch24Displacement(int64_t displacement);
216
217 void rangeCheck8(int64_t delta, ld::Internal& state, const ld::Atom* atom,
218 const ld::Fixup* fixup);
219 void rangeCheck16(int64_t delta, ld::Internal& state, const ld::Atom* atom,
220 const ld::Fixup* fixup);
221 void rangeCheckBranch32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
222 const ld::Fixup* fixup);
223 void rangeCheckAbsolute32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
224 const ld::Fixup* fixup);
225 void rangeCheckRIP32(int64_t delta, ld::Internal& state, const ld::Atom* atom,
226 const ld::Fixup* fixup);
227 void rangeCheckARM12(int64_t delta, ld::Internal& state, const ld::Atom* atom,
228 const ld::Fixup* fixup);
229 void rangeCheckARMBranch24(int64_t delta, ld::Internal& state, const ld::Atom* atom,
230 const ld::Fixup* fixup);
231 void rangeCheckThumbBranch22(int64_t delta, ld::Internal& state, const ld::Atom* atom,
232 const ld::Fixup* fixup);
233 void rangeCheckARM64Branch26(int64_t delta, ld::Internal& state, const ld::Atom* atom,
234 const ld::Fixup* fixup);
235 void rangeCheckARM64Page21(int64_t delta, ld::Internal& state, const ld::Atom* atom,
236 const ld::Fixup* fixup);
237
238
239 uint64_t sectionOffsetOf(const ld::Internal& state, const ld::Fixup* fixup);
240 uint64_t tlvTemplateOffsetOf(const ld::Internal& state, const ld::Fixup* fixup);
241 void synthesizeDebugNotes(ld::Internal& state);
242 const char* assureFullPath(const char* path);
243 void noteTextReloc(const ld::Atom* atom, const ld::Atom* target);
244
245
246 struct InstructionInfo {
247 uint32_t offsetInAtom;
248 const ld::Fixup* fixup;
249 const ld::Atom* target;
250 uint64_t targetAddress;
251 uint8_t* instructionContent;
252 uint64_t instructionAddress;
253 uint32_t instruction;
254 };
255
256 void setInfo(ld::Internal& state, const ld::Atom* atom, uint8_t* buffer, const std::map<uint32_t, const Fixup*>& usedHints,
257 uint32_t offsetInAtom, uint32_t delta, InstructionInfo* info);
258
259 static uint16_t get16LE(uint8_t* loc);
260 static void set16LE(uint8_t* loc, uint16_t value);
261 static uint32_t get32LE(uint8_t* loc);
262 static void set32LE(uint8_t* loc, uint32_t value);
263 static uint64_t get64LE(uint8_t* loc);
264 static void set64LE(uint8_t* loc, uint64_t value);
265
266 static uint16_t get16BE(uint8_t* loc);
267 static void set16BE(uint8_t* loc, uint16_t value);
268 static uint32_t get32BE(uint8_t* loc);
269 static void set32BE(uint8_t* loc, uint32_t value);
270 static uint64_t get64BE(uint8_t* loc);
271 static void set64BE(uint8_t* loc, uint64_t value);
272
273
274
275 const Options& _options;
276 std::map<const ld::dylib::File*, int> _dylibToOrdinal;
277 std::vector<const ld::dylib::File*> _dylibsToLoad;
278 std::vector<const char*> _dylibOrdinalPaths;
279 const bool _hasDyldInfo;
280 const bool _hasSymbolTable;
281 const bool _hasSectionRelocations;
282 const bool _hasSplitSegInfo;
283 const bool _hasFunctionStartsInfo;
284 const bool _hasDataInCodeInfo;
285 bool _hasDynamicSymbolTable;
286 bool _hasLocalRelocations;
287 bool _hasExternalRelocations;
288 bool _hasOptimizationHints;
289 uint64_t _fileSize;
290 std::map<uint64_t, uint32_t> _lazyPointerAddressToInfoOffset;
291 uint32_t _encryptedTEXTstartOffset;
292 uint32_t _encryptedTEXTendOffset;
293 public:
294 std::vector<const ld::Atom*> _localAtoms;
295 std::vector<const ld::Atom*> _exportedAtoms;
296 std::vector<const ld::Atom*> _importedAtoms;
297 uint32_t _localSymbolsStartIndex;
298 uint32_t _localSymbolsCount;
299 uint32_t _globalSymbolsStartIndex;
300 uint32_t _globalSymbolsCount;
301 uint32_t _importSymbolsStartIndex;
302 uint32_t _importSymbolsCount;
303 std::map<const ld::Atom*, uint32_t> _atomToSymbolIndex;
304 std::vector<RebaseInfo> _rebaseInfo;
305 std::vector<BindingInfo> _bindingInfo;
306 std::vector<BindingInfo> _lazyBindingInfo;
307 std::vector<BindingInfo> _weakBindingInfo;
308 std::vector<SplitSegInfoEntry> _splitSegInfos;
309 std::vector<SplitSegInfoV2Entry> _splitSegV2Infos;
310 class HeaderAndLoadCommandsAbtract* _headersAndLoadCommandAtom;
311 class RelocationsAtomAbstract* _sectionsRelocationsAtom;
312 class RelocationsAtomAbstract* _localRelocsAtom;
313 class RelocationsAtomAbstract* _externalRelocsAtom;
314 class ClassicLinkEditAtom* _symbolTableAtom;
315 class ClassicLinkEditAtom* _indirectSymbolTableAtom;
316 class StringPoolAtom* _stringPoolAtom;
317 class LinkEditAtom* _rebasingInfoAtom;
318 class LinkEditAtom* _bindingInfoAtom;
319 class LinkEditAtom* _lazyBindingInfoAtom;
320 class LinkEditAtom* _weakBindingInfoAtom;
321 class LinkEditAtom* _exportInfoAtom;
322 class LinkEditAtom* _splitSegInfoAtom;
323 class LinkEditAtom* _functionStartsAtom;
324 class LinkEditAtom* _dataInCodeAtom;
325 class LinkEditAtom* _optimizationHintsAtom;
326 };
327
328 } // namespace tool
329 } // namespace ld
330
331 #endif // __OUTPUT_FILE_H__