[llvm-commits] [lld] r150539 - in /lld/trunk: include/lld/Core/ lib/Core/ test/ tools/lld-core/
Nick Kledzik
kledzik at apple.com
Tue Feb 14 16:38:09 PST 2012
Author: kledzik
Date: Tue Feb 14 18:38:09 2012
New Revision: 150539
URL: http://llvm.org/viewvc/llvm-project?rev=150539&view=rev
Log:
Added:
lld/trunk/test/fixups-addend.objtxt
lld/trunk/test/fixups-dup-named.objtxt
lld/trunk/test/fixups-named.objtxt
lld/trunk/test/fixups-unnamed.objtxt
Removed:
lld/trunk/test/internal-name-attributes.objtxt
Modified:
lld/trunk/include/lld/Core/DefinedAtom.h
lld/trunk/include/lld/Core/Reference.h
lld/trunk/include/lld/Core/Resolver.h
lld/trunk/lib/Core/NativeFileFormat.h
lld/trunk/lib/Core/NativeReader.cpp
lld/trunk/lib/Core/NativeWriter.cpp
lld/trunk/lib/Core/Resolver.cpp
lld/trunk/lib/Core/SymbolTable.cpp
lld/trunk/lib/Core/YamlKeyValues.cpp
lld/trunk/lib/Core/YamlKeyValues.h
lld/trunk/lib/Core/YamlReader.cpp
lld/trunk/lib/Core/YamlWriter.cpp
lld/trunk/test/cstring-coalesce.objtxt
lld/trunk/tools/lld-core/lld-core.cpp
Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Feb 14 18:38:09 2012
@@ -34,7 +34,7 @@
/// Here are some example attribute sets for common atoms. If a particular
/// attribute is not listed, the default values are: definition=regular,
/// sectionChoice=basedOnContent, scope=translationUnit, merge=no,
-/// internalName=false, deadStrip=normal, interposable=no
+/// deadStrip=normal, interposable=no
///
/// C function: void foo() {} <br>
/// name=foo, type=code, perm=r_x, scope=global
@@ -71,16 +71,16 @@
/// mergeDupes=asAddressedWeak
///
/// literal c-string: "hello" <br>
-/// name=L0, internalName=true, type=cstring, perm=r__, scope=linkageUnit
+/// name="" type=cstring, perm=r__, scope=linkageUnit
///
/// literal double: 1.234 <br>
-/// name=L0, internalName=true, type=literal8, perm=r__, scope=linkageUnit
+/// name="" type=literal8, perm=r__, scope=linkageUnit
///
/// constant: { 1,2,3 } <br>
-/// name=L0, internalName=true, type=constant, perm=r__, scope=linkageUnit
+/// name="" type=constant, perm=r__, scope=linkageUnit
///
/// Pointer to initializer function: <br>
-/// name=_init, internalName=true, type=initializer, perm=rw_l,
+/// name="" type=initializer, perm=rw_l,
/// sectionChoice=customRequired
///
/// C function place in custom section: __attribute__((section("__foo")))
@@ -195,15 +195,18 @@
uint16_t modulus;
};
+ /// for use iterating over this Atom's References
+ class ReferenceHandler {
+ public:
+ virtual ~ReferenceHandler() {}
+ virtual void doReference(const Reference &) = 0;
+ };
+
/// ordinal - returns a value for the order of this Atom within its file.
/// This is used by the linker to order the layout of Atoms so that
/// the resulting image is stable and reproducible.
virtual uint64_t ordinal() const = 0;
-
- /// internalName - If the name is just a temporary label that should
- /// not show up in the final linked image.
- virtual bool internalName() const = 0;
-
+
/// size - the number of bytes of space this atom's content will occupy
/// in the final linked image. For a function atom, it is the number
/// of bytes of code in the function.
@@ -264,12 +267,9 @@
/// this Atom's content.
virtual llvm::ArrayRef<uint8_t> rawContent() const = 0;
- /// referencesBegin - used to start iterating this Atom's References
- virtual Reference::iterator referencesBegin() const = 0;
-
- /// referencesEnd - used to end iterating this Atom's References
- virtual Reference::iterator referencesEnd() const = 0;
-
+ /// iterator over this Atom's References
+ virtual void forEachReference(ReferenceHandler&) const = 0;
+
protected:
/// DefinedAtom is an abstract base class.
/// Only subclasses can access constructor.
Modified: lld/trunk/include/lld/Core/Reference.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Reference.h (original)
+++ lld/trunk/include/lld/Core/Reference.h Tue Feb 14 18:38:09 2012
@@ -12,22 +12,60 @@
#include <stdint.h>
-
namespace lld {
-class Atom;
-
+///
+/// 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.
+///
+/// For example if a function contains a call site to "malloc" 40 bytes into
+/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,
+/// kind=callsite, target=malloc, addend=0.
+///
+/// Besides supporting traditional "relocations", References are also used
+/// grouping atoms (group comdat), forcing layout (one atom must follow
+/// another), marking data-in-code (jump tables or ARM constants), etc.
+///
class Reference {
public:
- typedef Reference *iterator;
-
- const Atom *target;
- uint64_t addend;
- uint32_t offsetInAtom;
- uint16_t kind;
- uint16_t flags;
+ /// The meaning of positive kind values is architecture specific.
+ /// Negative kind values are architecture independent.
+ typedef int32_t Kind;
+
+ // A value to be added to the value of a target
+ typedef int64_t Addend;
+
+ /// What sort of reference this is.
+ virtual Kind kind() const = 0;
+
+ /// If the reference is a fixup in the Atom, then this returns the
+ /// byte offset into the Atom's content to do the fix up.
+ virtual uint64_t offsetInAtom() const = 0;
+
+ /// If the reference is an edge to another Atom, then this returns the
+ /// other Atom. Otherwise, it returns NULL.
+ virtual const class Atom * target() const = 0;
+
+ /// During linking, the linker may merge graphs which coalesces some nodes
+ /// (i.e. Atoms). To switch the target of a reference, this method is called.
+ virtual void setTarget(const class Atom *) = 0;
+
+ /// Some relocations require a symbol and a value (e.g. foo + 4).
+ virtual Addend addend() const = 0;
+
+protected:
+ /// Atom is an abstract base class. Only subclasses can access constructor.
+ Reference() {}
+
+ /// The memory for Reference objects is always managed by the owning File
+ /// object. Therefore, no one but the owning File object should call
+ /// delete on an Reference. In fact, some File objects may bulk allocate
+ /// an array of References, so they cannot be individually deleted by anyone.
+ virtual ~Reference() {}
};
+
} // namespace lld
#endif // LLD_CORE_REFERENCES_H_
Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Tue Feb 14 18:38:09 2012
@@ -70,6 +70,22 @@
void markLive(const Atom &atom, WhyLiveBackChain *previous);
void addAtoms(const std::vector<const DefinedAtom *>&);
+
+ // helper to update targets for use with forEachReference()
+ class MarkLiveReferences : public DefinedAtom::ReferenceHandler {
+ public:
+ MarkLiveReferences(Resolver& resolver, WhyLiveBackChain* chain)
+ : _resolver(resolver), _chain(chain) { }
+
+ virtual void doReference(const Reference& ref) {
+ _resolver.markLive(*ref.target(), _chain);
+ }
+
+ private:
+ Resolver& _resolver;
+ WhyLiveBackChain* _chain;
+ };
+
Platform &_platform;
const InputFiles &_inputFiles;
SymbolTable _symbolTable;
Modified: lld/trunk/lib/Core/NativeFileFormat.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeFileFormat.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeFileFormat.h (original)
+++ lld/trunk/lib/Core/NativeFileFormat.h Tue Feb 14 18:38:09 2012
@@ -80,6 +80,7 @@
uint32_t architecture;
uint32_t fileSize;
uint32_t chunkCount;
+ // NativeChunk chunks[]
};
//
@@ -90,8 +91,11 @@
NCS_AttributesArrayV1 = 2,
NCS_UndefinedAtomsV1 = 3,
NCS_Strings = 4,
- NCS_Content = 5,
- NCS_ReferencesArray = 6,
+ NCS_ReferencesArrayV1 = 5,
+ NCS_ReferencesArrayV2 = 6,
+ NCS_TargetsTable = 7,
+ NCS_AddendsTable = 8,
+ NCS_Content = 9,
};
//
@@ -125,6 +129,8 @@
struct NativeDefinedAtomIvarsV1 {
uint32_t nameOffset;
uint32_t attributesOffset;
+ uint32_t referencesStartIndex;
+ uint32_t referencesCount;
uint32_t contentOffset;
uint32_t contentSize;
};
@@ -137,7 +143,6 @@
uint32_t sectionNameOffset;
uint16_t align2;
uint16_t alignModulus;
- uint8_t internalName;
uint8_t scope;
uint8_t interposable;
uint8_t merge;
@@ -145,10 +150,7 @@
uint8_t sectionChoice;
uint8_t deadStrip;
uint8_t permissions;
- uint8_t thumb;
uint8_t alias;
- uint8_t pad1;
- uint8_t pad2;
};
@@ -164,6 +166,51 @@
+//
+// The NCS_ReferencesArrayV1 chunk contains an array of these structs
+//
+struct NativeReferenceIvarsV1 {
+ uint16_t offsetInAtom;
+ int16_t kind;
+ uint16_t targetIndex;
+ uint16_t addendIndex;
+};
+
+
+
+//
+// The NCS_ReferencesArrayV2 chunk contains an array of these structs
+//
+struct NativeReferenceIvarsV2 {
+ uint64_t offsetInAtom;
+ int64_t addend;
+ int32_t kind;
+ uint32_t targetIndex;
+};
+
+
+//
+// The NCS_TargetsTable chunk contains an array of uint32_t entries.
+// The C++ class Reference has a target() method that returns a
+// pointer to another Atom. We can't have pointers in object files,
+// so instead NativeReferenceIvarsV1 contains an index to the target.
+// The index is into this NCS_TargetsTable of uint32_t entries.
+// The values in this table are the index of the (target) atom in this file.
+// For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount.
+// For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to
+// NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount.
+//
+
+
+//
+// The NCS_AddendsTable chunk contains an array of int64_t entries.
+// If we allocated space for addends directly in NativeReferenceIvarsV1
+// it would double the size of that struct. But since addends are rare,
+// we instead just keep a pool of addends and have NativeReferenceIvarsV1
+// (if it needs an addend) just store the index (into the pool) of the
+// addend it needs.
+//
+
} // namespace lld
Modified: lld/trunk/lib/Core/NativeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeReader.cpp (original)
+++ lld/trunk/lib/Core/NativeReader.cpp Tue Feb 14 18:38:09 2012
@@ -44,10 +44,6 @@
virtual llvm::StringRef name() const;
- virtual bool internalName() const {
- return attributes().internalName;
- }
-
virtual uint64_t size() const {
return _ivarData->contentSize;
}
@@ -88,23 +84,17 @@
}
virtual bool isThumb() const {
- return (attributes().thumb != 0);
+ return false; //(attributes().thumb != 0);
}
virtual bool isAlias() const {
return (attributes().alias != 0);
}
- llvm::ArrayRef<uint8_t> rawContent() const;
+ virtual llvm::ArrayRef<uint8_t> rawContent() const;
- virtual Reference::iterator referencesBegin() const {
- return 0;
- }
-
- virtual Reference::iterator referencesEnd() const {
- return 0;
- }
-
+ virtual void forEachReference(ReferenceHandler&) const;
+
private:
const NativeAtomAttributesV1& attributes() const;
@@ -139,6 +129,35 @@
//
+// An object of this class is instantied for each NativeReferenceIvarsV1
+// struct in the NCS_ReferencesArrayV1 chunk.
+//
+class NativeReferenceV1 : public Reference {
+public:
+ NativeReferenceV1(const NativeFile& f,
+ const NativeReferenceIvarsV1* ivarData)
+ : _file(&f), _ivarData(ivarData) { }
+
+ virtual uint64_t offsetInAtom() const {
+ return _ivarData->offsetInAtom;
+ }
+
+ virtual Kind kind() const {
+ return _ivarData->kind;
+ }
+
+ virtual const Atom* target() const;
+ virtual Addend addend() const;
+ virtual void setTarget(const Atom* newAtom);
+
+private:
+ const NativeFile* _file;
+ const NativeReferenceIvarsV1* _ivarData;
+};
+
+
+
+//
// lld::File object for native llvm object file
//
class NativeFile : public File {
@@ -187,6 +206,15 @@
case NCS_UndefinedAtomsV1:
ec = file->processUndefinedAtomsV1(base, chunk);
break;
+ case NCS_ReferencesArrayV1:
+ ec = file->processReferencesV1(base, chunk);
+ break;
+ case NCS_TargetsTable:
+ ec = file->processTargetsTable(base, chunk);
+ break;
+ case NCS_AddendsTable:
+ ec = file->processAddendsTable(base, chunk);
+ break;
case NCS_Content:
ec = file->processContent(base, chunk);
break;
@@ -219,6 +247,8 @@
// to just delete the memory.
delete _definedAtoms.arrayStart;
delete _undefinedAtoms.arrayStart;
+ delete _references.arrayStart;
+ delete _targetsTable;
}
// visits each atom in the file
@@ -245,6 +275,7 @@
private:
friend class NativeDefinedAtomV1;
friend class NativeUndefinedAtomV1;
+ friend class NativeReferenceV1;
// instantiate array of DefinedAtoms from v1 ivar data in file
llvm::error_code processDefinedAtomsV1(const uint8_t* base,
@@ -272,6 +303,7 @@
this->_definedAtoms.arrayStart = atomsStart;
this->_definedAtoms.arrayEnd = atomsEnd;
this->_definedAtoms.elementSize = atomSize;
+ this->_definedAtoms.elementCount = chunk->elementCount;
return make_error_code(native_reader_error::success);
}
@@ -307,6 +339,77 @@
this->_undefinedAtoms.arrayStart = atomsStart;
this->_undefinedAtoms.arrayEnd = atomsEnd;
this->_undefinedAtoms.elementSize = atomSize;
+ this->_undefinedAtoms.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) {
+ if ( chunk->elementCount == 0 )
+ return make_error_code(native_reader_error::success);
+ const size_t refSize = sizeof(NativeReferenceV1);
+ size_t refsArraySize = chunk->elementCount * refSize;
+ uint8_t* refsStart = reinterpret_cast<uint8_t*>
+ (operator new(refsArraySize, std::nothrow));
+ if (refsStart == NULL )
+ return make_error_code(native_reader_error::memory_error);
+ const size_t ivarElementSize = chunk->fileSize
+ / chunk->elementCount;
+ if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
+ return make_error_code(native_reader_error::file_malformed);
+ uint8_t* refsEnd = refsStart + refsArraySize;
+ const NativeReferenceIvarsV1* ivarData =
+ reinterpret_cast<const NativeReferenceIvarsV1*>
+ (base + chunk->fileOffset);
+ for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
+ NativeReferenceV1* atomAllocSpace =
+ reinterpret_cast<NativeReferenceV1*>(s);
+ new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
+ ++ivarData;
+ }
+ this->_references.arrayStart = refsStart;
+ this->_references.arrayEnd = refsEnd;
+ this->_references.elementSize = refSize;
+ this->_references.elementCount = chunk->elementCount;
+ return make_error_code(native_reader_error::success);
+ }
+
+ // set up pointers to target table
+ llvm::error_code processTargetsTable(const uint8_t* base,
+ const NativeChunk* chunk) {
+ const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
+ (base + chunk->fileOffset);
+ this->_targetsTableCount = chunk->elementCount;
+ this->_targetsTable = new const Atom*[chunk->elementCount];
+ for (uint32_t i=0; i < chunk->elementCount; ++i) {
+ const uint32_t index = targetIndexes[i];
+ if ( index < _definedAtoms.elementCount ) {
+ const uint8_t* p = _definedAtoms.arrayStart
+ + index * _definedAtoms.elementSize;
+ this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
+ continue;
+ }
+ const uint32_t undefIndex = index - _definedAtoms.elementCount;
+ if ( undefIndex < _undefinedAtoms.elementCount ) {
+ const uint8_t* p = _undefinedAtoms.arrayStart
+ + undefIndex * _undefinedAtoms.elementSize;
+ this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
+ continue;
+ }
+ return make_error_code(native_reader_error::file_malformed);
+ }
+ return make_error_code(native_reader_error::success);
+ }
+
+
+ // set up pointers to addend pool in file
+ llvm::error_code processAddendsTable(const uint8_t* base,
+ const NativeChunk* chunk) {
+ this->_addends = reinterpret_cast<const Reference::Addend*>
+ (base + chunk->fileOffset);
+ this->_addendsMaxIndex = chunk->elementCount;
return make_error_code(native_reader_error::success);
}
@@ -331,9 +434,16 @@
return llvm::StringRef(&_strings[offset]);
}
- const NativeAtomAttributesV1& attribute(uint32_t offset) const {
- assert(offset < _attributesMaxOffset);
- return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + offset);
+ Reference::Addend addend(uint32_t index) const {
+ if ( index == 0 )
+ return 0; // addend index zero is used to mean "no addend"
+ assert(index <= _addendsMaxIndex);
+ return _addends[index-1]; // one-based indexing
+ }
+
+ const NativeAtomAttributesV1& attribute(uint32_t off) const {
+ assert(off < _attributesMaxOffset);
+ return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
}
const uint8_t* content(uint32_t offset, uint32_t size) const {
@@ -342,44 +452,75 @@
return result;
}
-
+ void forEachReference(DefinedAtom::ReferenceHandler& handler,
+ uint32_t start, uint32_t count) const {
+ assert(start < _references.elementCount);
+ assert(start+count <= _references.elementCount);
+ const uint8_t* arrStart = _references.arrayStart
+ + start * _references.elementSize;
+ const uint8_t* arrEnd = arrStart + count * _references.elementSize;
+ for(const uint8_t* p=arrStart; p != arrEnd; p += _references.elementSize) {
+ const NativeReferenceV1* ref
+ = reinterpret_cast<const NativeReferenceV1*>(p);
+ handler.doReference(*ref);
+ }
+ }
+
+ const Atom* target(uint32_t index) const {
+ assert(index < _targetsTableCount);
+ return _targetsTable[index];
+ }
+
+ void setTarget(uint32_t index, const Atom* newAtom) const {
+ assert(index > _targetsTableCount);
+ _targetsTable[index] = newAtom;
+ }
+
+
// private constructor, only called by make()
NativeFile(llvm::OwningPtr<llvm::MemoryBuffer>& mb, llvm::StringRef path) :
lld::File(path),
_buffer(mb.take()), // NativeFile now takes ownership of buffer
_header(NULL),
+ _targetsTable(NULL),
+ _targetsTableCount(0),
_strings(NULL),
_stringsMaxOffset(0),
+ _addends(NULL),
+ _addendsMaxIndex(0),
_contentStart(NULL),
_contentEnd(NULL)
{
_header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart());
- _definedAtoms.arrayStart = NULL;
- _undefinedAtoms.arrayStart = NULL;
}
- struct AtomArray {
- AtomArray() : arrayStart(NULL), arrayEnd(NULL),
- elementSize(0) { }
+ struct IvarArray {
+ IvarArray() : arrayStart(NULL), arrayEnd(NULL),
+ elementSize(0), elementCount(0) { }
const uint8_t* arrayStart;
const uint8_t* arrayEnd;
uint32_t elementSize;
- };
+ uint32_t elementCount;
+ };
llvm::OwningPtr<llvm::MemoryBuffer> _buffer;
const NativeFileHeader* _header;
- AtomArray _definedAtoms;
- AtomArray _undefinedAtoms;
+ IvarArray _definedAtoms;
+ IvarArray _undefinedAtoms;
const uint8_t* _attributes;
uint32_t _attributesMaxOffset;
+ IvarArray _references;
+ const Atom** _targetsTable;
+ uint32_t _targetsTableCount;
const char* _strings;
uint32_t _stringsMaxOffset;
+ const Reference::Addend* _addends;
+ uint32_t _addendsMaxIndex;
const uint8_t* _contentStart;
const uint8_t* _contentEnd;
};
-
-
+
inline const class File& NativeDefinedAtomV1::file() const {
return *_file;
}
@@ -410,8 +551,12 @@
return _file->string(offset);
}
-
-
+inline void NativeDefinedAtomV1::forEachReference(ReferenceHandler& hnd) const {
+ if ( _ivarData->referencesCount == 0 )
+ return;
+ _file->forEachReference(hnd, _ivarData->referencesStartIndex,
+ _ivarData->referencesCount);
+}
inline const class File& NativeUndefinedAtomV1::file() const {
return *_file;
@@ -422,6 +567,17 @@
}
+inline const Atom* NativeReferenceV1::target() const {
+ return _file->target(_ivarData->targetIndex);
+}
+
+inline Reference::Addend NativeReferenceV1::addend() const {
+ return _file->addend(_ivarData->addendIndex);
+}
+
+inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
+ return _file->setTarget(_ivarData->targetIndex, newAtom);
+}
//
Modified: lld/trunk/lib/Core/NativeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/NativeWriter.cpp (original)
+++ lld/trunk/lib/Core/NativeWriter.cpp Tue Feb 14 18:38:09 2012
@@ -12,6 +12,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "lld/Core/File.h"
#include "lld/Core/NativeWriter.h"
@@ -25,10 +26,13 @@
///
/// Class for writing native object files.
///
-class NativeWriter : public File::AtomHandler {
+class NativeWriter : public File::AtomHandler,
+ public DefinedAtom::ReferenceHandler {
public:
/// construct writer for an lld::File object
NativeWriter(const lld::File& file) : _file(file) {
+ // reserve first byte for unnamed atoms
+ _stringPool.push_back('\0');
// visit all atoms
_file.forEachAtom(*this);
// construct file header based on atom information accumulated
@@ -37,36 +41,73 @@
// write the lld::File in native format to the specified stream
void write(llvm::raw_ostream& out) {
+ assert( out.tell() == 0 );
out.write((char*)_headerBuffer, _headerBufferSize);
- if (!_definedAtomIvars.empty())
+
+ if (!_definedAtomIvars.empty()) {
+ assert( out.tell() == findChunk(NCS_DefinedAtomsV1).fileOffset );
out.write((char*)&_definedAtomIvars[0],
_definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1));
- if (!_attributes.empty())
+ }
+
+ if (!_attributes.empty()) {
+ assert( out.tell() == findChunk(NCS_AttributesArrayV1).fileOffset );
out.write((char*)&_attributes[0],
_attributes.size()*sizeof(NativeAtomAttributesV1));
- if ( !_undefinedAtomIvars.empty() )
+ }
+
+ if ( !_undefinedAtomIvars.empty() ) {
+ assert( out.tell() == findChunk(NCS_UndefinedAtomsV1).fileOffset );
out.write((char*)&_undefinedAtomIvars[0],
_undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
- if (!_stringPool.empty())
+ }
+
+ if (!_stringPool.empty()) {
+ assert( out.tell() == findChunk(NCS_Strings).fileOffset );
out.write(&_stringPool[0], _stringPool.size());
- if (!_contentPool.empty())
+ }
+
+ if ( !_references.empty() ) {
+ assert( out.tell() == findChunk(NCS_ReferencesArrayV1).fileOffset );
+ out.write((char*)&_references[0],
+ _references.size()*sizeof(NativeReferenceIvarsV1));
+ }
+
+ if ( !_targetsTableIndex.empty() ) {
+ assert( out.tell() == findChunk(NCS_TargetsTable).fileOffset );
+ writeTargetTable(out);
+ }
+
+ if ( !_addendsTableIndex.empty() ) {
+ assert( out.tell() == findChunk(NCS_AddendsTable).fileOffset );
+ writeAddendTable(out);
+ }
+
+ if (!_contentPool.empty()) {
+ assert( out.tell() == findChunk(NCS_Content).fileOffset );
out.write((char*)&_contentPool[0], _contentPool.size());
+ }
}
private:
// visitor routine called by forEachAtom()
- virtual void doDefinedAtom(const class DefinedAtom& atom) {
+ virtual void doDefinedAtom(const DefinedAtom& atom) {
+ _definedAtomIndex[&atom] = _definedAtomIvars.size();
NativeDefinedAtomIvarsV1 ivar;
+ unsigned refsCount;
ivar.nameOffset = getNameOffset(atom);
ivar.attributesOffset = getAttributeOffset(atom);
+ ivar.referencesStartIndex = getReferencesIndex(atom, refsCount);
+ ivar.referencesCount = refsCount;
ivar.contentOffset = getContentOffset(atom);
ivar.contentSize = atom.size();
_definedAtomIvars.push_back(ivar);
}
// visitor routine called by forEachAtom()
- virtual void doUndefinedAtom(const class UndefinedAtom& atom) {
+ virtual void doUndefinedAtom(const UndefinedAtom& atom) {
+ _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
NativeUndefinedAtomIvarsV1 ivar;
ivar.nameOffset = getNameOffset(atom);
ivar.flags = (atom.weakImport() ? 1 : 0);
@@ -74,13 +115,18 @@
}
// visitor routine called by forEachAtom()
- virtual void doFile(const class File &) {
+ virtual void doFile(const File &) {
}
// fill out native file header and chunk directory
void makeHeader() {
const bool hasUndefines = !_undefinedAtomIvars.empty();
- const int chunkCount = hasUndefines ? 5 : 4;
+ const bool hasTargetsTable = !_targetsTableIndex.empty();
+ const bool hasAddendTable = !_addendsTableIndex.empty();
+ int chunkCount = 5;
+ if ( hasUndefines ) ++chunkCount;
+ if ( hasTargetsTable ) ++chunkCount;
+ if ( hasAddendTable ) ++chunkCount;
_headerBufferSize = sizeof(NativeFileHeader)
+ chunkCount*sizeof(NativeChunk);
_headerBuffer = reinterpret_cast<NativeFileHeader*>
@@ -124,6 +170,9 @@
}
// create chunk for symbol strings
+ // pad end of string pool to 4-bytes
+ while ( (_stringPool.size() % 4) != 0 )
+ _stringPool.push_back('\0');
NativeChunk& chs = chunks[nextIndex++];
chs.signature = NCS_Strings;
chs.fileOffset = nextFileOffset;
@@ -131,6 +180,34 @@
chs.elementCount = _stringPool.size();
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;
+
+ // create chunk for target table
+ if ( hasTargetsTable ) {
+ NativeChunk& cht = chunks[nextIndex++];
+ cht.signature = NCS_TargetsTable;
+ cht.fileOffset = nextFileOffset;
+ cht.fileSize = _targetsTableIndex.size() * sizeof(uint32_t);
+ cht.elementCount = _targetsTableIndex.size();
+ nextFileOffset = cht.fileOffset + cht.fileSize;
+ }
+
+ // create chunk for addend table
+ if ( hasAddendTable ) {
+ NativeChunk& chad = chunks[nextIndex++];
+ chad.signature = NCS_AddendsTable;
+ chad.fileOffset = nextFileOffset;
+ chad.fileSize = _addendsTableIndex.size() * sizeof(Reference::Addend);
+ chad.elementCount = _addendsTableIndex.size();
+ nextFileOffset = chad.fileOffset + chad.fileSize;
+ }
+
// create chunk for content
NativeChunk& chc = chunks[nextIndex++];
chc.signature = NCS_Content;
@@ -142,6 +219,18 @@
_headerBuffer->fileSize = nextFileOffset;
}
+ // scan header to find particular chunk
+ NativeChunk& findChunk(uint32_t signature) {
+ const uint32_t chunkCount = _headerBuffer->chunkCount;
+ NativeChunk* chunks =
+ reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
+ + sizeof(NativeFileHeader));
+ for (uint32_t i=0; i < chunkCount; ++i) {
+ if ( chunks[i].signature == signature )
+ return chunks[i];
+ }
+ assert(0 && "findChunk() signature not found");
+ }
// append atom name to string pool and return offset
uint32_t getNameOffset(const Atom& atom) {
@@ -150,6 +239,8 @@
// append atom name to string pool and return offset
uint32_t getNameOffset(llvm::StringRef name) {
+ if ( name.empty() )
+ return 0;
uint32_t result = _stringPool.size();
_stringPool.insert(_stringPool.end(), name.size()+1, 0);
strcpy(&_stringPool[result], name.data());
@@ -206,7 +297,6 @@
attrs.sectionNameOffset = sectionNameOffset(atom);
attrs.align2 = atom.alignment().powerOf2;
attrs.alignModulus = atom.alignment().modulus;
- attrs.internalName = atom.internalName();
attrs.scope = atom.scope();
attrs.interposable = atom.interposable();
attrs.merge = atom.merge();
@@ -214,12 +304,99 @@
attrs.sectionChoice = atom.sectionChoice();
attrs.deadStrip = atom.deadStrip();
attrs.permissions = atom.permissions();
- attrs.thumb = atom.isThumb();
+ //attrs.thumb = atom.isThumb();
attrs.alias = atom.isAlias();
}
+ // add references for this atom in a contiguous block in NCS_ReferencesArrayV1
+ uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) {
+ count = 0;
+ size_t startRefSize = _references.size();
+ uint32_t result = startRefSize;
+ atom.forEachReference(*this);
+ count = _references.size() - startRefSize;
+ if ( count == 0 )
+ return 0;
+ else
+ return result;
+ }
+
+ void doReference(const Reference& ref) {
+ NativeReferenceIvarsV1 nref;
+ nref.offsetInAtom = ref.offsetInAtom();
+ nref.kind = ref.kind();
+ nref.targetIndex = this->getTargetIndex(ref.target());
+ nref.addendIndex = this->getAddendIndex(ref.addend());
+ _references.push_back(nref);
+ }
+
+ uint32_t getTargetIndex(const Atom* target) {
+ TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
+ if ( pos != _targetsTableIndex.end() ) {
+ return pos->second;
+ }
+ uint32_t result = _targetsTableIndex.size();
+ _targetsTableIndex[target] = result;
+ return result;
+ }
+
+ void writeTargetTable(llvm::raw_ostream& out) {
+ // Build table of target indexes
+ uint32_t maxTargetIndex = _targetsTableIndex.size();
+ uint32_t targetIndexes[maxTargetIndex];
+ for (TargetToIndex::iterator it = _targetsTableIndex.begin();
+ it != _targetsTableIndex.end(); ++it) {
+ const Atom* atom = it->first;
+ uint32_t targetIndex = it->second;
+ assert(targetIndex < maxTargetIndex);
+ uint32_t atomIndex = 0;
+ TargetToIndex::iterator pos = _definedAtomIndex.find(atom);
+ if ( pos != _definedAtomIndex.end() ) {
+ atomIndex = pos->second;
+ }
+ else {
+ pos = _undefinedAtomIndex.find(atom);
+ assert(pos != _undefinedAtomIndex.end());
+ atomIndex = pos->second + _definedAtomIvars.size();
+ }
+ targetIndexes[targetIndex] = atomIndex;
+ }
+ // write table
+ out.write((char*)&targetIndexes[0], maxTargetIndex*sizeof(uint32_t));
+ }
+
+ uint32_t getAddendIndex(Reference::Addend addend) {
+ if ( addend == 0 )
+ return 0; // addend index zero is used to mean "no addend"
+ AddendToIndex::const_iterator pos = _addendsTableIndex.find(addend);
+ if ( pos != _addendsTableIndex.end() ) {
+ return pos->second;
+ }
+ uint32_t result = _addendsTableIndex.size() + 1; // one-based index
+ _addendsTableIndex[addend] = result;
+ return result;
+ }
+
+ void writeAddendTable(llvm::raw_ostream& out) {
+ // Build table of addends
+ uint32_t maxAddendIndex = _addendsTableIndex.size();
+ Reference::Addend addends[maxAddendIndex];
+ for (AddendToIndex::iterator it = _addendsTableIndex.begin();
+ it != _addendsTableIndex.end(); ++it) {
+ Reference::Addend addend = it->first;
+ uint32_t index = it->second;
+ assert(index <= maxAddendIndex);
+ addends[index-1] = addend;
+ }
+ // write table
+ out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));
+ }
+
typedef std::vector<std::pair<llvm::StringRef, uint32_t> > NameToOffsetVector;
+ typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
+ typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
+
const lld::File& _file;
NativeFileHeader* _headerBuffer;
size_t _headerBufferSize;
@@ -228,6 +405,11 @@
std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
std::vector<NativeAtomAttributesV1> _attributes;
std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
+ std::vector<NativeReferenceIvarsV1> _references;
+ TargetToIndex _targetsTableIndex;
+ TargetToIndex _definedAtomIndex;
+ TargetToIndex _undefinedAtomIndex;
+ AddendToIndex _addendsTableIndex;
NameToOffsetVector _sectionNames;
};
Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Feb 14 18:38:09 2012
@@ -199,20 +199,34 @@
}
}
+// helper to update targets for use with forEachReference()
+class ReferenceUpdater : public DefinedAtom::ReferenceHandler {
+public:
+ ReferenceUpdater(SymbolTable& sym) : _symbolTable(sym) { }
+
+ virtual void doReference(const Reference& ref) {
+ const Atom* newTarget = _symbolTable.replacement(ref.target());
+ (const_cast<Reference*>(&ref))->setTarget(newTarget);
+ }
+
+private:
+ SymbolTable& _symbolTable;
+};
+
+
// switch all references to undefined or coalesced away atoms
// to the new defined atom
void Resolver::updateReferences() {
+ ReferenceUpdater updater(_symbolTable);
for (std::vector<const Atom *>::iterator it = _atoms.begin();
it != _atoms.end(); ++it) {
if ( const DefinedAtom* defAtom = (*it)->definedAtom() ) {
- for (Reference::iterator rit = defAtom->referencesBegin(),
- end = defAtom->referencesEnd(); rit != end; ++rit) {
- rit->target = _symbolTable.replacement(rit->target);
- }
+ defAtom->forEachReference(updater);
}
}
}
+
// for dead code stripping, recursively mark atom "live"
void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
// if -why_live cares about this symbol, then dump chain
@@ -240,10 +254,8 @@
thisChain.previous = previous;
thisChain.referer = &atom;
if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
- for (Reference::iterator rit = defAtom->referencesBegin(),
- end = defAtom->referencesEnd(); rit != end; ++rit) {
- this->markLive(*(rit->target), &thisChain);
- }
+ MarkLiveReferences markRefs(*this, &thisChain);
+ defAtom->forEachReference(markRefs);
}
}
Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Tue Feb 14 18:38:09 2012
@@ -38,7 +38,7 @@
void SymbolTable::add(const DefinedAtom &atom) {
assert(atom.scope() != DefinedAtom::scopeTranslationUnit);
- if ( !atom.internalName() ) {
+ if ( !atom.name().empty() ) {
this->addByName(atom);
}
else {
Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Tue Feb 14 18:38:09 2012
@@ -18,12 +18,12 @@
const char* const KeyValues::nameKeyword = "name";
+const char* const KeyValues::refNameKeyword = "ref-name";
const char* const KeyValues::definitionKeyword = "definition";
const char* const KeyValues::scopeKeyword = "scope";
const char* const KeyValues::contentTypeKeyword = "type";
const char* const KeyValues::deadStripKindKeyword = "dead-strip";
const char* const KeyValues::sectionChoiceKeyword = "section-choice";
-const char* const KeyValues::internalNameKeyword = "internal-name";
const char* const KeyValues::interposableKeyword = "interposable";
const char* const KeyValues::mergeKeyword = "merge";
const char* const KeyValues::isThumbKeyword = "is-thumb";
@@ -31,8 +31,14 @@
const char* const KeyValues::sectionNameKeyword = "section-name";
const char* const KeyValues::contentKeyword = "content";
const char* const KeyValues::sizeKeyword = "size";
+const char* const KeyValues::fixupsKeyword = "fixups";
const char* const KeyValues::permissionsKeyword = "permissions";
const char* const KeyValues::weakImportKeyword = "weak-import";
+const char* const KeyValues::fixupsKindKeyword = "kind";
+const char* const KeyValues::fixupsOffsetKeyword = "offset";
+const char* const KeyValues::fixupsTargetKeyword = "target";
+const char* const KeyValues::fixupsAddendKeyword = "addend";
+
const DefinedAtom::Definition KeyValues::definitionDefault = Atom::definitionRegular;
@@ -43,7 +49,6 @@
const DefinedAtom::Interposable KeyValues::interposableDefault = DefinedAtom::interposeNo;
const DefinedAtom::Merge KeyValues::mergeDefault = DefinedAtom::mergeNo;
const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;
-const bool KeyValues::internalNameDefault = false;
const bool KeyValues::isThumbDefault = false;
const bool KeyValues::isAliasDefault = false;
const bool KeyValues::weakImportDefault = false;
@@ -352,22 +357,6 @@
-bool KeyValues::internalName(const char* s)
-{
- if ( strcmp(s, "true") == 0 )
- return true;
- else if ( strcmp(s, "false") == 0 )
- return false;
- llvm::report_fatal_error("bad internal-name value");
-}
-
-const char* KeyValues::internalName(bool b) {
- return b ? "true" : "false";
-}
-
-
-
-
bool KeyValues::isThumb(const char* s)
{
if ( strcmp(s, "true") == 0 )
Modified: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h Tue Feb 14 18:38:09 2012
@@ -20,10 +20,12 @@
class KeyValues {
public:
static const char* const nameKeyword;
+ static const char* const refNameKeyword;
static const char* const sectionNameKeyword;
static const char* const contentKeyword;
static const char* const sizeKeyword;
-
+ static const char* const fixupsKeyword;
+
static const char* const definitionKeyword;
static const Atom::Definition definitionDefault;
static Atom::Definition definition(const char*);
@@ -64,11 +66,6 @@
static DefinedAtom::ContentPermissions permissions(const char*);
static const char* permissions(DefinedAtom::ContentPermissions);
- static const char* const internalNameKeyword;
- static const bool internalNameDefault;
- static bool internalName(const char*);
- static const char* internalName(bool);
-
static const char* const isThumbKeyword;
static const bool isThumbDefault;
static bool isThumb(const char*);
@@ -84,6 +81,12 @@
static bool weakImport(const char*);
static const char* weakImport(bool);
+
+ static const char* const fixupsKindKeyword;
+ static const char* const fixupsOffsetKeyword;
+ static const char* const fixupsTargetKeyword;
+ static const char* const fixupsAddendKeyword;
+
};
} // namespace yaml
Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Tue Feb 14 18:38:09 2012
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include <string.h>
+
#include "YamlKeyValues.h"
#include "lld/Core/YamlReader.h"
@@ -30,6 +32,8 @@
namespace lld {
namespace yaml {
+namespace {
+
class YAML {
public:
struct Entry {
@@ -214,7 +218,7 @@
sequenceBytes->push_back(contentByte);
state = inValueSequenceEnd;
}
- else if (c == ' ') {
+ else if ( (c == ' ') || (c == '\n') ) {
// eat white space
}
else if (c == ',') {
@@ -245,6 +249,44 @@
}
}
+
+
+class YAMLReference : public Reference {
+public:
+ YAMLReference() : _target(NULL), _targetName(NULL),
+ _offsetInAtom(0), _addend(0), _kind(0) { }
+
+ virtual uint64_t offsetInAtom() const {
+ return _offsetInAtom;
+ }
+
+ virtual Kind kind() const {
+ return _kind;
+ }
+
+ virtual const Atom* target() const {
+ return _target;
+ }
+
+ virtual Addend addend() const {
+ return _addend;
+ }
+
+ virtual void setTarget(const Atom* newAtom) {
+ _target = newAtom;
+ }
+
+ const Atom* _target;
+ const char* _targetName;
+ uint64_t _offsetInAtom;
+ Addend _addend;
+ Kind _kind;
+};
+
+
+
+class YAMLDefinedAtom;
+
class YAMLFile : public File {
public:
YAMLFile()
@@ -255,29 +297,24 @@
virtual bool justInTimeforEachAtom(llvm::StringRef name,
File::AtomHandler &) const;
- std::vector<DefinedAtom*> _definedAtoms;
- std::vector<UndefinedAtom*> _undefinedAtoms;
- std::vector<Reference> _references;
- unsigned int _lastRefIndex;
-};
+ void bindTargetReferences();
+ void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
+ void addUndefinedAtom(UndefinedAtom* atom);
+ Atom* findAtom(const char* name);
+
+ struct NameAtomPair {
+ NameAtomPair(const char* n, Atom* a) : name(n), atom(a) {}
+ const char* name;
+ Atom* atom;
+ };
-bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
- handler.doFile(*this);
- for (std::vector<DefinedAtom *>::const_iterator it = _definedAtoms.begin();
- it != _definedAtoms.end(); ++it) {
- handler.doDefinedAtom(**it);
- }
- for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
- it != _undefinedAtoms.end(); ++it) {
- handler.doUndefinedAtom(**it);
- }
- return true;
-}
+ std::vector<YAMLDefinedAtom*> _definedAtoms;
+ std::vector<UndefinedAtom*> _undefinedAtoms;
+ std::vector<YAMLReference> _references;
+ std::vector<NameAtomPair> _nameToAtomMapping;
+ unsigned int _lastRefIndex;
+};
-bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
- File::AtomHandler &handler) const {
- return false;
-}
class YAMLDefinedAtom : public DefinedAtom {
@@ -291,7 +328,6 @@
, DefinedAtom::Merge merge
, DefinedAtom::DeadStripKind deadStrip
, DefinedAtom::ContentPermissions perms
- , bool internalName
, bool isThumb
, bool isAlias
, DefinedAtom::Alignment alignment
@@ -313,7 +349,6 @@
, _merge(merge)
, _deadStrip(deadStrip)
, _permissions(perms)
- , _internalName(internalName)
, _isThumb(isThumb)
, _isAlias(isAlias)
, _refStartIndex(file._lastRefIndex)
@@ -326,13 +361,12 @@
}
virtual llvm::StringRef name() const {
- return _name;
+ if ( _name == NULL )
+ return llvm::StringRef();
+ else
+ return _name;
}
- virtual bool internalName() const {
- return _internalName;
- }
-
virtual uint64_t size() const {
return (_content ? _content->size() : _size);
}
@@ -393,16 +427,18 @@
}
- virtual Reference::iterator referencesBegin() const {
- if (_file._references.size() < _refStartIndex)
- return (Reference::iterator)&_file._references[_refStartIndex];
- return 0;
+ virtual void forEachReference(ReferenceHandler& handler) const {
+ for (uint32_t i=_refStartIndex; i < _refEndIndex; ++i) {
+ handler.doReference(_file._references[i]);
+ }
}
-
- virtual Reference::iterator referencesEnd() const {
- if (_file._references.size() < _refEndIndex)
- return (Reference::iterator)&_file._references[_refEndIndex];
- return 0;
+
+ void bindTargetReferences() {
+ for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
+ const char* targetName = _file._references[i]._targetName;
+ Atom* targetAtom = _file.findAtom(targetName);
+ _file._references[i]._target = targetAtom;
+ }
}
private:
@@ -420,7 +456,6 @@
DefinedAtom::Merge _merge;
DefinedAtom::DeadStripKind _deadStrip;
DefinedAtom::ContentPermissions _permissions;
- bool _internalName;
bool _isThumb;
bool _isAlias;
unsigned int _refStartIndex;
@@ -453,22 +488,71 @@
};
+bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
+ handler.doFile(*this);
+ for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();
+ it != _definedAtoms.end(); ++it) {
+ handler.doDefinedAtom(**it);
+ }
+ for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
+ it != _undefinedAtoms.end(); ++it) {
+ handler.doUndefinedAtom(**it);
+ }
+ return true;
+}
+
+bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
+ File::AtomHandler &handler) const {
+ return false;
+}
+
+void YAMLFile::bindTargetReferences() {
+ for (std::vector<YAMLDefinedAtom *>::const_iterator
+ it = _definedAtoms.begin(); it != _definedAtoms.end(); ++it) {
+ YAMLDefinedAtom* atom = *it;
+ atom->bindTargetReferences();
+ }
+}
+
+Atom* YAMLFile::findAtom(const char* name) {
+ for (std::vector<NameAtomPair>::const_iterator it = _nameToAtomMapping.begin();
+ it != _nameToAtomMapping.end(); ++it) {
+ if ( strcmp(name, it->name) == 0 )
+ return it->atom;
+ }
+ llvm::report_fatal_error("reference to atom that does not exist");
+}
+
+void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {
+ _definedAtoms.push_back(atom);
+ assert(refName != NULL);
+ _nameToAtomMapping.push_back(NameAtomPair(refName, atom));
+}
+
+void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
+ _undefinedAtoms.push_back(atom);
+ _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
+}
+
class YAMLAtomState {
public:
YAMLAtomState();
void setName(const char *n);
+ void setRefName(const char *n);
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&);
const char * _name;
+ const char * _refName;
const char * _sectionName;
unsigned long long _size;
uint32_t _ordinal;
@@ -482,16 +566,16 @@
DefinedAtom::Merge _merge;
DefinedAtom::DeadStripKind _deadStrip;
DefinedAtom::ContentPermissions _permissions;
- bool _internalName;
bool _isThumb;
bool _isAlias;
bool _weakImport;
- Reference _ref;
+ YAMLReference _ref;
};
YAMLAtomState::YAMLAtomState()
: _name(NULL)
+ , _refName(NULL)
, _sectionName(NULL)
, _size(0)
, _ordinal(0)
@@ -505,38 +589,31 @@
, _merge(KeyValues::mergeDefault)
, _deadStrip(KeyValues::deadStripKindDefault)
, _permissions(KeyValues::permissionsDefault)
- , _internalName(KeyValues::internalNameDefault)
, _isThumb(KeyValues::isThumbDefault)
, _isAlias(KeyValues::isAliasDefault)
, _weakImport(false)
{
- _ref.target = NULL;
- _ref.addend = 0;
- _ref.offsetInAtom = 0;
- _ref.kind = 0;
- _ref.flags = 0;
-}
+ }
void YAMLAtomState::makeAtom(YAMLFile& f) {
if ( _definition == Atom::definitionRegular ) {
- DefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,
+ YAMLDefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,
_sectionChoice, _interpose, _merge, _deadStrip,
- _permissions, _internalName, _isThumb, _isAlias,
+ _permissions, _isThumb, _isAlias,
_alignment, _name, _sectionName, _size, _content);
-
- f._definedAtoms.push_back(a);
+ f.addDefinedAtom(a, _refName ? _refName : _name);
++_ordinal;
}
else if ( _definition == Atom::definitionUndefined ) {
UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport);
-
- f._undefinedAtoms.push_back(a);
+ f.addUndefinedAtom(a);
++_ordinal;
}
// reset state for next atom
_name = NULL;
+ _refName = NULL;
_sectionName = NULL;
_size = 0;
_ordinal = 0;
@@ -554,17 +631,20 @@
_isThumb = KeyValues::isThumbDefault;
_isAlias = KeyValues::isAliasDefault;
_weakImport = KeyValues::weakImportDefault;
- _ref.target = NULL;
- _ref.addend = 0;
- _ref.offsetInAtom = 0;
- _ref.kind = 0;
- _ref.flags = 0;
+ _ref._target = NULL;
+ _ref._targetName = NULL;
+ _ref._addend = 0;
+ _ref._offsetInAtom = 0;
+ _ref._kind = 0;
}
void YAMLAtomState::setName(const char *n) {
_name = n;
}
+void YAMLAtomState::setRefName(const char *n) {
+ _refName = n;
+}
void YAMLAtomState::setAlign2(const char *s) {
llvm::StringRef str(s);
@@ -576,33 +656,54 @@
void YAMLAtomState::setFixupKind(const char *s) {
if (strcmp(s, "pcrel32") == 0)
- _ref.kind = 1;
+ _ref._kind = 1;
else if (strcmp(s, "call32") == 0)
- _ref.kind = 2;
- else
- llvm::report_fatal_error("bad fixup kind value");
+ _ref._kind = 2;
+ else {
+ int k;
+ llvm::StringRef(s).getAsInteger(10, k);
+ _ref._kind = k;
+ }
}
void YAMLAtomState::setFixupOffset(const char *s) {
if ((s[0] == '0') && (s[1] == 'x'))
- llvm::StringRef(s).getAsInteger(16, _ref.offsetInAtom);
+ llvm::StringRef(s).getAsInteger(16, _ref._offsetInAtom);
else
- llvm::StringRef(s).getAsInteger(10, _ref.offsetInAtom);
+ 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);
// clear for next ref
- _ref.target = NULL;
- _ref.addend = 0;
- _ref.offsetInAtom = 0;
- _ref.kind = 0;
- _ref.flags = 0;
+ _ref._target = NULL;
+ _ref._targetName = NULL;
+ _ref._addend = 0;
+ _ref._offsetInAtom = 0;
+ _ref._kind = 0;
}
+
+} // anonymous namespace
+
+
+
+
+
+/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
+/// into lld::File object(s) and append each to the specified vector<File*>.
llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
, std::vector<File *> &result) {
std::vector<const YAML::Entry *> entries;
@@ -628,6 +729,7 @@
atomState.makeAtom(*file);
haveAtom = false;
}
+ file->bindTargetReferences();
result.push_back(file);
}
file = new YAMLFile();
@@ -663,10 +765,10 @@
atomState.setName(entry->value);
haveAtom = true;
}
- else if (strcmp(entry->key, KeyValues::internalNameKeyword) == 0) {
- atomState._internalName = KeyValues::internalName(entry->value);
+ else if (strcmp(entry->key, KeyValues::refNameKeyword) == 0) {
+ atomState.setRefName(entry->value);
haveAtom = true;
- }
+ }
else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {
atomState._definition = KeyValues::definition(entry->value);
haveAtom = true;
@@ -725,8 +827,9 @@
atomState.setAlign2(entry->value);
haveAtom = true;
}
- else if (strcmp(entry->key, "fixups") == 0) {
+ else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {
inFixups = true;
+
}
else {
return make_error_code(yaml_reader_error::unknown_keyword);
@@ -739,16 +842,22 @@
haveFixup = false;
}
}
- if (strcmp(entry->key, "kind") == 0) {
+ if (strcmp(entry->key, KeyValues::fixupsKindKeyword) == 0) {
atomState.setFixupKind(entry->value);
haveFixup = true;
- } else if (strcmp(entry->key, "offset") == 0) {
+ }
+ else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {
atomState.setFixupOffset(entry->value);
haveFixup = true;
- } else if (strcmp(entry->key, "target") == 0) {
+ }
+ else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {
atomState.setFixupTarget(entry->value);
haveFixup = true;
}
+ else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {
+ atomState.setFixupAddend(entry->value);
+ haveFixup = true;
+ }
}
}
lastDepth = entry->depth;
@@ -757,10 +866,12 @@
atomState.makeAtom(*file);
}
+ file->bindTargetReferences();
result.push_back(file);
return make_error_code(yaml_reader_error::success);
}
+
//
// Fill in vector<File*> from path to input text file.
//
Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Tue Feb 14 18:38:09 2012
@@ -15,6 +15,8 @@
#include "lld/Core/Reference.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/DataTypes.h"
@@ -26,50 +28,154 @@
namespace lld {
namespace yaml {
-class Handler : public File::AtomHandler {
+namespace {
+///
+/// In most cases, atoms names are unambiguous, so references can just
+/// use the atom name as the target (e.g. target: foo). But in a few
+/// cases that does not work, so ref-names are added. These are labels
+/// used only in yaml. The labels do not exist in the Atom model.
+///
+/// One need for ref-names are when atoms have no user supplied name
+/// (e.g. c-string literal). Another case is when two object files with
+/// identically named static functions are merged (ld -r) into one object file.
+/// In that case referencing the function by name is ambiguous, so a unique
+/// ref-name is added.
+///
+class RefNameBuilder : public File::AtomHandler,
+ public DefinedAtom::ReferenceHandler {
public:
- Handler(llvm::raw_ostream &out) : _out(out), _firstAtom(true) { }
+ RefNameBuilder() { }
+
+ virtual void doReference(const Reference& ref) {
+ // create refname for any unnamed reference target
+ if ( ref.target()->name().empty() ) {
+ char* buffer;
+ asprintf(&buffer, "L%03d", _unnamedCounter++);
+ _refNames[ref.target()] = buffer;
+ }
+ }
+
+ virtual void doFile(const File &) { }
+
+ virtual void doDefinedAtom(const DefinedAtom& atom) {
+ // Build map of atoms names to detect duplicates
+ if ( ! atom.name().empty() )
+ buildDuplicateNameMap(atom);
+
+ // Find references to unnamed atoms and create ref-names for them.
+ _unnamedCounter = 0;
+ atom.forEachReference(*this);
+ }
+
+ virtual void doUndefinedAtom(const UndefinedAtom& atom) {
+ buildDuplicateNameMap(atom);
+ }
+
+ void buildDuplicateNameMap(const Atom& atom) {
+ assert(!atom.name().empty());
+ NameToAtom::iterator pos = _nameMap.find(atom.name());
+ if ( pos != _nameMap.end() ) {
+ // Found name collision, give each a unique ref-name.
+ char* buffer;
+ asprintf(&buffer, "%s.%03d", atom.name().data(), ++_collisionCount);
+ _refNames[&atom] = buffer;
+ const Atom* prevAtom = pos->second;
+ AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
+ if ( pos2 == _refNames.end() ) {
+ // only create ref-name for previous if none already created
+ asprintf(&buffer, "%s.%03d", prevAtom->name().data(), ++_collisionCount);
+ _refNames[prevAtom] = buffer;
+ }
+ }
+ else {
+ // First time we've seen this name, just add it to map.
+ _nameMap[atom.name()] = &atom;
+ }
+ }
+
+ bool hasRefName(const Atom* atom) {
+ return _refNames.count(atom);
+ }
+
+ const char* refName(const Atom* atom) {
+ return _refNames.find(atom)->second;
+ }
+
+private:
+ struct MyMappingInfo {
+ static llvm::StringRef getEmptyKey() { return llvm::StringRef(); }
+ static llvm::StringRef getTombstoneKey() { return llvm::StringRef(" ", 0); }
+ static unsigned getHashValue(llvm::StringRef const val) {
+ return llvm::HashString(val); }
+ static bool isEqual(llvm::StringRef const lhs,
+ llvm::StringRef const rhs) { return lhs.equals(rhs); }
+ };
+ typedef llvm::DenseMap<llvm::StringRef, const Atom*, MyMappingInfo> NameToAtom;
+ typedef llvm::DenseMap<const Atom*, const char*> AtomToRefName;
+
+ unsigned int _collisionCount;
+ unsigned int _unnamedCounter;
+ NameToAtom _nameMap;
+ AtomToRefName _refNames;
+};
+
+
+///
+/// Helper class for writeObjectText() to write out atoms in yaml format.
+///
+class AtomWriter : public File::AtomHandler,
+ public DefinedAtom::ReferenceHandler {
+public:
+ AtomWriter(RefNameBuilder& rnb, llvm::raw_ostream &out)
+ : _out(out), _rnb(rnb), _firstAtom(true) { }
virtual void doFile(const class File &) { _firstAtom = true; }
virtual void doDefinedAtom(const class DefinedAtom &atom) {
- // add blank line between atoms for readability
- if ( !_firstAtom )
- _out << "\n";
- _firstAtom = false;
-
+ // add blank line between atoms for readability
+ if ( !_firstAtom )
+ _out << "\n";
+ _firstAtom = false;
+
+ bool hasDash = false;
+ if ( !atom.name().empty() ) {
_out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< atom.name()
<< "\n";
-
- if ( atom.internalName() != KeyValues::internalNameDefault ) {
- _out << " "
- << KeyValues::internalNameKeyword
+ hasDash = true;
+ }
+
+ if ( _rnb.hasRefName(&atom) ) {
+ _out << (hasDash ? " " : " - ")
+ << KeyValues::refNameKeyword
<< ":"
- << spacePadding(KeyValues::internalNameKeyword)
- << KeyValues::internalName(atom.internalName())
+ << spacePadding(KeyValues::refNameKeyword)
+ << _rnb.refName(&atom)
<< "\n";
+ hasDash = true;
}
if ( atom.definition() != KeyValues::definitionDefault ) {
- _out << " "
+ _out << (hasDash ? " " : " - ")
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
<< KeyValues::definition(atom.definition())
<< "\n";
+ hasDash = true;
}
if ( atom.scope() != KeyValues::scopeDefault ) {
- _out << " "
+ _out << (hasDash ? " " : " - ")
<< KeyValues::scopeKeyword
<< ":"
<< spacePadding(KeyValues::scopeKeyword)
<< KeyValues::scope(atom.scope())
<< "\n";
+ hasDash = true;
}
if ( atom.interposable() != KeyValues::interposableDefault ) {
@@ -161,17 +267,51 @@
_out << " ]\n";
}
- if (atom.referencesBegin() != atom.referencesEnd()) {
+ _wroteFirstFixup = false;
+ atom.forEachReference(*this);
+ }
+
+ virtual void doReference(const Reference& ref) {
+ if ( !_wroteFirstFixup ) {
_out << " fixups:\n";
- for (Reference::iterator it = atom.referencesBegin(),
- end = atom.referencesEnd(); it != end; ++it) {
- _out << " - kind: " << it->kind << "\n";
- _out << " offset: " << it->offsetInAtom << "\n";
- }
+ _wroteFirstFixup = true;
+ }
+ _out << " - "
+ << KeyValues::fixupsOffsetKeyword
+ << ":"
+ << spacePadding(KeyValues::fixupsOffsetKeyword)
+ << ref.offsetInAtom()
+ << "\n";
+ _out << " "
+ << KeyValues::fixupsKindKeyword
+ << ":"
+ << spacePadding(KeyValues::fixupsKindKeyword)
+ << ref.kind()
+ << "\n";
+ const Atom* target = ref.target();
+ if ( target != NULL ) {
+ llvm::StringRef refName = target->name();
+ if ( _rnb.hasRefName(target) )
+ refName = _rnb.refName(target);
+ assert(!refName.empty());
+ _out << " "
+ << KeyValues::fixupsTargetKeyword
+ << ":"
+ << spacePadding(KeyValues::fixupsTargetKeyword)
+ << refName
+ << "\n";
+ }
+ if ( ref.addend() != 0 ) {
+ _out << " "
+ << KeyValues::fixupsAddendKeyword
+ << ":"
+ << spacePadding(KeyValues::fixupsAddendKeyword)
+ << ref.addend()
+ << "\n";
}
-
}
+
virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
// add blank line between atoms for readability
if ( !_firstAtom )
@@ -219,11 +359,26 @@
}
llvm::raw_ostream& _out;
+ RefNameBuilder _rnb;
bool _firstAtom;
+ bool _wroteFirstFixup;
};
+} // anonymous namespace
+
+
+
+///
+/// writeObjectText - writes the lld::File object as in YAML
+/// format to the specified stream.
+///
void writeObjectText(const File &file, llvm::raw_ostream &out) {
- Handler h(out);
+ // Figure what ref-name labels are needed
+ RefNameBuilder rnb;
+ file.forEachAtom(rnb);
+
+ // Write out all atoms
+ AtomWriter h(rnb, out);
out << "---\n";
out << "atoms:\n";
file.forEachAtom(h);
Modified: lld/trunk/test/cstring-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/cstring-coalesce.objtxt?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/test/cstring-coalesce.objtxt (original)
+++ lld/trunk/test/cstring-coalesce.objtxt Tue Feb 14 18:38:09 2012
@@ -6,28 +6,24 @@
---
atoms:
- - name: L0
- internal-name: true
+ - ref-name: L0
scope: hidden
type: c-string
content: [ 68, 65, 6c, 6c, 6f, 00 ]
- - name: L1
- internal-name: true
+ - ref-name: L1
scope: hidden
type: c-string
content: [ 74, 68, 65, 72, 65, 00 ]
---
atoms:
- - name: L2
- internal-name: true
+ - ref-name: L2
scope: hidden
type: c-string
content: [ 68, 65, 6c, 6c, 6f, 00 ]
---
atoms:
- - name: L2
- internal-name: true
+ - ref-name: L2
scope: hidden
type: c-string
content: [ 74, 68, 65, 72, 65, 00 ]
Added: lld/trunk/test/fixups-addend.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-addend.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-addend.objtxt (added)
+++ lld/trunk/test/fixups-addend.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,50 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test addends in fixups
+#
+
+---
+atoms:
+ - name: foo
+ type: code
+ content: [ 48, 8D, 3D, 00, 00, 00, 00,
+ 48, 8D, 3D, 00, 00, 00, 00 ]
+ fixups:
+ - offset: 3
+ kind: 3
+ target: bar
+ addend: 100
+ - offset: 10
+ kind: 3
+ target: bar
+ addend: -50
+
+ - name: func
+ type: code
+ content: [ 48, 8D, 3D, 00, 00, 00, 00,
+ 48, 8D, 3D, 00, 00, 00, 00 ]
+ fixups:
+ - offset: 3
+ kind: 3
+ target: bar
+ addend: 8000000000
+ - offset: 10
+ kind: 3
+ target: bar
+ addend: -50
+
+ - name: bar
+ definition: undefined
+
+
+...
+
+# CHECK: name: foo
+# CHECK: fixups:
+# CHECK: addend: 100
+# CHECK: addend: -50
+# CHECK: name: func
+# CHECK: fixups:
+# CHECK: addend: 8000000000
+# CHECK: addend: -50
Added: lld/trunk/test/fixups-dup-named.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-dup-named.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-dup-named.objtxt (added)
+++ lld/trunk/test/fixups-dup-named.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,31 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test fixups referencing multiple atoms that have the same name
+#
+
+---
+atoms:
+ - name: foo
+ type: code
+ content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ]
+ fixups:
+ - offset: 1
+ kind: 3
+ target: bar_1
+ - offset: 6
+ kind: 3
+ target: bar_2
+
+ - name: bar
+ ref-name: bar_1
+ scope: static
+
+ - name: bar
+ ref-name: bar_2
+ scope: static
+
+
+...
+
+# CHECK: ...
Added: lld/trunk/test/fixups-named.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-named.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-named.objtxt (added)
+++ lld/trunk/test/fixups-named.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,35 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test fixups to simple named atoms
+#
+
+---
+atoms:
+ - name: foo
+ type: code
+ content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ]
+ fixups:
+ - offset: 1
+ kind: 3
+ target: bar
+ - offset: 6
+ kind: 3
+ target: baz
+
+ - name: baz
+ scope: static
+ type: code
+
+ - name: bar
+ definition: undefined
+
+
+...
+
+# CHECK: name: foo
+# CHECK: fixups:
+# CHECK: target: bar
+# CHECK: target: baz
+# CHECK: ...
+
Added: lld/trunk/test/fixups-unnamed.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-unnamed.objtxt?rev=150539&view=auto
==============================================================================
--- lld/trunk/test/fixups-unnamed.objtxt (added)
+++ lld/trunk/test/fixups-unnamed.objtxt Tue Feb 14 18:38:09 2012
@@ -0,0 +1,40 @@
+# RUN: lld-core %s | FileCheck %s
+
+#
+# Test fixups to unnamed atoms
+#
+
+---
+atoms:
+ - name: foo
+ type: code
+ content: [ 48, 8D, 3D, 00, 00, 00, 00,
+ 48, 8D, 3D, 00, 00, 00, 00 ]
+ fixups:
+ - offset: 3
+ kind: 3
+ target: LC1
+ - offset: 10
+ kind: 3
+ target: LC2
+
+
+ - ref-name: LC1
+ scope: hidden
+ type: c-string
+ content: [ 68, 65, 6c, 6c, 6f, 00 ]
+
+ - ref-name: LC2
+ scope: hidden
+ type: c-string
+ content: [ 74, 68, 65, 72, 65, 00 ]
+
+
+...
+
+# CHECK: name: foo
+# CHECK: fixups:
+# CHECK: offset: 3
+# CHECK: offset: 10
+# CHECK: ref-name:
+# CHECK: ref-name:
Removed: lld/trunk/test/internal-name-attributes.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/internal-name-attributes.objtxt?rev=150538&view=auto
==============================================================================
--- lld/trunk/test/internal-name-attributes.objtxt (original)
+++ lld/trunk/test/internal-name-attributes.objtxt (removed)
@@ -1,27 +0,0 @@
-# RUN: lld-core %s | FileCheck %s
-
-#
-# Test that internal-name attributes are preserved
-#
-
----
-atoms:
- - name: foo
- internal-name: false
- - name: L0
- internal-name: true
- - name: L1
- internal-name: true
- - name: bar
-...
-
-
-# CHECK: name: foo
-# CHECK-NOT: internal-name: false
-# CHECK: name: L0
-# CHECK: internal-name: true
-# CHECK: name: L1
-# CHECK: internal-name: true
-# CHECK: name: bar
-# CHECK-NOT: internal-name: false
-# CHECK: ...
Modified: lld/trunk/tools/lld-core/lld-core.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=150539&r1=150538&r2=150539&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Tue Feb 14 18:38:09 2012
@@ -234,8 +234,9 @@
// read native file
llvm::OwningPtr<lld::File> natFile;
- parseNativeObjectFileOrSTDIN(tempPath, natFile);
-
+ if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) )
+ return 1;
+
// write new atom graph out as YAML doc
yaml::writeObjectText(*natFile, out);
More information about the llvm-commits
mailing list