blob: 05bbf15e780aedcb835067bf89f7d106e6d7dd8d [file] [log] [blame]
//===- Core/DefinedAtom.h - The Fundamental Unit of Linking ---------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_CORE_DEFINED_ATOM_H_
#define LLD_CORE_DEFINED_ATOM_H_
#include "lld/Core/Atom.h"
#include "lld/Core/Reference.h"
namespace llvm {
template <typename T>
class ArrayRef;
class StringRef;
}
namespace lld {
class File;
/// An atom is the fundamental unit of linking. A C function or global variable
/// is an atom. An atom has content and attributes. The content of a function
/// atom is the instructions that implement the function. The content of a
/// global variable atom is its initial bytes.
///
/// Here are some example attribute sets for common atoms. If a particular
/// attribute is not listed, the default values are: definition=regular,
/// sectionChoice=basedOnContent, scope=translationUnit, merge=no,
/// deadStrip=normal, interposable=no
///
/// C function: void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global
///
/// C static function: staic void func() {} <br>
/// name=func, type=code, perm=r_x
///
/// C global variable: int count = 1; <br>
/// name=count, type=data, perm=rw_, scope=global
///
/// C tentative definition: int bar; <br>
/// name=bar, type=zerofill, perm=rw_, scope=global,
/// merge=asTentative, interposable=yesAndRuntimeWeak
///
/// Uninitialized C static variable: static int stuff; <br>
/// name=stuff, type=zerofill, perm=rw_
///
/// Weak C function: __attribute__((weak)) void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global, merge=asWeak
///
/// Hidden C function: __attribute__((visibility("hidden"))) void foo() {}<br>
/// name=foo, type=code, perm=r_x, scope=linkageUnit
///
/// No-dead-strip function: __attribute__((used)) void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global, deadStrip=never
///
/// Non-inlined C++ inline method: inline void Foo::doit() {} <br>
/// name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global,
/// mergeDupes=asWeak
///
/// Non-inlined C++ inline method whose address is taken:
/// inline void Foo::doit() {} <br>
/// name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global,
/// mergeDupes=asAddressedWeak
///
/// literal c-string: "hello" <br>
/// name="" type=cstring, perm=r__, scope=linkageUnit
///
/// literal double: 1.234 <br>
/// name="" type=literal8, perm=r__, scope=linkageUnit
///
/// constant: { 1,2,3 } <br>
/// name="" type=constant, perm=r__, scope=linkageUnit
///
/// Pointer to initializer function: <br>
/// name="" type=initializer, perm=rw_l,
/// sectionChoice=customRequired
///
/// C function place in custom section: __attribute__((section("__foo")))
/// void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global,
/// sectionChoice=customRequired, sectionName=__foo
///
class DefinedAtom : public Atom {
public:
/// The scope in which this atom is acessible to other atoms.
enum Scope {
scopeTranslationUnit, ///< Accessible only to atoms in the same translation
/// unit (e.g. a C static).
scopeLinkageUnit, ///< Accessible to atoms being linked but not visible
/// to runtime loader (e.g. visibility=hidden).
scopeGlobal ///< Accessible to all atoms and visible to runtime
/// loader (e.g. visibility=default).
};
enum Interposable {
interposeNo, // linker can directly bind uses of this atom
interposeYes, // linker must indirect (through GOT) uses
interposeYesAndRuntimeWeak // must indirect and mark symbol weak in final
// linked image
};
enum Merge {
mergeNo, // Another atom with same name is error
mergeAsTentative, // Is ANSI C tentative defintion, can be coalesced
mergeAsWeak, // is C++ inline definition that was not inlined,
// but address was not taken, so atom can be hidden
// by linker
mergeAsWeakAndAddressUsed // is C++ definition inline definition whose
// address was taken.
};
enum ContentType {
typeUnknown, // for use with definitionUndefined
typeCode, // executable code
typeResolver, // function which returns address of target
typeBranchIsland, // linker created for large binaries
typeBranchShim, // linker created to switch thumb mode
typeStub, // linker created for calling external function
typeStubHelper, // linker created for initial stub binding
typeConstant, // a read-only constant
typeCString, // a zero terminated UTF8 C string
typeUTF16String, // a zero terminated UTF16 string
typeCFI, // a FDE or CIE from dwarf unwind info
typeLSDA, // extra unwinding info
typeLiteral4, // a four-btye read-only constant
typeLiteral8, // an eight-btye read-only constant
typeLiteral16, // a sixteen-btye read-only constant
typeData, // read-write data
typeZeroFill, // zero-fill data
typeObjC1Class, // ObjC1 class [Darwin]
typeLazyPointer, // pointer through which a stub jumps
typeLazyDylibPointer, // pointer through which a stub jumps [Darwin]
typeCFString, // NS/CFString object [Darwin]
typeGOT, // pointer to external symbol
typeInitializerPtr, // pointer to initializer function
typeTerminatorPtr, // pointer to terminator function
typeCStringPtr, // pointer to UTF8 C string [Darwin]
typeObjCClassPtr, // pointer to ObjC class [Darwin]
typeObjC2CategoryList, // pointers to ObjC category [Darwin]
typeDTraceDOF, // runtime data for Dtrace [Darwin]
typeTempLTO, // temporary atom for bitcode reader
typeCompactUnwindInfo, // runtime data for unwinder [Darwin]
typeThunkTLV, // thunk used to access a TLV [Darwin]
typeTLVInitialData, // initial data for a TLV [Darwin]
typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
typeTLVInitializerPtr, // pointer to thread local initializer [Darwin]
typeFirstInSection, // label for boundary of section [Darwin]
typeLastInSection, // label for boundary of section [Darwin]
};
enum ContentPermissions {
perm___ = 0, // mapped as unaccessible
permR__ = 8, // mapped read-only
permR_X = 8 + 2, // mapped readable and executable
permRW_ = 8 + 4, // mapped readable and writable
permRW_L = 8 + 4 + 1, // initially mapped r/w, then made read-only
// loader writable
};
enum SectionChoice {
sectionBasedOnContent, // linker infers final section based on content
sectionCustomPreferred, // linker may place in specific section
sectionCustomRequired // linker must place in specific section
};
enum DeadStripKind {
deadStripNormal, // linker may dead strip this atom
deadStripNever, // linker must never dead strip this atom
deadStripAlways // linker must remove this atom if unused
};
struct Alignment {
Alignment(int p2, int m = 0)
: powerOf2(p2)
, modulus(m) {}
uint16_t powerOf2;
uint16_t modulus;
};
/// ordinal - returns a value for the order of this Atom within its file.
/// This is used by the linker to order the layout of Atoms so that
/// the resulting image is stable and reproducible.
virtual uint64_t ordinal() const = 0;
/// size - the number of bytes of space this atom's content will occupy
/// in the final linked image. For a function atom, it is the number
/// of bytes of code in the function.
virtual uint64_t size() const = 0;
/// scope - The visibility of this atom to other atoms. C static functions
/// have scope scopeTranslationUnit. Regular C functions have scope
/// scopeGlobal. Functions compiled with visibility=hidden have scope
/// scopeLinkageUnit so they can be see by other atoms being linked but not
/// by the OS loader.
virtual Scope scope() const = 0;
/// interposable - Whether the linker should use direct or indirect
/// access to this atom.
virtual Interposable interposable() const = 0;
/// merge - how the linker should handle if multiple atoms have
/// the same name.
virtual Merge merge() const = 0;
/// contentType - The type of this atom, such as code or data.
virtual ContentType contentType() const = 0;
/// alignment - The alignment constraints on how this atom must be laid out
/// in the final linked image (e.g. 16-byte aligned).
virtual Alignment alignment() const = 0;
/// sectionChoice - Whether this atom must be in a specially named section
/// in the final linked image, or if the linker can infer the section
/// based on the contentType().
virtual SectionChoice sectionChoice() const = 0;
/// customSectionName - If sectionChoice() != sectionBasedOnContent, then
/// this return the name of the section the atom should be placed into.
virtual StringRef customSectionName() const = 0;
/// deadStrip - constraints on whether the linker may dead strip away
/// this atom.
virtual DeadStripKind deadStrip() const = 0;
/// permissions - Returns the OS memory protections required for this atom's
/// content at runtime. A function atom is R_X, a global variable is RW_,
/// and a read-only constant is R__.
virtual ContentPermissions permissions() const = 0;
/// isThumb - only applicable to ARM code. Tells the linker if the code
/// uses thumb or arm instructions. The linker needs to know this to
/// set the low bit of pointers to thumb functions.
virtual bool isThumb() const = 0;
/// isAlias - means this is a zero size atom that exists to provide an
/// alternate name for another atom. Alias atoms must have a special
/// Reference to the atom they alias which the layout engine recognizes
/// and forces the alias atom to layout right before the target atom.
virtual bool isAlias() const = 0;
/// rawContent - returns a reference to the raw (unrelocated) bytes of
/// this Atom's content.
virtual ArrayRef<uint8_t> rawContent() const = 0;
/// This class abstracts iterating over the sequence of References
/// in an Atom. Concrete instances of DefinedAtom must implement
/// the derefIterator() and incrementIterator() methods.
class reference_iterator {
public:
reference_iterator(const DefinedAtom& a, const void* it)
: _atom(a), _it(it) { }
const Reference* operator*() const {
return _atom.derefIterator(_it);
}
const Reference* operator->() const {
return _atom.derefIterator(_it);
}
bool operator!=(const reference_iterator& other) const {
return (this->_it != other._it);
}
reference_iterator& operator++() {
_atom.incrementIterator(_it);
return *this;
}
private:
const DefinedAtom& _atom;
const void* _it;
};
/// Returns an iterator to the beginning of this Atom's References
virtual reference_iterator begin() const = 0;
/// Returns an iterator to the end of this Atom's References
virtual reference_iterator end() const = 0;
static inline bool classof(const Atom *a) {
return a->definition() == definitionRegular;
}
static inline bool classof(const DefinedAtom *) { return true; }
protected:
/// DefinedAtom is an abstract base class.
/// Only subclasses can access constructor.
DefinedAtom() : Atom(definitionRegular) { }
/// The memory for DefinedAtom objects is always managed by the owning File
/// object. Therefore, no one but the owning File object should call
/// delete on an Atom. In fact, some File objects may bulk allocate
/// an array of Atoms, so they cannot be individually deleted by anyone.
virtual ~DefinedAtom() {}
/// Returns a pointer to the Reference object that the abstract
/// iterator "points" to.
virtual const Reference* derefIterator(const void* iter) const = 0;
/// Adjusts the abstract iterator to "point" to the next Reference object
/// for this Atom.
virtual void incrementIterator(const void*& iter) const = 0;
};
} // namespace lld
#endif // LLD_CORE_DEFINED_ATOM_H_