blob: 1255a22ee278c253cada32117621e9014760776e [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
Nick Kledzikabb69812012-05-31 22:34:00 +000046 virtual const class 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 isThumb() const {
Nick Kledzik49d6cc82012-02-15 00:38:09 +000098 return false; //(attributes().thumb != 0);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000099 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000100
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000101 virtual bool isAlias() const {
102 return (attributes().alias != 0);
103 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000104
Michael J. Spencere6203a52012-04-03 18:39:40 +0000105 virtual ArrayRef<uint8_t> rawContent() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000106
Nick Kledzik062a98c2012-04-08 23:52:13 +0000107 virtual reference_iterator begin() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000108
Nick Kledzik062a98c2012-04-08 23:52:13 +0000109 virtual reference_iterator end() const;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000110
111 virtual const Reference* derefIterator(const void*) const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000112
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000113 virtual void incrementIterator(const void*& it) const;
114
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000115private:
116 const NativeAtomAttributesV1& attributes() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000117
Nick Kledzikabb69812012-05-31 22:34:00 +0000118 const File *_file;
119 const NativeDefinedAtomIvarsV1 *_ivarData;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000120};
121
122
123
Nick Kledzik23384e82012-02-07 02:59:54 +0000124//
125// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
126// struct in the NCS_UndefinedAtomsV1 chunk.
127//
128class NativeUndefinedAtomV1 : public UndefinedAtom {
129public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000130 NativeUndefinedAtomV1(const File& f,
Nick Kledzik23384e82012-02-07 02:59:54 +0000131 const NativeUndefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000132 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik23384e82012-02-07 02:59:54 +0000133
Nick Kledzikabb69812012-05-31 22:34:00 +0000134 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000135 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000136
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000137 virtual CanBeNull canBeNull() const {
138 return (CanBeNull)(_ivarData->flags & 0x3);
Nick Kledzik23384e82012-02-07 02:59:54 +0000139 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000140
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000141
Nick Kledzik23384e82012-02-07 02:59:54 +0000142private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000143 const File *_file;
144 const NativeUndefinedAtomIvarsV1 *_ivarData;
Nick Kledzik23384e82012-02-07 02:59:54 +0000145};
146
147
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000148//
149// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
150// struct in the NCS_SharedLibraryAtomsV1 chunk.
151//
152class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
153public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000154 NativeSharedLibraryAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000155 const NativeSharedLibraryAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000156 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000157
Nick Kledzikabb69812012-05-31 22:34:00 +0000158 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000159 virtual StringRef name() const;
160 virtual StringRef loadName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000161
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000162 virtual bool canBeNullAtRuntime() const {
163 return (_ivarData->flags & 0x1);
164 }
165
166private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000167 const File *_file;
168 const NativeSharedLibraryAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000169};
170
171
172//
173// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
174// struct in the NCS_AbsoluteAtomsV1 chunk.
175//
176class NativeAbsoluteAtomV1 : public AbsoluteAtom {
177public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000178 NativeAbsoluteAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000179 const NativeAbsoluteAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000180 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000181
Nick Kledzikabb69812012-05-31 22:34:00 +0000182 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000183 virtual StringRef name() const;
Sid Manning2a590242012-10-18 17:16:19 +0000184 virtual Scope scope() const {
185 const NativeAtomAttributesV1& attr = absAttributes();
186 return (Scope)(attr.scope);
187 }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000188 virtual uint64_t value() const {
189 return _ivarData->value;
190 }
191
192private:
Sid Manning2a590242012-10-18 17:16:19 +0000193 const NativeAtomAttributesV1& absAttributes() const;
Nick Kledzikabb69812012-05-31 22:34:00 +0000194 const File *_file;
195 const NativeAbsoluteAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000196};
197
198
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000199
200//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000201// An object of this class is instantied for each NativeReferenceIvarsV1
202// struct in the NCS_ReferencesArrayV1 chunk.
203//
204class NativeReferenceV1 : public Reference {
205public:
Michael J. Spencerfa405272013-03-20 18:57:52 +0000206 NativeReferenceV1(const File& f, const NativeReferenceIvarsV1* ivarData)
207 : _file(&f), _ivarData(ivarData) {
208 setKind(ivarData->kind);
209 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000210
211 virtual uint64_t offsetInAtom() const {
212 return _ivarData->offsetInAtom;
213 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000214
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000215 virtual const Atom* target() const;
216 virtual Addend addend() const;
217 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000218 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000219
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000220private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000221 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000222 // since ivar data is mapped read-only.
223 void cloneIvarData() {
224 // TODO: do nothing on second call
225 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000226 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000227 std::nothrow));
228 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
229 }
230
Nick Kledzikabb69812012-05-31 22:34:00 +0000231 const File *_file;
232 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000233};
234
235
236
237//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000238// lld::File object for native llvm object file
239//
Nick Kledzikabb69812012-05-31 22:34:00 +0000240class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000241public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000242
243 /// Instantiates a File object from a native object file. Ownership
244 /// of the MemoryBuffer is transfered to the resulting File object.
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000245 static error_code make(
246 const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> &mb,
247 StringRef path, std::vector<std::unique_ptr<lld::File> > &result) {
248 const uint8_t *const base =
249 reinterpret_cast<const uint8_t *>(mb->getBufferStart());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000250 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000251 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000252 const NativeChunk *const chunks =
253 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000254 // make sure magic matches
255 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000256 return make_error_code(native_reader_error::unknown_file_format);
257
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000258 // make sure mapped file contains all needed data
259 const size_t fileSize = mb->getBufferSize();
260 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000261 return make_error_code(native_reader_error::file_too_short);
262
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000263 DEBUG_WITH_TYPE("ReaderNative",
264 llvm::dbgs() << " Native File Header:" << " fileSize="
265 << header->fileSize << " chunkCount="
266 << header->chunkCount << "\n");
Nick Kledzikabb69812012-05-31 22:34:00 +0000267
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000268 // instantiate NativeFile object and add values to it as found
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000269 std::unique_ptr<File> file(new File(ti, std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000270
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000271 // process each chunk
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000272 for (uint32_t i = 0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000273 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000274 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000275 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000276 if ( chunk->fileOffset > fileSize )
277 return make_error_code(native_reader_error::file_malformed);
278 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
279 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000280 // process chunk, based on signature
281 switch ( chunk->signature ) {
282 case NCS_DefinedAtomsV1:
283 ec = file->processDefinedAtomsV1(base, chunk);
284 break;
285 case NCS_AttributesArrayV1:
286 ec = file->processAttributesV1(base, chunk);
287 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000288 case NCS_UndefinedAtomsV1:
289 ec = file->processUndefinedAtomsV1(base, chunk);
290 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000291 case NCS_SharedLibraryAtomsV1:
292 ec = file->processSharedLibraryAtomsV1(base, chunk);
293 break;
294 case NCS_AbsoluteAtomsV1:
295 ec = file->processAbsoluteAtomsV1(base, chunk);
296 break;
Sid Manning2a590242012-10-18 17:16:19 +0000297 case NCS_AbsoluteAttributesV1:
298 ec = file->processAbsoluteAttributesV1(base, chunk);
299 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000300 case NCS_ReferencesArrayV1:
301 ec = file->processReferencesV1(base, chunk);
302 break;
303 case NCS_TargetsTable:
304 ec = file->processTargetsTable(base, chunk);
305 break;
306 case NCS_AddendsTable:
307 ec = file->processAddendsTable(base, chunk);
308 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000309 case NCS_Content:
310 ec = file->processContent(base, chunk);
311 break;
312 case NCS_Strings:
313 ec = file->processStrings(base, chunk);
314 break;
315 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000316 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000317 }
318 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000319 return ec;
320 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000321 }
322 // TO DO: validate enough chunks were used
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000323
324 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000325 << " ReaderNative DefinedAtoms:\n");
326 for (const DefinedAtom *a : file->defined() ) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000327 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000328 << llvm::format(" 0x%09lX", a)
329 << ", name=" << a->name()
330 << ", size=" << a->size()
331 << "\n");
332 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000333 (void)r;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000334 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
335 << " offset="
Nick Kledzikabb69812012-05-31 22:34:00 +0000336 << llvm::format("0x%03X", r->offsetInAtom())
337 << ", kind=" << r->kind()
338 << ", target=" << r->target()
339 << "\n");
340 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000341 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000342
Nick Kledzikabb69812012-05-31 22:34:00 +0000343 result.push_back(std::move(file));
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000344 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000345 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000346
Nick Kledzikabb69812012-05-31 22:34:00 +0000347 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000348 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000349
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000350 // All other ivar pointers are pointers into the MemoryBuffer, except
351 // the _definedAtoms array which was allocated to contain an array
352 // of Atom objects. The atoms have empty destructors, so it is ok
353 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000354 delete _definedAtoms._arrayStart;
355 delete _undefinedAtoms._arrayStart;
356 delete _sharedLibraryAtoms._arrayStart;
357 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000358 delete _references.arrayStart;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000359 delete [] _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000360 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000361
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000362 virtual const atom_collection<DefinedAtom>& defined() const {
363 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000364 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000365 virtual const atom_collection<UndefinedAtom>& undefined() const {
366 return _undefinedAtoms;
367 }
368 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
369 return _sharedLibraryAtoms;
370 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000371 virtual const atom_collection<AbsoluteAtom> &absolute() const {
372 return _absoluteAtoms;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000373 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000374 virtual const TargetInfo &getTargetInfo() const { return _targetInfo; }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000375
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000376private:
377 friend class NativeDefinedAtomV1;
Nick Kledzik23384e82012-02-07 02:59:54 +0000378 friend class NativeUndefinedAtomV1;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000379 friend class NativeSharedLibraryAtomV1;
380 friend class NativeAbsoluteAtomV1;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000381 friend class NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000382
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000383 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000384 error_code processDefinedAtomsV1(const uint8_t *base,
385 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000386 const size_t atomSize = sizeof(NativeDefinedAtomV1);
387 size_t atomsArraySize = chunk->elementCount * atomSize;
388 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
389 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000390 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000391 return make_error_code(native_reader_error::memory_error);
392 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000393 / chunk->elementCount;
394 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000395 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000396 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000397 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000398 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
399 (base + chunk->fileOffset);
400 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000401 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000402 reinterpret_cast<NativeDefinedAtomV1*>(s);
403 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
404 ++ivarData;
405 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000406 this->_definedAtoms._arrayStart = atomsStart;
407 this->_definedAtoms._arrayEnd = atomsEnd;
408 this->_definedAtoms._elementSize = atomSize;
409 this->_definedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000410 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000411 << " chunk DefinedAtomsV1: "
412 << " count=" << chunk->elementCount
413 << " chunkSize=" << chunk->fileSize
414 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000415 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000416 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000417
Nick Kledzikabb69812012-05-31 22:34:00 +0000418
419
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000420 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000421 error_code processAttributesV1(const uint8_t *base,
422 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000423 this->_attributes = base + chunk->fileOffset;
424 this->_attributesMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000425 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000426 << " chunk AttributesV1: "
427 << " count=" << chunk->elementCount
428 << " chunkSize=" << chunk->fileSize
429 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000430 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000431 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000432
Sid Manning2a590242012-10-18 17:16:19 +0000433 // set up pointers to attributes array
434 error_code processAbsoluteAttributesV1(const uint8_t *base,
435 const NativeChunk *chunk) {
436 this->_absAttributes = base + chunk->fileOffset;
437 this->_absAbsoluteMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000438 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Sid Manning2a590242012-10-18 17:16:19 +0000439 << " chunk AbsoluteAttributesV1: "
440 << " count=" << chunk->elementCount
441 << " chunkSize=" << chunk->fileSize
442 << "\n");
443 return make_error_code(native_reader_error::success);
444 }
445
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000446 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000447 error_code processUndefinedAtomsV1(const uint8_t *base,
448 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000449 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
450 size_t atomsArraySize = chunk->elementCount * atomSize;
451 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
452 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000453 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000454 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000455 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000456 / chunk->elementCount;
457 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
458 return make_error_code(native_reader_error::file_malformed);
459 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000460 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000461 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
462 (base + chunk->fileOffset);
463 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000464 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000465 reinterpret_cast<NativeUndefinedAtomV1*>(s);
466 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
467 ++ivarData;
468 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000469 this->_undefinedAtoms._arrayStart = atomsStart;
470 this->_undefinedAtoms._arrayEnd = atomsEnd;
471 this->_undefinedAtoms._elementSize = atomSize;
472 this->_undefinedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000473 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000474 << " chunk UndefinedAtomsV1:"
475 << " count=" << chunk->elementCount
476 << " chunkSize=" << chunk->fileSize
477 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000478 return make_error_code(native_reader_error::success);
479 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000480
481
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000482 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000483 error_code processSharedLibraryAtomsV1(const uint8_t *base,
484 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000485 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
486 size_t atomsArraySize = chunk->elementCount * atomSize;
487 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
488 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000489 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000490 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000491 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000492 / chunk->elementCount;
493 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
494 return make_error_code(native_reader_error::file_malformed);
495 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000496 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000497 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
498 (base + chunk->fileOffset);
499 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000500 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000501 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
502 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
503 ++ivarData;
504 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000505 this->_sharedLibraryAtoms._arrayStart = atomsStart;
506 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
507 this->_sharedLibraryAtoms._elementSize = atomSize;
508 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000509 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000510 << " chunk SharedLibraryAtomsV1:"
511 << " count=" << chunk->elementCount
512 << " chunkSize=" << chunk->fileSize
513 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000514 return make_error_code(native_reader_error::success);
515 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000516
517
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000518 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000519 error_code processAbsoluteAtomsV1(const uint8_t *base,
520 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000521 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
522 size_t atomsArraySize = chunk->elementCount * atomSize;
523 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
524 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000525 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000526 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000527 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000528 / chunk->elementCount;
529 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
530 return make_error_code(native_reader_error::file_malformed);
531 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000532 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000533 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
534 (base + chunk->fileOffset);
535 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000536 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000537 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
538 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
539 ++ivarData;
540 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000541 this->_absoluteAtoms._arrayStart = atomsStart;
542 this->_absoluteAtoms._arrayEnd = atomsEnd;
543 this->_absoluteAtoms._elementSize = atomSize;
544 this->_absoluteAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000545 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000546 << " chunk AbsoluteAtomsV1: "
547 << " count=" << chunk->elementCount
548 << " chunkSize=" << chunk->fileSize
549 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000550 return make_error_code(native_reader_error::success);
551 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000552
553
554
555
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000556 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000557 error_code processReferencesV1(const uint8_t *base,
558 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000559 if ( chunk->elementCount == 0 )
560 return make_error_code(native_reader_error::success);
561 const size_t refSize = sizeof(NativeReferenceV1);
562 size_t refsArraySize = chunk->elementCount * refSize;
563 uint8_t* refsStart = reinterpret_cast<uint8_t*>
564 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000565 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000566 return make_error_code(native_reader_error::memory_error);
567 const size_t ivarElementSize = chunk->fileSize
568 / chunk->elementCount;
569 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
570 return make_error_code(native_reader_error::file_malformed);
571 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000572 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000573 reinterpret_cast<const NativeReferenceIvarsV1*>
574 (base + chunk->fileOffset);
575 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000576 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000577 reinterpret_cast<NativeReferenceV1*>(s);
578 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
579 ++ivarData;
580 }
581 this->_references.arrayStart = refsStart;
582 this->_references.arrayEnd = refsEnd;
583 this->_references.elementSize = refSize;
584 this->_references.elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000585 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000586 << " chunk ReferencesV1: "
587 << " count=" << chunk->elementCount
588 << " chunkSize=" << chunk->fileSize
589 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000590 return make_error_code(native_reader_error::success);
591 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000592
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000593 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000594 error_code processTargetsTable(const uint8_t *base,
595 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000596 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
597 (base + chunk->fileOffset);
598 this->_targetsTableCount = chunk->elementCount;
599 this->_targetsTable = new const Atom*[chunk->elementCount];
600 for (uint32_t i=0; i < chunk->elementCount; ++i) {
601 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000602 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000603 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000604 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000605 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
606 continue;
607 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000608 const uint32_t undefIndex = index - _definedAtoms._elementCount;
609 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000610 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000611 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000612 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
613 continue;
614 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000615 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000616 - _undefinedAtoms._elementCount;
617 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000618 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000619 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000620 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
621 continue;
622 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000623 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000624 - _undefinedAtoms._elementCount
625 - _sharedLibraryAtoms._elementCount;
626 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000627 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000628 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000629 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
630 continue;
631 }
632 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000633 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000634 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000635 << " chunk Targets Table: "
636 << " count=" << chunk->elementCount
637 << " chunkSize=" << chunk->fileSize
638 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000639 return make_error_code(native_reader_error::success);
640 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000641
642
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000643 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000644 error_code processAddendsTable(const uint8_t *base,
645 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000646 this->_addends = reinterpret_cast<const Reference::Addend*>
647 (base + chunk->fileOffset);
648 this->_addendsMaxIndex = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000649 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000650 << " chunk Addends: "
651 << " count=" << chunk->elementCount
652 << " chunkSize=" << chunk->fileSize
653 << "\n");
Nick Kledzik23384e82012-02-07 02:59:54 +0000654 return make_error_code(native_reader_error::success);
655 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000656
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000657 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000658 error_code processStrings(const uint8_t *base,
659 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000660 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
661 this->_stringsMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000662 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000663 << " chunk Strings: "
664 << " chunkSize=" << chunk->fileSize
665 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000666 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000667 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000668
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000669 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000670 error_code processContent(const uint8_t *base,
671 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000672 this->_contentStart = base + chunk->fileOffset;
673 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000674 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000675 << " chunk content: "
676 << " chunkSize=" << chunk->fileSize
677 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000678 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000679 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000680
Michael J. Spencere6203a52012-04-03 18:39:40 +0000681 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000682 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000683 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000684 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000685
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000686 Reference::Addend addend(uint32_t index) const {
687 if ( index == 0 )
688 return 0; // addend index zero is used to mean "no addend"
689 assert(index <= _addendsMaxIndex);
690 return _addends[index-1]; // one-based indexing
691 }
692
693 const NativeAtomAttributesV1& attribute(uint32_t off) const {
694 assert(off < _attributesMaxOffset);
695 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000696 }
697
Sid Manning2a590242012-10-18 17:16:19 +0000698 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
699 assert(off < _absAbsoluteMaxOffset);
700 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
701 }
702
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000703 const uint8_t* content(uint32_t offset, uint32_t size) const {
704 const uint8_t* result = _contentStart + offset;
705 assert((result+size) <= _contentEnd);
706 return result;
707 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000708
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000709 const Reference* referenceByIndex(uintptr_t index) const {
710 assert(index < _references.elementCount);
711 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
712 return reinterpret_cast<const NativeReferenceV1*>(p);
713 }
714
Nick Kledzikb334be12012-04-07 01:31:00 +0000715 const Atom* target(uint16_t index) const {
716 if ( index == NativeReferenceIvarsV1::noTarget )
717 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000718 assert(index < _targetsTableCount);
719 return _targetsTable[index];
720 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000721
Nick Kledzikb334be12012-04-07 01:31:00 +0000722 void setTarget(uint16_t index, const Atom* newAtom) const {
723 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000724 assert(index > _targetsTableCount);
725 _targetsTable[index] = newAtom;
726 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000727
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000728 // private constructor, only called by make()
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000729 File(const TargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb,
730 StringRef path)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000731 : lld::File(path, kindObject),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000732 _buffer(std::move(mb)), // Reader now takes ownership of buffer
733 _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
734 _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
735 _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
736 _targetInfo(ti) {
737 _header =
738 reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000739 }
740
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000741 template <typename T>
742 class AtomArray : public File::atom_collection<T> {
743 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000744 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000745 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000746
747 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000748 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
749 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000750 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000751 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
752 }
753 virtual const T* deref(const void* it) const {
754 return reinterpret_cast<const T*>(it);
755 }
756 virtual void next(const void*& it) const {
757 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
758 p += _elementSize;
759 it = reinterpret_cast<const void*>(p);
760 }
761 const uint8_t* _arrayStart;
762 const uint8_t* _arrayEnd;
763 uint32_t _elementSize;
764 uint32_t _elementCount;
765 };
766
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000767 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000768 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000769 arrayStart(nullptr),
770 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000771 elementSize(0),
772 elementCount(0) { }
773
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000774 const uint8_t* arrayStart;
775 const uint8_t* arrayEnd;
776 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000777 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000778 };
779
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000780
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000781 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000782 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000783 AtomArray<DefinedAtom> _definedAtoms;
784 AtomArray<UndefinedAtom> _undefinedAtoms;
785 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
786 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000787 const uint8_t* _absAttributes;
788 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000789 const uint8_t* _attributes;
790 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000791 IvarArray _references;
792 const Atom** _targetsTable;
793 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000794 const char* _strings;
795 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000796 const Reference::Addend* _addends;
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000797 uint32_t _addendsMaxIndex;
798 const uint8_t *_contentStart;
799 const uint8_t *_contentEnd;
800 const TargetInfo &_targetInfo;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000801};
802
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000803inline const class lld::File &NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000804 return *_file;
805}
806
807inline uint64_t NativeDefinedAtomV1:: ordinal() const {
808 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000809 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000810}
811
Michael J. Spencere6203a52012-04-03 18:39:40 +0000812inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000813 return _file->string(_ivarData->nameOffset);
814}
815
816inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
817 return _file->attribute(_ivarData->attributesOffset);
818}
819
Michael J. Spencere6203a52012-04-03 18:39:40 +0000820inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Shankar Easwarandb74ffb2013-02-24 03:09:10 +0000821 if (( this->contentType() == DefinedAtom::typeZeroFill ) ||
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000822 ( this->contentType() == DefinedAtom::typeZeroFillFast))
Michael J. Spencere6203a52012-04-03 18:39:40 +0000823 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000824 const uint8_t* p = _file->content(_ivarData->contentOffset,
825 _ivarData->contentSize);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000826 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000827}
828
Michael J. Spencere6203a52012-04-03 18:39:40 +0000829inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000830 uint32_t offset = attributes().sectionNameOffset;
831 return _file->string(offset);
832}
833
Nick Kledzik062a98c2012-04-08 23:52:13 +0000834DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000835 uintptr_t index = _ivarData->referencesStartIndex;
836 const void* it = reinterpret_cast<const void*>(index);
837 return reference_iterator(*this, it);
838}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000839
Nick Kledzik062a98c2012-04-08 23:52:13 +0000840DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000841 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
842 const void* it = reinterpret_cast<const void*>(index);
843 return reference_iterator(*this, it);
844}
845
846const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
847 uintptr_t index = reinterpret_cast<uintptr_t>(it);
848 return _file->referenceByIndex(index);
849}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000850
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000851void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
852 uintptr_t index = reinterpret_cast<uintptr_t>(it);
853 ++index;
854 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000855}
Nick Kledzik23384e82012-02-07 02:59:54 +0000856
Nick Kledzikabb69812012-05-31 22:34:00 +0000857inline const class lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000858 return *_file;
859}
860
Michael J. Spencere6203a52012-04-03 18:39:40 +0000861inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000862 return _file->string(_ivarData->nameOffset);
863}
864
865
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000866
867
Nick Kledzikabb69812012-05-31 22:34:00 +0000868inline const class lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000869 return *_file;
870}
871
Michael J. Spencere6203a52012-04-03 18:39:40 +0000872inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000873 return _file->string(_ivarData->nameOffset);
874}
875
Michael J. Spencere6203a52012-04-03 18:39:40 +0000876inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000877 return _file->string(_ivarData->loadNameOffset);
878}
879
880
881
Nick Kledzikabb69812012-05-31 22:34:00 +0000882inline const class lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000883 return *_file;
884}
885
Michael J. Spencere6203a52012-04-03 18:39:40 +0000886inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000887 return _file->string(_ivarData->nameOffset);
888}
889
Sid Manning2a590242012-10-18 17:16:19 +0000890inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
891 return _file->absAttribute(_ivarData->attributesOffset);
892}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000893
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000894inline const Atom* NativeReferenceV1::target() const {
895 return _file->target(_ivarData->targetIndex);
896}
897
898inline Reference::Addend NativeReferenceV1::addend() const {
899 return _file->addend(_ivarData->addendIndex);
900}
901
902inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
903 return _file->setTarget(_ivarData->targetIndex, newAtom);
904}
Nick Kledzik23384e82012-02-07 02:59:54 +0000905
Nick Kledzikb334be12012-04-07 01:31:00 +0000906inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000907 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000908 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000909 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000910 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000911}
912
Nick Kledzikabb69812012-05-31 22:34:00 +0000913class Reader : public lld::Reader {
914public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000915 Reader(const TargetInfo &ti)
916 : lld::Reader(ti) {}
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000917
918 virtual error_code parseFile(
919 std::unique_ptr<MemoryBuffer> mb,
920 std::vector<std::unique_ptr<lld::File> > &result) {
921 return File::make(_targetInfo, mb, mb->getBufferIdentifier(), result);
Nick Kledzikabb69812012-05-31 22:34:00 +0000922 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000923};
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000924} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +0000925
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000926std::unique_ptr<Reader> createReaderNative(const TargetInfo &ti) {
927 return std::unique_ptr<Reader>(new lld::native::Reader(ti));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000928}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000929} // end namespace lld