blob: 0554dcecd1fbe33a8ea68a17918a495b61f5ebdd [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
165private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000166 const File *_file;
167 const NativeSharedLibraryAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000168};
169
170
171//
172// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
173// struct in the NCS_AbsoluteAtomsV1 chunk.
174//
175class NativeAbsoluteAtomV1 : public AbsoluteAtom {
176public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000177 NativeAbsoluteAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000178 const NativeAbsoluteAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000179 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000180
Nick Kledzikabb69812012-05-31 22:34:00 +0000181 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000182 virtual StringRef name() const;
Sid Manning2a590242012-10-18 17:16:19 +0000183 virtual Scope scope() const {
184 const NativeAtomAttributesV1& attr = absAttributes();
185 return (Scope)(attr.scope);
186 }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000187 virtual uint64_t value() const {
188 return _ivarData->value;
189 }
190
191private:
Sid Manning2a590242012-10-18 17:16:19 +0000192 const NativeAtomAttributesV1& absAttributes() const;
Nick Kledzikabb69812012-05-31 22:34:00 +0000193 const File *_file;
194 const NativeAbsoluteAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000195};
196
197
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000198
199//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000200// An object of this class is instantied for each NativeReferenceIvarsV1
201// struct in the NCS_ReferencesArrayV1 chunk.
202//
203class NativeReferenceV1 : public Reference {
204public:
Michael J. Spencerfa405272013-03-20 18:57:52 +0000205 NativeReferenceV1(const File& f, const NativeReferenceIvarsV1* ivarData)
206 : _file(&f), _ivarData(ivarData) {
207 setKind(ivarData->kind);
208 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000209
210 virtual uint64_t offsetInAtom() const {
211 return _ivarData->offsetInAtom;
212 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000213
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000214 virtual const Atom* target() const;
215 virtual Addend addend() const;
216 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000217 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000218
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000219private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000220 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000221 // since ivar data is mapped read-only.
222 void cloneIvarData() {
223 // TODO: do nothing on second call
224 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000225 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000226 std::nothrow));
227 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
228 }
229
Nick Kledzikabb69812012-05-31 22:34:00 +0000230 const File *_file;
231 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000232};
233
234
235
236//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000237// lld::File object for native llvm object file
238//
Nick Kledzikabb69812012-05-31 22:34:00 +0000239class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000240public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000241
242 /// Instantiates a File object from a native object file. Ownership
243 /// of the MemoryBuffer is transfered to the resulting File object.
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000244 static error_code make(const LinkingContext &context,
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000245 LinkerInput &input,
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000246 std::vector<std::unique_ptr<lld::File>> &result) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000247 const uint8_t *const base =
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000248 reinterpret_cast<const uint8_t *>(input.getBuffer().getBufferStart());
249 StringRef path(input.getBuffer().getBufferIdentifier());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000250 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000251 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000252 const NativeChunk *const chunks =
253 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000254 // make sure magic matches
255 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000256 return make_error_code(native_reader_error::unknown_file_format);
257
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000258 // make sure mapped file contains all needed data
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000259 const size_t fileSize = input.getBuffer().getBufferSize();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000260 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000261 return make_error_code(native_reader_error::file_too_short);
262
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000263 DEBUG_WITH_TYPE("ReaderNative",
264 llvm::dbgs() << " Native File Header:" << " fileSize="
265 << header->fileSize << " chunkCount="
266 << header->chunkCount << "\n");
Nick Kledzikabb69812012-05-31 22:34:00 +0000267
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000268 // instantiate NativeFile object and add values to it as found
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000269 std::unique_ptr<File> file(new File(context, std::move(input.takeBuffer()),
270 path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000271
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000272 // process each chunk
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000273 for (uint32_t i = 0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000274 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000275 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000276 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000277 if ( chunk->fileOffset > fileSize )
278 return make_error_code(native_reader_error::file_malformed);
279 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
280 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000281 // process chunk, based on signature
282 switch ( chunk->signature ) {
283 case NCS_DefinedAtomsV1:
284 ec = file->processDefinedAtomsV1(base, chunk);
285 break;
286 case NCS_AttributesArrayV1:
287 ec = file->processAttributesV1(base, chunk);
288 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000289 case NCS_UndefinedAtomsV1:
290 ec = file->processUndefinedAtomsV1(base, chunk);
291 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000292 case NCS_SharedLibraryAtomsV1:
293 ec = file->processSharedLibraryAtomsV1(base, chunk);
294 break;
295 case NCS_AbsoluteAtomsV1:
296 ec = file->processAbsoluteAtomsV1(base, chunk);
297 break;
Sid Manning2a590242012-10-18 17:16:19 +0000298 case NCS_AbsoluteAttributesV1:
299 ec = file->processAbsoluteAttributesV1(base, chunk);
300 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000301 case NCS_ReferencesArrayV1:
302 ec = file->processReferencesV1(base, chunk);
303 break;
304 case NCS_TargetsTable:
305 ec = file->processTargetsTable(base, chunk);
306 break;
307 case NCS_AddendsTable:
308 ec = file->processAddendsTable(base, chunk);
309 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000310 case NCS_Content:
311 ec = file->processContent(base, chunk);
312 break;
313 case NCS_Strings:
314 ec = file->processStrings(base, chunk);
315 break;
316 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000317 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000318 }
319 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000320 return ec;
321 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000322 }
323 // TO DO: validate enough chunks were used
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000324
325 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000326 << " ReaderNative DefinedAtoms:\n");
327 for (const DefinedAtom *a : file->defined() ) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000328 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000329 << llvm::format(" 0x%09lX", a)
330 << ", name=" << a->name()
331 << ", size=" << a->size()
332 << "\n");
333 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000334 (void)r;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000335 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
336 << " offset="
Nick Kledzikabb69812012-05-31 22:34:00 +0000337 << llvm::format("0x%03X", r->offsetInAtom())
338 << ", kind=" << r->kind()
339 << ", target=" << r->target()
340 << "\n");
341 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000342 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000343
Nick Kledzikabb69812012-05-31 22:34:00 +0000344 result.push_back(std::move(file));
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000345 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000346 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000347
Nick Kledzikabb69812012-05-31 22:34:00 +0000348 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000349 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000350
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000351 // All other ivar pointers are pointers into the MemoryBuffer, except
352 // the _definedAtoms array which was allocated to contain an array
353 // of Atom objects. The atoms have empty destructors, so it is ok
354 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000355 delete _definedAtoms._arrayStart;
356 delete _undefinedAtoms._arrayStart;
357 delete _sharedLibraryAtoms._arrayStart;
358 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000359 delete _references.arrayStart;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000360 delete [] _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000361 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000362
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000363 virtual const atom_collection<DefinedAtom>& defined() const {
364 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000365 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000366 virtual const atom_collection<UndefinedAtom>& undefined() const {
367 return _undefinedAtoms;
368 }
369 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
370 return _sharedLibraryAtoms;
371 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000372 virtual const atom_collection<AbsoluteAtom> &absolute() const {
373 return _absoluteAtoms;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000374 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000375 virtual const LinkingContext &getLinkingContext() const { return _context; }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000376
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000377private:
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000378 friend NativeDefinedAtomV1;
379 friend NativeUndefinedAtomV1;
380 friend NativeSharedLibraryAtomV1;
381 friend NativeAbsoluteAtomV1;
382 friend NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000383
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000384 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000385 error_code processDefinedAtomsV1(const uint8_t *base,
386 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000387 const size_t atomSize = sizeof(NativeDefinedAtomV1);
388 size_t atomsArraySize = chunk->elementCount * atomSize;
389 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
390 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000391 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000392 return make_error_code(native_reader_error::memory_error);
393 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000394 / chunk->elementCount;
395 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000396 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000397 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000398 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000399 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
400 (base + chunk->fileOffset);
401 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000402 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000403 reinterpret_cast<NativeDefinedAtomV1*>(s);
404 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
405 ++ivarData;
406 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000407 this->_definedAtoms._arrayStart = atomsStart;
408 this->_definedAtoms._arrayEnd = atomsEnd;
409 this->_definedAtoms._elementSize = atomSize;
410 this->_definedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000411 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000412 << " chunk DefinedAtomsV1: "
413 << " count=" << chunk->elementCount
414 << " chunkSize=" << chunk->fileSize
415 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000416 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000417 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000418
Nick Kledzikabb69812012-05-31 22:34:00 +0000419
420
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000421 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000422 error_code processAttributesV1(const uint8_t *base,
423 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000424 this->_attributes = base + chunk->fileOffset;
425 this->_attributesMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000426 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000427 << " chunk AttributesV1: "
428 << " count=" << chunk->elementCount
429 << " chunkSize=" << chunk->fileSize
430 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000431 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000432 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000433
Sid Manning2a590242012-10-18 17:16:19 +0000434 // set up pointers to attributes array
435 error_code processAbsoluteAttributesV1(const uint8_t *base,
436 const NativeChunk *chunk) {
437 this->_absAttributes = base + chunk->fileOffset;
438 this->_absAbsoluteMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000439 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Sid Manning2a590242012-10-18 17:16:19 +0000440 << " chunk AbsoluteAttributesV1: "
441 << " count=" << chunk->elementCount
442 << " chunkSize=" << chunk->fileSize
443 << "\n");
444 return make_error_code(native_reader_error::success);
445 }
446
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000447 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000448 error_code processUndefinedAtomsV1(const uint8_t *base,
449 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000450 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
451 size_t atomsArraySize = chunk->elementCount * atomSize;
452 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
453 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000454 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000455 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000456 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000457 / chunk->elementCount;
458 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
459 return make_error_code(native_reader_error::file_malformed);
460 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000461 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000462 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
463 (base + chunk->fileOffset);
464 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000465 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000466 reinterpret_cast<NativeUndefinedAtomV1*>(s);
467 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
468 ++ivarData;
469 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000470 this->_undefinedAtoms._arrayStart = atomsStart;
471 this->_undefinedAtoms._arrayEnd = atomsEnd;
472 this->_undefinedAtoms._elementSize = atomSize;
473 this->_undefinedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000474 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000475 << " chunk UndefinedAtomsV1:"
476 << " count=" << chunk->elementCount
477 << " chunkSize=" << chunk->fileSize
478 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000479 return make_error_code(native_reader_error::success);
480 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000481
482
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000483 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000484 error_code processSharedLibraryAtomsV1(const uint8_t *base,
485 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000486 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
487 size_t atomsArraySize = chunk->elementCount * atomSize;
488 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
489 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000490 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000491 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000492 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000493 / chunk->elementCount;
494 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
495 return make_error_code(native_reader_error::file_malformed);
496 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000497 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000498 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
499 (base + chunk->fileOffset);
500 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000501 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000502 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
503 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
504 ++ivarData;
505 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000506 this->_sharedLibraryAtoms._arrayStart = atomsStart;
507 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
508 this->_sharedLibraryAtoms._elementSize = atomSize;
509 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000510 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000511 << " chunk SharedLibraryAtomsV1:"
512 << " count=" << chunk->elementCount
513 << " chunkSize=" << chunk->fileSize
514 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000515 return make_error_code(native_reader_error::success);
516 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000517
518
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000519 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000520 error_code processAbsoluteAtomsV1(const uint8_t *base,
521 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000522 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
523 size_t atomsArraySize = chunk->elementCount * atomSize;
524 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
525 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000526 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000527 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000528 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000529 / chunk->elementCount;
530 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
531 return make_error_code(native_reader_error::file_malformed);
532 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000533 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000534 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
535 (base + chunk->fileOffset);
536 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000537 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000538 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
539 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
540 ++ivarData;
541 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000542 this->_absoluteAtoms._arrayStart = atomsStart;
543 this->_absoluteAtoms._arrayEnd = atomsEnd;
544 this->_absoluteAtoms._elementSize = atomSize;
545 this->_absoluteAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000546 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000547 << " chunk AbsoluteAtomsV1: "
548 << " count=" << chunk->elementCount
549 << " chunkSize=" << chunk->fileSize
550 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000551 return make_error_code(native_reader_error::success);
552 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000553
554
555
556
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000557 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000558 error_code processReferencesV1(const uint8_t *base,
559 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000560 if ( chunk->elementCount == 0 )
561 return make_error_code(native_reader_error::success);
562 const size_t refSize = sizeof(NativeReferenceV1);
563 size_t refsArraySize = chunk->elementCount * refSize;
564 uint8_t* refsStart = reinterpret_cast<uint8_t*>
565 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000566 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000567 return make_error_code(native_reader_error::memory_error);
568 const size_t ivarElementSize = chunk->fileSize
569 / chunk->elementCount;
570 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
571 return make_error_code(native_reader_error::file_malformed);
572 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000573 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000574 reinterpret_cast<const NativeReferenceIvarsV1*>
575 (base + chunk->fileOffset);
576 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000577 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000578 reinterpret_cast<NativeReferenceV1*>(s);
579 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
580 ++ivarData;
581 }
582 this->_references.arrayStart = refsStart;
583 this->_references.arrayEnd = refsEnd;
584 this->_references.elementSize = refSize;
585 this->_references.elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000586 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000587 << " chunk ReferencesV1: "
588 << " count=" << chunk->elementCount
589 << " chunkSize=" << chunk->fileSize
590 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000591 return make_error_code(native_reader_error::success);
592 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000593
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000594 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000595 error_code processTargetsTable(const uint8_t *base,
596 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000597 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
598 (base + chunk->fileOffset);
599 this->_targetsTableCount = chunk->elementCount;
600 this->_targetsTable = new const Atom*[chunk->elementCount];
601 for (uint32_t i=0; i < chunk->elementCount; ++i) {
602 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000603 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000604 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000605 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000606 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
607 continue;
608 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000609 const uint32_t undefIndex = index - _definedAtoms._elementCount;
610 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000611 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000612 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000613 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
614 continue;
615 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000616 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000617 - _undefinedAtoms._elementCount;
618 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000619 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000620 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000621 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
622 continue;
623 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000624 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000625 - _undefinedAtoms._elementCount
626 - _sharedLibraryAtoms._elementCount;
627 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000628 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000629 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000630 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
631 continue;
632 }
633 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000634 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000635 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000636 << " chunk Targets Table: "
637 << " count=" << chunk->elementCount
638 << " chunkSize=" << chunk->fileSize
639 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000640 return make_error_code(native_reader_error::success);
641 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000642
643
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000644 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000645 error_code processAddendsTable(const uint8_t *base,
646 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000647 this->_addends = reinterpret_cast<const Reference::Addend*>
648 (base + chunk->fileOffset);
649 this->_addendsMaxIndex = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000650 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000651 << " chunk Addends: "
652 << " count=" << chunk->elementCount
653 << " chunkSize=" << chunk->fileSize
654 << "\n");
Nick Kledzik23384e82012-02-07 02:59:54 +0000655 return make_error_code(native_reader_error::success);
656 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000657
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000658 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000659 error_code processStrings(const uint8_t *base,
660 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000661 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
662 this->_stringsMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000663 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000664 << " chunk Strings: "
665 << " chunkSize=" << chunk->fileSize
666 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000667 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000668 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000669
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000670 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000671 error_code processContent(const uint8_t *base,
672 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000673 this->_contentStart = base + chunk->fileOffset;
674 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000675 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000676 << " chunk content: "
677 << " chunkSize=" << chunk->fileSize
678 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000679 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000680 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000681
Michael J. Spencere6203a52012-04-03 18:39:40 +0000682 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000683 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000684 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000685 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000686
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000687 Reference::Addend addend(uint32_t index) const {
688 if ( index == 0 )
689 return 0; // addend index zero is used to mean "no addend"
690 assert(index <= _addendsMaxIndex);
691 return _addends[index-1]; // one-based indexing
692 }
693
694 const NativeAtomAttributesV1& attribute(uint32_t off) const {
695 assert(off < _attributesMaxOffset);
696 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000697 }
698
Sid Manning2a590242012-10-18 17:16:19 +0000699 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
700 assert(off < _absAbsoluteMaxOffset);
701 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
702 }
703
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000704 const uint8_t* content(uint32_t offset, uint32_t size) const {
705 const uint8_t* result = _contentStart + offset;
706 assert((result+size) <= _contentEnd);
707 return result;
708 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000709
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000710 const Reference* referenceByIndex(uintptr_t index) const {
711 assert(index < _references.elementCount);
712 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
713 return reinterpret_cast<const NativeReferenceV1*>(p);
714 }
715
Nick Kledzikb334be12012-04-07 01:31:00 +0000716 const Atom* target(uint16_t index) const {
717 if ( index == NativeReferenceIvarsV1::noTarget )
718 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000719 assert(index < _targetsTableCount);
720 return _targetsTable[index];
721 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000722
Nick Kledzikb334be12012-04-07 01:31:00 +0000723 void setTarget(uint16_t index, const Atom* newAtom) const {
724 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000725 assert(index > _targetsTableCount);
726 _targetsTable[index] = newAtom;
727 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000728
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000729 // private constructor, only called by make()
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000730 File(const LinkingContext &context, std::unique_ptr<llvm::MemoryBuffer> mb,
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000731 StringRef path)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000732 : lld::File(path, kindObject),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000733 _buffer(std::move(mb)), // Reader now takes ownership of buffer
734 _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
735 _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
736 _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000737 _context(context) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000738 _header =
739 reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000740 }
741
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000742 template <typename T>
743 class AtomArray : public File::atom_collection<T> {
744 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000745 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000746 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000747
748 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000749 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
750 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000751 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000752 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
753 }
754 virtual const T* deref(const void* it) const {
755 return reinterpret_cast<const T*>(it);
756 }
757 virtual void next(const void*& it) const {
758 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
759 p += _elementSize;
760 it = reinterpret_cast<const void*>(p);
761 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000762 virtual uint64_t size() const { return _elementCount; }
763 const uint8_t *_arrayStart;
764 const uint8_t *_arrayEnd;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000765 uint32_t _elementSize;
766 uint32_t _elementCount;
767 };
768
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000769 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000770 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000771 arrayStart(nullptr),
772 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000773 elementSize(0),
774 elementCount(0) { }
775
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000776 const uint8_t* arrayStart;
777 const uint8_t* arrayEnd;
778 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000779 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000780 };
781
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000782
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000783 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000784 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000785 AtomArray<DefinedAtom> _definedAtoms;
786 AtomArray<UndefinedAtom> _undefinedAtoms;
787 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
788 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000789 const uint8_t* _absAttributes;
790 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000791 const uint8_t* _attributes;
792 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000793 IvarArray _references;
794 const Atom** _targetsTable;
795 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000796 const char* _strings;
797 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000798 const Reference::Addend* _addends;
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000799 uint32_t _addendsMaxIndex;
800 const uint8_t *_contentStart;
801 const uint8_t *_contentEnd;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000802 const LinkingContext &_context;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000803};
804
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000805inline const lld::File &NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000806 return *_file;
807}
808
809inline uint64_t NativeDefinedAtomV1:: ordinal() const {
810 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000811 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000812}
813
Michael J. Spencere6203a52012-04-03 18:39:40 +0000814inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000815 return _file->string(_ivarData->nameOffset);
816}
817
818inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
819 return _file->attribute(_ivarData->attributesOffset);
820}
821
Michael J. Spencere6203a52012-04-03 18:39:40 +0000822inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000823 if (!occupiesDiskSpace())
Michael J. Spencere6203a52012-04-03 18:39:40 +0000824 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000825 const uint8_t* p = _file->content(_ivarData->contentOffset,
826 _ivarData->contentSize);
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000827 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000828}
829
Michael J. Spencere6203a52012-04-03 18:39:40 +0000830inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000831 uint32_t offset = attributes().sectionNameOffset;
832 return _file->string(offset);
833}
834
Nick Kledzik062a98c2012-04-08 23:52:13 +0000835DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000836 uintptr_t index = _ivarData->referencesStartIndex;
837 const void* it = reinterpret_cast<const void*>(index);
838 return reference_iterator(*this, it);
839}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000840
Nick Kledzik062a98c2012-04-08 23:52:13 +0000841DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000842 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
843 const void* it = reinterpret_cast<const void*>(index);
844 return reference_iterator(*this, it);
845}
846
847const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
848 uintptr_t index = reinterpret_cast<uintptr_t>(it);
849 return _file->referenceByIndex(index);
850}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000851
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000852void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
853 uintptr_t index = reinterpret_cast<uintptr_t>(it);
854 ++index;
855 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000856}
Nick Kledzik23384e82012-02-07 02:59:54 +0000857
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000858inline const lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000859 return *_file;
860}
861
Michael J. Spencere6203a52012-04-03 18:39:40 +0000862inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000863 return _file->string(_ivarData->nameOffset);
864}
865
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000866inline const UndefinedAtom *NativeUndefinedAtomV1::fallback() const {
867 if (!_ivarData->fallbackNameOffset)
868 return nullptr;
869 if (!_fallback)
870 _fallback.reset(new SimpleUndefinedAtom(
871 *_file, _file->string(_ivarData->fallbackNameOffset)));
872 return _fallback.get();
873}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000874
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000875inline const lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000876 return *_file;
877}
878
Michael J. Spencere6203a52012-04-03 18:39:40 +0000879inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000880 return _file->string(_ivarData->nameOffset);
881}
882
Michael J. Spencere6203a52012-04-03 18:39:40 +0000883inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000884 return _file->string(_ivarData->loadNameOffset);
885}
886
887
888
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000889inline const lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000890 return *_file;
891}
892
Michael J. Spencere6203a52012-04-03 18:39:40 +0000893inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000894 return _file->string(_ivarData->nameOffset);
895}
896
Sid Manning2a590242012-10-18 17:16:19 +0000897inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
898 return _file->absAttribute(_ivarData->attributesOffset);
899}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000900
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000901inline const Atom* NativeReferenceV1::target() const {
902 return _file->target(_ivarData->targetIndex);
903}
904
905inline Reference::Addend NativeReferenceV1::addend() const {
906 return _file->addend(_ivarData->addendIndex);
907}
908
909inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
910 return _file->setTarget(_ivarData->targetIndex, newAtom);
911}
Nick Kledzik23384e82012-02-07 02:59:54 +0000912
Nick Kledzikb334be12012-04-07 01:31:00 +0000913inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000914 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000915 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000916 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000917 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000918}
919
Nick Kledzikabb69812012-05-31 22:34:00 +0000920class Reader : public lld::Reader {
921public:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000922 Reader(const LinkingContext &context) : lld::Reader(context) {}
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000923
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000924 virtual error_code
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000925 parseFile(LinkerInput &input,
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000926 std::vector<std::unique_ptr<lld::File>> &result) const {
Joerg Sonnenberger5e235de2013-09-07 17:55:28 +0000927 return File::make(_context, input, result);
Nick Kledzikabb69812012-05-31 22:34:00 +0000928 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000929};
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000930} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +0000931
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000932std::unique_ptr<Reader> createReaderNative(const LinkingContext &context) {
933 return std::unique_ptr<Reader>(new lld::native::Reader(context));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000934}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000935} // end namespace lld