blob: b11f6805a51c67acb640346b8aae3fc5e3746e42 [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"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000011
Michael J. Spencercfd029f2012-03-28 19:04:02 +000012#include "lld/Core/Atom.h"
13#include "lld/Core/Error.h"
14#include "lld/Core/File.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000015
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/OwningPtr.h"
18#include "llvm/ADT/StringRef.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000019#include "llvm/Support/Debug.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000020#include "llvm/Support/ErrorHandling.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000021#include "llvm/Support/Format.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000022#include "llvm/Support/MemoryBuffer.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000023#include "llvm/Support/raw_ostream.h"
24
25#include "NativeFileFormat.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000026
Michael J. Spencercfd029f2012-03-28 19:04:02 +000027#include <vector>
Nick Kledzikb334be12012-04-07 01:31:00 +000028#include <memory>
Nick Kledzik55fd6be2012-01-16 22:03:44 +000029
30namespace lld {
Nick Kledzikabb69812012-05-31 22:34:00 +000031namespace native {
Nick Kledzik55fd6be2012-01-16 22:03:44 +000032
33// forward reference
Nick Kledzikabb69812012-05-31 22:34:00 +000034class File;
Nick Kledzik55fd6be2012-01-16 22:03:44 +000035
Nick Kledzik55fd6be2012-01-16 22:03:44 +000036//
37// An object of this class is instantied for each NativeDefinedAtomIvarsV1
38// struct in the NCS_DefinedAtomsV1 chunk.
39//
40class NativeDefinedAtomV1 : public DefinedAtom {
41public:
Nick Kledzikabb69812012-05-31 22:34:00 +000042 NativeDefinedAtomV1(const File& f,
Nick Kledzik55fd6be2012-01-16 22:03:44 +000043 const NativeDefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +000044 : _file(&f), _ivarData(ivarData) { }
45
Rui Ueyama7b7b0b92013-06-21 19:59:15 +000046 virtual const lld::File& file() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000047
48 virtual uint64_t ordinal() const;
49
Michael J. Spencere6203a52012-04-03 18:39:40 +000050 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000051
Nick Kledzik55fd6be2012-01-16 22:03:44 +000052 virtual uint64_t size() const {
53 return _ivarData->contentSize;
54 }
55
56 virtual DefinedAtom::Scope scope() const {
57 return (DefinedAtom::Scope)(attributes().scope);
58 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000059
Nick Kledzik55fd6be2012-01-16 22:03:44 +000060 virtual DefinedAtom::Interposable interposable() const {
61 return (DefinedAtom::Interposable)(attributes().interposable);
62 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000063
Nick Kledzik55fd6be2012-01-16 22:03:44 +000064 virtual DefinedAtom::Merge merge() const {
65 return (DefinedAtom::Merge)(attributes().merge);
66 }
67
68 virtual DefinedAtom::ContentType contentType() const {
Nick Kledzik23384e82012-02-07 02:59:54 +000069 const NativeAtomAttributesV1& attr = attributes();
70 return (DefinedAtom::ContentType)(attr.contentType);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000071 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000072
Nick Kledzik55fd6be2012-01-16 22:03:44 +000073 virtual DefinedAtom::Alignment alignment() const {
74 return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
75 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000076
Nick Kledzik55fd6be2012-01-16 22:03:44 +000077 virtual DefinedAtom::SectionChoice sectionChoice() const {
Nick Kledzik36293f62013-01-23 22:32:56 +000078 return (DefinedAtom::SectionChoice)(
79 attributes().sectionChoiceAndPosition >> 4);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000080 }
81
Michael J. Spencere6203a52012-04-03 18:39:40 +000082 virtual StringRef customSectionName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000083
Nick Kledzik36293f62013-01-23 22:32:56 +000084 virtual SectionPosition sectionPosition() const {
85 return (DefinedAtom::SectionPosition)(
86 attributes().sectionChoiceAndPosition & 0xF);
87 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +000088
Nick Kledzik55fd6be2012-01-16 22:03:44 +000089 virtual DefinedAtom::DeadStripKind deadStrip() const {
90 return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
Nick Kledzik6bc04c62012-02-22 21:56:59 +000091 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000092
Nick Kledzik55fd6be2012-01-16 22:03:44 +000093 virtual DefinedAtom::ContentPermissions permissions() const {
94 return (DefinedAtom::ContentPermissions)(attributes().permissions);
95 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000096
Nick Kledzik55fd6be2012-01-16 22:03:44 +000097 virtual bool isAlias() const {
98 return (attributes().alias != 0);
99 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000100
Michael J. Spencere6203a52012-04-03 18:39:40 +0000101 virtual ArrayRef<uint8_t> rawContent() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000102
Nick Kledzik062a98c2012-04-08 23:52:13 +0000103 virtual reference_iterator begin() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000104
Nick Kledzik062a98c2012-04-08 23:52:13 +0000105 virtual reference_iterator end() const;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000106
107 virtual const Reference* derefIterator(const void*) const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000108
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000109 virtual void incrementIterator(const void*& it) const;
110
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000111private:
112 const NativeAtomAttributesV1& attributes() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000113
Nick Kledzikabb69812012-05-31 22:34:00 +0000114 const File *_file;
115 const NativeDefinedAtomIvarsV1 *_ivarData;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000116};
117
118
119
Nick Kledzik23384e82012-02-07 02:59:54 +0000120//
121// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
122// struct in the NCS_UndefinedAtomsV1 chunk.
123//
124class NativeUndefinedAtomV1 : public UndefinedAtom {
125public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000126 NativeUndefinedAtomV1(const File& f,
Nick Kledzik23384e82012-02-07 02:59:54 +0000127 const NativeUndefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000128 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik23384e82012-02-07 02:59:54 +0000129
Nick Kledzikabb69812012-05-31 22:34:00 +0000130 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000131 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000132
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000133 virtual CanBeNull canBeNull() const {
134 return (CanBeNull)(_ivarData->flags & 0x3);
Nick Kledzik23384e82012-02-07 02:59:54 +0000135 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000136
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000137
Nick Kledzik23384e82012-02-07 02:59:54 +0000138private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000139 const File *_file;
140 const NativeUndefinedAtomIvarsV1 *_ivarData;
Nick Kledzik23384e82012-02-07 02:59:54 +0000141};
142
143
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000144//
145// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
146// struct in the NCS_SharedLibraryAtomsV1 chunk.
147//
148class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
149public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000150 NativeSharedLibraryAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000151 const NativeSharedLibraryAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000152 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000153
Nick Kledzikabb69812012-05-31 22:34:00 +0000154 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000155 virtual StringRef name() const;
156 virtual StringRef loadName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000157
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000158 virtual bool canBeNullAtRuntime() const {
159 return (_ivarData->flags & 0x1);
160 }
161
162private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000163 const File *_file;
164 const NativeSharedLibraryAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000165};
166
167
168//
169// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
170// struct in the NCS_AbsoluteAtomsV1 chunk.
171//
172class NativeAbsoluteAtomV1 : public AbsoluteAtom {
173public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000174 NativeAbsoluteAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000175 const NativeAbsoluteAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000176 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000177
Nick Kledzikabb69812012-05-31 22:34:00 +0000178 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000179 virtual StringRef name() const;
Sid Manning2a590242012-10-18 17:16:19 +0000180 virtual Scope scope() const {
181 const NativeAtomAttributesV1& attr = absAttributes();
182 return (Scope)(attr.scope);
183 }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000184 virtual uint64_t value() const {
185 return _ivarData->value;
186 }
187
188private:
Sid Manning2a590242012-10-18 17:16:19 +0000189 const NativeAtomAttributesV1& absAttributes() const;
Nick Kledzikabb69812012-05-31 22:34:00 +0000190 const File *_file;
191 const NativeAbsoluteAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000192};
193
194
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000195
196//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000197// An object of this class is instantied for each NativeReferenceIvarsV1
198// struct in the NCS_ReferencesArrayV1 chunk.
199//
200class NativeReferenceV1 : public Reference {
201public:
Michael J. Spencerfa405272013-03-20 18:57:52 +0000202 NativeReferenceV1(const File& f, const NativeReferenceIvarsV1* ivarData)
203 : _file(&f), _ivarData(ivarData) {
204 setKind(ivarData->kind);
205 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000206
207 virtual uint64_t offsetInAtom() const {
208 return _ivarData->offsetInAtom;
209 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000210
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000211 virtual const Atom* target() const;
212 virtual Addend addend() const;
213 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000214 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000215
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000216private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000217 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000218 // since ivar data is mapped read-only.
219 void cloneIvarData() {
220 // TODO: do nothing on second call
221 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000222 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000223 std::nothrow));
224 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
225 }
226
Nick Kledzikabb69812012-05-31 22:34:00 +0000227 const File *_file;
228 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000229};
230
231
232
233//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000234// lld::File object for native llvm object file
235//
Nick Kledzikabb69812012-05-31 22:34:00 +0000236class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000237public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000238
239 /// Instantiates a File object from a native object file. Ownership
240 /// of the MemoryBuffer is transfered to the resulting File object.
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000241 static error_code make(const LinkingContext &context,
242 std::unique_ptr<llvm::MemoryBuffer> &mb,
243 StringRef path,
244 std::vector<std::unique_ptr<lld::File>> &result) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000245 const uint8_t *const base =
246 reinterpret_cast<const uint8_t *>(mb->getBufferStart());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000247 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000248 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000249 const NativeChunk *const chunks =
250 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000251 // make sure magic matches
252 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000253 return make_error_code(native_reader_error::unknown_file_format);
254
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000255 // make sure mapped file contains all needed data
256 const size_t fileSize = mb->getBufferSize();
257 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000258 return make_error_code(native_reader_error::file_too_short);
259
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000260 DEBUG_WITH_TYPE("ReaderNative",
261 llvm::dbgs() << " Native File Header:" << " fileSize="
262 << header->fileSize << " chunkCount="
263 << header->chunkCount << "\n");
Nick Kledzikabb69812012-05-31 22:34:00 +0000264
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000265 // instantiate NativeFile object and add values to it as found
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000266 std::unique_ptr<File> file(new File(context, std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000267
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000268 // process each chunk
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000269 for (uint32_t i = 0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000270 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000271 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000272 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000273 if ( chunk->fileOffset > fileSize )
274 return make_error_code(native_reader_error::file_malformed);
275 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
276 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000277 // process chunk, based on signature
278 switch ( chunk->signature ) {
279 case NCS_DefinedAtomsV1:
280 ec = file->processDefinedAtomsV1(base, chunk);
281 break;
282 case NCS_AttributesArrayV1:
283 ec = file->processAttributesV1(base, chunk);
284 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000285 case NCS_UndefinedAtomsV1:
286 ec = file->processUndefinedAtomsV1(base, chunk);
287 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000288 case NCS_SharedLibraryAtomsV1:
289 ec = file->processSharedLibraryAtomsV1(base, chunk);
290 break;
291 case NCS_AbsoluteAtomsV1:
292 ec = file->processAbsoluteAtomsV1(base, chunk);
293 break;
Sid Manning2a590242012-10-18 17:16:19 +0000294 case NCS_AbsoluteAttributesV1:
295 ec = file->processAbsoluteAttributesV1(base, chunk);
296 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000297 case NCS_ReferencesArrayV1:
298 ec = file->processReferencesV1(base, chunk);
299 break;
300 case NCS_TargetsTable:
301 ec = file->processTargetsTable(base, chunk);
302 break;
303 case NCS_AddendsTable:
304 ec = file->processAddendsTable(base, chunk);
305 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000306 case NCS_Content:
307 ec = file->processContent(base, chunk);
308 break;
309 case NCS_Strings:
310 ec = file->processStrings(base, chunk);
311 break;
312 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000313 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000314 }
315 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000316 return ec;
317 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000318 }
319 // TO DO: validate enough chunks were used
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000320
321 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000322 << " ReaderNative DefinedAtoms:\n");
323 for (const DefinedAtom *a : file->defined() ) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000324 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000325 << llvm::format(" 0x%09lX", a)
326 << ", name=" << a->name()
327 << ", size=" << a->size()
328 << "\n");
329 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000330 (void)r;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000331 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
332 << " offset="
Nick Kledzikabb69812012-05-31 22:34:00 +0000333 << llvm::format("0x%03X", r->offsetInAtom())
334 << ", kind=" << r->kind()
335 << ", target=" << r->target()
336 << "\n");
337 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000338 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000339
Nick Kledzikabb69812012-05-31 22:34:00 +0000340 result.push_back(std::move(file));
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000341 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000342 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000343
Nick Kledzikabb69812012-05-31 22:34:00 +0000344 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000345 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000346
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000347 // All other ivar pointers are pointers into the MemoryBuffer, except
348 // the _definedAtoms array which was allocated to contain an array
349 // of Atom objects. The atoms have empty destructors, so it is ok
350 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000351 delete _definedAtoms._arrayStart;
352 delete _undefinedAtoms._arrayStart;
353 delete _sharedLibraryAtoms._arrayStart;
354 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000355 delete _references.arrayStart;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000356 delete [] _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000357 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000358
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000359 virtual const atom_collection<DefinedAtom>& defined() const {
360 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000361 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000362 virtual const atom_collection<UndefinedAtom>& undefined() const {
363 return _undefinedAtoms;
364 }
365 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
366 return _sharedLibraryAtoms;
367 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000368 virtual const atom_collection<AbsoluteAtom> &absolute() const {
369 return _absoluteAtoms;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000370 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000371 virtual const LinkingContext &getLinkingContext() const { return _context; }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000372
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000373private:
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000374 friend NativeDefinedAtomV1;
375 friend NativeUndefinedAtomV1;
376 friend NativeSharedLibraryAtomV1;
377 friend NativeAbsoluteAtomV1;
378 friend NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000379
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000380 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000381 error_code processDefinedAtomsV1(const uint8_t *base,
382 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000383 const size_t atomSize = sizeof(NativeDefinedAtomV1);
384 size_t atomsArraySize = chunk->elementCount * atomSize;
385 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
386 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000387 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000388 return make_error_code(native_reader_error::memory_error);
389 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000390 / chunk->elementCount;
391 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000392 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000393 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000394 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000395 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
396 (base + chunk->fileOffset);
397 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000398 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000399 reinterpret_cast<NativeDefinedAtomV1*>(s);
400 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
401 ++ivarData;
402 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000403 this->_definedAtoms._arrayStart = atomsStart;
404 this->_definedAtoms._arrayEnd = atomsEnd;
405 this->_definedAtoms._elementSize = atomSize;
406 this->_definedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000407 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000408 << " chunk DefinedAtomsV1: "
409 << " count=" << chunk->elementCount
410 << " chunkSize=" << chunk->fileSize
411 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000412 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000413 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000414
Nick Kledzikabb69812012-05-31 22:34:00 +0000415
416
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000417 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000418 error_code processAttributesV1(const uint8_t *base,
419 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000420 this->_attributes = base + chunk->fileOffset;
421 this->_attributesMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000422 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000423 << " chunk AttributesV1: "
424 << " count=" << chunk->elementCount
425 << " chunkSize=" << chunk->fileSize
426 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000427 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000428 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000429
Sid Manning2a590242012-10-18 17:16:19 +0000430 // set up pointers to attributes array
431 error_code processAbsoluteAttributesV1(const uint8_t *base,
432 const NativeChunk *chunk) {
433 this->_absAttributes = base + chunk->fileOffset;
434 this->_absAbsoluteMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000435 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Sid Manning2a590242012-10-18 17:16:19 +0000436 << " chunk AbsoluteAttributesV1: "
437 << " count=" << chunk->elementCount
438 << " chunkSize=" << chunk->fileSize
439 << "\n");
440 return make_error_code(native_reader_error::success);
441 }
442
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000443 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000444 error_code processUndefinedAtomsV1(const uint8_t *base,
445 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000446 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
447 size_t atomsArraySize = chunk->elementCount * atomSize;
448 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
449 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000450 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000451 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000452 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000453 / chunk->elementCount;
454 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
455 return make_error_code(native_reader_error::file_malformed);
456 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000457 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000458 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
459 (base + chunk->fileOffset);
460 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000461 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000462 reinterpret_cast<NativeUndefinedAtomV1*>(s);
463 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
464 ++ivarData;
465 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000466 this->_undefinedAtoms._arrayStart = atomsStart;
467 this->_undefinedAtoms._arrayEnd = atomsEnd;
468 this->_undefinedAtoms._elementSize = atomSize;
469 this->_undefinedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000470 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000471 << " chunk UndefinedAtomsV1:"
472 << " count=" << chunk->elementCount
473 << " chunkSize=" << chunk->fileSize
474 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000475 return make_error_code(native_reader_error::success);
476 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000477
478
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000479 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000480 error_code processSharedLibraryAtomsV1(const uint8_t *base,
481 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000482 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
483 size_t atomsArraySize = chunk->elementCount * atomSize;
484 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
485 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000486 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000487 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000488 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000489 / chunk->elementCount;
490 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
491 return make_error_code(native_reader_error::file_malformed);
492 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000493 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000494 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
495 (base + chunk->fileOffset);
496 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000497 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000498 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
499 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
500 ++ivarData;
501 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000502 this->_sharedLibraryAtoms._arrayStart = atomsStart;
503 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
504 this->_sharedLibraryAtoms._elementSize = atomSize;
505 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000506 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000507 << " chunk SharedLibraryAtomsV1:"
508 << " count=" << chunk->elementCount
509 << " chunkSize=" << chunk->fileSize
510 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000511 return make_error_code(native_reader_error::success);
512 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000513
514
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000515 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000516 error_code processAbsoluteAtomsV1(const uint8_t *base,
517 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000518 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
519 size_t atomsArraySize = chunk->elementCount * atomSize;
520 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
521 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000522 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000523 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000524 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000525 / chunk->elementCount;
526 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
527 return make_error_code(native_reader_error::file_malformed);
528 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000529 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000530 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
531 (base + chunk->fileOffset);
532 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000533 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000534 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
535 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
536 ++ivarData;
537 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000538 this->_absoluteAtoms._arrayStart = atomsStart;
539 this->_absoluteAtoms._arrayEnd = atomsEnd;
540 this->_absoluteAtoms._elementSize = atomSize;
541 this->_absoluteAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000542 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000543 << " chunk AbsoluteAtomsV1: "
544 << " count=" << chunk->elementCount
545 << " chunkSize=" << chunk->fileSize
546 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000547 return make_error_code(native_reader_error::success);
548 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000549
550
551
552
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000553 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000554 error_code processReferencesV1(const uint8_t *base,
555 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000556 if ( chunk->elementCount == 0 )
557 return make_error_code(native_reader_error::success);
558 const size_t refSize = sizeof(NativeReferenceV1);
559 size_t refsArraySize = chunk->elementCount * refSize;
560 uint8_t* refsStart = reinterpret_cast<uint8_t*>
561 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000562 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000563 return make_error_code(native_reader_error::memory_error);
564 const size_t ivarElementSize = chunk->fileSize
565 / chunk->elementCount;
566 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
567 return make_error_code(native_reader_error::file_malformed);
568 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000569 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000570 reinterpret_cast<const NativeReferenceIvarsV1*>
571 (base + chunk->fileOffset);
572 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000573 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000574 reinterpret_cast<NativeReferenceV1*>(s);
575 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
576 ++ivarData;
577 }
578 this->_references.arrayStart = refsStart;
579 this->_references.arrayEnd = refsEnd;
580 this->_references.elementSize = refSize;
581 this->_references.elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000582 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000583 << " chunk ReferencesV1: "
584 << " count=" << chunk->elementCount
585 << " chunkSize=" << chunk->fileSize
586 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000587 return make_error_code(native_reader_error::success);
588 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000589
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000590 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000591 error_code processTargetsTable(const uint8_t *base,
592 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000593 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
594 (base + chunk->fileOffset);
595 this->_targetsTableCount = chunk->elementCount;
596 this->_targetsTable = new const Atom*[chunk->elementCount];
597 for (uint32_t i=0; i < chunk->elementCount; ++i) {
598 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000599 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000600 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000601 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000602 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
603 continue;
604 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000605 const uint32_t undefIndex = index - _definedAtoms._elementCount;
606 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000607 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000608 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000609 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
610 continue;
611 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000612 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000613 - _undefinedAtoms._elementCount;
614 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000615 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000616 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000617 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
618 continue;
619 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000620 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000621 - _undefinedAtoms._elementCount
622 - _sharedLibraryAtoms._elementCount;
623 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000624 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000625 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000626 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
627 continue;
628 }
629 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000630 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000631 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000632 << " chunk Targets Table: "
633 << " count=" << chunk->elementCount
634 << " chunkSize=" << chunk->fileSize
635 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000636 return make_error_code(native_reader_error::success);
637 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000638
639
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000640 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000641 error_code processAddendsTable(const uint8_t *base,
642 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000643 this->_addends = reinterpret_cast<const Reference::Addend*>
644 (base + chunk->fileOffset);
645 this->_addendsMaxIndex = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000646 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000647 << " chunk Addends: "
648 << " count=" << chunk->elementCount
649 << " chunkSize=" << chunk->fileSize
650 << "\n");
Nick Kledzik23384e82012-02-07 02:59:54 +0000651 return make_error_code(native_reader_error::success);
652 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000653
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000654 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000655 error_code processStrings(const uint8_t *base,
656 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000657 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
658 this->_stringsMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000659 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000660 << " chunk Strings: "
661 << " chunkSize=" << chunk->fileSize
662 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000663 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000664 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000665
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000666 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000667 error_code processContent(const uint8_t *base,
668 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000669 this->_contentStart = base + chunk->fileOffset;
670 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000671 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000672 << " chunk content: "
673 << " chunkSize=" << chunk->fileSize
674 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000675 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000676 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000677
Michael J. Spencere6203a52012-04-03 18:39:40 +0000678 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000679 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000680 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000681 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000682
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000683 Reference::Addend addend(uint32_t index) const {
684 if ( index == 0 )
685 return 0; // addend index zero is used to mean "no addend"
686 assert(index <= _addendsMaxIndex);
687 return _addends[index-1]; // one-based indexing
688 }
689
690 const NativeAtomAttributesV1& attribute(uint32_t off) const {
691 assert(off < _attributesMaxOffset);
692 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000693 }
694
Sid Manning2a590242012-10-18 17:16:19 +0000695 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
696 assert(off < _absAbsoluteMaxOffset);
697 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
698 }
699
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000700 const uint8_t* content(uint32_t offset, uint32_t size) const {
701 const uint8_t* result = _contentStart + offset;
702 assert((result+size) <= _contentEnd);
703 return result;
704 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000705
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000706 const Reference* referenceByIndex(uintptr_t index) const {
707 assert(index < _references.elementCount);
708 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
709 return reinterpret_cast<const NativeReferenceV1*>(p);
710 }
711
Nick Kledzikb334be12012-04-07 01:31:00 +0000712 const Atom* target(uint16_t index) const {
713 if ( index == NativeReferenceIvarsV1::noTarget )
714 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000715 assert(index < _targetsTableCount);
716 return _targetsTable[index];
717 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000718
Nick Kledzikb334be12012-04-07 01:31:00 +0000719 void setTarget(uint16_t index, const Atom* newAtom) const {
720 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000721 assert(index > _targetsTableCount);
722 _targetsTable[index] = newAtom;
723 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000724
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000725 // private constructor, only called by make()
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000726 File(const LinkingContext &context, std::unique_ptr<llvm::MemoryBuffer> mb,
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000727 StringRef path)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000728 : lld::File(path, kindObject),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000729 _buffer(std::move(mb)), // Reader now takes ownership of buffer
730 _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
731 _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
732 _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000733 _context(context) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000734 _header =
735 reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000736 }
737
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000738 template <typename T>
739 class AtomArray : public File::atom_collection<T> {
740 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000741 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000742 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000743
744 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000745 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
746 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000747 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000748 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
749 }
750 virtual const T* deref(const void* it) const {
751 return reinterpret_cast<const T*>(it);
752 }
753 virtual void next(const void*& it) const {
754 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
755 p += _elementSize;
756 it = reinterpret_cast<const void*>(p);
757 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000758 virtual uint64_t size() const { return _elementCount; }
759 const uint8_t *_arrayStart;
760 const uint8_t *_arrayEnd;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000761 uint32_t _elementSize;
762 uint32_t _elementCount;
763 };
764
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000765 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000766 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000767 arrayStart(nullptr),
768 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000769 elementSize(0),
770 elementCount(0) { }
771
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000772 const uint8_t* arrayStart;
773 const uint8_t* arrayEnd;
774 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000775 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000776 };
777
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000778
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000779 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000780 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000781 AtomArray<DefinedAtom> _definedAtoms;
782 AtomArray<UndefinedAtom> _undefinedAtoms;
783 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
784 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000785 const uint8_t* _absAttributes;
786 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000787 const uint8_t* _attributes;
788 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000789 IvarArray _references;
790 const Atom** _targetsTable;
791 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000792 const char* _strings;
793 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000794 const Reference::Addend* _addends;
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000795 uint32_t _addendsMaxIndex;
796 const uint8_t *_contentStart;
797 const uint8_t *_contentEnd;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000798 const LinkingContext &_context;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000799};
800
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000801inline const lld::File &NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000802 return *_file;
803}
804
805inline uint64_t NativeDefinedAtomV1:: ordinal() const {
806 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000807 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000808}
809
Michael J. Spencere6203a52012-04-03 18:39:40 +0000810inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000811 return _file->string(_ivarData->nameOffset);
812}
813
814inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
815 return _file->attribute(_ivarData->attributesOffset);
816}
817
Michael J. Spencere6203a52012-04-03 18:39:40 +0000818inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Shankar Easwarandb74ffb2013-02-24 03:09:10 +0000819 if (( this->contentType() == DefinedAtom::typeZeroFill ) ||
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000820 ( this->contentType() == DefinedAtom::typeZeroFillFast))
Michael J. Spencere6203a52012-04-03 18:39:40 +0000821 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000822 const uint8_t* p = _file->content(_ivarData->contentOffset,
823 _ivarData->contentSize);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000824 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000825}
826
Michael J. Spencere6203a52012-04-03 18:39:40 +0000827inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000828 uint32_t offset = attributes().sectionNameOffset;
829 return _file->string(offset);
830}
831
Nick Kledzik062a98c2012-04-08 23:52:13 +0000832DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000833 uintptr_t index = _ivarData->referencesStartIndex;
834 const void* it = reinterpret_cast<const void*>(index);
835 return reference_iterator(*this, it);
836}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000837
Nick Kledzik062a98c2012-04-08 23:52:13 +0000838DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000839 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
840 const void* it = reinterpret_cast<const void*>(index);
841 return reference_iterator(*this, it);
842}
843
844const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
845 uintptr_t index = reinterpret_cast<uintptr_t>(it);
846 return _file->referenceByIndex(index);
847}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000848
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000849void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
850 uintptr_t index = reinterpret_cast<uintptr_t>(it);
851 ++index;
852 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000853}
Nick Kledzik23384e82012-02-07 02:59:54 +0000854
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000855inline const lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000856 return *_file;
857}
858
Michael J. Spencere6203a52012-04-03 18:39:40 +0000859inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000860 return _file->string(_ivarData->nameOffset);
861}
862
863
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000864
865
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000866inline const lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000867 return *_file;
868}
869
Michael J. Spencere6203a52012-04-03 18:39:40 +0000870inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000871 return _file->string(_ivarData->nameOffset);
872}
873
Michael J. Spencere6203a52012-04-03 18:39:40 +0000874inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000875 return _file->string(_ivarData->loadNameOffset);
876}
877
878
879
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000880inline const lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000881 return *_file;
882}
883
Michael J. Spencere6203a52012-04-03 18:39:40 +0000884inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000885 return _file->string(_ivarData->nameOffset);
886}
887
Sid Manning2a590242012-10-18 17:16:19 +0000888inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
889 return _file->absAttribute(_ivarData->attributesOffset);
890}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000891
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000892inline const Atom* NativeReferenceV1::target() const {
893 return _file->target(_ivarData->targetIndex);
894}
895
896inline Reference::Addend NativeReferenceV1::addend() const {
897 return _file->addend(_ivarData->addendIndex);
898}
899
900inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
901 return _file->setTarget(_ivarData->targetIndex, newAtom);
902}
Nick Kledzik23384e82012-02-07 02:59:54 +0000903
Nick Kledzikb334be12012-04-07 01:31:00 +0000904inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000905 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000906 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000907 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000908 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000909}
910
Nick Kledzikabb69812012-05-31 22:34:00 +0000911class Reader : public lld::Reader {
912public:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000913 Reader(const LinkingContext &context) : lld::Reader(context) {}
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000914
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000915 virtual error_code
916 parseFile(std::unique_ptr<MemoryBuffer> &mb,
917 std::vector<std::unique_ptr<lld::File>> &result) const {
918 return File::make(_context, mb, mb->getBufferIdentifier(), result);
Nick Kledzikabb69812012-05-31 22:34:00 +0000919 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000920};
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000921} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +0000922
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000923std::unique_ptr<Reader> createReaderNative(const LinkingContext &context) {
924 return std::unique_ptr<Reader>(new lld::native::Reader(context));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000925}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000926} // end namespace lld