blob: 7e29261f9d5228e1d1d28525a07a350ea0dda746 [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
211//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000212// An object of this class is instantied for each NativeReferenceIvarsV1
213// struct in the NCS_ReferencesArrayV1 chunk.
214//
215class NativeReferenceV1 : public Reference {
216public:
Michael J. Spencerfa405272013-03-20 18:57:52 +0000217 NativeReferenceV1(const File& f, const NativeReferenceIvarsV1* ivarData)
218 : _file(&f), _ivarData(ivarData) {
219 setKind(ivarData->kind);
220 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000221
222 virtual uint64_t offsetInAtom() const {
223 return _ivarData->offsetInAtom;
224 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000225
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000226 virtual const Atom* target() const;
227 virtual Addend addend() const;
228 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000229 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000230
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000231private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000232 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000233 // since ivar data is mapped read-only.
234 void cloneIvarData() {
235 // TODO: do nothing on second call
236 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000237 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000238 std::nothrow));
239 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
240 }
241
Nick Kledzikabb69812012-05-31 22:34:00 +0000242 const File *_file;
243 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000244};
245
246
247
248//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000249// lld::File object for native llvm object file
250//
Nick Kledzikabb69812012-05-31 22:34:00 +0000251class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000252public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000253
254 /// Instantiates a File object from a native object file. Ownership
255 /// of the MemoryBuffer is transfered to the resulting File object.
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000256 static error_code make(const LinkingContext &context,
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000257 std::unique_ptr<MemoryBuffer> mb,
258 std::vector<std::unique_ptr<lld::File> > &result) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000259 const uint8_t *const base =
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000260 reinterpret_cast<const uint8_t *>(mb->getBufferStart());
261 StringRef path(mb->getBufferIdentifier());
262 const NativeFileHeader *const header =
263 reinterpret_cast<const NativeFileHeader *>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000264 const NativeChunk *const chunks =
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000265 reinterpret_cast<const NativeChunk *>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000266 // make sure magic matches
Rui Ueyamaa3ada6b2013-11-16 01:31:24 +0000267 if (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC,
268 sizeof(header->magic)) != 0)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000269 return make_error_code(NativeReaderError::unknown_file_format);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000270
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000271 // make sure mapped file contains all needed data
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000272 const size_t fileSize = mb->getBufferSize();
273 if (header->fileSize > fileSize)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000274 return make_error_code(NativeReaderError::file_too_short);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000275
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000276 DEBUG_WITH_TYPE("ReaderNative",
277 llvm::dbgs() << " Native File Header:" << " fileSize="
278 << header->fileSize << " chunkCount="
279 << header->chunkCount << "\n");
Nick Kledzikabb69812012-05-31 22:34:00 +0000280
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000281 // instantiate NativeFile object and add values to it as found
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000282 std::unique_ptr<File> file(new File(context, std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000283
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000284 // process each chunk
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000285 for (uint32_t i = 0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000286 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000287 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000288 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000289 if ( chunk->fileOffset > fileSize )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000290 return make_error_code(NativeReaderError::file_malformed);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000291 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000292 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000293 // process chunk, based on signature
294 switch ( chunk->signature ) {
295 case NCS_DefinedAtomsV1:
296 ec = file->processDefinedAtomsV1(base, chunk);
297 break;
298 case NCS_AttributesArrayV1:
299 ec = file->processAttributesV1(base, chunk);
300 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000301 case NCS_UndefinedAtomsV1:
302 ec = file->processUndefinedAtomsV1(base, chunk);
303 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000304 case NCS_SharedLibraryAtomsV1:
305 ec = file->processSharedLibraryAtomsV1(base, chunk);
306 break;
307 case NCS_AbsoluteAtomsV1:
308 ec = file->processAbsoluteAtomsV1(base, chunk);
309 break;
Sid Manning2a590242012-10-18 17:16:19 +0000310 case NCS_AbsoluteAttributesV1:
311 ec = file->processAbsoluteAttributesV1(base, chunk);
312 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000313 case NCS_ReferencesArrayV1:
314 ec = file->processReferencesV1(base, chunk);
315 break;
316 case NCS_TargetsTable:
317 ec = file->processTargetsTable(base, chunk);
318 break;
319 case NCS_AddendsTable:
320 ec = file->processAddendsTable(base, chunk);
321 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000322 case NCS_Content:
323 ec = file->processContent(base, chunk);
324 break;
325 case NCS_Strings:
326 ec = file->processStrings(base, chunk);
327 break;
328 default:
Rui Ueyamac6015f62013-10-09 00:57:22 +0000329 return make_error_code(NativeReaderError::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000330 }
331 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000332 return ec;
333 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000334 }
335 // TO DO: validate enough chunks were used
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000336
337 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000338 << " ReaderNative DefinedAtoms:\n");
339 for (const DefinedAtom *a : file->defined() ) {
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000340 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000341 << llvm::format(" 0x%09lX", a)
342 << ", name=" << a->name()
343 << ", size=" << a->size()
344 << "\n");
345 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000346 (void)r;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000347 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
348 << " offset="
Nick Kledzikabb69812012-05-31 22:34:00 +0000349 << llvm::format("0x%03X", r->offsetInAtom())
350 << ", kind=" << r->kind()
351 << ", target=" << r->target()
352 << "\n");
353 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000354 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000355
Nick Kledzikabb69812012-05-31 22:34:00 +0000356 result.push_back(std::move(file));
Rui Ueyamac6015f62013-10-09 00:57:22 +0000357 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000358 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000359
Nick Kledzikabb69812012-05-31 22:34:00 +0000360 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000361 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000362
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000363 // All other ivar pointers are pointers into the MemoryBuffer, except
364 // the _definedAtoms array which was allocated to contain an array
365 // of Atom objects. The atoms have empty destructors, so it is ok
366 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000367 delete _definedAtoms._arrayStart;
368 delete _undefinedAtoms._arrayStart;
369 delete _sharedLibraryAtoms._arrayStart;
370 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000371 delete _references.arrayStart;
Michael J. Spencer20231f12013-01-26 12:26:56 +0000372 delete [] _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000373 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000374
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000375 virtual const atom_collection<DefinedAtom>& defined() const {
376 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000377 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000378 virtual const atom_collection<UndefinedAtom>& undefined() const {
379 return _undefinedAtoms;
380 }
381 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
382 return _sharedLibraryAtoms;
383 }
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000384 virtual const atom_collection<AbsoluteAtom> &absolute() const {
385 return _absoluteAtoms;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000386 }
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000387 virtual const LinkingContext &getLinkingContext() const { return _context; }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000388
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000389private:
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000390 friend NativeDefinedAtomV1;
391 friend NativeUndefinedAtomV1;
392 friend NativeSharedLibraryAtomV1;
393 friend NativeAbsoluteAtomV1;
394 friend NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000395
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000396 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000397 error_code processDefinedAtomsV1(const uint8_t *base,
398 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000399 const size_t atomSize = sizeof(NativeDefinedAtomV1);
400 size_t atomsArraySize = chunk->elementCount * atomSize;
401 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
402 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000403 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000404 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000405 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000406 / chunk->elementCount;
407 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000408 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000409 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000410 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000411 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
412 (base + chunk->fileOffset);
413 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000414 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000415 reinterpret_cast<NativeDefinedAtomV1*>(s);
416 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
417 ++ivarData;
418 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000419 this->_definedAtoms._arrayStart = atomsStart;
420 this->_definedAtoms._arrayEnd = atomsEnd;
421 this->_definedAtoms._elementSize = atomSize;
422 this->_definedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000423 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000424 << " chunk DefinedAtomsV1: "
425 << " count=" << chunk->elementCount
426 << " chunkSize=" << chunk->fileSize
427 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000428 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000429 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000430
Nick Kledzikabb69812012-05-31 22:34:00 +0000431
432
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000433 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000434 error_code processAttributesV1(const uint8_t *base,
435 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000436 this->_attributes = base + chunk->fileOffset;
437 this->_attributesMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000438 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000439 << " chunk AttributesV1: "
440 << " count=" << chunk->elementCount
441 << " chunkSize=" << chunk->fileSize
442 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000443 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000444 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000445
Sid Manning2a590242012-10-18 17:16:19 +0000446 // set up pointers to attributes array
447 error_code processAbsoluteAttributesV1(const uint8_t *base,
448 const NativeChunk *chunk) {
449 this->_absAttributes = base + chunk->fileOffset;
450 this->_absAbsoluteMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000451 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Sid Manning2a590242012-10-18 17:16:19 +0000452 << " chunk AbsoluteAttributesV1: "
453 << " count=" << chunk->elementCount
454 << " chunkSize=" << chunk->fileSize
455 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000456 return make_error_code(NativeReaderError::success);
Sid Manning2a590242012-10-18 17:16:19 +0000457 }
458
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000459 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000460 error_code processUndefinedAtomsV1(const uint8_t *base,
461 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000462 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
463 size_t atomsArraySize = chunk->elementCount * atomSize;
464 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
465 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000466 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000467 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000468 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000469 / chunk->elementCount;
470 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000471 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik23384e82012-02-07 02:59:54 +0000472 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000473 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000474 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
475 (base + chunk->fileOffset);
476 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000477 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000478 reinterpret_cast<NativeUndefinedAtomV1*>(s);
479 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
480 ++ivarData;
481 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000482 this->_undefinedAtoms._arrayStart = atomsStart;
483 this->_undefinedAtoms._arrayEnd = atomsEnd;
484 this->_undefinedAtoms._elementSize = atomSize;
485 this->_undefinedAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000486 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000487 << " chunk UndefinedAtomsV1:"
488 << " count=" << chunk->elementCount
489 << " chunkSize=" << chunk->fileSize
490 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000491 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000492 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000493
494
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000495 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000496 error_code processSharedLibraryAtomsV1(const uint8_t *base,
497 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000498 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
499 size_t atomsArraySize = chunk->elementCount * atomSize;
500 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
501 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000502 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000503 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000504 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000505 / chunk->elementCount;
506 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000507 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000508 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000509 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000510 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
511 (base + chunk->fileOffset);
512 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000513 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000514 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
515 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
516 ++ivarData;
517 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000518 this->_sharedLibraryAtoms._arrayStart = atomsStart;
519 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
520 this->_sharedLibraryAtoms._elementSize = atomSize;
521 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000522 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000523 << " chunk SharedLibraryAtomsV1:"
524 << " count=" << chunk->elementCount
525 << " chunkSize=" << chunk->fileSize
526 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000527 return make_error_code(NativeReaderError::success);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000528 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000529
530
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000531 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000532 error_code processAbsoluteAtomsV1(const uint8_t *base,
533 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000534 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
535 size_t atomsArraySize = chunk->elementCount * atomSize;
536 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
537 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000538 if (atomsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000539 return make_error_code(NativeReaderError::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000540 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000541 / chunk->elementCount;
542 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000543 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000544 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000545 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000546 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
547 (base + chunk->fileOffset);
548 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000549 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000550 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
551 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
552 ++ivarData;
553 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000554 this->_absoluteAtoms._arrayStart = atomsStart;
555 this->_absoluteAtoms._arrayEnd = atomsEnd;
556 this->_absoluteAtoms._elementSize = atomSize;
557 this->_absoluteAtoms._elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000558 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000559 << " chunk AbsoluteAtomsV1: "
560 << " count=" << chunk->elementCount
561 << " chunkSize=" << chunk->fileSize
562 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000563 return make_error_code(NativeReaderError::success);
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000564 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000565
566
567
568
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000569 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000570 error_code processReferencesV1(const uint8_t *base,
571 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000572 if ( chunk->elementCount == 0 )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000573 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000574 const size_t refSize = sizeof(NativeReferenceV1);
575 size_t refsArraySize = chunk->elementCount * refSize;
576 uint8_t* refsStart = reinterpret_cast<uint8_t*>
577 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000578 if (refsStart == nullptr)
Rui Ueyamac6015f62013-10-09 00:57:22 +0000579 return make_error_code(NativeReaderError::memory_error);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000580 const size_t ivarElementSize = chunk->fileSize
581 / chunk->elementCount;
582 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
Rui Ueyamac6015f62013-10-09 00:57:22 +0000583 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000584 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000585 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000586 reinterpret_cast<const NativeReferenceIvarsV1*>
587 (base + chunk->fileOffset);
588 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000589 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000590 reinterpret_cast<NativeReferenceV1*>(s);
591 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
592 ++ivarData;
593 }
594 this->_references.arrayStart = refsStart;
595 this->_references.arrayEnd = refsEnd;
596 this->_references.elementSize = refSize;
597 this->_references.elementCount = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000598 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000599 << " chunk ReferencesV1: "
600 << " count=" << chunk->elementCount
601 << " chunkSize=" << chunk->fileSize
602 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000603 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000604 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000605
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000606 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000607 error_code processTargetsTable(const uint8_t *base,
608 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000609 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
610 (base + chunk->fileOffset);
611 this->_targetsTableCount = chunk->elementCount;
612 this->_targetsTable = new const Atom*[chunk->elementCount];
613 for (uint32_t i=0; i < chunk->elementCount; ++i) {
614 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000615 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000616 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000617 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000618 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
619 continue;
620 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000621 const uint32_t undefIndex = index - _definedAtoms._elementCount;
622 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000623 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000624 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000625 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
626 continue;
627 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000628 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000629 - _undefinedAtoms._elementCount;
630 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000631 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000632 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000633 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
634 continue;
635 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000636 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000637 - _undefinedAtoms._elementCount
638 - _sharedLibraryAtoms._elementCount;
639 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000640 const uint8_t* p = _absoluteAtoms._arrayStart
Simon Atanasyan8ef39b52013-11-04 19:40:02 +0000641 + abIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000642 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
643 continue;
644 }
Rui Ueyamac6015f62013-10-09 00:57:22 +0000645 return make_error_code(NativeReaderError::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000646 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000647 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000648 << " chunk Targets Table: "
649 << " count=" << chunk->elementCount
650 << " chunkSize=" << chunk->fileSize
651 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000652 return make_error_code(NativeReaderError::success);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000653 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000654
655
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000656 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000657 error_code processAddendsTable(const uint8_t *base,
658 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000659 this->_addends = reinterpret_cast<const Reference::Addend*>
660 (base + chunk->fileOffset);
661 this->_addendsMaxIndex = chunk->elementCount;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000662 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000663 << " chunk Addends: "
664 << " count=" << chunk->elementCount
665 << " chunkSize=" << chunk->fileSize
666 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000667 return make_error_code(NativeReaderError::success);
Nick Kledzik23384e82012-02-07 02:59:54 +0000668 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000669
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000670 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000671 error_code processStrings(const uint8_t *base,
672 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000673 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
674 this->_stringsMaxOffset = chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000675 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000676 << " chunk Strings: "
677 << " chunkSize=" << chunk->fileSize
678 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000679 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000680 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000681
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000682 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000683 error_code processContent(const uint8_t *base,
684 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000685 this->_contentStart = base + chunk->fileOffset;
686 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000687 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000688 << " chunk content: "
689 << " chunkSize=" << chunk->fileSize
690 << "\n");
Rui Ueyamac6015f62013-10-09 00:57:22 +0000691 return make_error_code(NativeReaderError::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000692 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000693
Michael J. Spencere6203a52012-04-03 18:39:40 +0000694 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000695 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000696 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000697 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000698
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000699 Reference::Addend addend(uint32_t index) const {
700 if ( index == 0 )
701 return 0; // addend index zero is used to mean "no addend"
702 assert(index <= _addendsMaxIndex);
703 return _addends[index-1]; // one-based indexing
704 }
705
706 const NativeAtomAttributesV1& attribute(uint32_t off) const {
707 assert(off < _attributesMaxOffset);
708 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000709 }
710
Sid Manning2a590242012-10-18 17:16:19 +0000711 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
712 assert(off < _absAbsoluteMaxOffset);
713 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
714 }
715
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000716 const uint8_t* content(uint32_t offset, uint32_t size) const {
717 const uint8_t* result = _contentStart + offset;
718 assert((result+size) <= _contentEnd);
719 return result;
720 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000721
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000722 const Reference* referenceByIndex(uintptr_t index) const {
723 assert(index < _references.elementCount);
724 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
725 return reinterpret_cast<const NativeReferenceV1*>(p);
726 }
727
Nick Kledzikb334be12012-04-07 01:31:00 +0000728 const Atom* target(uint16_t index) const {
729 if ( index == NativeReferenceIvarsV1::noTarget )
730 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000731 assert(index < _targetsTableCount);
732 return _targetsTable[index];
733 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000734
Nick Kledzikb334be12012-04-07 01:31:00 +0000735 void setTarget(uint16_t index, const Atom* newAtom) const {
736 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000737 assert(index > _targetsTableCount);
738 _targetsTable[index] = newAtom;
739 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000740
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000741 // private constructor, only called by make()
Rui Ueyamac1800be2013-11-05 01:37:40 +0000742 File(const LinkingContext &context, std::unique_ptr<MemoryBuffer> mb,
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000743 StringRef path)
Michael J. Spencer0f3dd612013-03-20 18:57:27 +0000744 : lld::File(path, kindObject),
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000745 _buffer(std::move(mb)), // Reader now takes ownership of buffer
746 _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
747 _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
748 _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000749 _context(context) {
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000750 _header =
751 reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000752 }
753
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000754 template <typename T>
755 class AtomArray : public File::atom_collection<T> {
756 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000757 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000758 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000759
760 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000761 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
762 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000763 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000764 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
765 }
766 virtual const T* deref(const void* it) const {
767 return reinterpret_cast<const T*>(it);
768 }
769 virtual void next(const void*& it) const {
770 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
771 p += _elementSize;
772 it = reinterpret_cast<const void*>(p);
773 }
Shankar Easwarancc068912013-04-29 04:10:42 +0000774 virtual uint64_t size() const { return _elementCount; }
775 const uint8_t *_arrayStart;
776 const uint8_t *_arrayEnd;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000777 uint32_t _elementSize;
778 uint32_t _elementCount;
779 };
780
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000781 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000782 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000783 arrayStart(nullptr),
784 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000785 elementSize(0),
786 elementCount(0) { }
787
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000788 const uint8_t* arrayStart;
789 const uint8_t* arrayEnd;
790 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000791 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000792 };
793
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000794
Rui Ueyamac1800be2013-11-05 01:37:40 +0000795 std::unique_ptr<MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000796 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000797 AtomArray<DefinedAtom> _definedAtoms;
798 AtomArray<UndefinedAtom> _undefinedAtoms;
799 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
800 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000801 const uint8_t* _absAttributes;
802 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000803 const uint8_t* _attributes;
804 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000805 IvarArray _references;
806 const Atom** _targetsTable;
807 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000808 const char* _strings;
809 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000810 const Reference::Addend* _addends;
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000811 uint32_t _addendsMaxIndex;
812 const uint8_t *_contentStart;
813 const uint8_t *_contentEnd;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000814 const LinkingContext &_context;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000815};
816
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000817inline const lld::File &NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000818 return *_file;
819}
820
821inline uint64_t NativeDefinedAtomV1:: ordinal() const {
822 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000823 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000824}
825
Michael J. Spencere6203a52012-04-03 18:39:40 +0000826inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000827 return _file->string(_ivarData->nameOffset);
828}
829
830inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
831 return _file->attribute(_ivarData->attributesOffset);
832}
833
Michael J. Spencere6203a52012-04-03 18:39:40 +0000834inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000835 if (!occupiesDiskSpace())
Michael J. Spencere6203a52012-04-03 18:39:40 +0000836 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000837 const uint8_t* p = _file->content(_ivarData->contentOffset,
838 _ivarData->contentSize);
Shankar Easwarand17ba4b2013-08-23 20:03:21 +0000839 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000840}
841
Michael J. Spencere6203a52012-04-03 18:39:40 +0000842inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000843 uint32_t offset = attributes().sectionNameOffset;
844 return _file->string(offset);
845}
846
Nick Kledzik062a98c2012-04-08 23:52:13 +0000847DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000848 uintptr_t index = _ivarData->referencesStartIndex;
849 const void* it = reinterpret_cast<const void*>(index);
850 return reference_iterator(*this, it);
851}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000852
Nick Kledzik062a98c2012-04-08 23:52:13 +0000853DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000854 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
855 const void* it = reinterpret_cast<const void*>(index);
856 return reference_iterator(*this, it);
857}
858
859const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
860 uintptr_t index = reinterpret_cast<uintptr_t>(it);
861 return _file->referenceByIndex(index);
862}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000863
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000864void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
865 uintptr_t index = reinterpret_cast<uintptr_t>(it);
866 ++index;
867 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000868}
Nick Kledzik23384e82012-02-07 02:59:54 +0000869
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000870inline const lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000871 return *_file;
872}
873
Michael J. Spencere6203a52012-04-03 18:39:40 +0000874inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000875 return _file->string(_ivarData->nameOffset);
876}
877
Rui Ueyamae5416ec2013-09-12 19:14:05 +0000878inline const UndefinedAtom *NativeUndefinedAtomV1::fallback() const {
879 if (!_ivarData->fallbackNameOffset)
880 return nullptr;
881 if (!_fallback)
882 _fallback.reset(new SimpleUndefinedAtom(
883 *_file, _file->string(_ivarData->fallbackNameOffset)));
884 return _fallback.get();
885}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000886
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000887inline const lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000888 return *_file;
889}
890
Michael J. Spencere6203a52012-04-03 18:39:40 +0000891inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000892 return _file->string(_ivarData->nameOffset);
893}
894
Michael J. Spencere6203a52012-04-03 18:39:40 +0000895inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000896 return _file->string(_ivarData->loadNameOffset);
897}
898
899
900
Rui Ueyama7b7b0b92013-06-21 19:59:15 +0000901inline const lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000902 return *_file;
903}
904
Michael J. Spencere6203a52012-04-03 18:39:40 +0000905inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000906 return _file->string(_ivarData->nameOffset);
907}
908
Sid Manning2a590242012-10-18 17:16:19 +0000909inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
910 return _file->absAttribute(_ivarData->attributesOffset);
911}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000912
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000913inline const Atom* NativeReferenceV1::target() const {
914 return _file->target(_ivarData->targetIndex);
915}
916
917inline Reference::Addend NativeReferenceV1::addend() const {
918 return _file->addend(_ivarData->addendIndex);
919}
920
921inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
922 return _file->setTarget(_ivarData->targetIndex, newAtom);
923}
Nick Kledzik23384e82012-02-07 02:59:54 +0000924
Nick Kledzikb334be12012-04-07 01:31:00 +0000925inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000926 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000927 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000928 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000929 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000930}
931
Nick Kledzikabb69812012-05-31 22:34:00 +0000932class Reader : public lld::Reader {
933public:
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000934 Reader(const LinkingContext &context) : lld::Reader(context) {}
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000935
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000936 virtual error_code
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000937 parseFile(std::unique_ptr<MemoryBuffer> &mb,
938 std::vector<std::unique_ptr<lld::File> > &result) const {
939 return File::make(_context, std::move(mb), result);
Nick Kledzikabb69812012-05-31 22:34:00 +0000940 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000941};
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000942} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +0000943
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000944std::unique_ptr<Reader> createReaderNative(const LinkingContext &context) {
945 return std::unique_ptr<Reader>(new lld::native::Reader(context));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000946}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000947} // end namespace lld