1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
26 #ifndef __OBJECTFILE__
27 #define __OBJECTFILE__
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.
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.
43 // A Writer takes a vector of Atoms with all References resolved and produces an executable file.
48 namespace ObjectFile
{
62 ReaderOptions() : fFullyLoadArchives(false), fLoadObjcClassesInArchives(false), fFlatNamespace(false),
63 fDebugInfoStripping(kDebugInfoFull
), fTraceDylibs(false), fTraceIndirectDylibs(false), fTraceArchives(false), fTraceOutputFile(NULL
) {}
64 enum DebugInfoStripping
{ kDebugInfoNone
, kDebugInfoMinimal
, kDebugInfoFull
};
66 bool fFullyLoadArchives
;
67 bool fLoadObjcClassesInArchives
;
69 DebugInfoStripping fDebugInfoStripping
;
71 bool fTraceIndirectDylibs
;
73 const char* fTraceOutputFile
;
80 enum DebugInfoKind
{ kDebugInfoNone
=0, kDebugInfoStabs
=1, kDebugInfoDwarf
=2, kDebugInfoStabsUUID
=3 };
91 static Reader
* createReader(const char* path
, const ReaderOptions
& options
);
93 virtual const char* getPath() = 0;
94 virtual time_t getModificationTime() = 0;
95 virtual DebugInfoKind
getDebugInfoKind() = 0;
96 virtual std::vector
<class Atom
*>& getAtoms() = 0;
97 virtual std::vector
<class Atom
*>* getJustInTimeAtomsFor(const char* name
) = 0;
98 virtual std::vector
<Stab
>* getStabs() = 0;
99 unsigned int getSortOrder() const { return fSortOrder
; }
100 void setSortOrder(unsigned int order
) { fSortOrder
=order
; }
102 // For Dynamic Libraries only
103 virtual const char* getInstallPath() { return NULL
; }
104 virtual uint32_t getTimestamp() { return 0; }
105 virtual uint32_t getCurrentVersion() { return 0; }
106 virtual uint32_t getCompatibilityVersion() { return 0; }
107 virtual std::vector
<const char*>* getDependentLibraryPaths() { return NULL
; }
108 virtual bool reExports(Reader
*) { return false; }
109 virtual const char* parentUmbrella() { return NULL
; }
110 virtual std::vector
<const char*>* getAllowableClients() { return NULL
; }
113 Reader() : fSortOrder(0) {}
116 unsigned int fSortOrder
;
122 virtual const char* getName() const = 0;
123 virtual bool isContentReadable() const = 0;
124 virtual bool isContentWritable() const = 0;
125 virtual bool isContentExecutable() const = 0;
127 uint64_t getBaseAddress() const { return fBaseAddress
; }
128 void setBaseAddress(uint64_t addr
) { fBaseAddress
= addr
; }
129 virtual bool hasFixedAddress() const { return false; }
132 Segment() : fBaseAddress(0) {}
133 virtual ~Segment() {}
134 uint64_t fBaseAddress
;
142 unsigned int getIndex() { return fIndex
; }
143 uint64_t getBaseAddress() { return fBaseAddress
; }
144 void setBaseAddress(uint64_t addr
) { fBaseAddress
= addr
; }
148 Section() : fOther(NULL
), fBaseAddress(0), fIndex(0) {}
149 uint64_t fBaseAddress
;
156 // An atom is the fundamental unit of linking. A C function or global variable is an atom.
157 // An atom has content and some attributes. The content of a function atom is the instructions
158 // that implement the function. The content of a global variable atom is its initial bits.
161 // The name of an atom is the label name generated by the compiler. A C compiler names foo()
162 // as _foo. A C++ compiler names foo() as __Z3foov.
163 // The name refers to the first byte of the content. An atom cannot have multiple entry points.
164 // Such code is modeled as multiple atoms, each having a "follow on" reference to the next.
165 // A "follow on" reference is a contraint to the linker to the atoms must be laid out contiguously.
168 // An atom is in one of three scopes: translation-unit, linkage-unit, or global. These correspond
169 // to the C visibility of static, hidden, default.
172 // An atom is one of five defintion kinds:
173 // regular Most atoms.
174 // weak C++ compiler makes some functions weak if there might be multiple copies
175 // that the linker needs to coalesce.
176 // tentative A straggler from ancient C when the extern did not exist. "int foo;" is ambiguous.
177 // It could be a prototype or it could be a definition.
178 // external This is a "proxy" atom produced by a dylib reader. It has no content. It exists
179 // so that all References can be resolved.
180 // external-weak Same as external, but the definition in the dylib is weak.
182 // SymbolTableInclusion:
183 // An atom may or may not be in the symbol table in an object file.
184 // in Most atoms for functions or global data
185 // not-in Anonymous atoms such literal c-strings, or other compiler generated data
186 // in-never-strip Atom whose name the strip tool should never remove (e.g. REFERENCED_DYNAMICALLY in mach-o)
191 enum Scope
{ scopeTranslationUnit
, scopeLinkageUnit
, scopeGlobal
};
192 enum DefinitionKind
{ kRegularDefinition
, kWeakDefinition
, kTentativeDefinition
, kExternalDefinition
, kExternalWeakDefinition
};
193 enum SymbolTableInclusion
{ kSymbolTableNotIn
, kSymbolTableIn
, kSymbolTableInAndNeverStrip
};
195 virtual Reader
* getFile() const = 0;
196 virtual bool getTranslationUnitSource(const char** dir
, const char** name
) const = 0;
197 virtual const char* getName() const = 0;
198 virtual const char* getDisplayName() const = 0;
199 virtual Scope
getScope() const = 0;
200 virtual DefinitionKind
getDefinitionKind() const = 0;
201 virtual SymbolTableInclusion
getSymbolTableInclusion() const = 0;
202 virtual bool isZeroFill() const = 0;
203 virtual uint64_t getSize() const = 0;
204 virtual std::vector
<ObjectFile::Reference
*>& getReferences() const = 0;
205 virtual bool mustRemainInSection() const = 0;
206 virtual const char* getSectionName() const = 0;
207 virtual Segment
& getSegment() const = 0;
208 virtual bool requiresFollowOnAtom() const = 0;
209 virtual Atom
& getFollowOnAtom() const = 0;
210 virtual std::vector
<LineInfo
>* getLineInfo() const = 0;
211 virtual uint8_t getAlignment() const = 0;
212 virtual void copyRawContent(uint8_t buffer
[]) const = 0;
213 virtual void setScope(Scope
) = 0;
216 uint64_t getSectionOffset() const { return fSectionOffset
; }
217 uint64_t getSegmentOffset() const { return fSegmentOffset
; }
218 uint64_t getAddress() const { return fSection
->getBaseAddress() + fSectionOffset
; }
219 unsigned int getSortOrder() const { return fSortOrder
; }
220 class Section
* getSection() const { return fSection
; }
221 bool dontDeadStrip() const { return fDontDeadStrip
; }
223 void setSegmentOffset(uint64_t offset
) { fSegmentOffset
= offset
; }
224 void setSectionOffset(uint64_t offset
) { fSectionOffset
= offset
; }
225 void setSection(class Section
* sect
) { fSection
= sect
; }
226 unsigned int setSortOrder(unsigned int order
); // recursively sets follow-on atoms
227 void setDontDeadStrip() { fDontDeadStrip
= true; }
230 Atom() : fSegmentOffset(0), fSectionOffset(0), fSortOrder(0), fSection(NULL
), fDontDeadStrip(false) {}
233 uint64_t fSegmentOffset
;
234 uint64_t fSectionOffset
;
235 unsigned int fSortOrder
;
236 class Section
* fSection
;
242 // recursively sets follow-on atoms
243 inline unsigned int Atom::setSortOrder(unsigned int order
)
245 if ( this->requiresFollowOnAtom() ) {
247 return this->getFollowOnAtom().setSortOrder(order
+1);
258 // A Reference is a directed edge to another Atom. When an instruction in
259 // the content of an Atom refers to another Atom, that is represented by a
262 // There are two kinds of references: direct and by-name. With a direct Reference,
263 // the target is bound by the Reader that created it. For instance a reference to a
264 // static would produce a direct reference. A by-name reference requires the linker
265 // to find the target Atom with the required name in order to be bound.
267 // For a link to succeed all References must be bound.
269 // A Reference has an optional "from" target. This is used when the content to fix-up
270 // is the difference of two Atom address. For instance, if a pointer sized data Atom
271 // is to contain A - B, then the Atom would have on Reference with a target of "A" and
272 // a from-target of "B".
274 // A Reference also has a fix-up-offset. This is the offset into the content of the
275 // Atom holding the reference where the fix-up (relocation) will be applied.
283 virtual bool isTargetUnbound() const = 0;
284 virtual bool isFromTargetUnbound() const = 0;
285 virtual uint8_t getKind() const = 0;
286 virtual uint64_t getFixUpOffset() const = 0;
287 virtual const char* getTargetName() const = 0;
288 virtual Atom
& getTarget() const = 0;
289 virtual uint64_t getTargetOffset() const = 0;
290 virtual bool hasFromTarget() const = 0;
291 virtual Atom
& getFromTarget() const = 0;
292 virtual const char* getFromTargetName() const = 0;
293 virtual uint64_t getFromTargetOffset() const = 0;
295 virtual void setTarget(Atom
&, uint64_t offset
) = 0;
296 virtual void setFromTarget(Atom
&) = 0;
297 virtual const char* getDescription() const = 0;
301 virtual ~Reference() {}
305 }; // namespace ObjectFile
308 #endif // __OBJECTFILE__