• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- Core/DefinedAtom.h - An Atom with content --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLD_CORE_DEFINED_ATOM_H
10 #define LLD_CORE_DEFINED_ATOM_H
11 
12 #include "lld/Common/LLVM.h"
13 #include "lld/Core/Atom.h"
14 #include "lld/Core/Reference.h"
15 #include "llvm/Support/ErrorHandling.h"
16 
17 namespace lld {
18 class File;
19 
20 /// The fundamental unit of linking.
21 ///
22 /// A C function or global variable is an atom.  An atom has content and
23 /// attributes. The content of a function atom is the instructions that
24 /// implement the function.  The content of a global variable atom is its
25 /// initial bytes.
26 ///
27 /// Here are some example attribute sets for common atoms. If a particular
28 /// attribute is not listed, the default values are:  definition=regular,
29 /// sectionChoice=basedOnContent, scope=translationUnit, merge=no,
30 /// deadStrip=normal, interposable=no
31 ///
32 ///  C function:  void foo() {} <br>
33 ///    name=foo, type=code, perm=r_x, scope=global
34 ///
35 ///  C static function:  staic void func() {} <br>
36 ///    name=func, type=code, perm=r_x
37 ///
38 ///  C global variable:  int count = 1; <br>
39 ///    name=count, type=data, perm=rw_, scope=global
40 ///
41 ///  C tentative definition:  int bar; <br>
42 ///    name=bar, type=zerofill, perm=rw_, scope=global,
43 ///    merge=asTentative, interposable=yesAndRuntimeWeak
44 ///
45 ///  Uninitialized C static variable:  static int stuff; <br>
46 ///    name=stuff, type=zerofill, perm=rw_
47 ///
48 ///  Weak C function:  __attribute__((weak)) void foo() {} <br>
49 ///    name=foo, type=code, perm=r_x, scope=global, merge=asWeak
50 ///
51 ///  Hidden C function:  __attribute__((visibility("hidden"))) void foo() {}<br>
52 ///    name=foo, type=code, perm=r_x, scope=linkageUnit
53 ///
54 ///  No-dead-strip function:  __attribute__((used)) void foo() {} <br>
55 ///    name=foo, type=code, perm=r_x, scope=global, deadStrip=never
56 ///
57 ///  Non-inlined C++ inline method:  inline void Foo::doit() {} <br>
58 ///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global,
59 ///    mergeDupes=asWeak
60 ///
61 ///  Non-inlined C++ inline method whose address is taken:
62 ///     inline void Foo::doit() {} <br>
63 ///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global,
64 ///    mergeDupes=asAddressedWeak
65 ///
66 ///  literal c-string:  "hello" <br>
67 ///    name="" type=cstring, perm=r__, scope=linkageUnit
68 ///
69 ///  literal double:  1.234 <br>
70 ///    name="" type=literal8, perm=r__, scope=linkageUnit
71 ///
72 ///  constant:  { 1,2,3 } <br>
73 ///    name="" type=constant, perm=r__, scope=linkageUnit
74 ///
75 ///  Pointer to initializer function:  <br>
76 ///    name="" type=initializer, perm=rw_l,
77 ///    sectionChoice=customRequired
78 ///
79 ///  C function place in custom section:  __attribute__((section("__foo")))
80 ///                                       void foo() {} <br>
81 ///    name=foo, type=code, perm=r_x, scope=global,
82 ///    sectionChoice=customRequired, customSectionName=__foo
83 ///
84 class DefinedAtom : public Atom {
85 public:
86   enum Interposable {
87     interposeNo,            // linker can directly bind uses of this atom
88     interposeYes,           // linker must indirect (through GOT) uses
89     interposeYesAndRuntimeWeak // must indirect and mark symbol weak in final
90                                // linked image
91   };
92 
93   enum Merge {
94     mergeNo,                // Another atom with same name is error
95     mergeAsTentative,       // Is ANSI C tentative definition, can be coalesced
96     mergeAsWeak,            // Is C++ inline definition that was not inlined,
97                             // but address was not taken, so atom can be hidden
98                             // by linker
99     mergeAsWeakAndAddressUsed, // Is C++ definition inline definition whose
100                                // address was taken.
101     mergeSameNameAndSize,   // Another atom with different size is error
102     mergeByLargestSection,  // Choose an atom whose section is the largest.
103     mergeByContent,         // Merge with other constants with same content.
104   };
105 
106   enum ContentType {
107     typeUnknown,            // for use with definitionUndefined
108     typeMachHeader,         // atom representing mach_header [Darwin]
109     typeCode,               // executable code
110     typeResolver,           // function which returns address of target
111     typeBranchIsland,       // linker created for large binaries
112     typeBranchShim,         // linker created to switch thumb mode
113     typeStub,               // linker created for calling external function
114     typeStubHelper,         // linker created for initial stub binding
115     typeConstant,           // a read-only constant
116     typeCString,            // a zero terminated UTF8 C string
117     typeUTF16String,        // a zero terminated UTF16 string
118     typeCFI,                // a FDE or CIE from dwarf unwind info
119     typeLSDA,               // extra unwinding info
120     typeLiteral4,           // a four-btye read-only constant
121     typeLiteral8,           // an eight-btye read-only constant
122     typeLiteral16,          // a sixteen-btye read-only constant
123     typeData,               // read-write data
124     typeDataFast,           // allow data to be quickly accessed
125     typeZeroFill,           // zero-fill data
126     typeZeroFillFast,       // allow zero-fill data to be quicky accessed
127     typeConstData,          // read-only data after dynamic linker is done
128     typeObjC1Class,         // ObjC1 class [Darwin]
129     typeLazyPointer,        // pointer through which a stub jumps
130     typeLazyDylibPointer,   // pointer through which a stub jumps [Darwin]
131     typeNonLazyPointer,     // pointer to external symbol
132     typeCFString,           // NS/CFString object [Darwin]
133     typeGOT,                // pointer to external symbol
134     typeInitializerPtr,     // pointer to initializer function
135     typeTerminatorPtr,      // pointer to terminator function
136     typeCStringPtr,         // pointer to UTF8 C string [Darwin]
137     typeObjCClassPtr,       // pointer to ObjC class [Darwin]
138     typeObjC2CategoryList,  // pointers to ObjC category [Darwin]
139     typeObjCImageInfo,      // pointer to ObjC class [Darwin]
140     typeObjCMethodList,     // pointer to ObjC method list [Darwin]
141     typeDTraceDOF,          // runtime data for Dtrace [Darwin]
142     typeInterposingTuples,  // tuples of interposing info for dyld [Darwin]
143     typeTempLTO,            // temporary atom for bitcode reader
144     typeCompactUnwindInfo,  // runtime data for unwinder [Darwin]
145     typeProcessedUnwindInfo,// compressed compact unwind info [Darwin]
146     typeThunkTLV,           // thunk used to access a TLV [Darwin]
147     typeTLVInitialData,     // initial data for a TLV [Darwin]
148     typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
149     typeTLVInitializerPtr,  // pointer to thread local initializer [Darwin]
150     typeDSOHandle,          // atom representing DSO handle [Darwin]
151     typeSectCreate,         // Created via the -sectcreate option [Darwin]
152   };
153 
154   // Permission bits for atoms and segments. The order of these values are
155   // important, because the layout pass may sort atoms by permission if other
156   // attributes are the same.
157   enum ContentPermissions {
158     perm___  = 0,           // mapped as unaccessible
159     permR__  = 8,           // mapped read-only
160     permRW_  = 8 + 2,       // mapped readable and writable
161     permRW_L = 8 + 2 + 1,   // initially mapped r/w, then made read-only
162                             // loader writable
163     permR_X  = 8 + 4,       // mapped readable and executable
164     permRWX  = 8 + 2 + 4,   // mapped readable and writable and executable
165     permUnknown = 16        // unknown or invalid permissions
166   };
167 
168   enum SectionChoice {
169     sectionBasedOnContent,  // linker infers final section based on content
170     sectionCustomPreferred, // linker may place in specific section
171     sectionCustomRequired   // linker must place in specific section
172   };
173 
174   enum DeadStripKind {
175     deadStripNormal,        // linker may dead strip this atom
176     deadStripNever,         // linker must never dead strip this atom
177     deadStripAlways         // linker must remove this atom if unused
178   };
179 
180   enum DynamicExport {
181     /// The linker may or may not export this atom dynamically depending
182     ///   on the output type and other context of the link.
183     dynamicExportNormal,
184     /// The linker will always export this atom dynamically.
185     dynamicExportAlways,
186   };
187 
188   // Attributes describe a code model used by the atom.
189   enum CodeModel {
190     codeNA,           // no specific code model
191     // MIPS code models
192     codeMipsPIC,      // PIC function in a PIC / non-PIC mixed file
193     codeMipsMicro,    // microMIPS instruction encoding
194     codeMipsMicroPIC, // microMIPS instruction encoding + PIC
195     codeMips16,       // MIPS-16 instruction encoding
196     // ARM code models
197     codeARMThumb,     // ARM Thumb instruction set
198     codeARM_a,        // $a-like mapping symbol (for ARM code)
199     codeARM_d,        // $d-like mapping symbol (for data)
200     codeARM_t,        // $t-like mapping symbol (for Thumb code)
201   };
202 
203   struct Alignment {
valueAlignment204     Alignment(int v, int m = 0) : value(v), modulus(m) {}
205 
206     uint16_t value;
207     uint16_t modulus;
208 
209     bool operator==(const Alignment &rhs) const {
210       return (value == rhs.value) && (modulus == rhs.modulus);
211     }
212   };
213 
214   /// returns a value for the order of this Atom within its file.
215   ///
216   /// This is used by the linker to order the layout of Atoms so that the
217   /// resulting image is stable and reproducible.
218   virtual uint64_t ordinal() const = 0;
219 
220   /// the number of bytes of space this atom's content will occupy in the
221   /// final linked image.
222   ///
223   /// For a function atom, it is the number of bytes of code in the function.
224   virtual uint64_t size() const = 0;
225 
226   /// The size of the section from which the atom is instantiated.
227   ///
228   /// Merge::mergeByLargestSection is defined in terms of section size
229   /// and not in terms of atom size, so we need this function separate
230   /// from size().
sectionSize()231   virtual uint64_t sectionSize() const { return 0; }
232 
233   /// The visibility of this atom to other atoms.
234   ///
235   /// C static functions have scope scopeTranslationUnit.  Regular C functions
236   /// have scope scopeGlobal.  Functions compiled with visibility=hidden have
237   /// scope scopeLinkageUnit so they can be see by other atoms being linked but
238   /// not by the OS loader.
239   virtual Scope scope() const = 0;
240 
241   /// Whether the linker should use direct or indirect access to this
242   /// atom.
243   virtual Interposable interposable() const = 0;
244 
245   /// how the linker should handle if multiple atoms have the same name.
246   virtual Merge merge() const = 0;
247 
248   /// The type of this atom, such as code or data.
249   virtual ContentType contentType() const = 0;
250 
251   /// The alignment constraints on how this atom must be laid out in the
252   /// final linked image (e.g. 16-byte aligned).
253   virtual Alignment alignment() const = 0;
254 
255   /// Whether this atom must be in a specially named section in the final
256   /// linked image, or if the linker can infer the section based on the
257   /// contentType().
258   virtual SectionChoice sectionChoice() const = 0;
259 
260   /// If sectionChoice() != sectionBasedOnContent, then this return the
261   /// name of the section the atom should be placed into.
262   virtual StringRef customSectionName() const = 0;
263 
264   /// constraints on whether the linker may dead strip away this atom.
265   virtual DeadStripKind deadStrip() const = 0;
266 
267   /// Under which conditions should this atom be dynamically exported.
dynamicExport()268   virtual DynamicExport dynamicExport() const {
269     return dynamicExportNormal;
270   }
271 
272   /// Code model used by the atom.
codeModel()273   virtual CodeModel codeModel() const { return codeNA; }
274 
275   /// Returns the OS memory protections required for this atom's content
276   /// at runtime.
277   ///
278   /// A function atom is R_X, a global variable is RW_, and a read-only constant
279   /// is R__.
280   virtual ContentPermissions permissions() const;
281 
282   /// returns a reference to the raw (unrelocated) bytes of this Atom's
283   /// content.
284   virtual ArrayRef<uint8_t> rawContent() const = 0;
285 
286   /// This class abstracts iterating over the sequence of References
287   /// in an Atom.  Concrete instances of DefinedAtom must implement
288   /// the derefIterator() and incrementIterator() methods.
289   class reference_iterator {
290   public:
reference_iterator(const DefinedAtom & a,const void * it)291     reference_iterator(const DefinedAtom &a, const void *it)
292       : _atom(a), _it(it) { }
293 
294     const Reference *operator*() const {
295       return _atom.derefIterator(_it);
296     }
297 
298     const Reference *operator->() const {
299       return _atom.derefIterator(_it);
300     }
301 
302     bool operator==(const reference_iterator &other) const {
303       return _it == other._it;
304     }
305 
306     bool operator!=(const reference_iterator &other) const {
307       return !(*this == other);
308     }
309 
310     reference_iterator &operator++() {
311       _atom.incrementIterator(_it);
312       return *this;
313     }
314   private:
315     const DefinedAtom &_atom;
316     const void *_it;
317   };
318 
319   /// Returns an iterator to the beginning of this Atom's References.
320   virtual reference_iterator begin() const = 0;
321 
322   /// Returns an iterator to the end of this Atom's References.
323   virtual reference_iterator end() const = 0;
324 
325   /// Adds a reference to this atom.
addReference(Reference::KindNamespace ns,Reference::KindArch arch,Reference::KindValue kindValue,uint64_t off,const Atom * target,Reference::Addend a)326   virtual void addReference(Reference::KindNamespace ns,
327                             Reference::KindArch arch,
328                             Reference::KindValue kindValue, uint64_t off,
329                             const Atom *target, Reference::Addend a) {
330     llvm_unreachable("Subclass does not permit adding references");
331   }
332 
classof(const Atom * a)333   static bool classof(const Atom *a) {
334     return a->definition() == definitionRegular;
335   }
336 
337   /// Utility for deriving permissions from content type
338   static ContentPermissions permissions(ContentType type);
339 
340   /// Utility function to check if the atom occupies file space
occupiesDiskSpace()341   bool occupiesDiskSpace() const {
342     ContentType atomContentType = contentType();
343     return !(atomContentType == DefinedAtom::typeZeroFill ||
344              atomContentType == DefinedAtom::typeZeroFillFast ||
345              atomContentType == DefinedAtom::typeTLVInitialZeroFill);
346   }
347 
348   /// Utility function to check if relocations in this atom to other defined
349   /// atoms can be implicitly generated, and so we don't need to explicitly
350   /// emit those relocations.
relocsToDefinedCanBeImplicit()351   bool relocsToDefinedCanBeImplicit() const {
352     ContentType atomContentType = contentType();
353     return atomContentType == typeCFI;
354   }
355 
356 protected:
357   // DefinedAtom is an abstract base class. Only subclasses can access
358   // constructor.
DefinedAtom()359   DefinedAtom() : Atom(definitionRegular) { }
360 
361   ~DefinedAtom() override = default;
362 
363   /// Returns a pointer to the Reference object that the abstract
364   /// iterator "points" to.
365   virtual const Reference *derefIterator(const void *iter) const = 0;
366 
367   /// Adjusts the abstract iterator to "point" to the next Reference
368   /// object for this Atom.
369   virtual void incrementIterator(const void *&iter) const = 0;
370 };
371 } // end namespace lld
372 
373 #endif
374