blob: be80dc98c0809efee1df9d29daf43f877a0b3232 [file] [log] [blame]
Nick Kledzikabb69812012-05-31 22:34:00 +00001//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
Nick Kledzik55fd6be2012-01-16 22:03:44 +00002//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Michael J. Spencer64afcb42013-01-23 01:18:43 +000010#include "lld/ReaderWriter/Reader.h"
Rui Ueyamae5416ec2013-09-12 19:14:05 +000011#include "lld/ReaderWriter/Simple.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000012
Michael J. Spencercfd029f2012-03-28 19:04:02 +000013#include "lld/Core/Atom.h"
14#include "lld/Core/Error.h"
15#include "lld/Core/File.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000016
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/OwningPtr.h"
19#include "llvm/ADT/StringRef.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000020#include "llvm/Support/Debug.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000021#include "llvm/Support/ErrorHandling.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000022#include "llvm/Support/Format.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000023#include "llvm/Support/MemoryBuffer.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000024#include "llvm/Support/raw_ostream.h"
25
26#include "NativeFileFormat.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000027
Michael J. Spencercfd029f2012-03-28 19:04:02 +000028#include <vector>
Nick Kledzikb334be12012-04-07 01:31:00 +000029#include <memory>
Nick Kledzik55fd6be2012-01-16 22:03:44 +000030
31namespace lld {
Nick Kledzikabb69812012-05-31 22:34:00 +000032namespace native {
Nick Kledzik55fd6be2012-01-16 22:03:44 +000033
34// forward reference
Nick Kledzikabb69812012-05-31 22:34:00 +000035class File;
Nick Kledzik55fd6be2012-01-16 22:03:44 +000036
Nick Kledzik55fd6be2012-01-16 22:03:44 +000037//
38// An object of this class is instantied for each NativeDefinedAtomIvarsV1
39// struct in the NCS_DefinedAtomsV1 chunk.
40//
41class NativeDefinedAtomV1 : public DefinedAtom {
42public:
Nick Kledzikabb69812012-05-31 22:34:00 +000043 NativeDefinedAtomV1(const File& f,
Nick Kledzik55fd6be2012-01-16 22:03:44 +000044 const NativeDefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +000045 : _file(&f), _ivarData(ivarData) { }
46
Rui Ueyama7b7b0b92013-06-21 19:59:15 +000047 virtual const lld::File& file() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000048
49 virtual uint64_t ordinal() const;
50
Michael J. Spencere6203a52012-04-03 18:39:40 +000051 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000052
Nick Kledzik55fd6be2012-01-16 22:03:44 +000053 virtual uint64_t size() const {
54 return _ivarData->contentSize;
55 }
56
57 virtual DefinedAtom::Scope scope() const {
58 return (DefinedAtom::Scope)(attributes().scope);
59 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000060
Nick Kledzik55fd6be2012-01-16 22:03:44 +000061 virtual DefinedAtom::Interposable interposable() const {
62 return (DefinedAtom::Interposable)(attributes().interposable);
63 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000064
Nick Kledzik55fd6be2012-01-16 22:03:44 +000065 virtual DefinedAtom::Merge merge() const {
66 return (DefinedAtom::Merge)(attributes().merge);
67 }
68
69 virtual DefinedAtom::ContentType contentType() const {
Nick Kledzik23384e82012-02-07 02:59:54 +000070 const NativeAtomAttributesV1& attr = attributes();
71 return (DefinedAtom::ContentType)(attr.contentType);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000072 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000073
Nick Kledzik55fd6be2012-01-16 22:03:44 +000074 virtual DefinedAtom::Alignment alignment() const {
75 return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
76 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000077
Nick Kledzik55fd6be2012-01-16 22:03:44 +000078 virtual DefinedAtom::SectionChoice sectionChoice() const {
Nick Kledzik36293f62013-01-23 22:32:56 +000079 return (DefinedAtom::SectionChoice)(
80 attributes().sectionChoiceAndPosition >> 4);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000081 }
82
Michael J. Spencere6203a52012-04-03 18:39:40 +000083 virtual StringRef customSectionName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000084
Nick Kledzik36293f62013-01-23 22:32:56 +000085 virtual SectionPosition sectionPosition() const {
86 return (DefinedAtom::SectionPosition)(
87 attributes().sectionChoiceAndPosition & 0xF);
88 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +000089
Nick Kledzik55fd6be2012-01-16 22:03:44 +000090 virtual DefinedAtom::DeadStripKind deadStrip() const {
91 return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
Nick Kledzik6bc04c62012-02-22 21:56:59 +000092 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000093
Nick Kledzik55fd6be2012-01-16 22:03:44 +000094 virtual DefinedAtom::ContentPermissions permissions() const {
95 return (DefinedAtom::ContentPermissions)(attributes().permissions);
96 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000097
Nick Kledzik55fd6be2012-01-16 22:03:44 +000098 virtual bool isAlias() const {
99 return (attributes().alias != 0);
100 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000101
Michael J. Spencere6203a52012-04-03 18:39:40 +0000102 virtual ArrayRef<uint8_t> rawContent() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000103
Nick Kledzik062a98c2012-04-08 23:52:13 +0000104 virtual reference_iterator begin() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000105
Nick Kledzik062a98c2012-04-08 23:52:13 +0000106 virtual reference_iterator end() const;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000107
108 virtual const Reference* derefIterator(const void*) const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000109
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000110 virtual void incrementIterator(const void*& it) const;
111
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000112private:
113 const NativeAtomAttributesV1& attributes() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000114
Nick Kledzikabb69812012-05-31 22:34:00 +0000115 const File *_file;
116 const NativeDefinedAtomIvarsV1 *_ivarData;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000117};
118
119
120
Nick Kledzik23384e82012-02-07 02:59:54 +0000121//
122// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
123// struct in the NCS_UndefinedAtomsV1 chunk.
124//
125class NativeUndefinedAtomV1 : public UndefinedAtom {
126public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000127 NativeUndefinedAtomV1(const File& f,
Nick Kledzik23384e82012-02-07 02:59:54 +0000128 const NativeUndefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000129 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik23384e82012-02-07 02:59:54 +0000130
Nick Kledzikabb69812012-05-31 22:34:00 +0000131 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000132 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000133
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000134 virtual CanBeNull canBeNull() const {
135 return (CanBeNull)(_ivarData->flags & 0x3);
Nick Kledzik23384e82012-02-07 02:59:54 +0000136 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000137
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000138 virtual const UndefinedAtom *fallback() const;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000139
Nick Kledzik23384e82012-02-07 02:59:54 +0000140private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000141 const File *_file;
142 const NativeUndefinedAtomIvarsV1 *_ivarData;
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000143 mutable std::unique_ptr<const SimpleUndefinedAtom> _fallback;
Nick Kledzik23384e82012-02-07 02:59:54 +0000144};
145
146
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000147//
148// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
149// struct in the NCS_SharedLibraryAtomsV1 chunk.
150//
151class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
152public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000153 NativeSharedLibraryAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000154 const NativeSharedLibraryAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000155 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000156
Nick Kledzikabb69812012-05-31 22:34:00 +0000157 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000158 virtual StringRef name() const;
159 virtual StringRef loadName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000160
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000161 virtual bool canBeNullAtRuntime() const {
162 return (_ivarData->flags & 0x1);
163 }
164
Michael J. Spencer4355bb92013-09-26 22:08:43 +0000165 virtual Type type() const {
166 return (Type)_ivarData->type;
167 }
168
169 virtual uint64_t size() const {
170 return _ivarData->size;
171 }
172
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000173private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000174 const File *_file;
175 const NativeSharedLibraryAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000176};
177
178
179//
180// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
181// struct in the NCS_AbsoluteAtomsV1 chunk.
182//
183class NativeAbsoluteAtomV1 : public AbsoluteAtom {
184public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000185 NativeAbsoluteAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000186 const NativeAbsoluteAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000187 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000188
Nick Kledzikabb69812012-05-31 22:34:00 +0000189 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000190 virtual StringRef name() const;
Sid Manning2a590242012-10-18 17:16:19 +0000191 virtual Scope scope() const {
192 const NativeAtomAttributesV1& attr = absAttributes();
193 return (Scope)(attr.scope);
194 }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000195 virtual uint64_t value() const {
196 return _ivarData->value;
197 }
198
199private:
Sid Manning2a590242012-10-18 17:16:19 +0000200 const NativeAtomAttributesV1& absAttributes() const;
Nick Kledzikabb69812012-05-31 22:34:00 +0000201 const File *_file;
202 const NativeAbsoluteAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000203};
204
205
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000206
207//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000208// An object of this class is instantied for each NativeReferenceIvarsV1
209// struct in the NCS_ReferencesArrayV1 chunk.
210//
211class NativeReferenceV1 : public Reference {
212public:
Michael J. Spencerfa405272013-03-20 18:57:52 +0000213 NativeReferenceV1(const File& f, const NativeReferenceIvarsV1* ivarData)
214 : _file(&f), _ivarData(ivarData) {
215 setKind(ivarData->kind);
216 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000217
218 virtual uint64_t offsetInAtom() const {
219 return _ivarData->offsetInAtom;
220 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000221
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000222 virtual const Atom* target() const;
223 virtual Addend addend() const;
224 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000225 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000226
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000227private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000228 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000229 // since ivar data is mapped read-only.
230 void cloneIvarData() {
231 // TODO: do nothing on second call
232 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000233 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000234 std::nothrow));
235 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
236 }
237
Nick Kledzikabb69812012-05-31 22:34:00 +0000238 const File *_file;
239 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000240};
241
242
243
244//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000245// lld::File object for native llvm object file
246//
Nick Kledzikabb69812012-05-31 22:34:00 +0000247class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000248public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000249
250 /// Instantiates a File object from a native object file. Ownership
251 /// of the MemoryBuffer is transfered to the resulting File object.
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000252 static error_code make(const LinkingContext &context,
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000253 std::unique_ptr<MemoryBuffer> mb,
254 std::vector<std::unique_ptr<lld::File> > &result) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000255 const uint8_t *const base =
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000256 reinterpret_cast<const uint8_t *>(mb->getBufferStart());
257 StringRef path(mb->getBufferIdentifier());
258 const NativeFileHeader *const header =
259 reinterpret_cast<const NativeFileHeader *>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000260 const NativeChunk *const chunks =
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000261 reinterpret_cast<const NativeChunk *>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000262 // make sure magic matches
263 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000264 return make_error_code(NativeReaderError::unknown_file_format);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000265
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000266 // make sure mapped file contains all needed data
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000267 const size_t fileSize = mb->getBufferSize();
268 if (header->fileSize > fileSize)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000269 return make_error_code(NativeReaderError::file_too_short);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000270
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000271 DEBUG_WITH_TYPE("ReaderNative",
272 llvm::dbgs() << " Native File Header:" << " fileSize="
273 << header->fileSize << " chunkCount="
274 << header->chunkCount << "\n");
Nick Kledzikabb69812012-05-31 22:34:00 +0000275
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000276 // instantiate NativeFile object and add values to it as found
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000277 std::unique_ptr<File> file(new File(context, std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000278
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000279 // process each chunk
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000280 for (uint32_t i = 0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000281 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000282 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000283 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000284 if ( chunk->fileOffset > fileSize )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000285 return make_error_code(NativeReaderError::file_malformed);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000286 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000287 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000288 // process chunk, based on signature
289 switch ( chunk->signature ) {
290 case NCS_DefinedAtomsV1:
291 ec = file->processDefinedAtomsV1(base, chunk);
292 break;
293 case NCS_AttributesArrayV1:
294 ec = file->processAttributesV1(base, chunk);
295 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000296 case NCS_UndefinedAtomsV1:
297 ec = file->processUndefinedAtomsV1(base, chunk);
298 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000299 case NCS_SharedLibraryAtomsV1:
300 ec = file->processSharedLibraryAtomsV1(base, chunk);
301 break;
302 case NCS_AbsoluteAtomsV1:
303 ec = file->processAbsoluteAtomsV1(base, chunk);
304 break;
Sid Manning2a590242012-10-18 17:16:19 +0000305 case NCS_AbsoluteAttributesV1:
306 ec = file->processAbsoluteAttributesV1(base, chunk);
307 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000308 case NCS_ReferencesArrayV1:
309 ec = file->processReferencesV1(base, chunk);
310 break;
311 case NCS_TargetsTable:
312 ec = file->processTargetsTable(base, chunk);
313 break;
314 case NCS_AddendsTable:
315 ec = file->processAddendsTable(base, chunk);
316 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000317 case NCS_Content:
318 ec = file->processContent(base, chunk);
319 break;
320 case NCS_Strings:
321 ec = file->processStrings(base, chunk);
322 break;
323 default:
Rui Ueyamac6015f62013-10-09 00:57:22 +0000324 return make_error_code(NativeReaderError::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000325 }
326 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000327 return ec;
328 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000329 }
330 // TO DO: validate enough chunks were used
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000331
332 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000333 << " ReaderNative DefinedAtoms:\n");
334 for (const DefinedAtom *a : file->defined() ) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000335 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000336 << llvm::format(" 0x%09lX", a)
337 << ", name=" << a->name()
338 << ", size=" << a->size()
339 << "\n");
340 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000341 (void)r;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000342 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
343 << " offset="
Nick Kledzikabb69812012-05-31 22:34:00 +0000344 << llvm::format("0x%03X", r->offsetInAtom())
345 << ", kind=" << r->kind()
346 << ", target=" << r->target()
347 << "\n");
348 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000349 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000350
Nick Kledzikabb69812012-05-31 22:34:00 +0000351 result.push_back(std::move(file));
Rui Ueyamac6015f62013-10-09 00:57:22 +0000352 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000353 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000354
Nick Kledzikabb69812012-05-31 22:34:00 +0000355 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000356 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000357
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000358 // All other ivar pointers are pointers into the MemoryBuffer, except
359 // the _definedAtoms array which was allocated to contain an array
360 // of Atom objects. The atoms have empty destructors, so it is ok
361 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000362 delete _definedAtoms._arrayStart;
363 delete _undefinedAtoms._arrayStart;
364 delete _sharedLibraryAtoms._arrayStart;
365 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000366 delete _references.arrayStart;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000367 delete [] _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000368 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000369
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000370 virtual const atom_collection<DefinedAtom>& defined() const {
371 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000372 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000373 virtual const atom_collection<UndefinedAtom>& undefined() const {
374 return _undefinedAtoms;
375 }
376 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
377 return _sharedLibraryAtoms;
378 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000379 virtual const atom_collection<AbsoluteAtom> &absolute() const {
380 return _absoluteAtoms;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000381 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000382 virtual const LinkingContext &getLinkingContext() const { return _context; }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000383
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000384private:
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000385 friend NativeDefinedAtomV1;
386 friend NativeUndefinedAtomV1;
387 friend NativeSharedLibraryAtomV1;
388 friend NativeAbsoluteAtomV1;
389 friend NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000390
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000391 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000392 error_code processDefinedAtomsV1(const uint8_t *base,
393 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000394 const size_t atomSize = sizeof(NativeDefinedAtomV1);
395 size_t atomsArraySize = chunk->elementCount * atomSize;
396 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
397 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000398 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000399 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000400 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000401 / chunk->elementCount;
402 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000403 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000404 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000405 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000406 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
407 (base + chunk->fileOffset);
408 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000409 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000410 reinterpret_cast<NativeDefinedAtomV1*>(s);
411 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
412 ++ivarData;
413 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000414 this->_definedAtoms._arrayStart = atomsStart;
415 this->_definedAtoms._arrayEnd = atomsEnd;
416 this->_definedAtoms._elementSize = atomSize;
417 this->_definedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000418 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000419 << " chunk DefinedAtomsV1: "
420 << " count=" << chunk->elementCount
421 << " chunkSize=" << chunk->fileSize
422 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000423 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000424 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000425
Nick Kledzikabb69812012-05-31 22:34:00 +0000426
427
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000428 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000429 error_code processAttributesV1(const uint8_t *base,
430 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000431 this->_attributes = base + chunk->fileOffset;
432 this->_attributesMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000433 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000434 << " chunk AttributesV1: "
435 << " count=" << chunk->elementCount
436 << " chunkSize=" << chunk->fileSize
437 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000438 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000439 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000440
Sid Manning2a590242012-10-18 17:16:19 +0000441 // set up pointers to attributes array
442 error_code processAbsoluteAttributesV1(const uint8_t *base,
443 const NativeChunk *chunk) {
444 this->_absAttributes = base + chunk->fileOffset;
445 this->_absAbsoluteMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000446 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Sid Manning2a590242012-10-18 17:16:19 +0000447 << " chunk AbsoluteAttributesV1: "
448 << " count=" << chunk->elementCount
449 << " chunkSize=" << chunk->fileSize
450 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000451 return make_error_code(NativeReaderError::success);
Sid Manning2a590242012-10-18 17:16:19 +0000452 }
453
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000454 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000455 error_code processUndefinedAtomsV1(const uint8_t *base,
456 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000457 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
458 size_t atomsArraySize = chunk->elementCount * atomSize;
459 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
460 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000461 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000462 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000463 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000464 / chunk->elementCount;
465 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000466 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik23384e82012-02-07 02:59:54 +0000467 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000468 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000469 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
470 (base + chunk->fileOffset);
471 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000472 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000473 reinterpret_cast<NativeUndefinedAtomV1*>(s);
474 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
475 ++ivarData;
476 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000477 this->_undefinedAtoms._arrayStart = atomsStart;
478 this->_undefinedAtoms._arrayEnd = atomsEnd;
479 this->_undefinedAtoms._elementSize = atomSize;
480 this->_undefinedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000481 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000482 << " chunk UndefinedAtomsV1:"
483 << " count=" << chunk->elementCount
484 << " chunkSize=" << chunk->fileSize
485 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000486 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000487 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000488
489
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000490 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000491 error_code processSharedLibraryAtomsV1(const uint8_t *base,
492 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000493 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
494 size_t atomsArraySize = chunk->elementCount * atomSize;
495 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
496 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000497 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000498 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000499 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000500 / chunk->elementCount;
501 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000502 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000503 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000504 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000505 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
506 (base + chunk->fileOffset);
507 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000508 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000509 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
510 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
511 ++ivarData;
512 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000513 this->_sharedLibraryAtoms._arrayStart = atomsStart;
514 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
515 this->_sharedLibraryAtoms._elementSize = atomSize;
516 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000517 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000518 << " chunk SharedLibraryAtomsV1:"
519 << " count=" << chunk->elementCount
520 << " chunkSize=" << chunk->fileSize
521 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000522 return make_error_code(NativeReaderError::success);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000523 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000524
525
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000526 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000527 error_code processAbsoluteAtomsV1(const uint8_t *base,
528 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000529 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
530 size_t atomsArraySize = chunk->elementCount * atomSize;
531 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
532 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000533 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000534 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000535 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000536 / chunk->elementCount;
537 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000538 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000539 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000540 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000541 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
542 (base + chunk->fileOffset);
543 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000544 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000545 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
546 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
547 ++ivarData;
548 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000549 this->_absoluteAtoms._arrayStart = atomsStart;
550 this->_absoluteAtoms._arrayEnd = atomsEnd;
551 this->_absoluteAtoms._elementSize = atomSize;
552 this->_absoluteAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000553 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000554 << " chunk AbsoluteAtomsV1: "
555 << " count=" << chunk->elementCount
556 << " chunkSize=" << chunk->fileSize
557 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000558 return make_error_code(NativeReaderError::success);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000559 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000560
561
562
563
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000564 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000565 error_code processReferencesV1(const uint8_t *base,
566 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000567 if ( chunk->elementCount == 0 )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000568 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000569 const size_t refSize = sizeof(NativeReferenceV1);
570 size_t refsArraySize = chunk->elementCount * refSize;
571 uint8_t* refsStart = reinterpret_cast<uint8_t*>
572 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000573 if (refsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000574 return make_error_code(NativeReaderError::memory_error);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000575 const size_t ivarElementSize = chunk->fileSize
576 / chunk->elementCount;
577 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000578 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000579 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000580 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000581 reinterpret_cast<const NativeReferenceIvarsV1*>
582 (base + chunk->fileOffset);
583 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000584 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000585 reinterpret_cast<NativeReferenceV1*>(s);
586 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
587 ++ivarData;
588 }
589 this->_references.arrayStart = refsStart;
590 this->_references.arrayEnd = refsEnd;
591 this->_references.elementSize = refSize;
592 this->_references.elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000593 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000594 << " chunk ReferencesV1: "
595 << " count=" << chunk->elementCount
596 << " chunkSize=" << chunk->fileSize
597 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000598 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000599 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000600
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000601 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000602 error_code processTargetsTable(const uint8_t *base,
603 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000604 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
605 (base + chunk->fileOffset);
606 this->_targetsTableCount = chunk->elementCount;
607 this->_targetsTable = new const Atom*[chunk->elementCount];
608 for (uint32_t i=0; i < chunk->elementCount; ++i) {
609 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000610 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000611 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000612 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000613 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
614 continue;
615 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000616 const uint32_t undefIndex = index - _definedAtoms._elementCount;
617 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000618 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000619 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000620 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
621 continue;
622 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000623 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000624 - _undefinedAtoms._elementCount;
625 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000626 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000627 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000628 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
629 continue;
630 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000631 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000632 - _undefinedAtoms._elementCount
633 - _sharedLibraryAtoms._elementCount;
634 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000635 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000636 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000637 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
638 continue;
639 }
Rui Ueyamac6015f62013-10-09 00:57:22 +0000640 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000641 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000642 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000643 << " chunk Targets Table: "
644 << " count=" << chunk->elementCount
645 << " chunkSize=" << chunk->fileSize
646 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000647 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000648 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000649
650
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000651 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000652 error_code processAddendsTable(const uint8_t *base,
653 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000654 this->_addends = reinterpret_cast<const Reference::Addend*>
655 (base + chunk->fileOffset);
656 this->_addendsMaxIndex = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000657 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000658 << " chunk Addends: "
659 << " count=" << chunk->elementCount
660 << " chunkSize=" << chunk->fileSize
661 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000662 return make_error_code(NativeReaderError::success);
Nick Kledzik23384e82012-02-07 02:59:54 +0000663 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000664
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000665 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000666 error_code processStrings(const uint8_t *base,
667 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000668 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
669 this->_stringsMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000670 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000671 << " chunk Strings: "
672 << " chunkSize=" << chunk->fileSize
673 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000674 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000675 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000676
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000677 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000678 error_code processContent(const uint8_t *base,
679 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000680 this->_contentStart = base + chunk->fileOffset;
681 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000682 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000683 << " chunk content: "
684 << " chunkSize=" << chunk->fileSize
685 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000686 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000687 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000688
Michael J. Spencere6203a52012-04-03 18:39:40 +0000689 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000690 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000691 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000692 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000693
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000694 Reference::Addend addend(uint32_t index) const {
695 if ( index == 0 )
696 return 0; // addend index zero is used to mean "no addend"
697 assert(index <= _addendsMaxIndex);
698 return _addends[index-1]; // one-based indexing
699 }
700
701 const NativeAtomAttributesV1& attribute(uint32_t off) const {
702 assert(off < _attributesMaxOffset);
703 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000704 }
705
Sid Manning2a590242012-10-18 17:16:19 +0000706 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
707 assert(off < _absAbsoluteMaxOffset);
708 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
709 }
710
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000711 const uint8_t* content(uint32_t offset, uint32_t size) const {
712 const uint8_t* result = _contentStart + offset;
713 assert((result+size) <= _contentEnd);
714 return result;
715 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000716
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000717 const Reference* referenceByIndex(uintptr_t index) const {
718 assert(index < _references.elementCount);
719 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
720 return reinterpret_cast<const NativeReferenceV1*>(p);
721 }
722
Nick Kledzikb334be12012-04-07 01:31:00 +0000723 const Atom* target(uint16_t index) const {
724 if ( index == NativeReferenceIvarsV1::noTarget )
725 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000726 assert(index < _targetsTableCount);
727 return _targetsTable[index];
728 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000729
Nick Kledzikb334be12012-04-07 01:31:00 +0000730 void setTarget(uint16_t index, const Atom* newAtom) const {
731 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000732 assert(index > _targetsTableCount);
733 _targetsTable[index] = newAtom;
734 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000735
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000736 // private constructor, only called by make()
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000737 File(const LinkingContext &context, std::unique_ptr<llvm::MemoryBuffer> mb,
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000738 StringRef path)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000739 : lld::File(path, kindObject),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000740 _buffer(std::move(mb)), // Reader now takes ownership of buffer
741 _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
742 _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
743 _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000744 _context(context) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000745 _header =
746 reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000747 }
748
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000749 template <typename T>
750 class AtomArray : public File::atom_collection<T> {
751 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000752 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000753 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000754
755 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000756 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
757 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000758 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000759 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
760 }
761 virtual const T* deref(const void* it) const {
762 return reinterpret_cast<const T*>(it);
763 }
764 virtual void next(const void*& it) const {
765 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
766 p += _elementSize;
767 it = reinterpret_cast<const void*>(p);
768 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000769 virtual uint64_t size() const { return _elementCount; }
770 const uint8_t *_arrayStart;
771 const uint8_t *_arrayEnd;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000772 uint32_t _elementSize;
773 uint32_t _elementCount;
774 };
775
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000776 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000777 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000778 arrayStart(nullptr),
779 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000780 elementSize(0),
781 elementCount(0) { }
782
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000783 const uint8_t* arrayStart;
784 const uint8_t* arrayEnd;
785 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000786 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000787 };
788
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000789
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000790 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000791 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000792 AtomArray<DefinedAtom> _definedAtoms;
793 AtomArray<UndefinedAtom> _undefinedAtoms;
794 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
795 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000796 const uint8_t* _absAttributes;
797 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000798 const uint8_t* _attributes;
799 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000800 IvarArray _references;
801 const Atom** _targetsTable;
802 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000803 const char* _strings;
804 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000805 const Reference::Addend* _addends;
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000806 uint32_t _addendsMaxIndex;
807 const uint8_t *_contentStart;
808 const uint8_t *_contentEnd;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000809 const LinkingContext &_context;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000810};
811
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000812inline const lld::File &NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000813 return *_file;
814}
815
816inline uint64_t NativeDefinedAtomV1:: ordinal() const {
817 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000818 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000819}
820
Michael J. Spencere6203a52012-04-03 18:39:40 +0000821inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000822 return _file->string(_ivarData->nameOffset);
823}
824
825inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
826 return _file->attribute(_ivarData->attributesOffset);
827}
828
Michael J. Spencere6203a52012-04-03 18:39:40 +0000829inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000830 if (!occupiesDiskSpace())
Michael J. Spencere6203a52012-04-03 18:39:40 +0000831 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000832 const uint8_t* p = _file->content(_ivarData->contentOffset,
833 _ivarData->contentSize);
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000834 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000835}
836
Michael J. Spencere6203a52012-04-03 18:39:40 +0000837inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000838 uint32_t offset = attributes().sectionNameOffset;
839 return _file->string(offset);
840}
841
Nick Kledzik062a98c2012-04-08 23:52:13 +0000842DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000843 uintptr_t index = _ivarData->referencesStartIndex;
844 const void* it = reinterpret_cast<const void*>(index);
845 return reference_iterator(*this, it);
846}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000847
Nick Kledzik062a98c2012-04-08 23:52:13 +0000848DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000849 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
850 const void* it = reinterpret_cast<const void*>(index);
851 return reference_iterator(*this, it);
852}
853
854const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
855 uintptr_t index = reinterpret_cast<uintptr_t>(it);
856 return _file->referenceByIndex(index);
857}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000858
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000859void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
860 uintptr_t index = reinterpret_cast<uintptr_t>(it);
861 ++index;
862 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000863}
Nick Kledzik23384e82012-02-07 02:59:54 +0000864
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000865inline const lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000866 return *_file;
867}
868
Michael J. Spencere6203a52012-04-03 18:39:40 +0000869inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000870 return _file->string(_ivarData->nameOffset);
871}
872
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000873inline const UndefinedAtom *NativeUndefinedAtomV1::fallback() const {
874 if (!_ivarData->fallbackNameOffset)
875 return nullptr;
876 if (!_fallback)
877 _fallback.reset(new SimpleUndefinedAtom(
878 *_file, _file->string(_ivarData->fallbackNameOffset)));
879 return _fallback.get();
880}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000881
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000882inline const lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000883 return *_file;
884}
885
Michael J. Spencere6203a52012-04-03 18:39:40 +0000886inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000887 return _file->string(_ivarData->nameOffset);
888}
889
Michael J. Spencere6203a52012-04-03 18:39:40 +0000890inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000891 return _file->string(_ivarData->loadNameOffset);
892}
893
894
895
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000896inline const lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000897 return *_file;
898}
899
Michael J. Spencere6203a52012-04-03 18:39:40 +0000900inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000901 return _file->string(_ivarData->nameOffset);
902}
903
Sid Manning2a590242012-10-18 17:16:19 +0000904inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
905 return _file->absAttribute(_ivarData->attributesOffset);
906}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000907
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000908inline const Atom* NativeReferenceV1::target() const {
909 return _file->target(_ivarData->targetIndex);
910}
911
912inline Reference::Addend NativeReferenceV1::addend() const {
913 return _file->addend(_ivarData->addendIndex);
914}
915
916inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
917 return _file->setTarget(_ivarData->targetIndex, newAtom);
918}
Nick Kledzik23384e82012-02-07 02:59:54 +0000919
Nick Kledzikb334be12012-04-07 01:31:00 +0000920inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000921 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000922 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000923 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000924 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000925}
926
Nick Kledzikabb69812012-05-31 22:34:00 +0000927class Reader : public lld::Reader {
928public:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000929 Reader(const LinkingContext &context) : lld::Reader(context) {}
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000930
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000931 virtual error_code
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000932 parseFile(std::unique_ptr<MemoryBuffer> &mb,
933 std::vector<std::unique_ptr<lld::File> > &result) const {
934 return File::make(_context, std::move(mb), result);
Nick Kledzikabb69812012-05-31 22:34:00 +0000935 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000936};
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000937} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +0000938
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000939std::unique_ptr<Reader> createReaderNative(const LinkingContext &context) {
940 return std::unique_ptr<Reader>(new lld::native::Reader(context));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000941}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000942} // end namespace lld