blob: bb05a97a6a9d7f49eb50e9a039a1ed802c06872f [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.
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000241 static error_code make(
242 const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> &mb,
243 StringRef path, std::vector<std::unique_ptr<lld::File> > &result) {
244 const uint8_t *const base =
245 reinterpret_cast<const uint8_t *>(mb->getBufferStart());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000246 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000247 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000248 const NativeChunk *const chunks =
249 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000250 // make sure magic matches
251 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000252 return make_error_code(native_reader_error::unknown_file_format);
253
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000254 // make sure mapped file contains all needed data
255 const size_t fileSize = mb->getBufferSize();
256 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000257 return make_error_code(native_reader_error::file_too_short);
258
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000259 DEBUG_WITH_TYPE("ReaderNative",
260 llvm::dbgs() << " Native File Header:" << " fileSize="
261 << header->fileSize << " chunkCount="
262 << header->chunkCount << "\n");
Nick Kledzikabb69812012-05-31 22:34:00 +0000263
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000264 // instantiate NativeFile object and add values to it as found
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000265 std::unique_ptr<File> file(new File(ti, std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000266
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000267 // process each chunk
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000268 for (uint32_t i = 0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000269 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000270 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000271 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000272 if ( chunk->fileOffset > fileSize )
273 return make_error_code(native_reader_error::file_malformed);
274 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
275 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000276 // process chunk, based on signature
277 switch ( chunk->signature ) {
278 case NCS_DefinedAtomsV1:
279 ec = file->processDefinedAtomsV1(base, chunk);
280 break;
281 case NCS_AttributesArrayV1:
282 ec = file->processAttributesV1(base, chunk);
283 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000284 case NCS_UndefinedAtomsV1:
285 ec = file->processUndefinedAtomsV1(base, chunk);
286 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000287 case NCS_SharedLibraryAtomsV1:
288 ec = file->processSharedLibraryAtomsV1(base, chunk);
289 break;
290 case NCS_AbsoluteAtomsV1:
291 ec = file->processAbsoluteAtomsV1(base, chunk);
292 break;
Sid Manning2a590242012-10-18 17:16:19 +0000293 case NCS_AbsoluteAttributesV1:
294 ec = file->processAbsoluteAttributesV1(base, chunk);
295 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000296 case NCS_ReferencesArrayV1:
297 ec = file->processReferencesV1(base, chunk);
298 break;
299 case NCS_TargetsTable:
300 ec = file->processTargetsTable(base, chunk);
301 break;
302 case NCS_AddendsTable:
303 ec = file->processAddendsTable(base, chunk);
304 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000305 case NCS_Content:
306 ec = file->processContent(base, chunk);
307 break;
308 case NCS_Strings:
309 ec = file->processStrings(base, chunk);
310 break;
311 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000312 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000313 }
314 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000315 return ec;
316 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000317 }
318 // TO DO: validate enough chunks were used
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000319
320 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000321 << " ReaderNative DefinedAtoms:\n");
322 for (const DefinedAtom *a : file->defined() ) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000323 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000324 << llvm::format(" 0x%09lX", a)
325 << ", name=" << a->name()
326 << ", size=" << a->size()
327 << "\n");
328 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000329 (void)r;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000330 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
331 << " offset="
Nick Kledzikabb69812012-05-31 22:34:00 +0000332 << llvm::format("0x%03X", r->offsetInAtom())
333 << ", kind=" << r->kind()
334 << ", target=" << r->target()
335 << "\n");
336 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000337 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000338
Nick Kledzikabb69812012-05-31 22:34:00 +0000339 result.push_back(std::move(file));
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000340 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000341 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000342
Nick Kledzikabb69812012-05-31 22:34:00 +0000343 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000344 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000345
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000346 // All other ivar pointers are pointers into the MemoryBuffer, except
347 // the _definedAtoms array which was allocated to contain an array
348 // of Atom objects. The atoms have empty destructors, so it is ok
349 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000350 delete _definedAtoms._arrayStart;
351 delete _undefinedAtoms._arrayStart;
352 delete _sharedLibraryAtoms._arrayStart;
353 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000354 delete _references.arrayStart;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000355 delete [] _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000356 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000357
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000358 virtual const atom_collection<DefinedAtom>& defined() const {
359 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000360 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000361 virtual const atom_collection<UndefinedAtom>& undefined() const {
362 return _undefinedAtoms;
363 }
364 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
365 return _sharedLibraryAtoms;
366 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000367 virtual const atom_collection<AbsoluteAtom> &absolute() const {
368 return _absoluteAtoms;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000369 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000370 virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000371
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000372private:
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000373 friend NativeDefinedAtomV1;
374 friend NativeUndefinedAtomV1;
375 friend NativeSharedLibraryAtomV1;
376 friend NativeAbsoluteAtomV1;
377 friend NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000378
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000379 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000380 error_code processDefinedAtomsV1(const uint8_t *base,
381 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000382 const size_t atomSize = sizeof(NativeDefinedAtomV1);
383 size_t atomsArraySize = chunk->elementCount * atomSize;
384 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
385 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000386 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000387 return make_error_code(native_reader_error::memory_error);
388 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000389 / chunk->elementCount;
390 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000391 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000392 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000393 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000394 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
395 (base + chunk->fileOffset);
396 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000397 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000398 reinterpret_cast<NativeDefinedAtomV1*>(s);
399 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
400 ++ivarData;
401 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000402 this->_definedAtoms._arrayStart = atomsStart;
403 this->_definedAtoms._arrayEnd = atomsEnd;
404 this->_definedAtoms._elementSize = atomSize;
405 this->_definedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000406 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000407 << " chunk DefinedAtomsV1: "
408 << " count=" << chunk->elementCount
409 << " chunkSize=" << chunk->fileSize
410 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000411 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000412 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000413
Nick Kledzikabb69812012-05-31 22:34:00 +0000414
415
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000416 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000417 error_code processAttributesV1(const uint8_t *base,
418 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000419 this->_attributes = base + chunk->fileOffset;
420 this->_attributesMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000421 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000422 << " chunk AttributesV1: "
423 << " count=" << chunk->elementCount
424 << " chunkSize=" << chunk->fileSize
425 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000426 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000427 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000428
Sid Manning2a590242012-10-18 17:16:19 +0000429 // set up pointers to attributes array
430 error_code processAbsoluteAttributesV1(const uint8_t *base,
431 const NativeChunk *chunk) {
432 this->_absAttributes = base + chunk->fileOffset;
433 this->_absAbsoluteMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000434 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Sid Manning2a590242012-10-18 17:16:19 +0000435 << " chunk AbsoluteAttributesV1: "
436 << " count=" << chunk->elementCount
437 << " chunkSize=" << chunk->fileSize
438 << "\n");
439 return make_error_code(native_reader_error::success);
440 }
441
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000442 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000443 error_code processUndefinedAtomsV1(const uint8_t *base,
444 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000445 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
446 size_t atomsArraySize = chunk->elementCount * atomSize;
447 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
448 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000449 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000450 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000451 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000452 / chunk->elementCount;
453 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
454 return make_error_code(native_reader_error::file_malformed);
455 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000456 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000457 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
458 (base + chunk->fileOffset);
459 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000460 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000461 reinterpret_cast<NativeUndefinedAtomV1*>(s);
462 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
463 ++ivarData;
464 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000465 this->_undefinedAtoms._arrayStart = atomsStart;
466 this->_undefinedAtoms._arrayEnd = atomsEnd;
467 this->_undefinedAtoms._elementSize = atomSize;
468 this->_undefinedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000469 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000470 << " chunk UndefinedAtomsV1:"
471 << " count=" << chunk->elementCount
472 << " chunkSize=" << chunk->fileSize
473 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000474 return make_error_code(native_reader_error::success);
475 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000476
477
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000478 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000479 error_code processSharedLibraryAtomsV1(const uint8_t *base,
480 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000481 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
482 size_t atomsArraySize = chunk->elementCount * atomSize;
483 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
484 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000485 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000486 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000487 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000488 / chunk->elementCount;
489 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
490 return make_error_code(native_reader_error::file_malformed);
491 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000492 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000493 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
494 (base + chunk->fileOffset);
495 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000496 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000497 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
498 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
499 ++ivarData;
500 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000501 this->_sharedLibraryAtoms._arrayStart = atomsStart;
502 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
503 this->_sharedLibraryAtoms._elementSize = atomSize;
504 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000505 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000506 << " chunk SharedLibraryAtomsV1:"
507 << " count=" << chunk->elementCount
508 << " chunkSize=" << chunk->fileSize
509 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000510 return make_error_code(native_reader_error::success);
511 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000512
513
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000514 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000515 error_code processAbsoluteAtomsV1(const uint8_t *base,
516 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000517 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
518 size_t atomsArraySize = chunk->elementCount * atomSize;
519 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
520 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000521 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000522 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000523 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000524 / chunk->elementCount;
525 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
526 return make_error_code(native_reader_error::file_malformed);
527 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000528 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000529 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
530 (base + chunk->fileOffset);
531 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000532 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000533 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
534 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
535 ++ivarData;
536 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000537 this->_absoluteAtoms._arrayStart = atomsStart;
538 this->_absoluteAtoms._arrayEnd = atomsEnd;
539 this->_absoluteAtoms._elementSize = atomSize;
540 this->_absoluteAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000541 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000542 << " chunk AbsoluteAtomsV1: "
543 << " count=" << chunk->elementCount
544 << " chunkSize=" << chunk->fileSize
545 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000546 return make_error_code(native_reader_error::success);
547 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000548
549
550
551
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000552 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000553 error_code processReferencesV1(const uint8_t *base,
554 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000555 if ( chunk->elementCount == 0 )
556 return make_error_code(native_reader_error::success);
557 const size_t refSize = sizeof(NativeReferenceV1);
558 size_t refsArraySize = chunk->elementCount * refSize;
559 uint8_t* refsStart = reinterpret_cast<uint8_t*>
560 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000561 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000562 return make_error_code(native_reader_error::memory_error);
563 const size_t ivarElementSize = chunk->fileSize
564 / chunk->elementCount;
565 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
566 return make_error_code(native_reader_error::file_malformed);
567 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000568 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000569 reinterpret_cast<const NativeReferenceIvarsV1*>
570 (base + chunk->fileOffset);
571 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000572 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000573 reinterpret_cast<NativeReferenceV1*>(s);
574 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
575 ++ivarData;
576 }
577 this->_references.arrayStart = refsStart;
578 this->_references.arrayEnd = refsEnd;
579 this->_references.elementSize = refSize;
580 this->_references.elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000581 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000582 << " chunk ReferencesV1: "
583 << " count=" << chunk->elementCount
584 << " chunkSize=" << chunk->fileSize
585 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000586 return make_error_code(native_reader_error::success);
587 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000588
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000589 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000590 error_code processTargetsTable(const uint8_t *base,
591 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000592 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
593 (base + chunk->fileOffset);
594 this->_targetsTableCount = chunk->elementCount;
595 this->_targetsTable = new const Atom*[chunk->elementCount];
596 for (uint32_t i=0; i < chunk->elementCount; ++i) {
597 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000598 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000599 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000600 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000601 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
602 continue;
603 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000604 const uint32_t undefIndex = index - _definedAtoms._elementCount;
605 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000606 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000607 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000608 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
609 continue;
610 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000611 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000612 - _undefinedAtoms._elementCount;
613 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000614 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000615 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000616 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
617 continue;
618 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000619 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000620 - _undefinedAtoms._elementCount
621 - _sharedLibraryAtoms._elementCount;
622 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000623 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000624 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000625 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
626 continue;
627 }
628 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000629 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000630 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000631 << " chunk Targets Table: "
632 << " count=" << chunk->elementCount
633 << " chunkSize=" << chunk->fileSize
634 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000635 return make_error_code(native_reader_error::success);
636 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000637
638
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000639 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000640 error_code processAddendsTable(const uint8_t *base,
641 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000642 this->_addends = reinterpret_cast<const Reference::Addend*>
643 (base + chunk->fileOffset);
644 this->_addendsMaxIndex = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000645 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000646 << " chunk Addends: "
647 << " count=" << chunk->elementCount
648 << " chunkSize=" << chunk->fileSize
649 << "\n");
Nick Kledzik23384e82012-02-07 02:59:54 +0000650 return make_error_code(native_reader_error::success);
651 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000652
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000653 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000654 error_code processStrings(const uint8_t *base,
655 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000656 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
657 this->_stringsMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000658 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000659 << " chunk Strings: "
660 << " chunkSize=" << chunk->fileSize
661 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000662 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000663 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000664
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000665 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000666 error_code processContent(const uint8_t *base,
667 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000668 this->_contentStart = base + chunk->fileOffset;
669 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000670 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000671 << " chunk content: "
672 << " chunkSize=" << chunk->fileSize
673 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000674 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000675 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000676
Michael J. Spencere6203a52012-04-03 18:39:40 +0000677 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000678 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000679 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000680 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000681
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000682 Reference::Addend addend(uint32_t index) const {
683 if ( index == 0 )
684 return 0; // addend index zero is used to mean "no addend"
685 assert(index <= _addendsMaxIndex);
686 return _addends[index-1]; // one-based indexing
687 }
688
689 const NativeAtomAttributesV1& attribute(uint32_t off) const {
690 assert(off < _attributesMaxOffset);
691 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000692 }
693
Sid Manning2a590242012-10-18 17:16:19 +0000694 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
695 assert(off < _absAbsoluteMaxOffset);
696 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
697 }
698
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000699 const uint8_t* content(uint32_t offset, uint32_t size) const {
700 const uint8_t* result = _contentStart + offset;
701 assert((result+size) <= _contentEnd);
702 return result;
703 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000704
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000705 const Reference* referenceByIndex(uintptr_t index) const {
706 assert(index < _references.elementCount);
707 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
708 return reinterpret_cast<const NativeReferenceV1*>(p);
709 }
710
Nick Kledzikb334be12012-04-07 01:31:00 +0000711 const Atom* target(uint16_t index) const {
712 if ( index == NativeReferenceIvarsV1::noTarget )
713 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000714 assert(index < _targetsTableCount);
715 return _targetsTable[index];
716 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000717
Nick Kledzikb334be12012-04-07 01:31:00 +0000718 void setTarget(uint16_t index, const Atom* newAtom) const {
719 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000720 assert(index > _targetsTableCount);
721 _targetsTable[index] = newAtom;
722 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000723
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000724 // private constructor, only called by make()
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000725 File(const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb,
726 StringRef path)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000727 : lld::File(path, kindObject),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000728 _buffer(std::move(mb)), // Reader now takes ownership of buffer
729 _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
730 _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
731 _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
732 _targetInfo(ti) {
733 _header =
734 reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000735 }
736
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000737 template <typename T>
738 class AtomArray : public File::atom_collection<T> {
739 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000740 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000741 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000742
743 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000744 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
745 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000746 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000747 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
748 }
749 virtual const T* deref(const void* it) const {
750 return reinterpret_cast<const T*>(it);
751 }
752 virtual void next(const void*& it) const {
753 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
754 p += _elementSize;
755 it = reinterpret_cast<const void*>(p);
756 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000757 virtual uint64_t size() const { return _elementCount; }
758 const uint8_t *_arrayStart;
759 const uint8_t *_arrayEnd;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000760 uint32_t _elementSize;
761 uint32_t _elementCount;
762 };
763
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000764 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000765 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000766 arrayStart(nullptr),
767 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000768 elementSize(0),
769 elementCount(0) { }
770
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000771 const uint8_t* arrayStart;
772 const uint8_t* arrayEnd;
773 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000774 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000775 };
776
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000777
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000778 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000779 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000780 AtomArray<DefinedAtom> _definedAtoms;
781 AtomArray<UndefinedAtom> _undefinedAtoms;
782 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
783 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000784 const uint8_t* _absAttributes;
785 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000786 const uint8_t* _attributes;
787 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000788 IvarArray _references;
789 const Atom** _targetsTable;
790 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000791 const char* _strings;
792 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000793 const Reference::Addend* _addends;
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000794 uint32_t _addendsMaxIndex;
795 const uint8_t *_contentStart;
796 const uint8_t *_contentEnd;
797 const TargetInfo &_targetInfo;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000798};
799
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000800inline const lld::File &NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000801 return *_file;
802}
803
804inline uint64_t NativeDefinedAtomV1:: ordinal() const {
805 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000806 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000807}
808
Michael J. Spencere6203a52012-04-03 18:39:40 +0000809inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000810 return _file->string(_ivarData->nameOffset);
811}
812
813inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
814 return _file->attribute(_ivarData->attributesOffset);
815}
816
Michael J. Spencere6203a52012-04-03 18:39:40 +0000817inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Shankar Easwarandb74ffb2013-02-24 03:09:10 +0000818 if (( this->contentType() == DefinedAtom::typeZeroFill ) ||
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000819 ( this->contentType() == DefinedAtom::typeZeroFillFast))
Michael J. Spencere6203a52012-04-03 18:39:40 +0000820 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000821 const uint8_t* p = _file->content(_ivarData->contentOffset,
822 _ivarData->contentSize);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000823 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000824}
825
Michael J. Spencere6203a52012-04-03 18:39:40 +0000826inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000827 uint32_t offset = attributes().sectionNameOffset;
828 return _file->string(offset);
829}
830
Nick Kledzik062a98c2012-04-08 23:52:13 +0000831DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000832 uintptr_t index = _ivarData->referencesStartIndex;
833 const void* it = reinterpret_cast<const void*>(index);
834 return reference_iterator(*this, it);
835}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000836
Nick Kledzik062a98c2012-04-08 23:52:13 +0000837DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000838 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
839 const void* it = reinterpret_cast<const void*>(index);
840 return reference_iterator(*this, it);
841}
842
843const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
844 uintptr_t index = reinterpret_cast<uintptr_t>(it);
845 return _file->referenceByIndex(index);
846}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000847
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000848void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
849 uintptr_t index = reinterpret_cast<uintptr_t>(it);
850 ++index;
851 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000852}
Nick Kledzik23384e82012-02-07 02:59:54 +0000853
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000854inline const lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000855 return *_file;
856}
857
Michael J. Spencere6203a52012-04-03 18:39:40 +0000858inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000859 return _file->string(_ivarData->nameOffset);
860}
861
862
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000863
864
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000865inline const lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000866 return *_file;
867}
868
Michael J. Spencere6203a52012-04-03 18:39:40 +0000869inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000870 return _file->string(_ivarData->nameOffset);
871}
872
Michael J. Spencere6203a52012-04-03 18:39:40 +0000873inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000874 return _file->string(_ivarData->loadNameOffset);
875}
876
877
878
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000879inline const lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000880 return *_file;
881}
882
Michael J. Spencere6203a52012-04-03 18:39:40 +0000883inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000884 return _file->string(_ivarData->nameOffset);
885}
886
Sid Manning2a590242012-10-18 17:16:19 +0000887inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
888 return _file->absAttribute(_ivarData->attributesOffset);
889}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000890
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000891inline const Atom* NativeReferenceV1::target() const {
892 return _file->target(_ivarData->targetIndex);
893}
894
895inline Reference::Addend NativeReferenceV1::addend() const {
896 return _file->addend(_ivarData->addendIndex);
897}
898
899inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
900 return _file->setTarget(_ivarData->targetIndex, newAtom);
901}
Nick Kledzik23384e82012-02-07 02:59:54 +0000902
Nick Kledzikb334be12012-04-07 01:31:00 +0000903inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000904 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000905 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000906 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000907 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000908}
909
Nick Kledzikabb69812012-05-31 22:34:00 +0000910class Reader : public lld::Reader {
911public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000912 Reader(const TargetInfo &ti)
913 : lld::Reader(ti) {}
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000914
Michael J. Spencere6d56092013-04-05 22:04:44 +0000915 virtual error_code parseFile(
916 std::unique_ptr<MemoryBuffer> &mb,
917 std::vector<std::unique_ptr<lld::File> > &result) const {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000918 return File::make(_targetInfo, 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
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000923std::unique_ptr<Reader> createReaderNative(const TargetInfo &ti) {
924 return std::unique_ptr<Reader>(new lld::native::Reader(ti));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000925}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000926} // end namespace lld