(no commit message)
llvm-svn: 150539
diff --git a/lld/lib/Core/NativeReader.cpp b/lld/lib/Core/NativeReader.cpp
index 033cf98..bc86d19 100644
--- a/lld/lib/Core/NativeReader.cpp
+++ b/lld/lib/Core/NativeReader.cpp
@@ -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);
+}
//