]>
Commit | Line | Data |
---|---|---|
d696c285 | 1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
6e880c60 | 2 | * |
d696c285 | 3 | * Copyright (c) 2005-2006 Apple Computer, 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 |
48 | namespace ObjectFile { |
49 | ||
d696c285 A |
50 | |
51 | struct 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 |
59 | class ReaderOptions |
60 | { | |
61 | public: | |
69a49097 A |
62 | ReaderOptions() : fFullyLoadArchives(false), fLoadObjcClassesInArchives(false), fFlatNamespace(false), |
63 | fForFinalLinkedImage(false), fWhyLoad(false), fDebugInfoStripping(kDebugInfoFull), | |
64 | fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceOutputFile(NULL) {} | |
d696c285 | 65 | enum DebugInfoStripping { kDebugInfoNone, kDebugInfoMinimal, kDebugInfoFull }; |
c2646906 A |
66 | |
67 | bool fFullyLoadArchives; | |
68 | bool fLoadObjcClassesInArchives; | |
69 | bool fFlatNamespace; | |
69a49097 A |
70 | bool fForFinalLinkedImage; |
71 | bool fWhyLoad; | |
d696c285 | 72 | DebugInfoStripping fDebugInfoStripping; |
c2646906 A |
73 | bool fTraceDylibs; |
74 | bool fTraceIndirectDylibs; | |
75 | bool fTraceArchives; | |
d696c285 | 76 | const char* fTraceOutputFile; |
c2646906 A |
77 | }; |
78 | ||
79 | ||
80 | class Reader | |
81 | { | |
82 | public: | |
d696c285 A |
83 | enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 }; |
84 | struct Stab | |
85 | { | |
86 | class Atom* atom; | |
87 | uint8_t type; | |
88 | uint8_t other; | |
89 | uint16_t desc; | |
90 | uint32_t value; | |
91 | const char* string; | |
92 | }; | |
93 | ||
c2646906 | 94 | static Reader* createReader(const char* path, const ReaderOptions& options); |
d696c285 | 95 | |
c2646906 | 96 | virtual const char* getPath() = 0; |
d696c285 A |
97 | virtual time_t getModificationTime() = 0; |
98 | virtual DebugInfoKind getDebugInfoKind() = 0; | |
c2646906 A |
99 | virtual std::vector<class Atom*>& getAtoms() = 0; |
100 | virtual std::vector<class Atom*>* getJustInTimeAtomsFor(const char* name) = 0; | |
d696c285 A |
101 | virtual std::vector<Stab>* getStabs() = 0; |
102 | unsigned int getSortOrder() const { return fSortOrder; } | |
103 | void setSortOrder(unsigned int order) { fSortOrder=order; } | |
104 | ||
c2646906 A |
105 | // For Dynamic Libraries only |
106 | virtual const char* getInstallPath() { return NULL; } | |
107 | virtual uint32_t getTimestamp() { return 0; } | |
108 | virtual uint32_t getCurrentVersion() { return 0; } | |
109 | virtual uint32_t getCompatibilityVersion() { return 0; } | |
110 | virtual std::vector<const char*>* getDependentLibraryPaths() { return NULL; } | |
111 | virtual bool reExports(Reader*) { return false; } | |
d696c285 A |
112 | virtual const char* parentUmbrella() { return NULL; } |
113 | virtual std::vector<const char*>* getAllowableClients() { return NULL; } | |
114 | ||
c2646906 | 115 | protected: |
d696c285 | 116 | Reader() : fSortOrder(0) {} |
6e880c60 | 117 | virtual ~Reader() {} |
d696c285 A |
118 | |
119 | unsigned int fSortOrder; | |
c2646906 A |
120 | }; |
121 | ||
122 | class Segment | |
123 | { | |
124 | public: | |
125 | virtual const char* getName() const = 0; | |
126 | virtual bool isContentReadable() const = 0; | |
127 | virtual bool isContentWritable() const = 0; | |
128 | virtual bool isContentExecutable() const = 0; | |
d696c285 | 129 | |
c2646906 A |
130 | uint64_t getBaseAddress() const { return fBaseAddress; } |
131 | void setBaseAddress(uint64_t addr) { fBaseAddress = addr; } | |
6e880c60 | 132 | virtual bool hasFixedAddress() const { return false; } |
c2646906 A |
133 | |
134 | protected: | |
6e880c60 A |
135 | Segment() : fBaseAddress(0) {} |
136 | virtual ~Segment() {} | |
c2646906 A |
137 | uint64_t fBaseAddress; |
138 | }; | |
139 | ||
140 | class Reference; | |
141 | ||
d696c285 | 142 | class Section |
c2646906 A |
143 | { |
144 | public: | |
145 | unsigned int getIndex() { return fIndex; } | |
146 | uint64_t getBaseAddress() { return fBaseAddress; } | |
147 | void setBaseAddress(uint64_t addr) { fBaseAddress = addr; } | |
148 | void* fOther; | |
d696c285 | 149 | |
c2646906 A |
150 | protected: |
151 | Section() : fOther(NULL), fBaseAddress(0), fIndex(0) {} | |
152 | uint64_t fBaseAddress; | |
153 | unsigned int fIndex; | |
154 | }; | |
155 | ||
156 | ||
c2646906 | 157 | |
d696c285 A |
158 | // |
159 | // An atom is the fundamental unit of linking. A C function or global variable is an atom. | |
160 | // An atom has content and some attributes. The content of a function atom is the instructions | |
161 | // that implement the function. The content of a global variable atom is its initial bits. | |
162 | // | |
163 | // Name: | |
164 | // The name of an atom is the label name generated by the compiler. A C compiler names foo() | |
165 | // as _foo. A C++ compiler names foo() as __Z3foov. | |
166 | // The name refers to the first byte of the content. An atom cannot have multiple entry points. | |
167 | // Such code is modeled as multiple atoms, each having a "follow on" reference to the next. | |
168 | // A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously. | |
169 | // | |
170 | // Scope: | |
171 | // An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond | |
172 | // to the C visibility of static, hidden, default. | |
173 | // | |
174 | // DefinitionKind: | |
175 | // An atom is one of five defintion kinds: | |
176 | // regular Most atoms. | |
177 | // weak C++ compiler makes some functions weak if there might be multiple copies | |
178 | // that the linker needs to coalesce. | |
179 | // tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous. | |
180 | // It could be a prototype or it could be a definition. | |
181 | // external This is a "proxy" atom produced by a dylib reader. It has no content. It exists | |
182 | // so that all References can be resolved. | |
183 | // external-weak Same as external, but the definition in the dylib is weak. | |
184 | // | |
185 | // SymbolTableInclusion: | |
186 | // An atom may or may not be in the symbol table in an object file. | |
187 | // in Most atoms for functions or global data | |
188 | // not-in Anonymous atoms such literal c-strings, or other compiler generated data | |
189 | // in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o) | |
190 | // | |
191 | class Atom | |
c2646906 A |
192 | { |
193 | public: | |
194 | enum Scope { scopeTranslationUnit, scopeLinkageUnit, scopeGlobal }; | |
d696c285 | 195 | enum DefinitionKind { kRegularDefinition, kWeakDefinition, kTentativeDefinition, kExternalDefinition, kExternalWeakDefinition }; |
69a49097 | 196 | enum SymbolTableInclusion { kSymbolTableNotIn, kSymbolTableIn, kSymbolTableInAndNeverStrip, kSymbolTableInAsAbsolute }; |
d696c285 | 197 | |
c2646906 | 198 | virtual Reader* getFile() const = 0; |
d696c285 | 199 | virtual bool getTranslationUnitSource(const char** dir, const char** name) const = 0; |
c2646906 A |
200 | virtual const char* getName() const = 0; |
201 | virtual const char* getDisplayName() const = 0; | |
202 | virtual Scope getScope() const = 0; | |
d696c285 A |
203 | virtual DefinitionKind getDefinitionKind() const = 0; |
204 | virtual SymbolTableInclusion getSymbolTableInclusion() const = 0; | |
69a49097 | 205 | virtual bool dontDeadStrip() const = 0; |
c2646906 | 206 | virtual bool isZeroFill() const = 0; |
c2646906 A |
207 | virtual uint64_t getSize() const = 0; |
208 | virtual std::vector<ObjectFile::Reference*>& getReferences() const = 0; | |
209 | virtual bool mustRemainInSection() const = 0; | |
210 | virtual const char* getSectionName() const = 0; | |
211 | virtual Segment& getSegment() const = 0; | |
212 | virtual bool requiresFollowOnAtom() const = 0; | |
213 | virtual Atom& getFollowOnAtom() const = 0; | |
d696c285 | 214 | virtual std::vector<LineInfo>* getLineInfo() const = 0; |
c2646906 | 215 | virtual uint8_t getAlignment() const = 0; |
c2646906 | 216 | virtual void copyRawContent(uint8_t buffer[]) const = 0; |
c2646906 | 217 | virtual void setScope(Scope) = 0; |
c2646906 | 218 | |
d696c285 | 219 | |
c2646906 A |
220 | uint64_t getSectionOffset() const { return fSectionOffset; } |
221 | uint64_t getSegmentOffset() const { return fSegmentOffset; } | |
222 | uint64_t getAddress() const { return fSection->getBaseAddress() + fSectionOffset; } | |
223 | unsigned int getSortOrder() const { return fSortOrder; } | |
224 | class Section* getSection() const { return fSection; } | |
225 | ||
226 | void setSegmentOffset(uint64_t offset) { fSegmentOffset = offset; } | |
227 | void setSectionOffset(uint64_t offset) { fSectionOffset = offset; } | |
d696c285 | 228 | void setSection(class Section* sect) { fSection = sect; } |
c2646906 A |
229 | unsigned int setSortOrder(unsigned int order); // recursively sets follow-on atoms |
230 | ||
231 | protected: | |
69a49097 | 232 | Atom() : fSegmentOffset(0), fSectionOffset(0), fSortOrder(0), fSection(NULL) {} |
6e880c60 | 233 | virtual ~Atom() {} |
d696c285 | 234 | |
c2646906 A |
235 | uint64_t fSegmentOffset; |
236 | uint64_t fSectionOffset; | |
237 | unsigned int fSortOrder; | |
238 | class Section* fSection; | |
239 | }; | |
240 | ||
241 | ||
242 | ||
243 | // recursively sets follow-on atoms | |
244 | inline unsigned int Atom::setSortOrder(unsigned int order) | |
245 | { | |
246 | if ( this->requiresFollowOnAtom() ) { | |
247 | fSortOrder = order; | |
248 | return this->getFollowOnAtom().setSortOrder(order+1); | |
249 | } | |
250 | else { | |
251 | fSortOrder = order; | |
252 | return (order + 1); | |
253 | } | |
254 | } | |
255 | ||
256 | ||
257 | ||
d696c285 A |
258 | // |
259 | // A Reference is a directed edge to another Atom. When an instruction in | |
260 | // the content of an Atom refers to another Atom, that is represented by a | |
261 | // Reference. | |
262 | // | |
263 | // There are two kinds of references: direct and by-name. With a direct Reference, | |
264 | // the target is bound by the Reader that created it. For instance a reference to a | |
265 | // static would produce a direct reference. A by-name reference requires the linker | |
266 | // to find the target Atom with the required name in order to be bound. | |
267 | // | |
268 | // For a link to succeed all References must be bound. | |
269 | // | |
270 | // A Reference has an optional "from" target. This is used when the content to fix-up | |
271 | // is the difference of two Atom address. For instance, if a pointer sized data Atom | |
272 | // is to contain A - B, then the Atom would have on Reference with a target of "A" and | |
273 | // a from-target of "B". | |
274 | // | |
275 | // A Reference also has a fix-up-offset. This is the offset into the content of the | |
276 | // Atom holding the reference where the fix-up (relocation) will be applied. | |
277 | // | |
278 | // | |
279 | // | |
c2646906 A |
280 | class Reference |
281 | { | |
282 | public: | |
c2646906 | 283 | |
6e880c60 A |
284 | virtual bool isTargetUnbound() const = 0; |
285 | virtual bool isFromTargetUnbound() const = 0; | |
d696c285 | 286 | virtual uint8_t getKind() const = 0; |
c2646906 A |
287 | virtual uint64_t getFixUpOffset() const = 0; |
288 | virtual const char* getTargetName() const = 0; | |
289 | virtual Atom& getTarget() const = 0; | |
290 | virtual uint64_t getTargetOffset() const = 0; | |
6e880c60 | 291 | virtual bool hasFromTarget() const = 0; |
c2646906 A |
292 | virtual Atom& getFromTarget() const = 0; |
293 | virtual const char* getFromTargetName() const = 0; | |
294 | virtual uint64_t getFromTargetOffset() const = 0; | |
295 | ||
6e880c60 | 296 | virtual void setTarget(Atom&, uint64_t offset) = 0; |
c2646906 A |
297 | virtual void setFromTarget(Atom&) = 0; |
298 | virtual const char* getDescription() const = 0; | |
d696c285 | 299 | |
6e880c60 A |
300 | protected: |
301 | Reference() {} | |
302 | virtual ~Reference() {} | |
c2646906 A |
303 | }; |
304 | ||
305 | ||
306 | }; // namespace ObjectFile | |
307 | ||
308 | ||
309 | #endif // __OBJECTFILE__ |