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