blob: dd00514ebabe75e2ade7297914f18029be5ae737 [file] [log] [blame]
Nick Kledzikabb69812012-05-31 22:34:00 +00001//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
Nick Kledzik55fd6be2012-01-16 22:03:44 +00002//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Michael J. Spencer64afcb42013-01-23 01:18:43 +000010#include "lld/ReaderWriter/Reader.h"
Rui Ueyamae5416ec2013-09-12 19:14:05 +000011#include "lld/ReaderWriter/Simple.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000012
Michael J. Spencercfd029f2012-03-28 19:04:02 +000013#include "lld/Core/Atom.h"
14#include "lld/Core/Error.h"
15#include "lld/Core/File.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000016
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/OwningPtr.h"
19#include "llvm/ADT/StringRef.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000020#include "llvm/Support/Debug.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000021#include "llvm/Support/ErrorHandling.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000022#include "llvm/Support/Format.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000023#include "llvm/Support/MemoryBuffer.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000024#include "llvm/Support/raw_ostream.h"
25
26#include "NativeFileFormat.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000027
Michael J. Spencercfd029f2012-03-28 19:04:02 +000028#include <vector>
Nick Kledzikb334be12012-04-07 01:31:00 +000029#include <memory>
Nick Kledzik55fd6be2012-01-16 22:03:44 +000030
31namespace lld {
Nick Kledzikabb69812012-05-31 22:34:00 +000032namespace native {
Nick Kledzik55fd6be2012-01-16 22:03:44 +000033
34// forward reference
Nick Kledzikabb69812012-05-31 22:34:00 +000035class File;
Nick Kledzik55fd6be2012-01-16 22:03:44 +000036
Nick Kledzik55fd6be2012-01-16 22:03:44 +000037//
38// An object of this class is instantied for each NativeDefinedAtomIvarsV1
39// struct in the NCS_DefinedAtomsV1 chunk.
40//
41class NativeDefinedAtomV1 : public DefinedAtom {
42public:
Nick Kledzikabb69812012-05-31 22:34:00 +000043 NativeDefinedAtomV1(const File& f,
Nick Kledzik55fd6be2012-01-16 22:03:44 +000044 const NativeDefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +000045 : _file(&f), _ivarData(ivarData) { }
46
Rui Ueyama7b7b0b92013-06-21 19:59:15 +000047 virtual const lld::File& file() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000048
49 virtual uint64_t ordinal() const;
50
Michael J. Spencere6203a52012-04-03 18:39:40 +000051 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000052
Nick Kledzik55fd6be2012-01-16 22:03:44 +000053 virtual uint64_t size() const {
54 return _ivarData->contentSize;
55 }
56
57 virtual DefinedAtom::Scope scope() const {
58 return (DefinedAtom::Scope)(attributes().scope);
59 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000060
Nick Kledzik55fd6be2012-01-16 22:03:44 +000061 virtual DefinedAtom::Interposable interposable() const {
62 return (DefinedAtom::Interposable)(attributes().interposable);
63 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000064
Nick Kledzik55fd6be2012-01-16 22:03:44 +000065 virtual DefinedAtom::Merge merge() const {
66 return (DefinedAtom::Merge)(attributes().merge);
67 }
68
69 virtual DefinedAtom::ContentType contentType() const {
Nick Kledzik23384e82012-02-07 02:59:54 +000070 const NativeAtomAttributesV1& attr = attributes();
71 return (DefinedAtom::ContentType)(attr.contentType);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000072 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000073
Nick Kledzik55fd6be2012-01-16 22:03:44 +000074 virtual DefinedAtom::Alignment alignment() const {
75 return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
76 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000077
Nick Kledzik55fd6be2012-01-16 22:03:44 +000078 virtual DefinedAtom::SectionChoice sectionChoice() const {
Nick Kledzik36293f62013-01-23 22:32:56 +000079 return (DefinedAtom::SectionChoice)(
80 attributes().sectionChoiceAndPosition >> 4);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000081 }
82
Michael J. Spencere6203a52012-04-03 18:39:40 +000083 virtual StringRef customSectionName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000084
Nick Kledzik36293f62013-01-23 22:32:56 +000085 virtual SectionPosition sectionPosition() const {
86 return (DefinedAtom::SectionPosition)(
87 attributes().sectionChoiceAndPosition & 0xF);
88 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +000089
Nick Kledzik55fd6be2012-01-16 22:03:44 +000090 virtual DefinedAtom::DeadStripKind deadStrip() const {
91 return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
Nick Kledzik6bc04c62012-02-22 21:56:59 +000092 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000093
Michael J. Spencerb8ab9f52013-11-08 21:04:20 +000094 virtual DynamicExport dynamicExport() const {
95 return (DynamicExport)attributes().dynamicExport;
96 }
97
Nick Kledzik55fd6be2012-01-16 22:03:44 +000098 virtual DefinedAtom::ContentPermissions permissions() const {
99 return (DefinedAtom::ContentPermissions)(attributes().permissions);
100 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000101
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000102 virtual bool isAlias() const {
103 return (attributes().alias != 0);
104 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000105
Michael J. Spencere6203a52012-04-03 18:39:40 +0000106 virtual ArrayRef<uint8_t> rawContent() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000107
Nick Kledzik062a98c2012-04-08 23:52:13 +0000108 virtual reference_iterator begin() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000109
Nick Kledzik062a98c2012-04-08 23:52:13 +0000110 virtual reference_iterator end() const;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000111
112 virtual const Reference* derefIterator(const void*) const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000113
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000114 virtual void incrementIterator(const void*& it) const;
115
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000116private:
117 const NativeAtomAttributesV1& attributes() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000118
Nick Kledzikabb69812012-05-31 22:34:00 +0000119 const File *_file;
120 const NativeDefinedAtomIvarsV1 *_ivarData;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000121};
122
123
124
Nick Kledzik23384e82012-02-07 02:59:54 +0000125//
126// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
127// struct in the NCS_UndefinedAtomsV1 chunk.
128//
129class NativeUndefinedAtomV1 : public UndefinedAtom {
130public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000131 NativeUndefinedAtomV1(const File& f,
Nick Kledzik23384e82012-02-07 02:59:54 +0000132 const NativeUndefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000133 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik23384e82012-02-07 02:59:54 +0000134
Nick Kledzikabb69812012-05-31 22:34:00 +0000135 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000136 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000137
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000138 virtual CanBeNull canBeNull() const {
139 return (CanBeNull)(_ivarData->flags & 0x3);
Nick Kledzik23384e82012-02-07 02:59:54 +0000140 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000141
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000142 virtual const UndefinedAtom *fallback() const;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000143
Nick Kledzik23384e82012-02-07 02:59:54 +0000144private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000145 const File *_file;
146 const NativeUndefinedAtomIvarsV1 *_ivarData;
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000147 mutable std::unique_ptr<const SimpleUndefinedAtom> _fallback;
Nick Kledzik23384e82012-02-07 02:59:54 +0000148};
149
150
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000151//
152// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
153// struct in the NCS_SharedLibraryAtomsV1 chunk.
154//
155class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
156public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000157 NativeSharedLibraryAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000158 const NativeSharedLibraryAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000159 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000160
Nick Kledzikabb69812012-05-31 22:34:00 +0000161 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000162 virtual StringRef name() const;
163 virtual StringRef loadName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000164
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000165 virtual bool canBeNullAtRuntime() const {
166 return (_ivarData->flags & 0x1);
167 }
168
Michael J. Spencer4355bb92013-09-26 22:08:43 +0000169 virtual Type type() const {
170 return (Type)_ivarData->type;
171 }
172
173 virtual uint64_t size() const {
174 return _ivarData->size;
175 }
176
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000177private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000178 const File *_file;
179 const NativeSharedLibraryAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000180};
181
182
183//
184// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
185// struct in the NCS_AbsoluteAtomsV1 chunk.
186//
187class NativeAbsoluteAtomV1 : public AbsoluteAtom {
188public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000189 NativeAbsoluteAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000190 const NativeAbsoluteAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000191 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000192
Nick Kledzikabb69812012-05-31 22:34:00 +0000193 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000194 virtual StringRef name() const;
Sid Manning2a590242012-10-18 17:16:19 +0000195 virtual Scope scope() const {
196 const NativeAtomAttributesV1& attr = absAttributes();
197 return (Scope)(attr.scope);
198 }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000199 virtual uint64_t value() const {
200 return _ivarData->value;
201 }
202
203private:
Sid Manning2a590242012-10-18 17:16:19 +0000204 const NativeAtomAttributesV1& absAttributes() const;
Nick Kledzikabb69812012-05-31 22:34:00 +0000205 const File *_file;
206 const NativeAbsoluteAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000207};
208
209
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000210//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000211// An object of this class is instantied for each NativeReferenceIvarsV1
212// struct in the NCS_ReferencesArrayV1 chunk.
213//
214class NativeReferenceV1 : public Reference {
215public:
Rui Ueyama170a1a82013-12-20 07:48:29 +0000216 NativeReferenceV1(const File &f, const NativeReferenceIvarsV1 *ivarData)
217 : Reference((KindNamespace)ivarData->kindNamespace,
218 (KindArch)ivarData->kindArch, ivarData->kindValue),
219 _file(&f), _ivarData(ivarData) {}
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000220
221 virtual uint64_t offsetInAtom() const {
222 return _ivarData->offsetInAtom;
223 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000224
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000225 virtual const Atom* target() const;
226 virtual Addend addend() const;
227 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000228 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000229
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000230private:
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
Rui Ueyamae05b6292013-11-20 20:54:18 +0000236//
237// An object of this class is instantied for each NativeReferenceIvarsV1
238// struct in the NCS_ReferencesArrayV1 chunk.
239//
240class NativeReferenceV2 : public Reference {
241public:
Rui Ueyama170a1a82013-12-20 07:48:29 +0000242 NativeReferenceV2(const File &f, const NativeReferenceIvarsV2 *ivarData)
243 : Reference((KindNamespace)ivarData->kindNamespace,
244 (KindArch)ivarData->kindArch, ivarData->kindValue),
245 _file(&f), _ivarData(ivarData) {}
Rui Ueyamae05b6292013-11-20 20:54:18 +0000246
247 virtual uint64_t offsetInAtom() const {
248 return _ivarData->offsetInAtom;
249 }
250
251 virtual const Atom* target() const;
252 virtual Addend addend() const;
253 virtual void setTarget(const Atom* newAtom);
254 virtual void setAddend(Addend a);
255
256private:
257 const File *_file;
258 const NativeReferenceIvarsV2 *_ivarData;
259};
260
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000261
262//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000263// lld::File object for native llvm object file
264//
Nick Kledzikabb69812012-05-31 22:34:00 +0000265class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000266public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000267
268 /// Instantiates a File object from a native object file. Ownership
Alp Toker32e8bef2013-12-01 23:51:36 +0000269 /// of the MemoryBuffer is transferred to the resulting File object.
Nick Kledzike5552772013-12-19 21:58:00 +0000270 static error_code make(std::unique_ptr<MemoryBuffer> mb,
Rui Ueyama170a1a82013-12-20 07:48:29 +0000271 std::vector<std::unique_ptr<lld::File>> &result) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000272 const uint8_t *const base =
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000273 reinterpret_cast<const uint8_t *>(mb->getBufferStart());
274 StringRef path(mb->getBufferIdentifier());
275 const NativeFileHeader *const header =
276 reinterpret_cast<const NativeFileHeader *>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000277 const NativeChunk *const chunks =
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000278 reinterpret_cast<const NativeChunk *>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000279 // make sure magic matches
Rui Ueyamaa3ada6b2013-11-16 01:31:24 +0000280 if (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC,
281 sizeof(header->magic)) != 0)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000282 return make_error_code(NativeReaderError::unknown_file_format);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000283
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000284 // make sure mapped file contains all needed data
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000285 const size_t fileSize = mb->getBufferSize();
286 if (header->fileSize > fileSize)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000287 return make_error_code(NativeReaderError::file_too_short);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000288
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000289 DEBUG_WITH_TYPE("ReaderNative",
290 llvm::dbgs() << " Native File Header:" << " fileSize="
291 << header->fileSize << " chunkCount="
292 << header->chunkCount << "\n");
Nick Kledzikabb69812012-05-31 22:34:00 +0000293
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000294 // instantiate NativeFile object and add values to it as found
Nick Kledzike5552772013-12-19 21:58:00 +0000295 std::unique_ptr<File> file(new File(std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000296
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000297 // process each chunk
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000298 for (uint32_t i = 0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000299 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000300 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000301 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000302 if ( chunk->fileOffset > fileSize )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000303 return make_error_code(NativeReaderError::file_malformed);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000304 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000305 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000306 // process chunk, based on signature
307 switch ( chunk->signature ) {
308 case NCS_DefinedAtomsV1:
309 ec = file->processDefinedAtomsV1(base, chunk);
310 break;
311 case NCS_AttributesArrayV1:
312 ec = file->processAttributesV1(base, chunk);
313 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000314 case NCS_UndefinedAtomsV1:
315 ec = file->processUndefinedAtomsV1(base, chunk);
316 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000317 case NCS_SharedLibraryAtomsV1:
318 ec = file->processSharedLibraryAtomsV1(base, chunk);
319 break;
320 case NCS_AbsoluteAtomsV1:
321 ec = file->processAbsoluteAtomsV1(base, chunk);
322 break;
Sid Manning2a590242012-10-18 17:16:19 +0000323 case NCS_AbsoluteAttributesV1:
324 ec = file->processAbsoluteAttributesV1(base, chunk);
325 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000326 case NCS_ReferencesArrayV1:
327 ec = file->processReferencesV1(base, chunk);
328 break;
Rui Ueyamae05b6292013-11-20 20:54:18 +0000329 case NCS_ReferencesArrayV2:
330 ec = file->processReferencesV2(base, chunk);
331 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000332 case NCS_TargetsTable:
333 ec = file->processTargetsTable(base, chunk);
334 break;
335 case NCS_AddendsTable:
336 ec = file->processAddendsTable(base, chunk);
337 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000338 case NCS_Content:
339 ec = file->processContent(base, chunk);
340 break;
341 case NCS_Strings:
342 ec = file->processStrings(base, chunk);
343 break;
344 default:
Rui Ueyamac6015f62013-10-09 00:57:22 +0000345 return make_error_code(NativeReaderError::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000346 }
347 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000348 return ec;
349 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000350 }
351 // TO DO: validate enough chunks were used
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000352
Rui Ueyamab37c4312013-11-16 01:41:47 +0000353 DEBUG_WITH_TYPE("ReaderNative", {
354 llvm::dbgs() << " ReaderNative DefinedAtoms:\n";
355 for (const DefinedAtom *a : file->defined()) {
356 llvm::dbgs() << llvm::format(" 0x%09lX", a)
357 << ", name=" << a->name()
358 << ", size=" << a->size() << "\n";
359 for (const Reference *r : *a) {
360 llvm::dbgs() << " offset="
361 << llvm::format("0x%03X", r->offsetInAtom())
Nick Kledzike5552772013-12-19 21:58:00 +0000362 << ", kind=" << r->kindValue()
Rui Ueyamab37c4312013-11-16 01:41:47 +0000363 << ", target=" << r->target() << "\n";
364 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000365 }
Rui Ueyamab37c4312013-11-16 01:41:47 +0000366 });
Nick Kledzikabb69812012-05-31 22:34:00 +0000367 result.push_back(std::move(file));
Rui Ueyamac6015f62013-10-09 00:57:22 +0000368 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000369 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000370
Nick Kledzikabb69812012-05-31 22:34:00 +0000371 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000372 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000373
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000374 // All other ivar pointers are pointers into the MemoryBuffer, except
375 // the _definedAtoms array which was allocated to contain an array
376 // of Atom objects. The atoms have empty destructors, so it is ok
377 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000378 delete _definedAtoms._arrayStart;
379 delete _undefinedAtoms._arrayStart;
380 delete _sharedLibraryAtoms._arrayStart;
381 delete _absoluteAtoms._arrayStart;
Rui Ueyamae05b6292013-11-20 20:54:18 +0000382 delete _referencesV1.arrayStart;
383 delete _referencesV2.arrayStart;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000384 delete [] _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000385 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000386
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000387 virtual const atom_collection<DefinedAtom>& defined() const {
388 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000389 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000390 virtual const atom_collection<UndefinedAtom>& undefined() const {
391 return _undefinedAtoms;
392 }
393 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
394 return _sharedLibraryAtoms;
395 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000396 virtual const atom_collection<AbsoluteAtom> &absolute() const {
397 return _absoluteAtoms;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000398 }
399
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000400private:
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000401 friend NativeDefinedAtomV1;
402 friend NativeUndefinedAtomV1;
403 friend NativeSharedLibraryAtomV1;
404 friend NativeAbsoluteAtomV1;
405 friend NativeReferenceV1;
Rui Ueyamae05b6292013-11-20 20:54:18 +0000406 friend NativeReferenceV2;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000407
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000408 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000409 error_code processDefinedAtomsV1(const uint8_t *base,
410 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000411 const size_t atomSize = sizeof(NativeDefinedAtomV1);
412 size_t atomsArraySize = chunk->elementCount * atomSize;
413 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
414 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000415 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000416 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000417 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000418 / chunk->elementCount;
419 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000420 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000421 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000422 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000423 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
424 (base + chunk->fileOffset);
425 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000426 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000427 reinterpret_cast<NativeDefinedAtomV1*>(s);
428 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
429 ++ivarData;
430 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000431 this->_definedAtoms._arrayStart = atomsStart;
432 this->_definedAtoms._arrayEnd = atomsEnd;
433 this->_definedAtoms._elementSize = atomSize;
434 this->_definedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000435 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000436 << " chunk DefinedAtomsV1: "
437 << " count=" << chunk->elementCount
438 << " chunkSize=" << chunk->fileSize
439 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000440 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000441 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000442
Nick Kledzikabb69812012-05-31 22:34:00 +0000443
444
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000445 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000446 error_code processAttributesV1(const uint8_t *base,
447 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000448 this->_attributes = base + chunk->fileOffset;
449 this->_attributesMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000450 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000451 << " chunk AttributesV1: "
452 << " count=" << chunk->elementCount
453 << " chunkSize=" << chunk->fileSize
454 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000455 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000456 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000457
Sid Manning2a590242012-10-18 17:16:19 +0000458 // set up pointers to attributes array
459 error_code processAbsoluteAttributesV1(const uint8_t *base,
460 const NativeChunk *chunk) {
461 this->_absAttributes = base + chunk->fileOffset;
462 this->_absAbsoluteMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000463 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Sid Manning2a590242012-10-18 17:16:19 +0000464 << " chunk AbsoluteAttributesV1: "
465 << " count=" << chunk->elementCount
466 << " chunkSize=" << chunk->fileSize
467 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000468 return make_error_code(NativeReaderError::success);
Sid Manning2a590242012-10-18 17:16:19 +0000469 }
470
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000471 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000472 error_code processUndefinedAtomsV1(const uint8_t *base,
473 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000474 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
475 size_t atomsArraySize = chunk->elementCount * atomSize;
476 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
477 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000478 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000479 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000480 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000481 / chunk->elementCount;
482 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000483 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik23384e82012-02-07 02:59:54 +0000484 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000485 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000486 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
487 (base + chunk->fileOffset);
488 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000489 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000490 reinterpret_cast<NativeUndefinedAtomV1*>(s);
491 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
492 ++ivarData;
493 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000494 this->_undefinedAtoms._arrayStart = atomsStart;
495 this->_undefinedAtoms._arrayEnd = atomsEnd;
496 this->_undefinedAtoms._elementSize = atomSize;
497 this->_undefinedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000498 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000499 << " chunk UndefinedAtomsV1:"
500 << " count=" << chunk->elementCount
501 << " chunkSize=" << chunk->fileSize
502 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000503 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000504 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000505
506
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000507 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000508 error_code processSharedLibraryAtomsV1(const uint8_t *base,
509 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000510 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
511 size_t atomsArraySize = chunk->elementCount * atomSize;
512 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
513 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000514 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000515 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000516 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000517 / chunk->elementCount;
518 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000519 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000520 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000521 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000522 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
523 (base + chunk->fileOffset);
524 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000525 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000526 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
527 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
528 ++ivarData;
529 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000530 this->_sharedLibraryAtoms._arrayStart = atomsStart;
531 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
532 this->_sharedLibraryAtoms._elementSize = atomSize;
533 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000534 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000535 << " chunk SharedLibraryAtomsV1:"
536 << " count=" << chunk->elementCount
537 << " chunkSize=" << chunk->fileSize
538 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000539 return make_error_code(NativeReaderError::success);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000540 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000541
542
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000543 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000544 error_code processAbsoluteAtomsV1(const uint8_t *base,
545 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000546 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
547 size_t atomsArraySize = chunk->elementCount * atomSize;
548 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
549 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000550 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000551 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000552 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000553 / chunk->elementCount;
554 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000555 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000556 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000557 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000558 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
559 (base + chunk->fileOffset);
560 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000561 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000562 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
563 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
564 ++ivarData;
565 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000566 this->_absoluteAtoms._arrayStart = atomsStart;
567 this->_absoluteAtoms._arrayEnd = atomsEnd;
568 this->_absoluteAtoms._elementSize = atomSize;
569 this->_absoluteAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000570 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000571 << " chunk AbsoluteAtomsV1: "
572 << " count=" << chunk->elementCount
573 << " chunkSize=" << chunk->fileSize
574 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000575 return make_error_code(NativeReaderError::success);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000576 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000577
Rui Ueyamae05b6292013-11-20 20:54:18 +0000578 template<class T, class U>
579 error_code processReferences(const uint8_t *base, const NativeChunk *chunk,
580 uint8_t *&refsStart, uint8_t *&refsEnd) const {
581 if (chunk->elementCount == 0)
582 return make_error_code(NativeReaderError::success);
583 size_t refsArraySize = chunk->elementCount * sizeof(T);
584 refsStart = reinterpret_cast<uint8_t *>(
585 operator new(refsArraySize, std::nothrow));
586 if (refsStart == nullptr)
587 return make_error_code(NativeReaderError::memory_error);
588 const size_t ivarElementSize = chunk->fileSize / chunk->elementCount;
589 if (ivarElementSize != sizeof(U))
590 return make_error_code(NativeReaderError::file_malformed);
591 refsEnd = refsStart + refsArraySize;
592 const U* ivarData = reinterpret_cast<const U *>(base + chunk->fileOffset);
593 for (uint8_t *s = refsStart; s != refsEnd; s += sizeof(T), ++ivarData) {
594 T *atomAllocSpace = reinterpret_cast<T *>(s);
595 new (atomAllocSpace) T(*this, ivarData);
596 }
597 return make_error_code(NativeReaderError::success);
598 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000599
Alp Toker32e8bef2013-12-01 23:51:36 +0000600 // instantiate array of References from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000601 error_code processReferencesV1(const uint8_t *base,
602 const NativeChunk *chunk) {
Rui Ueyamae05b6292013-11-20 20:54:18 +0000603 uint8_t *refsStart, *refsEnd;
604 if (error_code ec
605 = processReferences<NativeReferenceV1, NativeReferenceIvarsV1>(
606 base, chunk, refsStart, refsEnd))
607 return ec;
608 this->_referencesV1.arrayStart = refsStart;
609 this->_referencesV1.arrayEnd = refsEnd;
610 this->_referencesV1.elementSize = sizeof(NativeReferenceV1);
611 this->_referencesV1.elementCount = chunk->elementCount;
612 DEBUG_WITH_TYPE("ReaderNative", {
613 llvm::dbgs() << " chunk ReferencesV1: "
614 << " count=" << chunk->elementCount
615 << " chunkSize=" << chunk->fileSize << "\n";
616 });
617 return make_error_code(NativeReaderError::success);
618 }
619
Alp Toker32e8bef2013-12-01 23:51:36 +0000620 // instantiate array of References from v2 ivar data in file
Rui Ueyamae05b6292013-11-20 20:54:18 +0000621 error_code processReferencesV2(const uint8_t *base,
622 const NativeChunk *chunk) {
623 uint8_t *refsStart, *refsEnd;
624 if (error_code ec
625 = processReferences<NativeReferenceV2, NativeReferenceIvarsV2>(
626 base, chunk, refsStart, refsEnd))
627 return ec;
628 this->_referencesV2.arrayStart = refsStart;
629 this->_referencesV2.arrayEnd = refsEnd;
630 this->_referencesV2.elementSize = sizeof(NativeReferenceV2);
631 this->_referencesV2.elementCount = chunk->elementCount;
632 DEBUG_WITH_TYPE("ReaderNative", {
633 llvm::dbgs() << " chunk ReferencesV2: "
634 << " count=" << chunk->elementCount
635 << " chunkSize=" << chunk->fileSize << "\n";
636 });
Rui Ueyamac6015f62013-10-09 00:57:22 +0000637 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000638 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000639
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000640 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000641 error_code processTargetsTable(const uint8_t *base,
642 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000643 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
644 (base + chunk->fileOffset);
645 this->_targetsTableCount = chunk->elementCount;
646 this->_targetsTable = new const Atom*[chunk->elementCount];
647 for (uint32_t i=0; i < chunk->elementCount; ++i) {
648 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000649 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000650 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000651 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000652 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
653 continue;
654 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000655 const uint32_t undefIndex = index - _definedAtoms._elementCount;
656 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000657 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000658 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000659 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
660 continue;
661 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000662 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000663 - _undefinedAtoms._elementCount;
664 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000665 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000666 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000667 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
668 continue;
669 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000670 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000671 - _undefinedAtoms._elementCount
672 - _sharedLibraryAtoms._elementCount;
673 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000674 const uint8_t* p = _absoluteAtoms._arrayStart
Simon Atanasyan8ef39b52013-11-04 19:40:02 +0000675 + abIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000676 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
677 continue;
678 }
Rui Ueyamac6015f62013-10-09 00:57:22 +0000679 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000680 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000681 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000682 << " chunk Targets Table: "
683 << " count=" << chunk->elementCount
684 << " chunkSize=" << chunk->fileSize
685 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000686 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000687 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000688
689
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000690 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000691 error_code processAddendsTable(const uint8_t *base,
692 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000693 this->_addends = reinterpret_cast<const Reference::Addend*>
694 (base + chunk->fileOffset);
695 this->_addendsMaxIndex = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000696 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000697 << " chunk Addends: "
698 << " count=" << chunk->elementCount
699 << " chunkSize=" << chunk->fileSize
700 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000701 return make_error_code(NativeReaderError::success);
Nick Kledzik23384e82012-02-07 02:59:54 +0000702 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000703
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000704 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000705 error_code processStrings(const uint8_t *base,
706 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000707 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
708 this->_stringsMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000709 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000710 << " chunk Strings: "
711 << " chunkSize=" << chunk->fileSize
712 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000713 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000714 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000715
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000716 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000717 error_code processContent(const uint8_t *base,
718 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000719 this->_contentStart = base + chunk->fileOffset;
720 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000721 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000722 << " chunk content: "
723 << " chunkSize=" << chunk->fileSize
724 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000725 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000726 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000727
Michael J. Spencere6203a52012-04-03 18:39:40 +0000728 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000729 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000730 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000731 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000732
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000733 Reference::Addend addend(uint32_t index) const {
734 if ( index == 0 )
735 return 0; // addend index zero is used to mean "no addend"
736 assert(index <= _addendsMaxIndex);
737 return _addends[index-1]; // one-based indexing
738 }
739
740 const NativeAtomAttributesV1& attribute(uint32_t off) const {
741 assert(off < _attributesMaxOffset);
742 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000743 }
744
Sid Manning2a590242012-10-18 17:16:19 +0000745 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
746 assert(off < _absAbsoluteMaxOffset);
747 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
748 }
749
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000750 const uint8_t* content(uint32_t offset, uint32_t size) const {
751 const uint8_t* result = _contentStart + offset;
752 assert((result+size) <= _contentEnd);
753 return result;
754 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000755
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000756 const Reference* referenceByIndex(uintptr_t index) const {
Rui Ueyamae05b6292013-11-20 20:54:18 +0000757 if (index < _referencesV1.elementCount) {
758 return reinterpret_cast<const NativeReferenceV1*>(
759 _referencesV1.arrayStart + index * _referencesV1.elementSize);
760 }
761 assert(index < _referencesV2.elementCount);
762 return reinterpret_cast<const NativeReferenceV2*>(
763 _referencesV2.arrayStart + index * _referencesV2.elementSize);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000764 }
765
Rui Ueyamae05b6292013-11-20 20:54:18 +0000766 const Atom* targetV1(uint16_t index) const {
Nick Kledzikb334be12012-04-07 01:31:00 +0000767 if ( index == NativeReferenceIvarsV1::noTarget )
768 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000769 assert(index < _targetsTableCount);
770 return _targetsTable[index];
771 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000772
Rui Ueyamae05b6292013-11-20 20:54:18 +0000773 void setTargetV1(uint16_t index, const Atom* newAtom) const {
Nick Kledzikb334be12012-04-07 01:31:00 +0000774 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000775 assert(index > _targetsTableCount);
776 _targetsTable[index] = newAtom;
777 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000778
Rui Ueyamae05b6292013-11-20 20:54:18 +0000779 const Atom* targetV2(uint32_t index) const {
780 if (index == NativeReferenceIvarsV2::noTarget)
781 return nullptr;
782 assert(index < _targetsTableCount);
783 return _targetsTable[index];
784 }
785
786 void setTargetV2(uint32_t index, const Atom* newAtom) const {
787 assert(index != NativeReferenceIvarsV2::noTarget);
788 assert(index > _targetsTableCount);
789 _targetsTable[index] = newAtom;
790 }
791
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000792 // private constructor, only called by make()
Nick Kledzike5552772013-12-19 21:58:00 +0000793 File(std::unique_ptr<MemoryBuffer> mb, StringRef path)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000794 : lld::File(path, kindObject),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000795 _buffer(std::move(mb)), // Reader now takes ownership of buffer
796 _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
797 _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
Nick Kledzike5552772013-12-19 21:58:00 +0000798 _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000799 _header =
800 reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000801 }
802
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000803 template <typename T>
804 class AtomArray : public File::atom_collection<T> {
805 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000806 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000807 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000808
809 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000810 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
811 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000812 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000813 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
814 }
815 virtual const T* deref(const void* it) const {
816 return reinterpret_cast<const T*>(it);
817 }
818 virtual void next(const void*& it) const {
819 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
820 p += _elementSize;
821 it = reinterpret_cast<const void*>(p);
822 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000823 virtual uint64_t size() const { return _elementCount; }
824 const uint8_t *_arrayStart;
825 const uint8_t *_arrayEnd;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000826 uint32_t _elementSize;
827 uint32_t _elementCount;
828 };
829
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000830 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000831 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000832 arrayStart(nullptr),
833 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000834 elementSize(0),
835 elementCount(0) { }
836
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000837 const uint8_t* arrayStart;
838 const uint8_t* arrayEnd;
839 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000840 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000841 };
842
Nick Kledzikf30e8482013-12-20 20:34:19 +0000843 std::unique_ptr<MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000844 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000845 AtomArray<DefinedAtom> _definedAtoms;
846 AtomArray<UndefinedAtom> _undefinedAtoms;
847 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
848 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000849 const uint8_t* _absAttributes;
850 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000851 const uint8_t* _attributes;
852 uint32_t _attributesMaxOffset;
Rui Ueyamae05b6292013-11-20 20:54:18 +0000853 IvarArray _referencesV1;
854 IvarArray _referencesV2;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000855 const Atom** _targetsTable;
856 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000857 const char* _strings;
858 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000859 const Reference::Addend* _addends;
Nick Kledzikf30e8482013-12-20 20:34:19 +0000860 uint32_t _addendsMaxIndex;
861 const uint8_t *_contentStart;
862 const uint8_t *_contentEnd;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000863};
864
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000865inline const lld::File &NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000866 return *_file;
867}
868
869inline uint64_t NativeDefinedAtomV1:: ordinal() const {
870 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000871 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000872}
873
Michael J. Spencere6203a52012-04-03 18:39:40 +0000874inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000875 return _file->string(_ivarData->nameOffset);
876}
877
878inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
879 return _file->attribute(_ivarData->attributesOffset);
880}
881
Michael J. Spencere6203a52012-04-03 18:39:40 +0000882inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000883 if (!occupiesDiskSpace())
Michael J. Spencere6203a52012-04-03 18:39:40 +0000884 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000885 const uint8_t* p = _file->content(_ivarData->contentOffset,
886 _ivarData->contentSize);
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000887 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000888}
889
Michael J. Spencere6203a52012-04-03 18:39:40 +0000890inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000891 uint32_t offset = attributes().sectionNameOffset;
892 return _file->string(offset);
893}
894
Nick Kledzik062a98c2012-04-08 23:52:13 +0000895DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000896 uintptr_t index = _ivarData->referencesStartIndex;
897 const void* it = reinterpret_cast<const void*>(index);
898 return reference_iterator(*this, it);
899}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000900
Nick Kledzik062a98c2012-04-08 23:52:13 +0000901DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000902 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
903 const void* it = reinterpret_cast<const void*>(index);
904 return reference_iterator(*this, it);
905}
906
907const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
908 uintptr_t index = reinterpret_cast<uintptr_t>(it);
909 return _file->referenceByIndex(index);
910}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000911
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000912void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
913 uintptr_t index = reinterpret_cast<uintptr_t>(it);
914 ++index;
915 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000916}
Nick Kledzik23384e82012-02-07 02:59:54 +0000917
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000918inline const lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000919 return *_file;
920}
921
Michael J. Spencere6203a52012-04-03 18:39:40 +0000922inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000923 return _file->string(_ivarData->nameOffset);
924}
925
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000926inline const UndefinedAtom *NativeUndefinedAtomV1::fallback() const {
927 if (!_ivarData->fallbackNameOffset)
928 return nullptr;
929 if (!_fallback)
930 _fallback.reset(new SimpleUndefinedAtom(
931 *_file, _file->string(_ivarData->fallbackNameOffset)));
932 return _fallback.get();
933}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000934
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000935inline const lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000936 return *_file;
937}
938
Michael J. Spencere6203a52012-04-03 18:39:40 +0000939inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000940 return _file->string(_ivarData->nameOffset);
941}
942
Michael J. Spencere6203a52012-04-03 18:39:40 +0000943inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000944 return _file->string(_ivarData->loadNameOffset);
945}
946
947
948
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000949inline const lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000950 return *_file;
951}
952
Michael J. Spencere6203a52012-04-03 18:39:40 +0000953inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000954 return _file->string(_ivarData->nameOffset);
955}
956
Sid Manning2a590242012-10-18 17:16:19 +0000957inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
958 return _file->absAttribute(_ivarData->attributesOffset);
959}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000960
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000961inline const Atom* NativeReferenceV1::target() const {
Rui Ueyamae05b6292013-11-20 20:54:18 +0000962 return _file->targetV1(_ivarData->targetIndex);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000963}
964
965inline Reference::Addend NativeReferenceV1::addend() const {
966 return _file->addend(_ivarData->addendIndex);
967}
968
969inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
Rui Ueyamae05b6292013-11-20 20:54:18 +0000970 return _file->setTargetV1(_ivarData->targetIndex, newAtom);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000971}
Nick Kledzik23384e82012-02-07 02:59:54 +0000972
Nick Kledzikb334be12012-04-07 01:31:00 +0000973inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000974 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000975 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000976 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000977 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000978}
979
Rui Ueyamae05b6292013-11-20 20:54:18 +0000980inline const Atom* NativeReferenceV2::target() const {
981 return _file->targetV2(_ivarData->targetIndex);
982}
983
984inline Reference::Addend NativeReferenceV2::addend() const {
985 return _ivarData->addend;
986}
987
988inline void NativeReferenceV2::setTarget(const Atom* newAtom) {
989 return _file->setTargetV2(_ivarData->targetIndex, newAtom);
990}
991
992inline void NativeReferenceV2::setAddend(Addend a) {
993 // Do nothing if addend value is not being changed.
994 if (addend() == a)
995 return;
996 llvm_unreachable("setAddend() not supported");
997}
998
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000999} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +00001000
Nick Kledzike5552772013-12-19 21:58:00 +00001001namespace {
1002
1003class NativeReader : public Reader {
1004public:
Rui Ueyama170a1a82013-12-20 07:48:29 +00001005 virtual bool canParse(file_magic magic, StringRef,
1006 const MemoryBuffer &mb) const {
Nick Kledzike5552772013-12-19 21:58:00 +00001007 const NativeFileHeader *const header =
Rui Ueyama170a1a82013-12-20 07:48:29 +00001008 reinterpret_cast<const NativeFileHeader *>(mb.getBufferStart());
1009 return (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC,
1010 sizeof(header->magic)) == 0);
Nick Kledzike5552772013-12-19 21:58:00 +00001011 }
Rui Ueyama170a1a82013-12-20 07:48:29 +00001012
Nick Kledzike5552772013-12-19 21:58:00 +00001013 virtual error_code
1014 parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &,
1015 std::vector<std::unique_ptr<File>> &result) const {
1016 return lld::native::File::make(std::move(mb), result);
1017 return error_code::success();
1018 }
1019};
Nick Kledzik55fd6be2012-01-16 22:03:44 +00001020}
Nick Kledzike5552772013-12-19 21:58:00 +00001021
1022void Registry::addSupportNativeObjects() {
Rui Ueyama170a1a82013-12-20 07:48:29 +00001023 add(std::unique_ptr<Reader>(new NativeReader()));
Nick Kledzike5552772013-12-19 21:58:00 +00001024}
1025
Michael J. Spencer64afcb42013-01-23 01:18:43 +00001026} // end namespace lld