forked from OSchip/llvm-project
Cleaned up Atom attribues some more. Added lots of doxygen comments
llvm-svn: 147105
This commit is contained in:
parent
7869d8c01e
commit
f46669c828
|
@ -10,6 +10,8 @@
|
|||
#ifndef LLD_CORE_ATOM_H_
|
||||
#define LLD_CORE_ATOM_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "lld/Core/Reference.h"
|
||||
|
||||
namespace llvm {
|
||||
|
@ -27,21 +29,85 @@ class File;
|
|||
/// 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, mergeDups=false,
|
||||
/// autoHide=false, internalName=false, deadStrip=normal
|
||||
///
|
||||
/// 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=data, perm=rw_, scope=global, definition=tentative
|
||||
///
|
||||
/// 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, definition=weak
|
||||
///
|
||||
/// 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,
|
||||
/// mergeDups=true, autoHide=true
|
||||
///
|
||||
/// Non-inlined C++ inline method whose address is taken:
|
||||
/// inline void Foo::doit() {} <br>
|
||||
/// name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, mergeDups=true
|
||||
///
|
||||
/// literal c-string: "hello" <br>
|
||||
/// name=L0, internalName=true, type=cstring, perm=r__,
|
||||
/// scope=linkageUnit, mergeDups=true
|
||||
///
|
||||
/// literal double: 1.234 <br>
|
||||
/// name=L0, internalName=true, type=literal8, perm=r__,
|
||||
/// scope=linkageUnit, mergeDups=true
|
||||
///
|
||||
/// constant: { 1,2,3 } <br>
|
||||
/// name=L0, internalName=true, type=constant, perm=r__,
|
||||
/// scope=linkageUnit, mergeDups=true
|
||||
///
|
||||
/// Pointer to initializer function: <br>
|
||||
/// name=_init, internalName=true, 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 Atom {
|
||||
public:
|
||||
/// The scope in which this atom is acessible to other atoms.
|
||||
enum Scope {
|
||||
scopeTranslationUnit, // static, private to translation unit
|
||||
scopeLinkageUnit, // hidden, accessible to just atoms being linked
|
||||
scopeGlobal // default
|
||||
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) .
|
||||
};
|
||||
|
||||
/// Whether this atom is defined or a proxy for an undefined symbol
|
||||
enum Definition {
|
||||
definitionRegular, // usual C/C++ function or global variable
|
||||
definitionWeak, // can be silently overridden by regular definition
|
||||
definitionTentative, // C-only pre-ANSI support aka common
|
||||
definitionAbsolute, // asm-only (foo = 10) not tied to any content
|
||||
definitionUndefined, // Only in .o files to model reference to undef
|
||||
definitionSharedLibrary // Only in shared libraries to model export
|
||||
definitionRegular, ///< Normal C/C++ function or global variable.
|
||||
definitionWeak, ///< Can be silently overridden by definitionRegular
|
||||
definitionTentative, ///< C-only pre-ANSI support aka common.
|
||||
definitionAbsolute, ///< Asm-only (foo = 10). Not tied to any content.
|
||||
definitionUndefined, ///< Only in .o files to model reference to undef.
|
||||
definitionSharedLibrary ///< Only in shared libraries to model export.
|
||||
};
|
||||
|
||||
enum ContentType {
|
||||
|
@ -113,13 +179,8 @@ public:
|
|||
uint16_t modulus;
|
||||
};
|
||||
|
||||
// MacOSX specific compact unwind info
|
||||
struct UnwindInfo {
|
||||
uint32_t startOffset;
|
||||
uint32_t unwindInfo;
|
||||
|
||||
typedef UnwindInfo *iterator;
|
||||
};
|
||||
/// file - returns the File that produced/owns this Atom
|
||||
virtual const class File& file() const = 0;
|
||||
|
||||
/// name - The name of the atom. For a function atom, it is the (mangled)
|
||||
/// name of the function.
|
||||
|
@ -193,29 +254,84 @@ public:
|
|||
}
|
||||
|
||||
/// permissions - Returns the OS memory protections required for this atom's
|
||||
/// content at runtime. A function atom is R_X and a global variable is RW_.
|
||||
/// 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;
|
||||
|
||||
///
|
||||
virtual void copyRawContent(uint8_t buffer[]) 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.
|
||||
bool isThumb() const {
|
||||
return _thumb;
|
||||
}
|
||||
|
||||
/// 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.
|
||||
bool isAlias() const {
|
||||
return _alias;
|
||||
}
|
||||
|
||||
/// rawContent - returns a reference to the raw (unrelocated) bytes of
|
||||
/// this Atom's content.
|
||||
virtual llvm::ArrayRef<uint8_t> rawContent() const;
|
||||
|
||||
/// referencesBegin - used to start iterating this Atom's References
|
||||
virtual Reference::iterator referencesBegin() const;
|
||||
|
||||
bool isThumb() const { return _thumb; }
|
||||
bool isAlias() const { return _alias; }
|
||||
|
||||
/// referencesEnd - used to end iterating this Atom's References
|
||||
virtual Reference::iterator referencesEnd() const;
|
||||
|
||||
/// setLive - sets or clears the liveness bit. Used by linker to do
|
||||
/// dead code stripping.
|
||||
void setLive(bool l) { _live = l; }
|
||||
|
||||
/// live - returns the liveness bit. Used by linker to do
|
||||
/// dead code stripping.
|
||||
bool live() const { return _live; }
|
||||
|
||||
virtual const class File *file() const = 0;
|
||||
virtual bool translationUnitSource(llvm::StringRef &path) const;
|
||||
virtual uint64_t objectAddress() const = 0;
|
||||
virtual Reference::iterator referencesBegin() const;
|
||||
virtual Reference::iterator referencesEnd() const;
|
||||
virtual UnwindInfo::iterator beginUnwind() const;
|
||||
virtual UnwindInfo::iterator endUnwind() const;
|
||||
/// 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.
|
||||
uint64_t ordinal() const {
|
||||
assert(_mode == modeOrdinal);
|
||||
return _address;
|
||||
}
|
||||
|
||||
/// sectionOffset - returns the section offset assigned to this Atom within
|
||||
/// its final section.
|
||||
uint64_t sectionOffset() const {
|
||||
assert(_mode == modeSectionOffset);
|
||||
return _address;
|
||||
}
|
||||
|
||||
Atom( Definition d
|
||||
/// finalAddress - returns the address assigned to Atom within the final
|
||||
/// linked image.
|
||||
uint64_t finalAddress() const {
|
||||
assert(_mode == modeFinalAddress);
|
||||
return _address;
|
||||
}
|
||||
|
||||
/// setSectionOffset - assigns an offset within a section in the final
|
||||
/// linked image.
|
||||
void setSectionOffset(uint64_t off) {
|
||||
assert(_mode != modeFinalAddress);
|
||||
_address = off;
|
||||
_mode = modeSectionOffset;
|
||||
}
|
||||
|
||||
/// setSectionOffset - assigns an offset within a section in the final
|
||||
/// linked image.
|
||||
void setFinalAddress(uint64_t addr) {
|
||||
assert(_mode == modeSectionOffset);
|
||||
_address = addr;
|
||||
_mode = modeFinalAddress;
|
||||
}
|
||||
|
||||
/// constructor
|
||||
Atom( uint64_t ord
|
||||
, Definition d
|
||||
, Scope s
|
||||
, ContentType ct
|
||||
, SectionChoice sc
|
||||
|
@ -224,20 +340,31 @@ public:
|
|||
, bool IsThumb
|
||||
, bool IsAlias
|
||||
, Alignment a)
|
||||
: _alignmentModulus(a.modulus)
|
||||
: _address(ord)
|
||||
, _alignmentModulus(a.modulus)
|
||||
, _alignmentPowerOf2(a.powerOf2)
|
||||
, _definition(d)
|
||||
, _internalName(internalName)
|
||||
, _deadStrip(ds)
|
||||
, _mode(modeOrdinal)
|
||||
, _thumb(IsThumb)
|
||||
, _alias(IsAlias)
|
||||
, _contentType(ct)
|
||||
, _scope(s)
|
||||
, _sectionChoice(sc) {}
|
||||
|
||||
virtual ~Atom();
|
||||
|
||||
protected:
|
||||
/// The memory for Atom 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 ~Atom();
|
||||
|
||||
/// The __address field has different meanings throughout the life of an Atom.
|
||||
enum AddressMode { modeOrdinal, modeSectionOffset, modeFinalAddress };
|
||||
|
||||
uint64_t _address;
|
||||
uint16_t _alignmentModulus;
|
||||
uint8_t _alignmentPowerOf2;
|
||||
ContentType _contentType : 8;
|
||||
|
@ -246,6 +373,7 @@ protected:
|
|||
SectionChoice _sectionChoice: 2;
|
||||
bool _internalName : 1;
|
||||
DeadStripKind _deadStrip : 2;
|
||||
AddressMode _mode : 2;
|
||||
bool _mergeDuplicates : 1;
|
||||
bool _thumb : 1;
|
||||
bool _autoHide : 1;
|
||||
|
|
|
@ -34,6 +34,9 @@ public:
|
|||
virtual bool justInTimeforEachAtom( llvm::StringRef name
|
||||
, AtomHandler &) const = 0;
|
||||
|
||||
virtual bool translationUnitSource(llvm::StringRef &path) const;
|
||||
|
||||
|
||||
private:
|
||||
llvm::StringRef _path;
|
||||
};
|
||||
|
|
|
@ -20,8 +20,9 @@ namespace lld {
|
|||
/// It exists as a place holder for a future atom.
|
||||
class UndefinedAtom : public Atom {
|
||||
public:
|
||||
UndefinedAtom(llvm::StringRef nm)
|
||||
: Atom( Atom::definitionUndefined
|
||||
UndefinedAtom(llvm::StringRef nm, const File& f)
|
||||
: Atom( 0,
|
||||
Atom::definitionUndefined
|
||||
, Atom::scopeLinkageUnit
|
||||
, Atom::typeUnknown
|
||||
, Atom::sectionBasedOnContent
|
||||
|
@ -30,15 +31,11 @@ public:
|
|||
, false
|
||||
, false
|
||||
, Atom::Alignment(0))
|
||||
, _name(nm) {}
|
||||
, _name(nm), _file(f) {}
|
||||
|
||||
// overrides of Atom
|
||||
virtual const File *file() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool translationUnitSource(llvm::StringRef path) const {
|
||||
return false;
|
||||
virtual const File& file() const {
|
||||
return _file;
|
||||
}
|
||||
|
||||
virtual llvm::StringRef name() const {
|
||||
|
@ -58,6 +55,7 @@ protected:
|
|||
virtual ~UndefinedAtom() {}
|
||||
|
||||
llvm::StringRef _name;
|
||||
const File& _file;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
|
|
@ -16,10 +16,6 @@ namespace lld {
|
|||
|
||||
Atom::~Atom() {}
|
||||
|
||||
bool Atom::translationUnitSource(llvm::StringRef &path) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
llvm::StringRef Atom::name() const {
|
||||
return llvm::StringRef();
|
||||
}
|
||||
|
@ -44,12 +40,5 @@ namespace lld {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Atom::UnwindInfo::iterator Atom::beginUnwind() const{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Atom::UnwindInfo::iterator Atom::endUnwind() const{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace lld
|
||||
|
|
|
@ -13,4 +13,9 @@ namespace lld {
|
|||
|
||||
File::~File() {}
|
||||
|
||||
bool File::translationUnitSource(llvm::StringRef &path) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -183,14 +183,14 @@ void Resolver::updateReferences() {
|
|||
void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
|
||||
// if -why_live cares about this symbol, then dump chain
|
||||
if ((previous->referer != NULL) && _platform.printWhyLive(atom.name())) {
|
||||
llvm::errs() << atom.name() << " from " << atom.file()->path() << "\n";
|
||||
llvm::errs() << atom.name() << " from " << atom.file().path() << "\n";
|
||||
int depth = 1;
|
||||
for (WhyLiveBackChain *p = previous; p != NULL;
|
||||
p = p->previous, ++depth) {
|
||||
for (int i = depth; i > 0; --i)
|
||||
llvm::errs() << " ";
|
||||
llvm::errs() << p->referer->name() << " from "
|
||||
<< p->referer->file()->path() << "\n";
|
||||
<< p->referer->file().path() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,8 @@ bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
|
|||
|
||||
class YAMLAtom : public Atom {
|
||||
public:
|
||||
YAMLAtom( Definition d
|
||||
YAMLAtom( uint64_t ord
|
||||
, Definition d
|
||||
, Scope s
|
||||
, ContentType ct
|
||||
, SectionChoice sc
|
||||
|
@ -247,18 +248,18 @@ public:
|
|||
, bool tb
|
||||
, bool al
|
||||
, Alignment a
|
||||
, YAMLFile *f
|
||||
, YAMLFile& f
|
||||
, const char *n)
|
||||
: Atom(d, s, ct, sc, intn, dsk, tb, al, a)
|
||||
: Atom(ord, d, s, ct, sc, intn, dsk, tb, al, a)
|
||||
, _file(f)
|
||||
, _name(n)
|
||||
, _size(0)
|
||||
, _refStartIndex(f->_lastRefIndex)
|
||||
, _refEndIndex(f->_references.size()) {
|
||||
f->_lastRefIndex = _refEndIndex;
|
||||
, _refStartIndex(f._lastRefIndex)
|
||||
, _refEndIndex(f._references.size()) {
|
||||
f._lastRefIndex = _refEndIndex;
|
||||
}
|
||||
|
||||
virtual const class File *file() const {
|
||||
virtual const class File& file() const {
|
||||
return _file;
|
||||
}
|
||||
|
||||
|
@ -282,7 +283,7 @@ public:
|
|||
virtual Reference::iterator referencesBegin() const;
|
||||
virtual Reference::iterator referencesEnd() const;
|
||||
private:
|
||||
YAMLFile *_file;
|
||||
YAMLFile& _file;
|
||||
const char *_name;
|
||||
unsigned long _size;
|
||||
unsigned int _refStartIndex;
|
||||
|
@ -290,14 +291,14 @@ private:
|
|||
};
|
||||
|
||||
Reference::iterator YAMLAtom::referencesBegin() const {
|
||||
if (_file->_references.size() < _refStartIndex)
|
||||
return (Reference::iterator)&_file->_references[_refStartIndex];
|
||||
if (_file._references.size() < _refStartIndex)
|
||||
return (Reference::iterator)&_file._references[_refStartIndex];
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference::iterator YAMLAtom::referencesEnd() const {
|
||||
if (_file->_references.size() < _refEndIndex)
|
||||
return (Reference::iterator)&_file->_references[_refEndIndex];
|
||||
if (_file._references.size() < _refEndIndex)
|
||||
return (Reference::iterator)&_file._references[_refEndIndex];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -316,9 +317,10 @@ public:
|
|||
void setFixupTarget(const char *n);
|
||||
void addFixup(YAMLFile *f);
|
||||
|
||||
void makeAtom(YAMLFile *);
|
||||
void makeAtom(YAMLFile&);
|
||||
|
||||
private:
|
||||
uint64_t _ordinal;
|
||||
const char *_name;
|
||||
Atom::Alignment _align;
|
||||
Atom::ContentType _type;
|
||||
|
@ -334,7 +336,8 @@ private:
|
|||
};
|
||||
|
||||
YAMLAtomState::YAMLAtomState()
|
||||
: _name(NULL)
|
||||
: _ordinal(0)
|
||||
, _name(NULL)
|
||||
, _align(0, 0)
|
||||
, _type(Atom::typeData)
|
||||
, _scope(Atom::scopeGlobal)
|
||||
|
@ -349,13 +352,14 @@ YAMLAtomState::YAMLAtomState()
|
|||
_ref.flags = 0;
|
||||
}
|
||||
|
||||
void YAMLAtomState::makeAtom(YAMLFile *f) {
|
||||
Atom *a = new YAMLAtom(_def, _scope, _type, _sectionChoice,
|
||||
void YAMLAtomState::makeAtom(YAMLFile& f) {
|
||||
Atom *a = new YAMLAtom(_ordinal, _def, _scope, _type, _sectionChoice,
|
||||
_internalName, _dontDeadStrip, _thumb, _alias,
|
||||
_align, f, _name);
|
||||
|
||||
f->_atoms.push_back(a);
|
||||
|
||||
f._atoms.push_back(a);
|
||||
++_ordinal;
|
||||
|
||||
// reset state for next atom
|
||||
_name = NULL;
|
||||
_align.powerOf2 = 0;
|
||||
|
@ -472,7 +476,7 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
if (entry->beginDocument) {
|
||||
if (file != NULL) {
|
||||
if (haveAtom) {
|
||||
atomState.makeAtom(file);
|
||||
atomState.makeAtom(*file);
|
||||
haveAtom = false;
|
||||
}
|
||||
result.push_back(file);
|
||||
|
@ -502,7 +506,7 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
if (depthForAtoms == entry->depth) {
|
||||
if (entry->beginSequence) {
|
||||
if (haveAtom) {
|
||||
atomState.makeAtom(file);
|
||||
atomState.makeAtom(*file);
|
||||
haveAtom = false;
|
||||
}
|
||||
}
|
||||
|
@ -546,7 +550,7 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
lastDepth = entry->depth;
|
||||
}
|
||||
if (haveAtom) {
|
||||
atomState.makeAtom(file);
|
||||
atomState.makeAtom(*file);
|
||||
}
|
||||
|
||||
result.push_back(file);
|
||||
|
|
Loading…
Reference in New Issue