blob: 814215fea5272e44ad3a6fab4e498c1f0cdd7d7a [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 }
88
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:
Nick Kledzikabb69812012-05-31 22:34:00 +0000206 NativeReferenceV1(const File& f,
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000207 const NativeReferenceIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000208 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000209
210 virtual uint64_t offsetInAtom() const {
211 return _ivarData->offsetInAtom;
212 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000213
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000214 virtual Kind kind() const {
215 return _ivarData->kind;
216 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000217
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000218 virtual void setKind(Kind);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000219 virtual const Atom* target() const;
220 virtual Addend addend() const;
221 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000222 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000223
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000224private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000225 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000226 // since ivar data is mapped read-only.
227 void cloneIvarData() {
228 // TODO: do nothing on second call
229 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000230 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000231 std::nothrow));
232 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
233 }
234
Nick Kledzikabb69812012-05-31 22:34:00 +0000235 const File *_file;
236 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000237};
238
239
240
241//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000242// lld::File object for native llvm object file
243//
Nick Kledzikabb69812012-05-31 22:34:00 +0000244class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000245public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000246
247 /// Instantiates a File object from a native object file. Ownership
248 /// of the MemoryBuffer is transfered to the resulting File object.
Nick Kledzikabb69812012-05-31 22:34:00 +0000249 static error_code make(std::unique_ptr<llvm::MemoryBuffer> &mb,
Michael J. Spencere6203a52012-04-03 18:39:40 +0000250 StringRef path,
Nick Kledzikabb69812012-05-31 22:34:00 +0000251 std::vector<std::unique_ptr<lld::File>> &result) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000252 const uint8_t* const base =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000253 reinterpret_cast<const uint8_t*>(mb->getBufferStart());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000254 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000255 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000256 const NativeChunk *const chunks =
257 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000258 // make sure magic matches
259 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000260 return make_error_code(native_reader_error::unknown_file_format);
261
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000262 // make sure mapped file contains all needed data
263 const size_t fileSize = mb->getBufferSize();
264 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000265 return make_error_code(native_reader_error::file_too_short);
266
Nick Kledzikabb69812012-05-31 22:34:00 +0000267 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
268 << " Native File Header:"
269 << " fileSize=" << header->fileSize
270 << " chunkCount=" << header->chunkCount
271 << "\n");
272
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000273 // instantiate NativeFile object and add values to it as found
Nick Kledzikabb69812012-05-31 22:34:00 +0000274 std::unique_ptr<File> file(new File(std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000275
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000276 // process each chunk
277 for(uint32_t i=0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000278 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000279 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000280 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000281 if ( chunk->fileOffset > fileSize )
282 return make_error_code(native_reader_error::file_malformed);
283 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
284 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000285 // process chunk, based on signature
286 switch ( chunk->signature ) {
287 case NCS_DefinedAtomsV1:
288 ec = file->processDefinedAtomsV1(base, chunk);
289 break;
290 case NCS_AttributesArrayV1:
291 ec = file->processAttributesV1(base, chunk);
292 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000293 case NCS_UndefinedAtomsV1:
294 ec = file->processUndefinedAtomsV1(base, chunk);
295 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000296 case NCS_SharedLibraryAtomsV1:
297 ec = file->processSharedLibraryAtomsV1(base, chunk);
298 break;
299 case NCS_AbsoluteAtomsV1:
300 ec = file->processAbsoluteAtomsV1(base, chunk);
301 break;
Sid Manning2a590242012-10-18 17:16:19 +0000302 case NCS_AbsoluteAttributesV1:
303 ec = file->processAbsoluteAttributesV1(base, chunk);
304 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000305 case NCS_ReferencesArrayV1:
306 ec = file->processReferencesV1(base, chunk);
307 break;
308 case NCS_TargetsTable:
309 ec = file->processTargetsTable(base, chunk);
310 break;
311 case NCS_AddendsTable:
312 ec = file->processAddendsTable(base, chunk);
313 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000314 case NCS_Content:
315 ec = file->processContent(base, chunk);
316 break;
317 case NCS_Strings:
318 ec = file->processStrings(base, chunk);
319 break;
320 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000321 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000322 }
323 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000324 return ec;
325 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000326 }
327 // TO DO: validate enough chunks were used
328
329 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
330 << " ReaderNative DefinedAtoms:\n");
331 for (const DefinedAtom *a : file->defined() ) {
332 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
333 << llvm::format(" 0x%09lX", a)
334 << ", name=" << a->name()
335 << ", size=" << a->size()
336 << "\n");
337 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000338 (void)r;
339 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000340 << " offset="
341 << llvm::format("0x%03X", r->offsetInAtom())
342 << ", kind=" << r->kind()
343 << ", target=" << r->target()
344 << "\n");
345 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000346 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000347
Nick Kledzikabb69812012-05-31 22:34:00 +0000348 result.push_back(std::move(file));
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000349 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000350 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000351
Nick Kledzikabb69812012-05-31 22:34:00 +0000352 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000353 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000354
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000355 // All other ivar pointers are pointers into the MemoryBuffer, except
356 // the _definedAtoms array which was allocated to contain an array
357 // of Atom objects. The atoms have empty destructors, so it is ok
358 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000359 delete _definedAtoms._arrayStart;
360 delete _undefinedAtoms._arrayStart;
361 delete _sharedLibraryAtoms._arrayStart;
362 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000363 delete _references.arrayStart;
364 delete _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000365 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000366
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000367 virtual const atom_collection<DefinedAtom>& defined() const {
368 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000369 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000370 virtual const atom_collection<UndefinedAtom>& undefined() const {
371 return _undefinedAtoms;
372 }
373 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
374 return _sharedLibraryAtoms;
375 }
376 virtual const atom_collection<AbsoluteAtom>& absolute() const {
377 return _absoluteAtoms;
378 }
379
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000380private:
381 friend class NativeDefinedAtomV1;
Nick Kledzik23384e82012-02-07 02:59:54 +0000382 friend class NativeUndefinedAtomV1;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000383 friend class NativeSharedLibraryAtomV1;
384 friend class NativeAbsoluteAtomV1;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000385 friend class NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000386
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000387 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000388 error_code processDefinedAtomsV1(const uint8_t *base,
389 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000390 const size_t atomSize = sizeof(NativeDefinedAtomV1);
391 size_t atomsArraySize = chunk->elementCount * atomSize;
392 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
393 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000394 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000395 return make_error_code(native_reader_error::memory_error);
396 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000397 / chunk->elementCount;
398 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000399 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000400 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000401 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000402 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
403 (base + chunk->fileOffset);
404 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000405 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000406 reinterpret_cast<NativeDefinedAtomV1*>(s);
407 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
408 ++ivarData;
409 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000410 this->_definedAtoms._arrayStart = atomsStart;
411 this->_definedAtoms._arrayEnd = atomsEnd;
412 this->_definedAtoms._elementSize = atomSize;
413 this->_definedAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000414 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
415 << " chunk DefinedAtomsV1: "
416 << " count=" << chunk->elementCount
417 << " chunkSize=" << chunk->fileSize
418 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000419 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000420 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000421
Nick Kledzikabb69812012-05-31 22:34:00 +0000422
423
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000424 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000425 error_code processAttributesV1(const uint8_t *base,
426 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000427 this->_attributes = base + chunk->fileOffset;
428 this->_attributesMaxOffset = chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000429 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
430 << " chunk AttributesV1: "
431 << " count=" << chunk->elementCount
432 << " chunkSize=" << chunk->fileSize
433 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000434 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000435 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000436
Sid Manning2a590242012-10-18 17:16:19 +0000437 // set up pointers to attributes array
438 error_code processAbsoluteAttributesV1(const uint8_t *base,
439 const NativeChunk *chunk) {
440 this->_absAttributes = base + chunk->fileOffset;
441 this->_absAbsoluteMaxOffset = chunk->fileSize;
442 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
443 << " chunk AbsoluteAttributesV1: "
444 << " count=" << chunk->elementCount
445 << " chunkSize=" << chunk->fileSize
446 << "\n");
447 return make_error_code(native_reader_error::success);
448 }
449
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000450 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000451 error_code processUndefinedAtomsV1(const uint8_t *base,
452 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000453 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
454 size_t atomsArraySize = chunk->elementCount * atomSize;
455 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
456 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000457 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000458 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000459 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000460 / chunk->elementCount;
461 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
462 return make_error_code(native_reader_error::file_malformed);
463 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000464 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000465 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
466 (base + chunk->fileOffset);
467 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000468 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000469 reinterpret_cast<NativeUndefinedAtomV1*>(s);
470 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
471 ++ivarData;
472 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000473 this->_undefinedAtoms._arrayStart = atomsStart;
474 this->_undefinedAtoms._arrayEnd = atomsEnd;
475 this->_undefinedAtoms._elementSize = atomSize;
476 this->_undefinedAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000477 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
478 << " chunk UndefinedAtomsV1:"
479 << " count=" << chunk->elementCount
480 << " chunkSize=" << chunk->fileSize
481 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000482 return make_error_code(native_reader_error::success);
483 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000484
485
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000486 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000487 error_code processSharedLibraryAtomsV1(const uint8_t *base,
488 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000489 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
490 size_t atomsArraySize = chunk->elementCount * atomSize;
491 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
492 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000493 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000494 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000495 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000496 / chunk->elementCount;
497 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
498 return make_error_code(native_reader_error::file_malformed);
499 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000500 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000501 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
502 (base + chunk->fileOffset);
503 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000504 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000505 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
506 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
507 ++ivarData;
508 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000509 this->_sharedLibraryAtoms._arrayStart = atomsStart;
510 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
511 this->_sharedLibraryAtoms._elementSize = atomSize;
512 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000513 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
514 << " chunk SharedLibraryAtomsV1:"
515 << " count=" << chunk->elementCount
516 << " chunkSize=" << chunk->fileSize
517 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000518 return make_error_code(native_reader_error::success);
519 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000520
521
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000522 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000523 error_code processAbsoluteAtomsV1(const uint8_t *base,
524 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000525 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
526 size_t atomsArraySize = chunk->elementCount * atomSize;
527 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
528 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000529 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000530 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000531 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000532 / chunk->elementCount;
533 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
534 return make_error_code(native_reader_error::file_malformed);
535 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000536 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000537 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
538 (base + chunk->fileOffset);
539 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000540 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000541 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
542 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
543 ++ivarData;
544 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000545 this->_absoluteAtoms._arrayStart = atomsStart;
546 this->_absoluteAtoms._arrayEnd = atomsEnd;
547 this->_absoluteAtoms._elementSize = atomSize;
548 this->_absoluteAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000549 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
550 << " chunk AbsoluteAtomsV1: "
551 << " count=" << chunk->elementCount
552 << " chunkSize=" << chunk->fileSize
553 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000554 return make_error_code(native_reader_error::success);
555 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000556
557
558
559
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000560 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000561 error_code processReferencesV1(const uint8_t *base,
562 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000563 if ( chunk->elementCount == 0 )
564 return make_error_code(native_reader_error::success);
565 const size_t refSize = sizeof(NativeReferenceV1);
566 size_t refsArraySize = chunk->elementCount * refSize;
567 uint8_t* refsStart = reinterpret_cast<uint8_t*>
568 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000569 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000570 return make_error_code(native_reader_error::memory_error);
571 const size_t ivarElementSize = chunk->fileSize
572 / chunk->elementCount;
573 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
574 return make_error_code(native_reader_error::file_malformed);
575 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000576 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000577 reinterpret_cast<const NativeReferenceIvarsV1*>
578 (base + chunk->fileOffset);
579 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000580 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000581 reinterpret_cast<NativeReferenceV1*>(s);
582 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
583 ++ivarData;
584 }
585 this->_references.arrayStart = refsStart;
586 this->_references.arrayEnd = refsEnd;
587 this->_references.elementSize = refSize;
588 this->_references.elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000589 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
590 << " chunk ReferencesV1: "
591 << " count=" << chunk->elementCount
592 << " chunkSize=" << chunk->fileSize
593 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000594 return make_error_code(native_reader_error::success);
595 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000596
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000597 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000598 error_code processTargetsTable(const uint8_t *base,
599 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000600 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
601 (base + chunk->fileOffset);
602 this->_targetsTableCount = chunk->elementCount;
603 this->_targetsTable = new const Atom*[chunk->elementCount];
604 for (uint32_t i=0; i < chunk->elementCount; ++i) {
605 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000606 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000607 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000608 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000609 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
610 continue;
611 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000612 const uint32_t undefIndex = index - _definedAtoms._elementCount;
613 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000614 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000615 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000616 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
617 continue;
618 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000619 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000620 - _undefinedAtoms._elementCount;
621 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000622 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000623 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000624 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
625 continue;
626 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000627 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000628 - _undefinedAtoms._elementCount
629 - _sharedLibraryAtoms._elementCount;
630 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000631 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000632 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000633 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
634 continue;
635 }
636 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000637 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000638 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
639 << " chunk Targets Table: "
640 << " count=" << chunk->elementCount
641 << " chunkSize=" << chunk->fileSize
642 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000643 return make_error_code(native_reader_error::success);
644 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000645
646
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000647 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000648 error_code processAddendsTable(const uint8_t *base,
649 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000650 this->_addends = reinterpret_cast<const Reference::Addend*>
651 (base + chunk->fileOffset);
652 this->_addendsMaxIndex = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000653 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
654 << " chunk Addends: "
655 << " count=" << chunk->elementCount
656 << " chunkSize=" << chunk->fileSize
657 << "\n");
Nick Kledzik23384e82012-02-07 02:59:54 +0000658 return make_error_code(native_reader_error::success);
659 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000660
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000661 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000662 error_code processStrings(const uint8_t *base,
663 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000664 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
665 this->_stringsMaxOffset = chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000666 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
667 << " chunk Strings: "
668 << " chunkSize=" << chunk->fileSize
669 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000670 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000671 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000672
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000673 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000674 error_code processContent(const uint8_t *base,
675 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000676 this->_contentStart = base + chunk->fileOffset;
677 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000678 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
679 << " chunk content: "
680 << " chunkSize=" << chunk->fileSize
681 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000682 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000683 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000684
Michael J. Spencere6203a52012-04-03 18:39:40 +0000685 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000686 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000687 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000688 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000689
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000690 Reference::Addend addend(uint32_t index) const {
691 if ( index == 0 )
692 return 0; // addend index zero is used to mean "no addend"
693 assert(index <= _addendsMaxIndex);
694 return _addends[index-1]; // one-based indexing
695 }
696
697 const NativeAtomAttributesV1& attribute(uint32_t off) const {
698 assert(off < _attributesMaxOffset);
699 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000700 }
701
Sid Manning2a590242012-10-18 17:16:19 +0000702 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
703 assert(off < _absAbsoluteMaxOffset);
704 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
705 }
706
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000707 const uint8_t* content(uint32_t offset, uint32_t size) const {
708 const uint8_t* result = _contentStart + offset;
709 assert((result+size) <= _contentEnd);
710 return result;
711 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000712
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000713 const Reference* referenceByIndex(uintptr_t index) const {
714 assert(index < _references.elementCount);
715 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
716 return reinterpret_cast<const NativeReferenceV1*>(p);
717 }
718
Nick Kledzikb334be12012-04-07 01:31:00 +0000719 const Atom* target(uint16_t index) const {
720 if ( index == NativeReferenceIvarsV1::noTarget )
721 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000722 assert(index < _targetsTableCount);
723 return _targetsTable[index];
724 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000725
Nick Kledzikb334be12012-04-07 01:31:00 +0000726 void setTarget(uint16_t index, const Atom* newAtom) const {
727 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000728 assert(index > _targetsTableCount);
729 _targetsTable[index] = newAtom;
730 }
Nick Kledzikb334be12012-04-07 01:31:00 +0000731
Michael J. Spencer765792d2012-04-03 18:40:27 +0000732
733
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000734 // private constructor, only called by make()
Nick Kledzikabb69812012-05-31 22:34:00 +0000735 File(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
736 lld::File(path),
737 _buffer(std::move(mb)), // Reader now takes ownership of buffer
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000738 _header(nullptr),
739 _targetsTable(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000740 _targetsTableCount(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000741 _strings(nullptr),
Nick Kledzik23384e82012-02-07 02:59:54 +0000742 _stringsMaxOffset(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000743 _addends(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000744 _addendsMaxIndex(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000745 _contentStart(nullptr),
746 _contentEnd(nullptr)
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000747 {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000748 _header = reinterpret_cast<const NativeFileHeader*>
749 (_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000750 }
751
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000752 template <typename T>
753 class AtomArray : public File::atom_collection<T> {
754 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000755 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000756 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000757
758 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000759 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
760 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000761 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000762 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
763 }
764 virtual const T* deref(const void* it) const {
765 return reinterpret_cast<const T*>(it);
766 }
767 virtual void next(const void*& it) const {
768 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
769 p += _elementSize;
770 it = reinterpret_cast<const void*>(p);
771 }
772 const uint8_t* _arrayStart;
773 const uint8_t* _arrayEnd;
774 uint32_t _elementSize;
775 uint32_t _elementCount;
776 };
777
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000778 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000779 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000780 arrayStart(nullptr),
781 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000782 elementSize(0),
783 elementCount(0) { }
784
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000785 const uint8_t* arrayStart;
786 const uint8_t* arrayEnd;
787 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000788 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000789 };
790
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000791
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000792 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000793 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000794 AtomArray<DefinedAtom> _definedAtoms;
795 AtomArray<UndefinedAtom> _undefinedAtoms;
796 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
797 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000798 const uint8_t* _absAttributes;
799 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000800 const uint8_t* _attributes;
801 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000802 IvarArray _references;
803 const Atom** _targetsTable;
804 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000805 const char* _strings;
806 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000807 const Reference::Addend* _addends;
808 uint32_t _addendsMaxIndex;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000809 const uint8_t* _contentStart;
810 const uint8_t* _contentEnd;
811};
812
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000813
Nick Kledzikabb69812012-05-31 22:34:00 +0000814inline const class lld::File& NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000815 return *_file;
816}
817
818inline uint64_t NativeDefinedAtomV1:: ordinal() const {
819 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000820 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000821}
822
Michael J. Spencere6203a52012-04-03 18:39:40 +0000823inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000824 return _file->string(_ivarData->nameOffset);
825}
826
827inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
828 return _file->attribute(_ivarData->attributesOffset);
829}
830
Michael J. Spencere6203a52012-04-03 18:39:40 +0000831inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000832 if ( this->contentType() == DefinedAtom::typeZeroFill )
Michael J. Spencere6203a52012-04-03 18:39:40 +0000833 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000834 const uint8_t* p = _file->content(_ivarData->contentOffset,
835 _ivarData->contentSize);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000836 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000837}
838
Michael J. Spencere6203a52012-04-03 18:39:40 +0000839inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000840 uint32_t offset = attributes().sectionNameOffset;
841 return _file->string(offset);
842}
843
Nick Kledzik062a98c2012-04-08 23:52:13 +0000844DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000845 uintptr_t index = _ivarData->referencesStartIndex;
846 const void* it = reinterpret_cast<const void*>(index);
847 return reference_iterator(*this, it);
848}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000849
Nick Kledzik062a98c2012-04-08 23:52:13 +0000850DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000851 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
852 const void* it = reinterpret_cast<const void*>(index);
853 return reference_iterator(*this, it);
854}
855
856const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
857 uintptr_t index = reinterpret_cast<uintptr_t>(it);
858 return _file->referenceByIndex(index);
859}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000860
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000861void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
862 uintptr_t index = reinterpret_cast<uintptr_t>(it);
863 ++index;
864 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000865}
Nick Kledzik23384e82012-02-07 02:59:54 +0000866
Nick Kledzikabb69812012-05-31 22:34:00 +0000867inline const class lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000868 return *_file;
869}
870
Michael J. Spencere6203a52012-04-03 18:39:40 +0000871inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000872 return _file->string(_ivarData->nameOffset);
873}
874
875
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000876
877
Nick Kledzikabb69812012-05-31 22:34:00 +0000878inline const class lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000879 return *_file;
880}
881
Michael J. Spencere6203a52012-04-03 18:39:40 +0000882inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000883 return _file->string(_ivarData->nameOffset);
884}
885
Michael J. Spencere6203a52012-04-03 18:39:40 +0000886inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000887 return _file->string(_ivarData->loadNameOffset);
888}
889
890
891
Nick Kledzikabb69812012-05-31 22:34:00 +0000892inline const class lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000893 return *_file;
894}
895
Michael J. Spencere6203a52012-04-03 18:39:40 +0000896inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000897 return _file->string(_ivarData->nameOffset);
898}
899
Sid Manning2a590242012-10-18 17:16:19 +0000900inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
901 return _file->absAttribute(_ivarData->attributesOffset);
902}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000903
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000904inline const Atom* NativeReferenceV1::target() const {
905 return _file->target(_ivarData->targetIndex);
906}
907
908inline Reference::Addend NativeReferenceV1::addend() const {
909 return _file->addend(_ivarData->addendIndex);
910}
911
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000912inline void NativeReferenceV1::setKind(Kind k) {
913 this->cloneIvarData();
914 const_cast<NativeReferenceIvarsV1*>(_ivarData)->kind = k;
915}
916
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000917inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
918 return _file->setTarget(_ivarData->targetIndex, newAtom);
919}
Nick Kledzik23384e82012-02-07 02:59:54 +0000920
Nick Kledzikb334be12012-04-07 01:31:00 +0000921inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000922 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000923 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000924 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000925 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000926}
927
Nick Kledzikabb69812012-05-31 22:34:00 +0000928class Reader : public lld::Reader {
929public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000930 Reader(const TargetInfo &ti)
931 : lld::Reader(ti) {}
Nick Kledzikabb69812012-05-31 22:34:00 +0000932
933 virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
934 std::vector<std::unique_ptr<lld::File>> &result) {
935 return File::make(mb, mb->getBufferIdentifier(), result);
936 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000937};
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000938} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +0000939
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000940std::unique_ptr<Reader> createReaderNative(const TargetInfo &ti) {
941 return std::unique_ptr<Reader>(new lld::native::Reader(ti));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000942}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000943} // end namespace lld