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