forked from OSchip/llvm-project
Add support for SharedLibraryAtoms (proxy atoms for exported symbols from a
shared library) and AbsoluteAtoms (proxy atoms for absolute address (e.g. ROM)). Redesign weak importing as can-be-null-at-runtime and can-be-null-at-build-time. Add lots of test cases for all the above. llvm-svn: 151204
This commit is contained in:
parent
1a3c3d4537
commit
6bc04c6904
|
@ -0,0 +1,41 @@
|
|||
//===- Core/AbsoluteAtom.h - An absolute Atom -----------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_CORE_ABSOLUTE_ATOM_H_
|
||||
#define LLD_CORE_ABSOLUTE_ATOM_H_
|
||||
|
||||
#include "lld/Core/Atom.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// An AbsoluteAtom has no content.
|
||||
/// It exists to represent content at fixed addresses in memory.
|
||||
class AbsoluteAtom : public Atom {
|
||||
public:
|
||||
virtual Definition definition() const {
|
||||
return Atom::definitionAbsolute;
|
||||
}
|
||||
|
||||
/// like dynamic_cast, if atom is definitionAbsolute
|
||||
/// returns atom cast to AbsoluteAtom*, else returns NULL
|
||||
virtual const AbsoluteAtom* absoluteAtom() const {
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual uint64_t value() const = 0;
|
||||
|
||||
|
||||
protected:
|
||||
AbsoluteAtom() {}
|
||||
virtual ~AbsoluteAtom() {}
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif // LLD_CORE_ABSOLUTE_ATOM_H_
|
|
@ -21,8 +21,10 @@ namespace lld {
|
|||
class File;
|
||||
class DefinedAtom;
|
||||
class UndefinedAtom;
|
||||
class SharedLibraryAtom;
|
||||
class AbsoluteAtom;
|
||||
|
||||
///
|
||||
///
|
||||
/// The linker has a Graph Theory model of linking. An object file is seen
|
||||
/// as a set of Atoms with References to other Atoms. Each Atom is a node
|
||||
/// and each Reference is an edge. An Atom can be a DefinedAtom which has
|
||||
|
@ -52,12 +54,20 @@ public:
|
|||
|
||||
/// definedAtom - like dynamic_cast, if atom is definitionRegular
|
||||
/// returns atom cast to DefinedAtom*, else returns nullptr;
|
||||
virtual const DefinedAtom* definedAtom() const { return 0; }
|
||||
virtual const DefinedAtom* definedAtom() const { return NULL; }
|
||||
|
||||
/// undefinedAtom - like dynamic_cast, if atom is definitionUndefined
|
||||
/// returns atom cast to UndefinedAtom*, else returns NULL;
|
||||
virtual const UndefinedAtom* undefinedAtom() const { return NULL; }
|
||||
|
||||
/// sharedLibraryAtom - like dynamic_cast, if atom is definitionSharedLibrary
|
||||
/// returns atom cast to SharedLibraryAtom*, else returns nullptr;
|
||||
virtual const SharedLibraryAtom* sharedLibraryAtom() const { return NULL; }
|
||||
|
||||
/// absoluteAtom - like dynamic_cast, if atom is definitionAbsolute
|
||||
/// returns atom cast to AbsoluteAtom*, else returns nullptr;
|
||||
virtual const AbsoluteAtom* absoluteAtom() const { return NULL; }
|
||||
|
||||
protected:
|
||||
/// Atom is an abstract base class. Only subclasses can access constructor.
|
||||
Atom() {}
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/Core/AbsoluteAtom.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
|
@ -27,6 +29,8 @@ public:
|
|||
virtual ~AtomHandler() {}
|
||||
virtual void doDefinedAtom(const class DefinedAtom &) = 0;
|
||||
virtual void doUndefinedAtom(const class UndefinedAtom &) = 0;
|
||||
virtual void doSharedLibraryAtom(const class SharedLibraryAtom &) = 0;
|
||||
virtual void doAbsoluteAtom(const class AbsoluteAtom &) = 0;
|
||||
virtual void doFile(const class File &) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
// AtomHandler methods
|
||||
virtual void doDefinedAtom(const class DefinedAtom&);
|
||||
virtual void doUndefinedAtom(const class UndefinedAtom&);
|
||||
virtual void doSharedLibraryAtom(const class SharedLibraryAtom &);
|
||||
virtual void doAbsoluteAtom(const class AbsoluteAtom &);
|
||||
virtual void doFile(const File&);
|
||||
|
||||
/// @brief do work of merging and resolving and return list
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
//===- Core/SharedLibraryAtom.h - A Shared Library Atom -------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_CORE_SHARED_LIBRARY_ATOM_H_
|
||||
#define LLD_CORE_SHARED_LIBRARY_ATOM_H_
|
||||
|
||||
#include "lld/Core/Atom.h"
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// A SharedLibraryAtom has no content.
|
||||
/// It exists to represent a symbol which will be bound at runtime.
|
||||
class SharedLibraryAtom : public Atom {
|
||||
public:
|
||||
virtual Definition definition() const {
|
||||
return Atom::definitionSharedLibrary;
|
||||
}
|
||||
|
||||
/// like dynamic_cast, if atom is definitionSharedLibrary
|
||||
/// returns atom cast to SharedLibraryAtom*, else returns NULL
|
||||
virtual const SharedLibraryAtom* sharedLibraryAtom() const {
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Returns shared library name used to load it at runtime.
|
||||
/// On linux that is the DT_NEEDED name.
|
||||
/// On Darwin it is the LC_DYLIB_LOAD dylib name.
|
||||
virtual llvm::StringRef loadName() const = 0;
|
||||
|
||||
/// Returns if shared library symbol can be missing at runtime and if
|
||||
/// so the loader should silently resolve address of symbol to be NULL.
|
||||
virtual bool canBeNullAtRuntime() const = 0;
|
||||
|
||||
protected:
|
||||
SharedLibraryAtom() {}
|
||||
virtual ~SharedLibraryAtom() {}
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif // LLD_CORE_SHARED_LIBRARY_ATOM_H_
|
|
@ -24,6 +24,8 @@ namespace lld {
|
|||
class Atom;
|
||||
class DefinedAtom;
|
||||
class UndefinedAtom;
|
||||
class SharedLibraryAtom;
|
||||
class AbsoluteAtom;
|
||||
class Platform;
|
||||
|
||||
/// The SymbolTable class is responsible for coalescing atoms.
|
||||
|
@ -41,6 +43,12 @@ public:
|
|||
/// @brief add atom to symbol table
|
||||
void add(const UndefinedAtom &);
|
||||
|
||||
/// @brief add atom to symbol table
|
||||
void add(const SharedLibraryAtom &);
|
||||
|
||||
/// @brief add atom to symbol table
|
||||
void add(const AbsoluteAtom &);
|
||||
|
||||
/// @brief checks if name is in symbol table and if so atom is not
|
||||
/// UndefinedAtom
|
||||
bool isDefined(llvm::StringRef sym);
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#include "lld/Core/Atom.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// An UndefinedAtom has no content.
|
||||
|
@ -30,9 +28,40 @@ public:
|
|||
return this;
|
||||
}
|
||||
|
||||
/// returns if undefined symbol can be missing at runtime
|
||||
virtual bool weakImport() const = 0;
|
||||
/// Whether this undefined symbol needs to be resolved,
|
||||
/// or whether it can just evaluate to NULL.
|
||||
/// This concept is often called "weak", but that term
|
||||
/// is overloaded to mean other things too.
|
||||
enum CanBeNull {
|
||||
/// Normal symbols must be resolved at build time
|
||||
canBeNullNever,
|
||||
|
||||
/// This symbol can be missing at runtime and will evalute to NULL.
|
||||
/// That is, the static linker still must find a definition (usually
|
||||
/// is some shared library), but at runtime, the dynamic loader
|
||||
/// will allow the symbol to be missing and resolved to NULL.
|
||||
///
|
||||
/// On Darwin this is generated using a function prototype with
|
||||
/// __attribute__((weak_import)).
|
||||
/// On linux this is generated using a function prototype with
|
||||
/// __attribute__((weak)).
|
||||
canBeNullAtRuntime,
|
||||
|
||||
|
||||
/// This symbol can be missing at build time.
|
||||
/// That is, the static linker will not error if a definition for
|
||||
/// this symbol is not found at build time. Instead, the linker
|
||||
/// will build an executable that lets the dynamic loader find the
|
||||
/// symbol at runtime.
|
||||
/// This feature is not supported on Darwin.
|
||||
/// On linux this is generated using a function prototype with
|
||||
/// __attribute__((weak)).
|
||||
canBeNullAtBuildtime
|
||||
};
|
||||
|
||||
virtual CanBeNull canBeNull() const = 0;
|
||||
|
||||
|
||||
protected:
|
||||
UndefinedAtom() {}
|
||||
virtual ~UndefinedAtom() {}
|
||||
|
|
|
@ -78,6 +78,24 @@ public:
|
|||
virtual void errorWithUndefines(const std::vector<const Atom *>& undefs,
|
||||
const std::vector<const Atom *>& all) = 0;
|
||||
|
||||
/// When core linking finds undefined atoms from different object
|
||||
/// files that have different canBeNull values, this method is called.
|
||||
/// The useUndef2 parameter is set to which canBeNull setting the
|
||||
/// linker should use, and can be changed by this method. Or this
|
||||
/// method can emit a warning/error about the mismatch.
|
||||
virtual void undefineCanBeNullMismatch(const UndefinedAtom& undef1,
|
||||
const UndefinedAtom& undef2,
|
||||
bool& useUndef2) = 0;
|
||||
|
||||
/// When core linking finds shared library atoms from different object
|
||||
/// files that have different attribute values, this method is called.
|
||||
/// The useShlib2 parameter is set to which atom attributes the
|
||||
/// linker should use, and can be changed by this method. Or this
|
||||
/// method can emit a warning/error about the mismatch.
|
||||
virtual void sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
|
||||
const SharedLibraryAtom& shLib2,
|
||||
bool& useShlib2) = 0;
|
||||
|
||||
/// @brief last chance for platform to tweak atoms
|
||||
virtual void postResolveTweaks(std::vector<const Atom *>& all) = 0;
|
||||
};
|
||||
|
|
|
@ -90,12 +90,14 @@ enum NativeChunkSignatures {
|
|||
NCS_DefinedAtomsV1 = 1,
|
||||
NCS_AttributesArrayV1 = 2,
|
||||
NCS_UndefinedAtomsV1 = 3,
|
||||
NCS_Strings = 4,
|
||||
NCS_ReferencesArrayV1 = 5,
|
||||
NCS_ReferencesArrayV2 = 6,
|
||||
NCS_TargetsTable = 7,
|
||||
NCS_AddendsTable = 8,
|
||||
NCS_Content = 9,
|
||||
NCS_SharedLibraryAtomsV1 = 4,
|
||||
NCS_AbsoluteAtomsV1 = 5,
|
||||
NCS_Strings = 6,
|
||||
NCS_ReferencesArrayV1 = 7,
|
||||
NCS_ReferencesArrayV2 = 8,
|
||||
NCS_TargetsTable = 9,
|
||||
NCS_AddendsTable = 10,
|
||||
NCS_Content = 11,
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -165,6 +167,27 @@ struct NativeUndefinedAtomIvarsV1 {
|
|||
|
||||
|
||||
|
||||
//
|
||||
// The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs
|
||||
//
|
||||
struct NativeSharedLibraryAtomIvarsV1 {
|
||||
uint32_t nameOffset;
|
||||
uint32_t loadNameOffset;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The NCS_AbsoluteAtomsV1 chunk contains an array of these structs
|
||||
//
|
||||
struct NativeAbsoluteAtomIvarsV1 {
|
||||
uint32_t nameOffset;
|
||||
uint32_t reserved;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The NCS_ReferencesArrayV1 chunk contains an array of these structs
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
|
||||
virtual DefinedAtom::DeadStripKind deadStrip() const {
|
||||
return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
|
||||
}
|
||||
}
|
||||
|
||||
virtual DefinedAtom::ContentPermissions permissions() const {
|
||||
return (DefinedAtom::ContentPermissions)(attributes().permissions);
|
||||
|
@ -117,16 +117,64 @@ public:
|
|||
virtual const File& file() const;
|
||||
virtual llvm::StringRef name() const;
|
||||
|
||||
virtual bool weakImport() const {
|
||||
return (_ivarData->flags & 0x1);
|
||||
virtual CanBeNull canBeNull() const {
|
||||
return (CanBeNull)(_ivarData->flags & 0x3);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const NativeFile* _file;
|
||||
const NativeUndefinedAtomIvarsV1* _ivarData;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
|
||||
// struct in the NCS_SharedLibraryAtomsV1 chunk.
|
||||
//
|
||||
class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
|
||||
public:
|
||||
NativeSharedLibraryAtomV1(const NativeFile& f,
|
||||
const NativeSharedLibraryAtomIvarsV1* ivarData)
|
||||
: _file(&f), _ivarData(ivarData) { }
|
||||
|
||||
virtual const File& file() const;
|
||||
virtual llvm::StringRef name() const;
|
||||
virtual llvm::StringRef loadName() const;
|
||||
|
||||
virtual bool canBeNullAtRuntime() const {
|
||||
return (_ivarData->flags & 0x1);
|
||||
}
|
||||
|
||||
private:
|
||||
const NativeFile* _file;
|
||||
const NativeSharedLibraryAtomIvarsV1* _ivarData;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
|
||||
// struct in the NCS_AbsoluteAtomsV1 chunk.
|
||||
//
|
||||
class NativeAbsoluteAtomV1 : public AbsoluteAtom {
|
||||
public:
|
||||
NativeAbsoluteAtomV1(const NativeFile& f,
|
||||
const NativeAbsoluteAtomIvarsV1* ivarData)
|
||||
: _file(&f), _ivarData(ivarData) { }
|
||||
|
||||
virtual const File& file() const;
|
||||
virtual llvm::StringRef name() const;
|
||||
|
||||
virtual uint64_t value() const {
|
||||
return _ivarData->value;
|
||||
}
|
||||
|
||||
private:
|
||||
const NativeFile* _file;
|
||||
const NativeAbsoluteAtomIvarsV1* _ivarData;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// An object of this class is instantied for each NativeReferenceIvarsV1
|
||||
|
@ -206,6 +254,12 @@ public:
|
|||
case NCS_UndefinedAtomsV1:
|
||||
ec = file->processUndefinedAtomsV1(base, chunk);
|
||||
break;
|
||||
case NCS_SharedLibraryAtomsV1:
|
||||
ec = file->processSharedLibraryAtomsV1(base, chunk);
|
||||
break;
|
||||
case NCS_AbsoluteAtomsV1:
|
||||
ec = file->processAbsoluteAtomsV1(base, chunk);
|
||||
break;
|
||||
case NCS_ReferencesArrayV1:
|
||||
ec = file->processReferencesV1(base, chunk);
|
||||
break;
|
||||
|
@ -247,23 +301,45 @@ public:
|
|||
// to just delete the memory.
|
||||
delete _definedAtoms.arrayStart;
|
||||
delete _undefinedAtoms.arrayStart;
|
||||
delete _sharedLibraryAtoms.arrayStart;
|
||||
delete _absoluteAtoms.arrayStart;
|
||||
delete _references.arrayStart;
|
||||
delete _targetsTable;
|
||||
}
|
||||
|
||||
// visits each atom in the file
|
||||
virtual bool forEachAtom(AtomHandler& handler) const {
|
||||
bool didSomething = false;
|
||||
for(const uint8_t* p=_definedAtoms.arrayStart; p != _definedAtoms.arrayEnd;
|
||||
p += _definedAtoms.elementSize) {
|
||||
const DefinedAtom* atom = reinterpret_cast<const DefinedAtom*>(p);
|
||||
handler.doDefinedAtom(*atom);
|
||||
didSomething = true;
|
||||
}
|
||||
for(const uint8_t* p=_undefinedAtoms.arrayStart; p != _undefinedAtoms.arrayEnd;
|
||||
p += _undefinedAtoms.elementSize) {
|
||||
for(const uint8_t* p=_undefinedAtoms.arrayStart;
|
||||
p != _undefinedAtoms.arrayEnd;
|
||||
p += _undefinedAtoms.elementSize) {
|
||||
const UndefinedAtom* atom = reinterpret_cast<const UndefinedAtom*>(p);
|
||||
handler.doUndefinedAtom(*atom);
|
||||
didSomething = true;
|
||||
}
|
||||
return (_definedAtoms.arrayStart != _definedAtoms.arrayEnd);
|
||||
for(const uint8_t* p=_sharedLibraryAtoms.arrayStart;
|
||||
p != _sharedLibraryAtoms.arrayEnd;
|
||||
p += _sharedLibraryAtoms.elementSize) {
|
||||
const SharedLibraryAtom* atom
|
||||
= reinterpret_cast<const SharedLibraryAtom*>(p);
|
||||
handler.doSharedLibraryAtom(*atom);
|
||||
didSomething = true;
|
||||
}
|
||||
for(const uint8_t* p=_absoluteAtoms.arrayStart;
|
||||
p != _absoluteAtoms.arrayEnd;
|
||||
p += _absoluteAtoms.elementSize) {
|
||||
const AbsoluteAtom* atom
|
||||
= reinterpret_cast<const AbsoluteAtom*>(p);
|
||||
handler.doAbsoluteAtom(*atom);
|
||||
didSomething = true;
|
||||
}
|
||||
return didSomething;
|
||||
}
|
||||
|
||||
// not used
|
||||
|
@ -275,6 +351,8 @@ public:
|
|||
private:
|
||||
friend class NativeDefinedAtomV1;
|
||||
friend class NativeUndefinedAtomV1;
|
||||
friend class NativeSharedLibraryAtomV1;
|
||||
friend class NativeAbsoluteAtomV1;
|
||||
friend class NativeReferenceV1;
|
||||
|
||||
// instantiate array of DefinedAtoms from v1 ivar data in file
|
||||
|
@ -308,12 +386,14 @@ private:
|
|||
}
|
||||
|
||||
// set up pointers to attributes array
|
||||
llvm::error_code processAttributesV1(const uint8_t* base, const NativeChunk* chunk) {
|
||||
llvm::error_code processAttributesV1(const uint8_t* base,
|
||||
const NativeChunk* chunk) {
|
||||
this->_attributes = base + chunk->fileOffset;
|
||||
this->_attributesMaxOffset = chunk->fileSize;
|
||||
return make_error_code(native_reader_error::success);
|
||||
}
|
||||
|
||||
// instantiate array of UndefinedAtoms from v1 ivar data in file
|
||||
llvm::error_code processUndefinedAtomsV1(const uint8_t* base,
|
||||
const NativeChunk* chunk) {
|
||||
const size_t atomSize = sizeof(NativeUndefinedAtomV1);
|
||||
|
@ -344,6 +424,70 @@ private:
|
|||
}
|
||||
|
||||
|
||||
// instantiate array of ShareLibraryAtoms from v1 ivar data in file
|
||||
llvm::error_code processSharedLibraryAtomsV1(const uint8_t* base,
|
||||
const NativeChunk* chunk) {
|
||||
const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
|
||||
size_t atomsArraySize = chunk->elementCount * atomSize;
|
||||
uint8_t* atomsStart = reinterpret_cast<uint8_t*>
|
||||
(operator new(atomsArraySize, std::nothrow));
|
||||
if (atomsStart == NULL )
|
||||
return make_error_code(native_reader_error::memory_error);
|
||||
const size_t ivarElementSize = chunk->fileSize
|
||||
/ chunk->elementCount;
|
||||
if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
|
||||
return make_error_code(native_reader_error::file_malformed);
|
||||
uint8_t* atomsEnd = atomsStart + atomsArraySize;
|
||||
const NativeSharedLibraryAtomIvarsV1* ivarData =
|
||||
reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
|
||||
(base + chunk->fileOffset);
|
||||
for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
|
||||
NativeSharedLibraryAtomV1* atomAllocSpace =
|
||||
reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
|
||||
new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
|
||||
++ivarData;
|
||||
}
|
||||
this->_sharedLibraryAtoms.arrayStart = atomsStart;
|
||||
this->_sharedLibraryAtoms.arrayEnd = atomsEnd;
|
||||
this->_sharedLibraryAtoms.elementSize = atomSize;
|
||||
this->_sharedLibraryAtoms.elementCount = chunk->elementCount;
|
||||
return make_error_code(native_reader_error::success);
|
||||
}
|
||||
|
||||
|
||||
// instantiate array of AbsoluteAtoms from v1 ivar data in file
|
||||
llvm::error_code processAbsoluteAtomsV1(const uint8_t* base,
|
||||
const NativeChunk* chunk) {
|
||||
const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
|
||||
size_t atomsArraySize = chunk->elementCount * atomSize;
|
||||
uint8_t* atomsStart = reinterpret_cast<uint8_t*>
|
||||
(operator new(atomsArraySize, std::nothrow));
|
||||
if (atomsStart == NULL )
|
||||
return make_error_code(native_reader_error::memory_error);
|
||||
const size_t ivarElementSize = chunk->fileSize
|
||||
/ chunk->elementCount;
|
||||
if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
|
||||
return make_error_code(native_reader_error::file_malformed);
|
||||
uint8_t* atomsEnd = atomsStart + atomsArraySize;
|
||||
const NativeAbsoluteAtomIvarsV1* ivarData =
|
||||
reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
|
||||
(base + chunk->fileOffset);
|
||||
for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
|
||||
NativeAbsoluteAtomV1* atomAllocSpace =
|
||||
reinterpret_cast<NativeAbsoluteAtomV1*>(s);
|
||||
new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
|
||||
++ivarData;
|
||||
}
|
||||
this->_absoluteAtoms.arrayStart = atomsStart;
|
||||
this->_absoluteAtoms.arrayEnd = atomsEnd;
|
||||
this->_absoluteAtoms.elementSize = atomSize;
|
||||
this->_absoluteAtoms.elementCount = chunk->elementCount;
|
||||
return make_error_code(native_reader_error::success);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// instantiate array of Referemces from v1 ivar data in file
|
||||
llvm::error_code processReferencesV1(const uint8_t* base,
|
||||
const NativeChunk* chunk) {
|
||||
|
@ -398,7 +542,24 @@ private:
|
|||
this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
|
||||
continue;
|
||||
}
|
||||
return make_error_code(native_reader_error::file_malformed);
|
||||
const uint32_t slIndex = index - _definedAtoms.elementCount
|
||||
- _undefinedAtoms.elementCount;
|
||||
if ( slIndex < _sharedLibraryAtoms.elementCount ) {
|
||||
const uint8_t* p = _sharedLibraryAtoms.arrayStart
|
||||
+ slIndex * _sharedLibraryAtoms.elementSize;
|
||||
this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
|
||||
continue;
|
||||
}
|
||||
const uint32_t abIndex = index - _definedAtoms.elementCount
|
||||
- _undefinedAtoms.elementCount
|
||||
- _sharedLibraryAtoms.elementCount;
|
||||
if ( abIndex < _absoluteAtoms.elementCount ) {
|
||||
const uint8_t* p = _absoluteAtoms.arrayStart
|
||||
+ slIndex * _absoluteAtoms.elementSize;
|
||||
this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
|
||||
continue;
|
||||
}
|
||||
return make_error_code(native_reader_error::file_malformed);
|
||||
}
|
||||
return make_error_code(native_reader_error::success);
|
||||
}
|
||||
|
@ -491,7 +652,8 @@ private:
|
|||
_contentStart(NULL),
|
||||
_contentEnd(NULL)
|
||||
{
|
||||
_header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart());
|
||||
_header = reinterpret_cast<const NativeFileHeader*>
|
||||
(_buffer->getBufferStart());
|
||||
}
|
||||
|
||||
struct IvarArray {
|
||||
|
@ -507,6 +669,8 @@ private:
|
|||
const NativeFileHeader* _header;
|
||||
IvarArray _definedAtoms;
|
||||
IvarArray _undefinedAtoms;
|
||||
IvarArray _sharedLibraryAtoms;
|
||||
IvarArray _absoluteAtoms;
|
||||
const uint8_t* _attributes;
|
||||
uint32_t _attributesMaxOffset;
|
||||
IvarArray _references;
|
||||
|
@ -567,6 +731,31 @@ inline llvm::StringRef NativeUndefinedAtomV1::name() const {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline const class File& NativeSharedLibraryAtomV1::file() const {
|
||||
return *_file;
|
||||
}
|
||||
|
||||
inline llvm::StringRef NativeSharedLibraryAtomV1::name() const {
|
||||
return _file->string(_ivarData->nameOffset);
|
||||
}
|
||||
|
||||
inline llvm::StringRef NativeSharedLibraryAtomV1::loadName() const {
|
||||
return _file->string(_ivarData->loadNameOffset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline const class File& NativeAbsoluteAtomV1::file() const {
|
||||
return *_file;
|
||||
}
|
||||
|
||||
inline llvm::StringRef NativeAbsoluteAtomV1::name() const {
|
||||
return _file->string(_ivarData->nameOffset);
|
||||
}
|
||||
|
||||
|
||||
inline const Atom* NativeReferenceV1::target() const {
|
||||
return _file->target(_ivarData->targetIndex);
|
||||
}
|
||||
|
|
|
@ -61,7 +61,21 @@ public:
|
|||
out.write((char*)&_undefinedAtomIvars[0],
|
||||
_undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
|
||||
}
|
||||
|
||||
|
||||
if ( !_sharedLibraryAtomIvars.empty() ) {
|
||||
assert( out.tell() == findChunk(NCS_SharedLibraryAtomsV1).fileOffset );
|
||||
out.write((char*)&_sharedLibraryAtomIvars[0],
|
||||
_sharedLibraryAtomIvars.size()
|
||||
* sizeof(NativeSharedLibraryAtomIvarsV1));
|
||||
}
|
||||
|
||||
if ( !_absoluteAtomIvars.empty() ) {
|
||||
assert( out.tell() == findChunk(NCS_AbsoluteAtomsV1).fileOffset );
|
||||
out.write((char*)&_absoluteAtomIvars[0],
|
||||
_absoluteAtomIvars.size()
|
||||
* sizeof(NativeAbsoluteAtomIvarsV1));
|
||||
}
|
||||
|
||||
if (!_stringPool.empty()) {
|
||||
assert( out.tell() == findChunk(NCS_Strings).fileOffset );
|
||||
out.write(&_stringPool[0], _stringPool.size());
|
||||
|
@ -110,23 +124,55 @@ private:
|
|||
_undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
|
||||
NativeUndefinedAtomIvarsV1 ivar;
|
||||
ivar.nameOffset = getNameOffset(atom);
|
||||
ivar.flags = (atom.weakImport() ? 1 : 0);
|
||||
ivar.flags = (atom.canBeNull() & 0x03);
|
||||
_undefinedAtomIvars.push_back(ivar);
|
||||
}
|
||||
|
||||
// visitor routine called by forEachAtom()
|
||||
virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
|
||||
_sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
|
||||
NativeSharedLibraryAtomIvarsV1 ivar;
|
||||
ivar.nameOffset = getNameOffset(atom);
|
||||
ivar.loadNameOffset = getSharedLibraryNameOffset(atom.loadName());
|
||||
ivar.flags = atom.canBeNullAtRuntime();
|
||||
_sharedLibraryAtomIvars.push_back(ivar);
|
||||
}
|
||||
|
||||
// visitor routine called by forEachAtom()
|
||||
virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
|
||||
_absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
|
||||
NativeAbsoluteAtomIvarsV1 ivar;
|
||||
ivar.nameOffset = getNameOffset(atom);
|
||||
ivar.reserved = 0;
|
||||
ivar.value = atom.value();
|
||||
_absoluteAtomIvars.push_back(ivar);
|
||||
}
|
||||
|
||||
// visitor routine called by forEachAtom()
|
||||
virtual void doFile(const File &) {
|
||||
}
|
||||
|
||||
// fill out native file header and chunk directory
|
||||
void makeHeader() {
|
||||
const bool hasDefines = !_definedAtomIvars.empty();
|
||||
const bool hasUndefines = !_undefinedAtomIvars.empty();
|
||||
const bool hasSharedLibraries = !_sharedLibraryAtomIvars.empty();
|
||||
const bool hasAbsolutes = !_absoluteAtomIvars.empty();
|
||||
const bool hasReferences = !_references.empty();
|
||||
const bool hasTargetsTable = !_targetsTableIndex.empty();
|
||||
const bool hasAddendTable = !_addendsTableIndex.empty();
|
||||
int chunkCount = 5;
|
||||
const bool hasContent = !_contentPool.empty();
|
||||
|
||||
int chunkCount = 1; // always have string pool chunk
|
||||
if ( hasDefines ) chunkCount += 2;
|
||||
if ( hasUndefines ) ++chunkCount;
|
||||
if ( hasSharedLibraries ) ++chunkCount;
|
||||
if ( hasAbsolutes ) ++chunkCount;
|
||||
if ( hasReferences ) ++chunkCount;
|
||||
if ( hasTargetsTable ) ++chunkCount;
|
||||
if ( hasAddendTable ) ++chunkCount;
|
||||
if ( hasContent ) ++chunkCount;
|
||||
|
||||
_headerBufferSize = sizeof(NativeFileHeader)
|
||||
+ chunkCount*sizeof(NativeChunk);
|
||||
_headerBuffer = reinterpret_cast<NativeFileHeader*>
|
||||
|
@ -140,23 +186,25 @@ private:
|
|||
_headerBuffer->fileSize = 0;
|
||||
_headerBuffer->chunkCount = chunkCount;
|
||||
|
||||
|
||||
// create chunk for atom ivar array
|
||||
// create chunk for defined atom ivar array
|
||||
int nextIndex = 0;
|
||||
NativeChunk& chd = chunks[nextIndex++];
|
||||
chd.signature = NCS_DefinedAtomsV1;
|
||||
chd.fileOffset = _headerBufferSize;
|
||||
chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
|
||||
chd.elementCount = _definedAtomIvars.size();
|
||||
uint32_t nextFileOffset = chd.fileOffset + chd.fileSize;
|
||||
uint32_t nextFileOffset = _headerBufferSize;
|
||||
if ( hasDefines ) {
|
||||
NativeChunk& chd = chunks[nextIndex++];
|
||||
chd.signature = NCS_DefinedAtomsV1;
|
||||
chd.fileOffset = nextFileOffset;
|
||||
chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
|
||||
chd.elementCount = _definedAtomIvars.size();
|
||||
nextFileOffset = chd.fileOffset + chd.fileSize;
|
||||
|
||||
// create chunk for attributes
|
||||
NativeChunk& cha = chunks[nextIndex++];
|
||||
cha.signature = NCS_AttributesArrayV1;
|
||||
cha.fileOffset = nextFileOffset;
|
||||
cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
|
||||
cha.elementCount = _attributes.size();
|
||||
nextFileOffset = cha.fileOffset + cha.fileSize;
|
||||
// create chunk for attributes
|
||||
NativeChunk& cha = chunks[nextIndex++];
|
||||
cha.signature = NCS_AttributesArrayV1;
|
||||
cha.fileOffset = nextFileOffset;
|
||||
cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
|
||||
cha.elementCount = _attributes.size();
|
||||
nextFileOffset = cha.fileOffset + cha.fileSize;
|
||||
}
|
||||
|
||||
// create chunk for undefined atom array
|
||||
if ( hasUndefines ) {
|
||||
|
@ -169,6 +217,28 @@ private:
|
|||
nextFileOffset = chu.fileOffset + chu.fileSize;
|
||||
}
|
||||
|
||||
// create chunk for shared library atom array
|
||||
if ( hasSharedLibraries ) {
|
||||
NativeChunk& chsl = chunks[nextIndex++];
|
||||
chsl.signature = NCS_SharedLibraryAtomsV1;
|
||||
chsl.fileOffset = nextFileOffset;
|
||||
chsl.fileSize = _sharedLibraryAtomIvars.size() *
|
||||
sizeof(NativeSharedLibraryAtomIvarsV1);
|
||||
chsl.elementCount = _sharedLibraryAtomIvars.size();
|
||||
nextFileOffset = chsl.fileOffset + chsl.fileSize;
|
||||
}
|
||||
|
||||
// create chunk for shared library atom array
|
||||
if ( hasAbsolutes ) {
|
||||
NativeChunk& chsl = chunks[nextIndex++];
|
||||
chsl.signature = NCS_AbsoluteAtomsV1;
|
||||
chsl.fileOffset = nextFileOffset;
|
||||
chsl.fileSize = _absoluteAtomIvars.size() *
|
||||
sizeof(NativeAbsoluteAtomIvarsV1);
|
||||
chsl.elementCount = _absoluteAtomIvars.size();
|
||||
nextFileOffset = chsl.fileOffset + chsl.fileSize;
|
||||
}
|
||||
|
||||
// create chunk for symbol strings
|
||||
// pad end of string pool to 4-bytes
|
||||
while ( (_stringPool.size() % 4) != 0 )
|
||||
|
@ -181,13 +251,15 @@ private:
|
|||
nextFileOffset = chs.fileOffset + chs.fileSize;
|
||||
|
||||
// create chunk for references
|
||||
NativeChunk& chr = chunks[nextIndex++];
|
||||
chr.signature = NCS_ReferencesArrayV1;
|
||||
chr.fileOffset = nextFileOffset;
|
||||
chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1);
|
||||
chr.elementCount = _references.size();
|
||||
nextFileOffset = chr.fileOffset + chr.fileSize;
|
||||
|
||||
if ( hasReferences ) {
|
||||
NativeChunk& chr = chunks[nextIndex++];
|
||||
chr.signature = NCS_ReferencesArrayV1;
|
||||
chr.fileOffset = nextFileOffset;
|
||||
chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1);
|
||||
chr.elementCount = _references.size();
|
||||
nextFileOffset = chr.fileOffset + chr.fileSize;
|
||||
}
|
||||
|
||||
// create chunk for target table
|
||||
if ( hasTargetsTable ) {
|
||||
NativeChunk& cht = chunks[nextIndex++];
|
||||
|
@ -209,13 +281,15 @@ private:
|
|||
}
|
||||
|
||||
// create chunk for content
|
||||
NativeChunk& chc = chunks[nextIndex++];
|
||||
chc.signature = NCS_Content;
|
||||
chc.fileOffset = nextFileOffset;
|
||||
chc.fileSize = _contentPool.size();
|
||||
chc.elementCount = _contentPool.size();
|
||||
nextFileOffset = chc.fileOffset + chc.fileSize;
|
||||
|
||||
if ( hasContent ) {
|
||||
NativeChunk& chc = chunks[nextIndex++];
|
||||
chc.signature = NCS_Content;
|
||||
chc.fileOffset = nextFileOffset;
|
||||
chc.fileSize = _contentPool.size();
|
||||
chc.elementCount = _contentPool.size();
|
||||
nextFileOffset = chc.fileOffset + chc.fileSize;
|
||||
}
|
||||
|
||||
_headerBuffer->fileSize = nextFileOffset;
|
||||
}
|
||||
|
||||
|
@ -237,7 +311,23 @@ private:
|
|||
return this->getNameOffset(atom.name());
|
||||
}
|
||||
|
||||
// append atom name to string pool and return offset
|
||||
// check if name is already in pool or append and return offset
|
||||
uint32_t getSharedLibraryNameOffset(llvm::StringRef name) {
|
||||
assert( ! name.empty() );
|
||||
// look to see if this library name was used by another atom
|
||||
for(NameToOffsetVector::iterator it = _sharedLibraryNames.begin();
|
||||
it != _sharedLibraryNames.end(); ++it) {
|
||||
if ( name.equals(it->first) )
|
||||
return it->second;
|
||||
}
|
||||
// first use of this library name
|
||||
uint32_t result = this->getNameOffset(name);
|
||||
_sharedLibraryNames.push_back(
|
||||
std::make_pair<llvm::StringRef, uint32_t>(name, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
// append atom name to string pool and return offset
|
||||
uint32_t getNameOffset(llvm::StringRef name) {
|
||||
if ( name.empty() )
|
||||
return 0;
|
||||
|
@ -356,8 +446,26 @@ private:
|
|||
}
|
||||
else {
|
||||
pos = _undefinedAtomIndex.find(atom);
|
||||
assert(pos != _undefinedAtomIndex.end());
|
||||
atomIndex = pos->second + _definedAtomIvars.size();
|
||||
if ( pos != _undefinedAtomIndex.end() ) {
|
||||
atomIndex = pos->second + _definedAtomIvars.size();
|
||||
}
|
||||
else {
|
||||
pos = _sharedLibraryAtomIndex.find(atom);
|
||||
if ( pos != _sharedLibraryAtomIndex.end() ) {
|
||||
assert(pos != _sharedLibraryAtomIndex.end());
|
||||
atomIndex = pos->second
|
||||
+ _definedAtomIvars.size()
|
||||
+ _undefinedAtomIndex.size();
|
||||
}
|
||||
else {
|
||||
pos = _absoluteAtomIndex.find(atom);
|
||||
assert(pos != _absoluteAtomIndex.end());
|
||||
atomIndex = pos->second
|
||||
+ _definedAtomIvars.size()
|
||||
+ _undefinedAtomIndex.size()
|
||||
+ _sharedLibraryAtomIndex.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
targetIndexes[targetIndex] = atomIndex;
|
||||
}
|
||||
|
@ -405,12 +513,17 @@ private:
|
|||
std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
|
||||
std::vector<NativeAtomAttributesV1> _attributes;
|
||||
std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
|
||||
std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
|
||||
std::vector<NativeAbsoluteAtomIvarsV1> _absoluteAtomIvars;
|
||||
std::vector<NativeReferenceIvarsV1> _references;
|
||||
TargetToIndex _targetsTableIndex;
|
||||
TargetToIndex _definedAtomIndex;
|
||||
TargetToIndex _undefinedAtomIndex;
|
||||
TargetToIndex _sharedLibraryAtomIndex;
|
||||
TargetToIndex _absoluteAtomIndex;
|
||||
AddendToIndex _addendsTableIndex;
|
||||
NameToOffsetVector _sectionNames;
|
||||
NameToOffsetVector _sharedLibraryNames;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -134,6 +134,24 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
|
|||
}
|
||||
}
|
||||
|
||||
void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
|
||||
// add to list of known atoms
|
||||
_atoms.push_back(&atom);
|
||||
|
||||
// tell symbol table
|
||||
_symbolTable.add(atom);
|
||||
}
|
||||
|
||||
void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
|
||||
// add to list of known atoms
|
||||
_atoms.push_back(&atom);
|
||||
|
||||
// tell symbol table
|
||||
_symbolTable.add(atom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// utility to add a vector of atoms
|
||||
void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
|
||||
for (std::vector<const DefinedAtom *>::const_iterator it = newAtoms.begin();
|
||||
|
|
|
@ -11,10 +11,11 @@
|
|||
#include "lld/Core/Atom.h"
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/Core/AbsoluteAtom.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/InputFiles.h"
|
||||
#include "lld/Core/Resolver.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
#include "lld/Platform/Platform.h"
|
||||
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
@ -36,6 +37,14 @@ void SymbolTable::add(const UndefinedAtom &atom) {
|
|||
this->addByName(atom);
|
||||
}
|
||||
|
||||
void SymbolTable::add(const SharedLibraryAtom &atom) {
|
||||
this->addByName(atom);
|
||||
}
|
||||
|
||||
void SymbolTable::add(const AbsoluteAtom &atom) {
|
||||
this->addByName(atom);
|
||||
}
|
||||
|
||||
void SymbolTable::add(const DefinedAtom &atom) {
|
||||
assert(atom.scope() != DefinedAtom::scopeTranslationUnit);
|
||||
if ( !atom.name().empty() ) {
|
||||
|
@ -49,7 +58,9 @@ void SymbolTable::add(const DefinedAtom &atom) {
|
|||
enum NameCollisionResolution {
|
||||
NCR_First,
|
||||
NCR_Second,
|
||||
NCR_Dup,
|
||||
NCR_DupDef,
|
||||
NCR_DupUndef,
|
||||
NCR_DupShLib,
|
||||
NCR_Error
|
||||
};
|
||||
|
||||
|
@ -57,7 +68,7 @@ static NameCollisionResolution cases[4][4] = {
|
|||
//regular absolute undef sharedLib
|
||||
{
|
||||
// first is regular
|
||||
NCR_Dup, NCR_Error, NCR_First, NCR_First
|
||||
NCR_DupDef, NCR_Error, NCR_First, NCR_First
|
||||
},
|
||||
{
|
||||
// first is absolute
|
||||
|
@ -65,11 +76,11 @@ static NameCollisionResolution cases[4][4] = {
|
|||
},
|
||||
{
|
||||
// first is undef
|
||||
NCR_Second, NCR_Second, NCR_First, NCR_Second
|
||||
NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
|
||||
},
|
||||
{
|
||||
// first is sharedLib
|
||||
NCR_Second, NCR_Second, NCR_First, NCR_First
|
||||
NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -129,7 +140,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
|
|||
case NCR_Second:
|
||||
useNew = true;
|
||||
break;
|
||||
case NCR_Dup:
|
||||
case NCR_DupDef:
|
||||
assert(existing->definition() == Atom::definitionRegular);
|
||||
assert(newAtom.definition() == Atom::definitionRegular);
|
||||
switch ( mergeSelect(((DefinedAtom*)existing)->merge(),
|
||||
|
@ -148,6 +159,39 @@ void SymbolTable::addByName(const Atom & newAtom) {
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case NCR_DupUndef: {
|
||||
const UndefinedAtom* existingUndef = existing->undefinedAtom();
|
||||
const UndefinedAtom* newUndef = newAtom.undefinedAtom();
|
||||
assert(existingUndef != NULL);
|
||||
assert(newUndef != NULL);
|
||||
if ( existingUndef->canBeNull() == newUndef->canBeNull() ) {
|
||||
useNew = false;
|
||||
}
|
||||
else {
|
||||
useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
|
||||
// give platform a change to override which to use
|
||||
_platform.undefineCanBeNullMismatch(*existingUndef,
|
||||
*newUndef, useNew);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NCR_DupShLib: {
|
||||
const SharedLibraryAtom* existingShLib = existing->sharedLibraryAtom();
|
||||
const SharedLibraryAtom* newShLib = newAtom.sharedLibraryAtom();
|
||||
assert(existingShLib != NULL);
|
||||
assert(newShLib != NULL);
|
||||
if ( (existingShLib->canBeNullAtRuntime()
|
||||
== newShLib->canBeNullAtRuntime()) &&
|
||||
existingShLib->loadName().equals(newShLib->loadName()) ) {
|
||||
useNew = false;
|
||||
}
|
||||
else {
|
||||
useNew = false; // use existing shared library by default
|
||||
// give platform a change to override which to use
|
||||
_platform.sharedLibrarylMismatch(*existingShLib, *newShLib, useNew);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause");
|
||||
}
|
||||
|
|
|
@ -30,10 +30,12 @@ const char* const KeyValues::isThumbKeyword = "is-thumb";
|
|||
const char* const KeyValues::isAliasKeyword = "is-alias";
|
||||
const char* const KeyValues::sectionNameKeyword = "section-name";
|
||||
const char* const KeyValues::contentKeyword = "content";
|
||||
const char* const KeyValues::loadNameKeyword = "load-name";
|
||||
const char* const KeyValues::sizeKeyword = "size";
|
||||
const char* const KeyValues::valueKeyword = "value";
|
||||
const char* const KeyValues::fixupsKeyword = "fixups";
|
||||
const char* const KeyValues::permissionsKeyword = "permissions";
|
||||
const char* const KeyValues::weakImportKeyword = "weak-import";
|
||||
const char* const KeyValues::canBeNullKeyword = "can-be-null";
|
||||
const char* const KeyValues::fixupsKindKeyword = "kind";
|
||||
const char* const KeyValues::fixupsOffsetKeyword = "offset";
|
||||
const char* const KeyValues::fixupsTargetKeyword = "target";
|
||||
|
@ -51,7 +53,7 @@ const DefinedAtom::Merge KeyValues::mergeDefault = DefinedAtom::mer
|
|||
const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;
|
||||
const bool KeyValues::isThumbDefault = false;
|
||||
const bool KeyValues::isAliasDefault = false;
|
||||
const bool KeyValues::weakImportDefault = false;
|
||||
const UndefinedAtom::CanBeNull KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
|
||||
|
||||
|
||||
|
||||
|
@ -389,17 +391,34 @@ const char* KeyValues::isAlias(bool b) {
|
|||
|
||||
|
||||
|
||||
bool KeyValues::weakImport(const char* s)
|
||||
struct CanBeNullMapping {
|
||||
const char* string;
|
||||
UndefinedAtom::CanBeNull value;
|
||||
};
|
||||
|
||||
static const CanBeNullMapping cbnMappings[] = {
|
||||
{ "never", UndefinedAtom::canBeNullNever },
|
||||
{ "at-runtime", UndefinedAtom::canBeNullAtRuntime },
|
||||
{ "at-buildtime", UndefinedAtom::canBeNullAtBuildtime },
|
||||
{ NULL, UndefinedAtom::canBeNullNever }
|
||||
};
|
||||
|
||||
|
||||
UndefinedAtom::CanBeNull KeyValues::canBeNull(const char* s)
|
||||
{
|
||||
if ( strcmp(s, "true") == 0 )
|
||||
return true;
|
||||
else if ( strcmp(s, "false") == 0 )
|
||||
return false;
|
||||
llvm::report_fatal_error("bad weak-import value");
|
||||
for (const CanBeNullMapping* p = cbnMappings; p->string != NULL; ++p) {
|
||||
if ( strcmp(p->string, s) == 0 )
|
||||
return p->value;
|
||||
}
|
||||
llvm::report_fatal_error("bad can-be-null value");
|
||||
}
|
||||
|
||||
const char* KeyValues::weakImport(bool b) {
|
||||
return b ? "true" : "false";
|
||||
const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) {
|
||||
for (const CanBeNullMapping* p = cbnMappings; p->string != NULL; ++p) {
|
||||
if ( p->value == c )
|
||||
return p->string;
|
||||
}
|
||||
llvm::report_fatal_error("bad can-be-null value");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "lld/Core/Atom.h"
|
||||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
|
||||
|
||||
namespace lld {
|
||||
|
@ -24,6 +25,8 @@ public:
|
|||
static const char* const sectionNameKeyword;
|
||||
static const char* const contentKeyword;
|
||||
static const char* const sizeKeyword;
|
||||
static const char* const loadNameKeyword;
|
||||
static const char* const valueKeyword;
|
||||
static const char* const fixupsKeyword;
|
||||
|
||||
static const char* const definitionKeyword;
|
||||
|
@ -76,10 +79,10 @@ public:
|
|||
static bool isAlias(const char*);
|
||||
static const char* isAlias(bool);
|
||||
|
||||
static const char* const weakImportKeyword;
|
||||
static const bool weakImportDefault;
|
||||
static bool weakImport(const char*);
|
||||
static const char* weakImport(bool);
|
||||
static const char* const canBeNullKeyword;
|
||||
static const UndefinedAtom::CanBeNull canBeNullDefault;
|
||||
static UndefinedAtom::CanBeNull canBeNull(const char*);
|
||||
static const char* canBeNull(UndefinedAtom::CanBeNull);
|
||||
|
||||
|
||||
static const char* const fixupsKindKeyword;
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
#include "lld/Core/YamlReader.h"
|
||||
#include "lld/Core/Atom.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/Core/AbsoluteAtom.h"
|
||||
#include "lld/Core/Error.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
|
@ -200,9 +203,7 @@ void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &entries) {
|
|||
}
|
||||
break;
|
||||
case inValue:
|
||||
if (isalnum(c) || (c == '-') || (c == '_')) {
|
||||
*p++ = c;
|
||||
} else if (c == '\n') {
|
||||
if (c == '\n') {
|
||||
*p = '\0';
|
||||
entries.push_back(new Entry(key, value, NULL, depth,
|
||||
nextKeyIsStartOfDocument,
|
||||
|
@ -212,6 +213,9 @@ void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &entries) {
|
|||
state = inDocument;
|
||||
depth = 0;
|
||||
}
|
||||
else {
|
||||
*p++ = c;
|
||||
}
|
||||
break;
|
||||
case inValueSequence:
|
||||
if (c == ']') {
|
||||
|
@ -300,6 +304,8 @@ public:
|
|||
void bindTargetReferences();
|
||||
void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
|
||||
void addUndefinedAtom(UndefinedAtom* atom);
|
||||
void addSharedLibraryAtom(SharedLibraryAtom* atom);
|
||||
void addAbsoluteAtom(AbsoluteAtom* atom);
|
||||
Atom* findAtom(const char* name);
|
||||
|
||||
struct NameAtomPair {
|
||||
|
@ -310,6 +316,8 @@ public:
|
|||
|
||||
std::vector<YAMLDefinedAtom*> _definedAtoms;
|
||||
std::vector<UndefinedAtom*> _undefinedAtoms;
|
||||
std::vector<SharedLibraryAtom*> _sharedLibraryAtoms;
|
||||
std::vector<AbsoluteAtom*> _absoluteAtoms;
|
||||
std::vector<YAMLReference> _references;
|
||||
std::vector<NameAtomPair> _nameToAtomMapping;
|
||||
unsigned int _lastRefIndex;
|
||||
|
@ -465,8 +473,9 @@ private:
|
|||
|
||||
class YAMLUndefinedAtom : public UndefinedAtom {
|
||||
public:
|
||||
YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm, bool wi)
|
||||
: _file(f), _name(nm), _ordinal(ord), _weakImport(wi) { }
|
||||
YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm,
|
||||
UndefinedAtom::CanBeNull cbn)
|
||||
: _file(f), _name(nm), _ordinal(ord), _canBeNull(cbn) { }
|
||||
|
||||
virtual const class File& file() const {
|
||||
return _file;
|
||||
|
@ -476,18 +485,81 @@ public:
|
|||
return _name;
|
||||
}
|
||||
|
||||
virtual bool weakImport() const {
|
||||
return _weakImport;
|
||||
virtual CanBeNull canBeNull() const {
|
||||
return _canBeNull;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
YAMLFile& _file;
|
||||
const char * _name;
|
||||
uint32_t _ordinal;
|
||||
bool _weakImport;
|
||||
UndefinedAtom::CanBeNull _canBeNull;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class YAMLSharedLibraryAtom : public SharedLibraryAtom {
|
||||
public:
|
||||
YAMLSharedLibraryAtom(YAMLFile& f, int32_t ord, const char* nm,
|
||||
const char* ldnm, bool cbn)
|
||||
: _file(f), _name(nm), _ordinal(ord),
|
||||
_loadName(ldnm), _canBeNull(cbn) { }
|
||||
|
||||
virtual const class File& file() const {
|
||||
return _file;
|
||||
}
|
||||
|
||||
virtual llvm::StringRef name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
virtual llvm::StringRef loadName() const {
|
||||
return _loadName;
|
||||
}
|
||||
|
||||
virtual bool canBeNullAtRuntime() const {
|
||||
return _canBeNull;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
YAMLFile& _file;
|
||||
const char * _name;
|
||||
uint32_t _ordinal;
|
||||
const char * _loadName;
|
||||
bool _canBeNull;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class YAMLAbsoluteAtom : public AbsoluteAtom {
|
||||
public:
|
||||
YAMLAbsoluteAtom(YAMLFile& f, int32_t ord, const char* nm, uint64_t v)
|
||||
: _file(f), _name(nm), _ordinal(ord), _value(v) { }
|
||||
|
||||
virtual const class File& file() const {
|
||||
return _file;
|
||||
}
|
||||
|
||||
virtual llvm::StringRef name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
virtual uint64_t value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
YAMLFile& _file;
|
||||
const char * _name;
|
||||
uint32_t _ordinal;
|
||||
uint64_t _value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
|
||||
handler.doFile(*this);
|
||||
for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();
|
||||
|
@ -498,6 +570,17 @@ bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
|
|||
it != _undefinedAtoms.end(); ++it) {
|
||||
handler.doUndefinedAtom(**it);
|
||||
}
|
||||
for (std::vector<SharedLibraryAtom *>::const_iterator
|
||||
it = _sharedLibraryAtoms.begin();
|
||||
it != _sharedLibraryAtoms.end(); ++it) {
|
||||
handler.doSharedLibraryAtom(**it);
|
||||
}
|
||||
for (std::vector<AbsoluteAtom *>::const_iterator
|
||||
it = _absoluteAtoms.begin();
|
||||
it != _absoluteAtoms.end(); ++it) {
|
||||
handler.doAbsoluteAtom(**it);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -534,6 +617,16 @@ void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
|
|||
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
|
||||
}
|
||||
|
||||
void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom* atom) {
|
||||
_sharedLibraryAtoms.push_back(atom);
|
||||
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
|
||||
}
|
||||
|
||||
void YAMLFile::addAbsoluteAtom(AbsoluteAtom* atom) {
|
||||
_absoluteAtoms.push_back(atom);
|
||||
_nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
|
||||
}
|
||||
|
||||
|
||||
class YAMLAtomState {
|
||||
public:
|
||||
|
@ -544,9 +637,7 @@ public:
|
|||
void setAlign2(const char *n);
|
||||
|
||||
void setFixupKind(const char *n);
|
||||
void setFixupOffset(const char *n);
|
||||
void setFixupTarget(const char *n);
|
||||
void setFixupAddend(const char *n);
|
||||
void addFixup(YAMLFile *f);
|
||||
|
||||
void makeAtom(YAMLFile&);
|
||||
|
@ -554,7 +645,9 @@ public:
|
|||
const char * _name;
|
||||
const char * _refName;
|
||||
const char * _sectionName;
|
||||
const char* _loadName;
|
||||
unsigned long long _size;
|
||||
uint64_t _value;
|
||||
uint32_t _ordinal;
|
||||
std::vector<uint8_t>* _content;
|
||||
DefinedAtom::Alignment _alignment;
|
||||
|
@ -568,7 +661,7 @@ public:
|
|||
DefinedAtom::ContentPermissions _permissions;
|
||||
bool _isThumb;
|
||||
bool _isAlias;
|
||||
bool _weakImport;
|
||||
UndefinedAtom::CanBeNull _canBeNull;
|
||||
YAMLReference _ref;
|
||||
};
|
||||
|
||||
|
@ -577,7 +670,9 @@ YAMLAtomState::YAMLAtomState()
|
|||
: _name(NULL)
|
||||
, _refName(NULL)
|
||||
, _sectionName(NULL)
|
||||
, _loadName(NULL)
|
||||
, _size(0)
|
||||
, _value(0)
|
||||
, _ordinal(0)
|
||||
, _content(NULL)
|
||||
, _alignment(0, 0)
|
||||
|
@ -591,7 +686,7 @@ YAMLAtomState::YAMLAtomState()
|
|||
, _permissions(KeyValues::permissionsDefault)
|
||||
, _isThumb(KeyValues::isThumbDefault)
|
||||
, _isAlias(KeyValues::isAliasDefault)
|
||||
, _weakImport(false)
|
||||
, _canBeNull(KeyValues::canBeNullDefault)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -606,16 +701,30 @@ void YAMLAtomState::makeAtom(YAMLFile& f) {
|
|||
++_ordinal;
|
||||
}
|
||||
else if ( _definition == Atom::definitionUndefined ) {
|
||||
UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport);
|
||||
UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _canBeNull);
|
||||
f.addUndefinedAtom(a);
|
||||
++_ordinal;
|
||||
}
|
||||
|
||||
else if ( _definition == Atom::definitionSharedLibrary ) {
|
||||
bool nullable = (_canBeNull == UndefinedAtom::canBeNullAtRuntime);
|
||||
SharedLibraryAtom *a = new YAMLSharedLibraryAtom(f, _ordinal, _name,
|
||||
_loadName, nullable);
|
||||
f.addSharedLibraryAtom(a);
|
||||
++_ordinal;
|
||||
}
|
||||
else if ( _definition == Atom::definitionAbsolute ) {
|
||||
AbsoluteAtom *a = new YAMLAbsoluteAtom(f, _ordinal, _name, _value);
|
||||
f.addAbsoluteAtom(a);
|
||||
++_ordinal;
|
||||
}
|
||||
|
||||
// reset state for next atom
|
||||
_name = NULL;
|
||||
_refName = NULL;
|
||||
_sectionName = NULL;
|
||||
_loadName = NULL;
|
||||
_size = 0;
|
||||
_value = 0;
|
||||
_ordinal = 0;
|
||||
_content = NULL;
|
||||
_alignment.powerOf2= 0;
|
||||
|
@ -630,7 +739,7 @@ void YAMLAtomState::makeAtom(YAMLFile& f) {
|
|||
_permissions = KeyValues::permissionsDefault;
|
||||
_isThumb = KeyValues::isThumbDefault;
|
||||
_isAlias = KeyValues::isAliasDefault;
|
||||
_weakImport = KeyValues::weakImportDefault;
|
||||
_canBeNull = KeyValues::canBeNullDefault;
|
||||
_ref._target = NULL;
|
||||
_ref._targetName = NULL;
|
||||
_ref._addend = 0;
|
||||
|
@ -666,24 +775,10 @@ void YAMLAtomState::setFixupKind(const char *s) {
|
|||
}
|
||||
}
|
||||
|
||||
void YAMLAtomState::setFixupOffset(const char *s) {
|
||||
if ((s[0] == '0') && (s[1] == 'x'))
|
||||
llvm::StringRef(s).getAsInteger(16, _ref._offsetInAtom);
|
||||
else
|
||||
llvm::StringRef(s).getAsInteger(10, _ref._offsetInAtom);
|
||||
}
|
||||
|
||||
void YAMLAtomState::setFixupTarget(const char *s) {
|
||||
_ref._targetName = s;
|
||||
}
|
||||
|
||||
void YAMLAtomState::setFixupAddend(const char *s) {
|
||||
if ((s[0] == '0') && (s[1] == 'x'))
|
||||
llvm::StringRef(s).getAsInteger(16, _ref._addend);
|
||||
else
|
||||
llvm::StringRef(s).getAsInteger(10, _ref._addend);
|
||||
}
|
||||
|
||||
|
||||
void YAMLAtomState::addFixup(YAMLFile *f) {
|
||||
f->_references.push_back(_ref);
|
||||
|
@ -805,8 +900,12 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
atomState._isAlias = KeyValues::isAlias(entry->value);
|
||||
haveAtom = true;
|
||||
}
|
||||
else if (strcmp(entry->key, KeyValues::weakImportKeyword) == 0) {
|
||||
atomState._weakImport = KeyValues::weakImport(entry->value);
|
||||
else if (strcmp(entry->key, KeyValues::canBeNullKeyword) == 0) {
|
||||
atomState._canBeNull = KeyValues::canBeNull(entry->value);
|
||||
if ( atomState._definition == Atom::definitionSharedLibrary ) {
|
||||
if ( atomState._canBeNull == UndefinedAtom::canBeNullAtBuildtime )
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
}
|
||||
haveAtom = true;
|
||||
}
|
||||
else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) {
|
||||
|
@ -829,7 +928,14 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
}
|
||||
else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {
|
||||
inFixups = true;
|
||||
|
||||
}
|
||||
else if (strcmp(entry->key, KeyValues::loadNameKeyword) == 0) {
|
||||
atomState._loadName = entry->value;
|
||||
haveAtom = true;
|
||||
}
|
||||
else if (strcmp(entry->key, KeyValues::valueKeyword) == 0) {
|
||||
llvm::StringRef(entry->value).getAsInteger(0, atomState._value);
|
||||
haveAtom = true;
|
||||
}
|
||||
else {
|
||||
return make_error_code(yaml_reader_error::unknown_keyword);
|
||||
|
@ -847,7 +953,8 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
haveFixup = true;
|
||||
}
|
||||
else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {
|
||||
atomState.setFixupOffset(entry->value);
|
||||
llvm::StringRef(entry->value).getAsInteger(0,
|
||||
atomState._ref._offsetInAtom);
|
||||
haveFixup = true;
|
||||
}
|
||||
else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {
|
||||
|
@ -855,7 +962,8 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
haveFixup = true;
|
||||
}
|
||||
else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {
|
||||
atomState.setFixupAddend(entry->value);
|
||||
llvm::StringRef(entry->value).getAsInteger(0,
|
||||
atomState._ref._addend);
|
||||
haveFixup = true;
|
||||
}
|
||||
}
|
||||
|
@ -865,9 +973,10 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
|
|||
if (haveAtom) {
|
||||
atomState.makeAtom(*file);
|
||||
}
|
||||
|
||||
file->bindTargetReferences();
|
||||
result.push_back(file);
|
||||
if ( file != NULL ) {
|
||||
file->bindTargetReferences();
|
||||
result.push_back(file);
|
||||
}
|
||||
return make_error_code(yaml_reader_error::success);
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,14 @@ public:
|
|||
buildDuplicateNameMap(atom);
|
||||
}
|
||||
|
||||
virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
|
||||
buildDuplicateNameMap(atom);
|
||||
}
|
||||
|
||||
virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
|
||||
buildDuplicateNameMap(atom);
|
||||
}
|
||||
|
||||
void buildDuplicateNameMap(const Atom& atom) {
|
||||
assert(!atom.name().empty());
|
||||
NameToAtom::iterator pos = _nameMap.find(atom.name());
|
||||
|
@ -132,10 +140,14 @@ public:
|
|||
virtual void doFile(const class File &) { _firstAtom = true; }
|
||||
|
||||
virtual void doDefinedAtom(const class DefinedAtom &atom) {
|
||||
// add blank line between atoms for readability
|
||||
if ( !_firstAtom )
|
||||
if ( _firstAtom ) {
|
||||
_out << "atoms:\n";
|
||||
_firstAtom = false;
|
||||
}
|
||||
else {
|
||||
// add blank line between atoms for readability
|
||||
_out << "\n";
|
||||
_firstAtom = false;
|
||||
}
|
||||
|
||||
bool hasDash = false;
|
||||
if ( !atom.name().empty() ) {
|
||||
|
@ -313,35 +325,115 @@ public:
|
|||
|
||||
|
||||
virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
|
||||
// add blank line between atoms for readability
|
||||
if ( !_firstAtom )
|
||||
_out << "\n";
|
||||
if ( _firstAtom ) {
|
||||
_out << "atoms:\n";
|
||||
_firstAtom = false;
|
||||
}
|
||||
else {
|
||||
// add blank line between atoms for readability
|
||||
_out << "\n";
|
||||
}
|
||||
|
||||
_out << " - "
|
||||
<< KeyValues::nameKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::nameKeyword)
|
||||
<< atom.name()
|
||||
<< "\n";
|
||||
_out << " - "
|
||||
<< KeyValues::nameKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::nameKeyword)
|
||||
<< atom.name()
|
||||
<< "\n";
|
||||
|
||||
_out << " "
|
||||
<< KeyValues::definitionKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::definitionKeyword)
|
||||
<< KeyValues::definition(atom.definition())
|
||||
<< "\n";
|
||||
_out << " "
|
||||
<< KeyValues::definitionKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::definitionKeyword)
|
||||
<< KeyValues::definition(atom.definition())
|
||||
<< "\n";
|
||||
|
||||
if ( atom.weakImport() != KeyValues::weakImportDefault ) {
|
||||
if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
|
||||
_out << " "
|
||||
<< KeyValues::weakImportKeyword
|
||||
<< KeyValues::canBeNullKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::weakImportKeyword)
|
||||
<< KeyValues::weakImport(atom.weakImport())
|
||||
<< spacePadding(KeyValues::canBeNullKeyword)
|
||||
<< KeyValues::canBeNull(atom.canBeNull())
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) {
|
||||
if ( _firstAtom ) {
|
||||
_out << "atoms:\n";
|
||||
_firstAtom = false;
|
||||
}
|
||||
else {
|
||||
// add blank line between atoms for readability
|
||||
_out << "\n";
|
||||
}
|
||||
|
||||
_out << " - "
|
||||
<< KeyValues::nameKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::nameKeyword)
|
||||
<< atom.name()
|
||||
<< "\n";
|
||||
|
||||
_out << " "
|
||||
<< KeyValues::definitionKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::definitionKeyword)
|
||||
<< KeyValues::definition(atom.definition())
|
||||
<< "\n";
|
||||
|
||||
if ( !atom.loadName().empty() ) {
|
||||
_out << " "
|
||||
<< KeyValues::loadNameKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::loadNameKeyword)
|
||||
<< atom.loadName()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if ( atom.canBeNullAtRuntime() ) {
|
||||
_out << " "
|
||||
<< KeyValues::canBeNullKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::canBeNullKeyword)
|
||||
<< KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void doAbsoluteAtom(const AbsoluteAtom& atom) {
|
||||
if ( _firstAtom ) {
|
||||
_out << "atoms:\n";
|
||||
_firstAtom = false;
|
||||
}
|
||||
else {
|
||||
// add blank line between atoms for readability
|
||||
_out << "\n";
|
||||
}
|
||||
|
||||
_out << " - "
|
||||
<< KeyValues::nameKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::nameKeyword)
|
||||
<< atom.name()
|
||||
<< "\n";
|
||||
|
||||
_out << " "
|
||||
<< KeyValues::definitionKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::definitionKeyword)
|
||||
<< KeyValues::definition(atom.definition())
|
||||
<< "\n";
|
||||
|
||||
_out << " "
|
||||
<< KeyValues::valueKeyword
|
||||
<< ":"
|
||||
<< spacePadding(KeyValues::valueKeyword)
|
||||
<< "0x";
|
||||
_out.write_hex(atom.value());
|
||||
_out << "\n";
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// return a string of the correct number of spaces to align value
|
||||
|
@ -380,7 +472,6 @@ void writeObjectText(const File &file, llvm::raw_ostream &out) {
|
|||
// Write out all atoms
|
||||
AtomWriter h(rnb, out);
|
||||
out << "---\n";
|
||||
out << "atoms:\n";
|
||||
file.forEachAtom(h);
|
||||
out << "...\n";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# RUN: lld-core %s | FileCheck %s
|
||||
|
||||
#
|
||||
# Test that absolute symbols are parsed and preserved
|
||||
#
|
||||
|
||||
---
|
||||
atoms:
|
||||
- name: putchar
|
||||
definition: absolute
|
||||
value: 0xFFFF0040
|
||||
|
||||
- name: reset
|
||||
definition: absolute
|
||||
value: 0xFFFF0080
|
||||
|
||||
...
|
||||
|
||||
# CHECK: name: putchar
|
||||
# CHECK: definition: absolute
|
||||
# CHECK: value: 0xffff0040
|
||||
# CHECK: name: reset
|
||||
# CHECK: definition: absolute
|
||||
# CHECK: value: 0xffff0080
|
||||
# CHECK: ...
|
|
@ -0,0 +1,11 @@
|
|||
# RUN: lld-core %s | FileCheck %s
|
||||
|
||||
#
|
||||
# Test that an empty file is handled properly
|
||||
#
|
||||
|
||||
---
|
||||
...
|
||||
|
||||
# CHECK: ---
|
||||
# CHECK: ...
|
|
@ -0,0 +1,34 @@
|
|||
# RUN: lld-core %s | FileCheck %s
|
||||
|
||||
#
|
||||
# Test that shared-library symbols are parsed and preserved
|
||||
#
|
||||
|
||||
---
|
||||
atoms:
|
||||
- name: malloc
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: free
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: fast_malloc
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
can-be-null: at-runtime
|
||||
|
||||
...
|
||||
|
||||
# CHECK: name: malloc
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: load-name: libc.so
|
||||
# CHECK: name: free
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: load-name: libc.so
|
||||
# CHECK: name: fast_malloc
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: load-name: libc.so
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: ...
|
|
@ -0,0 +1,110 @@
|
|||
# RUN: lld-core %s | FileCheck %s
|
||||
|
||||
#
|
||||
# Test that shared library symbols preserve their attributes and merge properly
|
||||
#
|
||||
|
||||
---
|
||||
atoms:
|
||||
- name: foo1
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: foo2
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: bar1
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar2
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: mismatchNull1
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: mismatchNull2
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: mismatchload1
|
||||
definition: shared-library
|
||||
load-name: liba.so
|
||||
|
||||
- name: mismatchload2
|
||||
definition: shared-library
|
||||
load-name: libb.so
|
||||
|
||||
---
|
||||
atoms:
|
||||
- name: foo2
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: foo3
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: bar2
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar3
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: mismatchNull1
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
|
||||
- name: mismatchNull2
|
||||
definition: shared-library
|
||||
load-name: libc.so
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: mismatchload1
|
||||
definition: shared-library
|
||||
load-name: libb.so
|
||||
|
||||
- name: mismatchload2
|
||||
definition: shared-library
|
||||
load-name: liba.so
|
||||
|
||||
...
|
||||
|
||||
# CHECK: name: foo1
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: name: foo2
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: name: bar1
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: name: bar2
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: name: mismatchNull1
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: name: mismatchNull2
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK-NOT: can-be-null: at-runtime
|
||||
# CHECK: name: mismatchload1
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: load-name: liba.so
|
||||
# CHECK: name: mismatchload2
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: load-name: libb.so
|
||||
# CHECK: name: foo3
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: name: bar3
|
||||
# CHECK: definition: shared-library
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: ...
|
|
@ -0,0 +1,117 @@
|
|||
# RUN: lld-core %s | FileCheck %s
|
||||
|
||||
#
|
||||
# Test that undefined symbols preserve their attributes and merge properly
|
||||
#
|
||||
|
||||
---
|
||||
atoms:
|
||||
- name: regular_func
|
||||
definition: undefined
|
||||
can-be-null: never
|
||||
|
||||
- name: weak_import_func
|
||||
definition: undefined
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: weak_func
|
||||
definition: undefined
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar1
|
||||
definition: undefined
|
||||
can-be-null: never
|
||||
|
||||
- name: bar2
|
||||
definition: undefined
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar3
|
||||
definition: undefined
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar4
|
||||
definition: undefined
|
||||
can-be-null: never
|
||||
|
||||
- name: bar5
|
||||
definition: undefined
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar6
|
||||
definition: undefined
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar7
|
||||
definition: undefined
|
||||
can-be-null: never
|
||||
|
||||
- name: bar8
|
||||
definition: undefined
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar9
|
||||
definition: undefined
|
||||
can-be-null: at-buildtime
|
||||
|
||||
---
|
||||
atoms:
|
||||
- name: bar1
|
||||
definition: undefined
|
||||
can-be-null: never
|
||||
|
||||
- name: bar2
|
||||
definition: undefined
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar3
|
||||
definition: undefined
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar4
|
||||
definition: undefined
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar5
|
||||
definition: undefined
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar6
|
||||
definition: undefined
|
||||
can-be-null: never
|
||||
|
||||
- name: bar7
|
||||
definition: undefined
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar8
|
||||
definition: undefined
|
||||
can-be-null: never
|
||||
|
||||
- name: bar9
|
||||
definition: undefined
|
||||
can-be-null: at-runtime
|
||||
...
|
||||
|
||||
# CHECK: name: regular_func
|
||||
# CHECK: definition: undefined
|
||||
# CHECK: name: weak_import_func
|
||||
# CHECK: definition: undefined
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: name: weak_func
|
||||
# CHECK: definition: undefined
|
||||
# CHECK: can-be-null: at-buildtime
|
||||
# CHECK: name: bar1
|
||||
# CHECK: name: bar2
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: name: bar3
|
||||
# CHECK: can-be-null: at-buildtime
|
||||
# CHECK: name: bar4
|
||||
# CHECK: name: bar5
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: name: bar7
|
||||
# CHECK: name: bar6
|
||||
# CHECK: name: bar8
|
||||
# CHECK: name: bar9
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: ...
|
|
@ -141,6 +141,17 @@ public:
|
|||
virtual void errorWithUndefines(const std::vector<const Atom *> &undefs,
|
||||
const std::vector<const Atom *> &all) {}
|
||||
|
||||
// print out undefined can-be-null mismatches
|
||||
virtual void undefineCanBeNullMismatch(const UndefinedAtom& undef1,
|
||||
const UndefinedAtom& undef2,
|
||||
bool& useUndef2) { }
|
||||
|
||||
// print out shared library mismatches
|
||||
virtual void sharedLibrarylMismatch(const SharedLibraryAtom& shLib1,
|
||||
const SharedLibraryAtom& shLib2,
|
||||
bool& useShlib2) { }
|
||||
|
||||
|
||||
// last chance for platform to tweak atoms
|
||||
virtual void postResolveTweaks(std::vector<const Atom *> &all) {}
|
||||
|
||||
|
@ -186,6 +197,20 @@ public:
|
|||
if ( atom )
|
||||
handler.doUndefinedAtom(*atom);
|
||||
}
|
||||
// visit shared library atoms
|
||||
for (std::vector<const Atom *>::iterator it = _atoms.begin();
|
||||
it != _atoms.end(); ++it) {
|
||||
const SharedLibraryAtom* atom = (*it)->sharedLibraryAtom();
|
||||
if ( atom )
|
||||
handler.doSharedLibraryAtom(*atom);
|
||||
}
|
||||
// visit absolute atoms
|
||||
for (std::vector<const Atom *>::iterator it = _atoms.begin();
|
||||
it != _atoms.end(); ++it) {
|
||||
const AbsoluteAtom* atom = (*it)->absoluteAtom();
|
||||
if ( atom )
|
||||
handler.doAbsoluteAtom(*atom);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -220,7 +245,7 @@ int main(int argc, const char *argv[]) {
|
|||
// write new atom graph out as YAML doc
|
||||
std::string errorInfo;
|
||||
llvm::raw_fd_ostream out("-", errorInfo);
|
||||
//yaml::writeObjectText(outFile, out);
|
||||
// yaml::writeObjectText(outFile, out);
|
||||
|
||||
// make unique temp .o file to put generated object file
|
||||
int fd;
|
||||
|
@ -232,6 +257,8 @@ int main(int argc, const char *argv[]) {
|
|||
writeNativeObjectFile(outFile, binaryOut);
|
||||
binaryOut.close(); // manually close so that file can be read next
|
||||
|
||||
// out << "native file: " << tempPath.str() << "\n";
|
||||
|
||||
// read native file
|
||||
llvm::OwningPtr<lld::File> natFile;
|
||||
if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) )
|
||||
|
|
Loading…
Reference in New Issue