forked from OSchip/llvm-project
This update does the following:
* Moves enum Scope from DefinedAtom.h to Atom.h * Adds scope method to AbsoluteAtom class * Updates YAML to print scope of AbsoluteAtoms * Update Native Reader/Writer to handle this new, "attribute" * Adds testcase Reviewed and approved by Nick Kledzik llvm-svn: 166189
This commit is contained in:
parent
12be639dfc
commit
2a59024ff8
|
@ -18,8 +18,16 @@ namespace lld {
|
|||
/// It exists to represent content at fixed addresses in memory.
|
||||
class AbsoluteAtom : public Atom {
|
||||
public:
|
||||
|
||||
virtual uint64_t value() 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;
|
||||
|
||||
static inline bool classof(const Atom *a) {
|
||||
return a->definition() == definitionAbsolute;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,17 @@ public:
|
|||
definitionSharedLibrary ///< Only in shared libraries to model export.
|
||||
};
|
||||
|
||||
/// 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).
|
||||
};
|
||||
|
||||
|
||||
/// file - returns the File that produced/owns this Atom
|
||||
virtual const class File& file() const = 0;
|
||||
|
||||
|
|
|
@ -88,16 +88,6 @@ class File;
|
|||
///
|
||||
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
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// to consume an ELF file and produces atoms out of it.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/ReaderWriter/ReaderELF.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
|
@ -115,14 +114,18 @@ private:
|
|||
/// particular address. This atom has no content its address will be used by
|
||||
/// the writer to fixup references that point to it.
|
||||
template<llvm::support::endianness target_endianness, bool is64Bits>
|
||||
class ELFAbsoluteAtom final: public AbsoluteAtom {
|
||||
class ELFAbsoluteAtom final : public AbsoluteAtom {
|
||||
|
||||
typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
|
||||
|
||||
public:
|
||||
ELFAbsoluteAtom(const File &file,
|
||||
llvm::StringRef name,
|
||||
const Elf_Sym *symbol,
|
||||
uint64_t value)
|
||||
: _owningFile(file)
|
||||
, _name(name)
|
||||
, _symbol(symbol)
|
||||
, _value(value)
|
||||
{}
|
||||
|
||||
|
@ -130,6 +133,15 @@ public:
|
|||
return _owningFile;
|
||||
}
|
||||
|
||||
virtual Scope scope() const {
|
||||
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
|
||||
return scopeLinkageUnit;
|
||||
if (_symbol->getBinding() == llvm::ELF::STB_LOCAL)
|
||||
return scopeTranslationUnit;
|
||||
else
|
||||
return scopeGlobal;
|
||||
}
|
||||
|
||||
virtual llvm::StringRef name() const {
|
||||
return _name;
|
||||
}
|
||||
|
@ -141,6 +153,7 @@ public:
|
|||
private:
|
||||
const File &_owningFile;
|
||||
llvm::StringRef _name;
|
||||
const Elf_Sym *_symbol;
|
||||
uint64_t _value;
|
||||
};
|
||||
|
||||
|
@ -308,6 +321,7 @@ public:
|
|||
ret = typeZeroFill;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -319,7 +333,6 @@ public:
|
|||
|| _symbol->st_shndx == llvm::ELF::SHN_COMMON) {
|
||||
return Alignment(llvm::Log2_64(_symbol->st_value));
|
||||
}
|
||||
|
||||
return Alignment(llvm::Log2_64(_section->sh_addralign));
|
||||
}
|
||||
|
||||
|
@ -422,7 +435,6 @@ private:
|
|||
llvm::StringRef _sectionName;
|
||||
const Elf_Sym *_symbol;
|
||||
const Elf_Shdr *_section;
|
||||
|
||||
// _contentData will hold the bits that make up the atom.
|
||||
llvm::ArrayRef<uint8_t> _contentData;
|
||||
|
||||
|
@ -543,7 +555,7 @@ public:
|
|||
auto *newAtom = new (_readerStorage.Allocate
|
||||
<ELFAbsoluteAtom<target_endianness, is64Bits> > ())
|
||||
ELFAbsoluteAtom<target_endianness, is64Bits>
|
||||
(*this, symbolName, symbol->st_value);
|
||||
(*this, symbolName, symbol, symbol->st_value);
|
||||
|
||||
_absoluteAtoms._atoms.push_back(newAtom);
|
||||
_symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
|
||||
|
|
|
@ -601,14 +601,28 @@ void ELFSymbolTableChunk<target_endianness, is64Bits>
|
|||
b = ELF::STB_WEAK;
|
||||
else
|
||||
b = ELF::STB_GLOBAL;
|
||||
} else if (const AbsoluteAtom *aa = llvm::dyn_cast<const AbsoluteAtom>(a)){
|
||||
} else if (const AbsoluteAtom *aa = llvm::dyn_cast<const AbsoluteAtom>(a)){
|
||||
//FIXME: Absolute atoms need more properties to differentiate each other
|
||||
// based on binding and type of symbol
|
||||
symbol->st_value = aa->value();
|
||||
t = ELF::STT_OBJECT;
|
||||
|
||||
switch (aa->scope()) {
|
||||
case AbsoluteAtom::scopeLinkageUnit:
|
||||
symbol->st_other = ELF::STV_HIDDEN;
|
||||
b = ELF::STB_LOCAL;
|
||||
break;
|
||||
case AbsoluteAtom::scopeTranslationUnit:
|
||||
b = ELF::STB_LOCAL;
|
||||
break;
|
||||
case AbsoluteAtom::scopeGlobal:
|
||||
b = ELF::STB_GLOBAL;
|
||||
break;
|
||||
}
|
||||
symbol->st_value = aa->value();
|
||||
} else {
|
||||
symbol->st_value = 0;
|
||||
t = ELF::STT_NOTYPE;
|
||||
b = ELF::STB_LOCAL;
|
||||
symbol->st_value = 0;
|
||||
t = ELF::STT_NOTYPE;
|
||||
b = ELF::STB_LOCAL;
|
||||
}
|
||||
symbol->setBindingAndType(b, t);
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ struct NativeFileHeader {
|
|||
enum NativeChunkSignatures {
|
||||
NCS_DefinedAtomsV1 = 1,
|
||||
NCS_AttributesArrayV1 = 2,
|
||||
NCS_AbsoluteAttributesV1 = 12,
|
||||
NCS_UndefinedAtomsV1 = 3,
|
||||
NCS_SharedLibraryAtomsV1 = 4,
|
||||
NCS_AbsoluteAtomsV1 = 5,
|
||||
|
@ -183,6 +184,7 @@ struct NativeSharedLibraryAtomIvarsV1 {
|
|||
//
|
||||
struct NativeAbsoluteAtomIvarsV1 {
|
||||
uint32_t nameOffset;
|
||||
uint32_t attributesOffset;
|
||||
uint32_t reserved;
|
||||
uint64_t value;
|
||||
};
|
||||
|
|
|
@ -175,12 +175,16 @@ public:
|
|||
|
||||
virtual const lld::File& file() const;
|
||||
virtual StringRef name() const;
|
||||
|
||||
virtual Scope scope() const {
|
||||
const NativeAtomAttributesV1& attr = absAttributes();
|
||||
return (Scope)(attr.scope);
|
||||
}
|
||||
virtual uint64_t value() const {
|
||||
return _ivarData->value;
|
||||
}
|
||||
|
||||
private:
|
||||
const NativeAtomAttributesV1& absAttributes() const;
|
||||
const File *_file;
|
||||
const NativeAbsoluteAtomIvarsV1 *_ivarData;
|
||||
};
|
||||
|
@ -289,6 +293,9 @@ public:
|
|||
case NCS_AbsoluteAtomsV1:
|
||||
ec = file->processAbsoluteAtomsV1(base, chunk);
|
||||
break;
|
||||
case NCS_AbsoluteAttributesV1:
|
||||
ec = file->processAbsoluteAttributesV1(base, chunk);
|
||||
break;
|
||||
case NCS_ReferencesArrayV1:
|
||||
ec = file->processReferencesV1(base, chunk);
|
||||
break;
|
||||
|
@ -425,6 +432,19 @@ private:
|
|||
return make_error_code(native_reader_error::success);
|
||||
}
|
||||
|
||||
// set up pointers to attributes array
|
||||
error_code processAbsoluteAttributesV1(const uint8_t *base,
|
||||
const NativeChunk *chunk) {
|
||||
this->_absAttributes = base + chunk->fileOffset;
|
||||
this->_absAbsoluteMaxOffset = chunk->fileSize;
|
||||
DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
|
||||
<< " chunk AbsoluteAttributesV1: "
|
||||
<< " count=" << chunk->elementCount
|
||||
<< " chunkSize=" << chunk->fileSize
|
||||
<< "\n");
|
||||
return make_error_code(native_reader_error::success);
|
||||
}
|
||||
|
||||
// instantiate array of UndefinedAtoms from v1 ivar data in file
|
||||
error_code processUndefinedAtomsV1(const uint8_t *base,
|
||||
const NativeChunk *chunk) {
|
||||
|
@ -677,6 +697,11 @@ private:
|
|||
return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
|
||||
}
|
||||
|
||||
const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
|
||||
assert(off < _absAbsoluteMaxOffset);
|
||||
return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
|
||||
}
|
||||
|
||||
const uint8_t* content(uint32_t offset, uint32_t size) const {
|
||||
const uint8_t* result = _contentStart + offset;
|
||||
assert((result+size) <= _contentEnd);
|
||||
|
@ -768,6 +793,8 @@ private:
|
|||
AtomArray<UndefinedAtom> _undefinedAtoms;
|
||||
AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
AtomArray<AbsoluteAtom> _absoluteAtoms;
|
||||
const uint8_t* _absAttributes;
|
||||
uint32_t _absAbsoluteMaxOffset;
|
||||
const uint8_t* _attributes;
|
||||
uint32_t _attributesMaxOffset;
|
||||
IvarArray _references;
|
||||
|
@ -868,6 +895,9 @@ inline StringRef NativeAbsoluteAtomV1::name() const {
|
|||
return _file->string(_ivarData->nameOffset);
|
||||
}
|
||||
|
||||
inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
|
||||
return _file->absAttribute(_ivarData->attributesOffset);
|
||||
}
|
||||
|
||||
inline const Atom* NativeReferenceV1::target() const {
|
||||
return _file->target(_ivarData->targetIndex);
|
||||
|
|
|
@ -102,6 +102,11 @@ private:
|
|||
_absoluteAtomIvars.size()
|
||||
* sizeof(NativeAbsoluteAtomIvarsV1));
|
||||
}
|
||||
if (!_absAttributes.empty()) {
|
||||
assert( out.tell() == findChunk(NCS_AbsoluteAttributesV1).fileOffset );
|
||||
out.write((char*)&_absAttributes[0],
|
||||
_absAttributes.size()*sizeof(NativeAtomAttributesV1));
|
||||
}
|
||||
|
||||
if (!_stringPool.empty()) {
|
||||
assert( out.tell() == findChunk(NCS_Strings).fileOffset );
|
||||
|
@ -164,6 +169,7 @@ private:
|
|||
_absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
|
||||
NativeAbsoluteAtomIvarsV1 ivar;
|
||||
ivar.nameOffset = getNameOffset(atom);
|
||||
ivar.attributesOffset = getAttributeOffset(atom);
|
||||
ivar.reserved = 0;
|
||||
ivar.value = atom.value();
|
||||
_absoluteAtomIvars.push_back(ivar);
|
||||
|
@ -184,7 +190,7 @@ private:
|
|||
if ( hasDefines ) chunkCount += 2;
|
||||
if ( hasUndefines ) ++chunkCount;
|
||||
if ( hasSharedLibraries ) ++chunkCount;
|
||||
if ( hasAbsolutes ) ++chunkCount;
|
||||
if ( hasAbsolutes ) chunkCount += 2;
|
||||
if ( hasReferences ) ++chunkCount;
|
||||
if ( hasTargetsTable ) ++chunkCount;
|
||||
if ( hasAddendTable ) ++chunkCount;
|
||||
|
@ -247,13 +253,21 @@ private:
|
|||
|
||||
// create chunk for shared library atom array
|
||||
if ( hasAbsolutes ) {
|
||||
NativeChunk& chsl = chunks[nextIndex++];
|
||||
chsl.signature = NCS_AbsoluteAtomsV1;
|
||||
chsl.fileOffset = nextFileOffset;
|
||||
chsl.fileSize = _absoluteAtomIvars.size() *
|
||||
NativeChunk& chabs = chunks[nextIndex++];
|
||||
chabs.signature = NCS_AbsoluteAtomsV1;
|
||||
chabs.fileOffset = nextFileOffset;
|
||||
chabs.fileSize = _absoluteAtomIvars.size() *
|
||||
sizeof(NativeAbsoluteAtomIvarsV1);
|
||||
chsl.elementCount = _absoluteAtomIvars.size();
|
||||
nextFileOffset = chsl.fileOffset + chsl.fileSize;
|
||||
chabs.elementCount = _absoluteAtomIvars.size();
|
||||
nextFileOffset = chabs.fileOffset + chabs.fileSize;
|
||||
|
||||
// create chunk for attributes
|
||||
NativeChunk& cha = chunks[nextIndex++];
|
||||
cha.signature = NCS_AbsoluteAttributesV1;
|
||||
cha.fileOffset = nextFileOffset;
|
||||
cha.fileSize = _absAttributes.size()*sizeof(NativeAtomAttributesV1);
|
||||
cha.elementCount = _absAttributes.size();
|
||||
nextFileOffset = cha.fileOffset + cha.fileSize;
|
||||
}
|
||||
|
||||
// create chunk for symbol strings
|
||||
|
@ -380,6 +394,21 @@ private:
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32_t getAttributeOffset(const class AbsoluteAtom& atom) {
|
||||
NativeAtomAttributesV1 attrs;
|
||||
computeAbsoluteAttributes(atom, attrs);
|
||||
for(unsigned int i=0; i < _absAttributes.size(); ++i) {
|
||||
if ( !memcmp(&_absAttributes[i], &attrs, sizeof(NativeAtomAttributesV1)) ) {
|
||||
// found that this set of attributes already used, so re-use
|
||||
return i * sizeof(NativeAtomAttributesV1);
|
||||
}
|
||||
}
|
||||
// append new attribute set to end
|
||||
uint32_t result = _absAttributes.size() * sizeof(NativeAtomAttributesV1);
|
||||
_absAttributes.push_back(attrs);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t sectionNameOffset(const class DefinedAtom& atom) {
|
||||
// if section based on content, then no custom section name available
|
||||
if ( atom.sectionChoice() == DefinedAtom::sectionBasedOnContent )
|
||||
|
@ -414,6 +443,11 @@ private:
|
|||
attrs.alias = atom.isAlias();
|
||||
}
|
||||
|
||||
void computeAbsoluteAttributes(const class AbsoluteAtom& atom,
|
||||
NativeAtomAttributesV1& attrs) {
|
||||
attrs.scope = atom.scope();
|
||||
}
|
||||
|
||||
// add references for this atom in a contiguous block in NCS_ReferencesArrayV1
|
||||
uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) {
|
||||
count = 0;
|
||||
|
@ -528,6 +562,7 @@ private:
|
|||
std::vector<uint8_t> _contentPool;
|
||||
std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
|
||||
std::vector<NativeAtomAttributesV1> _attributes;
|
||||
std::vector<NativeAtomAttributesV1> _absAttributes;
|
||||
std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
|
||||
std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
|
||||
std::vector<NativeAbsoluteAtomIvarsV1> _absoluteAtomIvars;
|
||||
|
|
|
@ -39,6 +39,10 @@ public:
|
|||
return OwningFile;
|
||||
}
|
||||
|
||||
virtual Scope scope() const {
|
||||
return scopeGlobal;
|
||||
}
|
||||
|
||||
virtual llvm::StringRef name() const {
|
||||
return Name;
|
||||
}
|
||||
|
|
|
@ -429,6 +429,10 @@ public:
|
|||
return _file;
|
||||
}
|
||||
|
||||
virtual Scope scope() const {
|
||||
return scopeGlobal;
|
||||
}
|
||||
|
||||
virtual StringRef name() const {
|
||||
return _name;
|
||||
}
|
||||
|
|
|
@ -412,6 +412,14 @@ public:
|
|||
<< KeyValues::definition(atom.definition())
|
||||
<< "\n";
|
||||
|
||||
if ( atom.scope() != KeyValues::scopeDefault ) {
|
||||
out << " "
|
||||
<< "scope:"
|
||||
<< spacePadding(strlen("scope"))
|
||||
<< KeyValues::scope(atom.scope())
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
out << " "
|
||||
<< "value:"
|
||||
<< spacePadding(strlen("value"))
|
||||
|
|
|
@ -75,10 +75,10 @@ struct ScopeMapping {
|
|||
};
|
||||
|
||||
static const ScopeMapping scopeMappings[] = {
|
||||
{ "global", DefinedAtom::scopeGlobal },
|
||||
{ "hidden", DefinedAtom::scopeLinkageUnit },
|
||||
{ "static", DefinedAtom::scopeTranslationUnit },
|
||||
{ nullptr, DefinedAtom::scopeGlobal }
|
||||
{ "global", Atom::scopeGlobal },
|
||||
{ "hidden", Atom::scopeLinkageUnit },
|
||||
{ "static", Atom::scopeTranslationUnit },
|
||||
{ nullptr, Atom::scopeGlobal }
|
||||
};
|
||||
|
||||
bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out)
|
||||
|
@ -92,7 +92,7 @@ bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out)
|
|||
return true;
|
||||
}
|
||||
|
||||
const char* KeyValues::scope(DefinedAtom::Scope s) {
|
||||
const char* KeyValues::scope(Atom::Scope s) {
|
||||
for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
|
||||
if ( p->value == s )
|
||||
return p->string;
|
||||
|
@ -106,7 +106,6 @@ const char* KeyValues::scope(DefinedAtom::Scope s) {
|
|||
|
||||
|
||||
|
||||
|
||||
struct ContentTypeMapping {
|
||||
const char* string;
|
||||
DefinedAtom::ContentType value;
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
static const char* const scopeKeyword;
|
||||
static const DefinedAtom::Scope scopeDefault;
|
||||
static bool scope(StringRef, DefinedAtom::Scope&);
|
||||
static const char* scope(DefinedAtom::Scope);
|
||||
static const char* scope(Atom::Scope);
|
||||
|
||||
static const char* const contentTypeKeyword;
|
||||
static const DefinedAtom::ContentType contentTypeDefault;
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# Source File:
|
||||
# .local absGlobalSymbol
|
||||
# .set absLocalSymbol,0xC0000
|
||||
# .type absLocalSymbol, @object
|
||||
# .globl absGlobalSymbol
|
||||
# .set absGlobalSymbol,0xD0000
|
||||
# .type absGlobalSymbol, @object
|
||||
|
||||
# built using: "gcc -m32"
|
||||
#
|
||||
RUN: lld-core -reader ELF %p/Inputs/abs-test.i386 | FileCheck -check-prefix=YAML %s
|
||||
|
||||
YAML: - name: absLocalSymbol
|
||||
YAML: definition: absolute
|
||||
YAML: value: 0xc0000
|
||||
|
||||
YAML: - name: absGlobalSymbol
|
||||
YAML: definition: absolute
|
||||
YAML: scope: global
|
||||
YAML: value: 0xd0000
|
Loading…
Reference in New Issue