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