]> git.saurik.com Git - apple/ld64.git/blob - src/ObjectFile.h
1f42994454e5f9aae1d88af12683acb2bb2218bd
[apple/ld64.git] / src / ObjectFile.h
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005-2007 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
26 #ifndef __OBJECTFILE__
27 #define __OBJECTFILE__
28
29 #include <stdint.h>
30 #include <vector>
31 #include <map>
32 #include <set>
33
34
35
36 //
37 // These classes represent the abstract Atoms and References that are the basis of the linker.
38 // An Atom and a Reference correspond to a Node and Edge in graph theory.
39 //
40 // A Reader is a class which parses an object file and presents it as Atoms and References.
41 // All linking operations are done on Atoms and References. This makes the linker file
42 // format independent.
43 //
44 // A Writer takes a vector of Atoms with all References resolved and produces an executable file.
45 //
46 //
47
48
49
50 namespace ObjectFile {
51
52
53 struct LineInfo
54 {
55 uint32_t atomOffset;
56 const char* fileName;
57 uint32_t lineNumber;
58 };
59
60
61 class ReaderOptions
62 {
63 public:
64 ReaderOptions() : fFullyLoadArchives(false), fLoadAllObjcObjectsFromArchives(false), fFlatNamespace(false),
65 fLinkingMainExecutable(false), fSlowx86Stubs(false),
66 fForFinalLinkedImage(false), fForStatic(false), fForDyld(false), fMakeTentativeDefinitionsReal(false),
67 fWhyLoad(false), fRootSafe(false), fSetuidSafe(false),fDebugInfoStripping(kDebugInfoFull),
68 fImplicitlyLinkPublicDylibs(true), fLogObjectFiles(false), fLogAllFiles(false),
69 fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false),
70 fTraceOutputFile(NULL), fVersionMin(kMinUnset) {}
71 enum DebugInfoStripping { kDebugInfoNone, kDebugInfoMinimal, kDebugInfoFull };
72 enum VersionMin { kMinUnset, k10_1, k10_2, k10_3, k10_4, k10_5, k10_6 };
73
74 struct AliasPair {
75 const char* realName;
76 const char* alias;
77 };
78
79 bool fFullyLoadArchives;
80 bool fLoadAllObjcObjectsFromArchives;
81 bool fFlatNamespace;
82 bool fLinkingMainExecutable;
83 bool fSlowx86Stubs;
84 bool fForFinalLinkedImage;
85 bool fForStatic;
86 bool fForDyld;
87 bool fMakeTentativeDefinitionsReal;
88 bool fWhyLoad;
89 bool fRootSafe;
90 bool fSetuidSafe;
91 DebugInfoStripping fDebugInfoStripping;
92 bool fImplicitlyLinkPublicDylibs;
93 bool fLogObjectFiles;
94 bool fLogAllFiles;
95 bool fTraceDylibs;
96 bool fTraceIndirectDylibs;
97 bool fTraceArchives;
98 const char* fTraceOutputFile;
99 VersionMin fVersionMin;
100 std::vector<AliasPair> fAliases;
101 };
102
103
104 class Reader
105 {
106 public:
107 enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 };
108 struct Stab
109 {
110 class Atom* atom;
111 uint8_t type;
112 uint8_t other;
113 uint16_t desc;
114 uint32_t value;
115 const char* string;
116 };
117 enum ObjcConstraint { kObjcNone, kObjcRetainRelease, kObjcRetainReleaseOrGC, kObjcGC };
118 enum CpuConstraint { kCpuAny = 0 };
119
120 class DylibHander
121 {
122 public:
123 virtual ~DylibHander() {}
124 virtual Reader* findDylib(const char* installPath, const char* fromPath) = 0;
125 };
126
127
128 static Reader* createReader(const char* path, const ReaderOptions& options);
129
130 virtual const char* getPath() = 0;
131 virtual time_t getModificationTime() = 0;
132 virtual DebugInfoKind getDebugInfoKind() = 0;
133 virtual std::vector<class Atom*>& getAtoms() = 0;
134 virtual std::vector<class Atom*>* getJustInTimeAtomsFor(const char* name) = 0;
135 virtual std::vector<Stab>* getStabs() = 0;
136 virtual ObjcConstraint getObjCConstraint() { return kObjcNone; }
137 virtual uint32_t updateCpuConstraint(uint32_t current) { return current; }
138 virtual bool objcReplacementClasses() { return false; }
139
140 // For relocatable object files only
141 virtual bool canScatterAtoms() { return true; }
142 virtual void optimize(std::vector<ObjectFile::Atom*>&, std::vector<ObjectFile::Atom*>&,
143 std::vector<const char*>&, const std::set<ObjectFile::Atom*>&,
144 uint32_t, ObjectFile::Reader* writer,
145 const std::vector<const char*>& llvmOptions,
146 bool allGlobalsAReDeadStripRoots, int okind,
147 bool verbose, bool saveTemps, const char* outputFilePath,
148 bool pie, bool allowTextRelocs) { }
149 virtual bool hasLongBranchStubs() { return false; }
150
151 // For Dynamic Libraries only
152 virtual const char* getInstallPath() { return NULL; }
153 virtual uint32_t getTimestamp() { return 0; }
154 virtual uint32_t getCurrentVersion() { return 0; }
155 virtual uint32_t getCompatibilityVersion() { return 0; }
156 virtual void processIndirectLibraries(DylibHander* handler) { }
157 virtual void setExplicitlyLinked() { }
158 virtual bool explicitlyLinked() { return false; }
159 virtual bool implicitlyLinked() { return false; }
160 virtual bool providedExportAtom() { return false; }
161 virtual const char* parentUmbrella() { return NULL; }
162 virtual std::vector<const char*>* getAllowableClients() { return NULL; }
163 virtual bool hasWeakExternals() { return false; }
164 virtual bool isLazyLoadedDylib() { return false; }
165
166 protected:
167 Reader() {}
168 virtual ~Reader() {}
169 };
170
171 class Segment
172 {
173 public:
174 virtual const char* getName() const = 0;
175 virtual bool isContentReadable() const = 0;
176 virtual bool isContentWritable() const = 0;
177 virtual bool isContentExecutable() const = 0;
178
179 uint64_t getBaseAddress() const { return fBaseAddress; }
180 void setBaseAddress(uint64_t addr) { fBaseAddress = addr; }
181 virtual bool hasFixedAddress() const { return false; }
182
183 protected:
184 Segment() : fBaseAddress(0) {}
185 virtual ~Segment() {}
186 uint64_t fBaseAddress;
187 };
188
189 class Reference;
190
191 class Section
192 {
193 public:
194 unsigned int getIndex() { return fIndex; }
195 uint64_t getBaseAddress() { return fBaseAddress; }
196 void setBaseAddress(uint64_t addr) { fBaseAddress = addr; }
197 void* fOther;
198
199 protected:
200 Section() : fOther(NULL), fBaseAddress(0), fIndex(0) {}
201 uint64_t fBaseAddress;
202 unsigned int fIndex;
203 };
204
205
206 struct Alignment
207 {
208 Alignment(int p2, int m=0) : powerOf2(p2), modulus(m) {}
209 uint8_t trailingZeros() const { return (modulus==0) ? powerOf2 : __builtin_ctz(modulus); }
210 uint16_t powerOf2;
211 uint16_t modulus;
212 };
213
214 //
215 // An atom is the fundamental unit of linking. A C function or global variable is an atom.
216 // An atom has content and some attributes. The content of a function atom is the instructions
217 // that implement the function. The content of a global variable atom is its initial bits.
218 //
219 // Name:
220 // The name of an atom is the label name generated by the compiler. A C compiler names foo()
221 // as _foo. A C++ compiler names foo() as __Z3foov.
222 // The name refers to the first byte of the content. An atom cannot have multiple entry points.
223 // Such code is modeled as multiple atoms, each having a "follow on" reference to the next.
224 // A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously.
225 //
226 // Scope:
227 // An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond
228 // to the C visibility of static, hidden, default.
229 //
230 // DefinitionKind:
231 // An atom is one of five defintion kinds:
232 // regular Most atoms.
233 // weak C++ compiler makes some functions weak if there might be multiple copies
234 // that the linker needs to coalesce.
235 // tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous.
236 // It could be a prototype or it could be a definition.
237 // external This is a "proxy" atom produced by a dylib reader. It has no content. It exists
238 // so that all References can be resolved.
239 // external-weak Same as external, but the definition in the dylib is weak.
240 //
241 // SymbolTableInclusion:
242 // An atom may or may not be in the symbol table in an object file.
243 // in Most atoms for functions or global data
244 // not-in Anonymous atoms such literal c-strings, or other compiler generated data
245 // in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o)
246 //
247 // Ordinal:
248 // When a reader is created it is given a base ordinal number. All atoms created by the reader
249 // should return a contiguous range of ordinal values that start at the base ordinal. The ordinal
250 // values are used by the linker to sort the atom graph when producing the output file.
251 //
252 class Atom
253 {
254 public:
255 enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal };
256 enum DefinitionKind { kRegularDefinition, kWeakDefinition, kTentativeDefinition, kExternalDefinition, kExternalWeakDefinition, kAbsoluteSymbol };
257 enum SymbolTableInclusion { kSymbolTableNotIn, kSymbolTableIn, kSymbolTableInAndNeverStrip, kSymbolTableInAsAbsolute };
258
259 virtual Reader* getFile() const = 0;
260 virtual bool getTranslationUnitSource(const char** dir, const char** name) const = 0;
261 virtual const char* getName() const = 0;
262 virtual const char* getDisplayName() const = 0;
263 virtual Scope getScope() const = 0;
264 virtual DefinitionKind getDefinitionKind() const = 0;
265 virtual SymbolTableInclusion getSymbolTableInclusion() const = 0;
266 virtual bool dontDeadStrip() const = 0;
267 virtual bool isZeroFill() const = 0;
268 virtual bool isThumb() const = 0;
269 virtual uint64_t getSize() const = 0;
270 virtual std::vector<ObjectFile::Reference*>& getReferences() const = 0;
271 virtual bool mustRemainInSection() const = 0;
272 virtual const char* getSectionName() const = 0;
273 virtual Segment& getSegment() const = 0;
274 virtual Atom& getFollowOnAtom() const = 0;
275 virtual uint32_t getOrdinal() const = 0;
276 virtual std::vector<LineInfo>* getLineInfo() const = 0;
277 virtual Alignment getAlignment() const = 0;
278 virtual void copyRawContent(uint8_t buffer[]) const = 0;
279 virtual void setScope(Scope) = 0;
280
281
282 uint64_t getSectionOffset() const { return fSectionOffset; }
283 uint64_t getAddress() const { return fSection->getBaseAddress() + fSectionOffset; }
284 class Section* getSection() const { return fSection; }
285
286 virtual void setSectionOffset(uint64_t offset) { fSectionOffset = offset; }
287 virtual void setSection(class Section* sect) { fSection = sect; }
288
289 protected:
290 Atom() : fSectionOffset(0), fSection(NULL) {}
291 virtual ~Atom() {}
292
293 uint64_t fSectionOffset;
294 class Section* fSection;
295 };
296
297
298 //
299 // A Reference is a directed edge to another Atom. When an instruction in
300 // the content of an Atom refers to another Atom, that is represented by a
301 // Reference.
302 //
303 // There are two kinds of references: direct and by-name. With a direct Reference,
304 // the target is bound by the Reader that created it. For instance a reference to a
305 // static would produce a direct reference. A by-name reference requires the linker
306 // to find the target Atom with the required name in order to be bound.
307 //
308 // For a link to succeed all References must be bound.
309 //
310 // A Reference has an optional "from" target. This is used when the content to fix-up
311 // is the difference of two Atom address. For instance, if a pointer sized data Atom
312 // is to contain A - B, then the Atom would have on Reference with a target of "A" and
313 // a from-target of "B".
314 //
315 // A Reference also has a fix-up-offset. This is the offset into the content of the
316 // Atom holding the reference where the fix-up (relocation) will be applied.
317 //
318 //
319 //
320 class Reference
321 {
322 public:
323 enum TargetBinding { kUnboundByName, kBoundDirectly, kBoundByName, kDontBind };
324
325 virtual TargetBinding getTargetBinding() const = 0;
326 virtual TargetBinding getFromTargetBinding() const = 0;
327 virtual uint8_t getKind() const = 0;
328 virtual uint64_t getFixUpOffset() const = 0;
329 virtual const char* getTargetName() const = 0;
330 virtual Atom& getTarget() const = 0;
331 virtual uint64_t getTargetOffset() const = 0;
332 virtual Atom& getFromTarget() const = 0;
333 virtual const char* getFromTargetName() const = 0;
334 virtual uint64_t getFromTargetOffset() const = 0;
335
336 virtual void setTarget(Atom&, uint64_t offset) = 0;
337 virtual void setFromTarget(Atom&) = 0;
338 virtual const char* getDescription() const = 0;
339
340 protected:
341 Reference() {}
342 virtual ~Reference() {}
343 };
344
345
346 }; // namespace ObjectFile
347
348
349 #endif // __OBJECTFILE__