blob: 0a69ae4171db55611f8ceb391b9e8160ebf41033 [file] [log] [blame]
Nick Kledzikabb69812012-05-31 22:34:00 +00001//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
Nick Kledzik55fd6be2012-01-16 22:03:44 +00002//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Michael J. Spencer64afcb42013-01-23 01:18:43 +000010#include "lld/ReaderWriter/Reader.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000011
Michael J. Spencercfd029f2012-03-28 19:04:02 +000012#include "lld/Core/Atom.h"
13#include "lld/Core/Error.h"
14#include "lld/Core/File.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000015
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/OwningPtr.h"
18#include "llvm/ADT/StringRef.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000019#include "llvm/Support/Debug.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000020#include "llvm/Support/ErrorHandling.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000021#include "llvm/Support/Format.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000022#include "llvm/Support/MemoryBuffer.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000023#include "llvm/Support/raw_ostream.h"
24
25#include "NativeFileFormat.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000026
Michael J. Spencercfd029f2012-03-28 19:04:02 +000027#include <vector>
Nick Kledzikb334be12012-04-07 01:31:00 +000028#include <memory>
Nick Kledzik55fd6be2012-01-16 22:03:44 +000029
30namespace lld {
Nick Kledzikabb69812012-05-31 22:34:00 +000031namespace native {
Nick Kledzik55fd6be2012-01-16 22:03:44 +000032
33// forward reference
Nick Kledzikabb69812012-05-31 22:34:00 +000034class File;
Nick Kledzik55fd6be2012-01-16 22:03:44 +000035
Nick Kledzik55fd6be2012-01-16 22:03:44 +000036//
37// An object of this class is instantied for each NativeDefinedAtomIvarsV1
38// struct in the NCS_DefinedAtomsV1 chunk.
39//
40class NativeDefinedAtomV1 : public DefinedAtom {
41public:
Nick Kledzikabb69812012-05-31 22:34:00 +000042 NativeDefinedAtomV1(const File& f,
Nick Kledzik55fd6be2012-01-16 22:03:44 +000043 const NativeDefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +000044 : _file(&f), _ivarData(ivarData) { }
45
Nick Kledzikabb69812012-05-31 22:34:00 +000046 virtual const class lld::File& file() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000047
48 virtual uint64_t ordinal() const;
49
Michael J. Spencere6203a52012-04-03 18:39:40 +000050 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000051
Nick Kledzik55fd6be2012-01-16 22:03:44 +000052 virtual uint64_t size() const {
53 return _ivarData->contentSize;
54 }
55
56 virtual DefinedAtom::Scope scope() const {
57 return (DefinedAtom::Scope)(attributes().scope);
58 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000059
Nick Kledzik55fd6be2012-01-16 22:03:44 +000060 virtual DefinedAtom::Interposable interposable() const {
61 return (DefinedAtom::Interposable)(attributes().interposable);
62 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000063
Nick Kledzik55fd6be2012-01-16 22:03:44 +000064 virtual DefinedAtom::Merge merge() const {
65 return (DefinedAtom::Merge)(attributes().merge);
66 }
67
68 virtual DefinedAtom::ContentType contentType() const {
Nick Kledzik23384e82012-02-07 02:59:54 +000069 const NativeAtomAttributesV1& attr = attributes();
70 return (DefinedAtom::ContentType)(attr.contentType);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000071 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000072
Nick Kledzik55fd6be2012-01-16 22:03:44 +000073 virtual DefinedAtom::Alignment alignment() const {
74 return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
75 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000076
Nick Kledzik55fd6be2012-01-16 22:03:44 +000077 virtual DefinedAtom::SectionChoice sectionChoice() const {
78 return (DefinedAtom::SectionChoice)(attributes().sectionChoice);
79 }
80
Michael J. Spencere6203a52012-04-03 18:39:40 +000081 virtual StringRef customSectionName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000082
Nick Kledzik55fd6be2012-01-16 22:03:44 +000083 virtual DefinedAtom::DeadStripKind deadStrip() const {
84 return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
Nick Kledzik6bc04c62012-02-22 21:56:59 +000085 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000086
Nick Kledzik55fd6be2012-01-16 22:03:44 +000087 virtual DefinedAtom::ContentPermissions permissions() const {
88 return (DefinedAtom::ContentPermissions)(attributes().permissions);
89 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000090
Nick Kledzik55fd6be2012-01-16 22:03:44 +000091 virtual bool isThumb() const {
Nick Kledzik49d6cc82012-02-15 00:38:09 +000092 return false; //(attributes().thumb != 0);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000093 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000094
Nick Kledzik55fd6be2012-01-16 22:03:44 +000095 virtual bool isAlias() const {
96 return (attributes().alias != 0);
97 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000098
Michael J. Spencere6203a52012-04-03 18:39:40 +000099 virtual ArrayRef<uint8_t> rawContent() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000100
Nick Kledzik062a98c2012-04-08 23:52:13 +0000101 virtual reference_iterator begin() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000102
Nick Kledzik062a98c2012-04-08 23:52:13 +0000103 virtual reference_iterator end() const;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000104
105 virtual const Reference* derefIterator(const void*) const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000106
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000107 virtual void incrementIterator(const void*& it) const;
108
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000109private:
110 const NativeAtomAttributesV1& attributes() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000111
Nick Kledzikabb69812012-05-31 22:34:00 +0000112 const File *_file;
113 const NativeDefinedAtomIvarsV1 *_ivarData;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000114};
115
116
117
Nick Kledzik23384e82012-02-07 02:59:54 +0000118//
119// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
120// struct in the NCS_UndefinedAtomsV1 chunk.
121//
122class NativeUndefinedAtomV1 : public UndefinedAtom {
123public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000124 NativeUndefinedAtomV1(const File& f,
Nick Kledzik23384e82012-02-07 02:59:54 +0000125 const NativeUndefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000126 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik23384e82012-02-07 02:59:54 +0000127
Nick Kledzikabb69812012-05-31 22:34:00 +0000128 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000129 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000130
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000131 virtual CanBeNull canBeNull() const {
132 return (CanBeNull)(_ivarData->flags & 0x3);
Nick Kledzik23384e82012-02-07 02:59:54 +0000133 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000134
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000135
Nick Kledzik23384e82012-02-07 02:59:54 +0000136private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000137 const File *_file;
138 const NativeUndefinedAtomIvarsV1 *_ivarData;
Nick Kledzik23384e82012-02-07 02:59:54 +0000139};
140
141
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000142//
143// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
144// struct in the NCS_SharedLibraryAtomsV1 chunk.
145//
146class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
147public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000148 NativeSharedLibraryAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000149 const NativeSharedLibraryAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000150 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000151
Nick Kledzikabb69812012-05-31 22:34:00 +0000152 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000153 virtual StringRef name() const;
154 virtual StringRef loadName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000155
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000156 virtual bool canBeNullAtRuntime() const {
157 return (_ivarData->flags & 0x1);
158 }
159
160private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000161 const File *_file;
162 const NativeSharedLibraryAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000163};
164
165
166//
167// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
168// struct in the NCS_AbsoluteAtomsV1 chunk.
169//
170class NativeAbsoluteAtomV1 : public AbsoluteAtom {
171public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000172 NativeAbsoluteAtomV1(const File& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000173 const NativeAbsoluteAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000174 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000175
Nick Kledzikabb69812012-05-31 22:34:00 +0000176 virtual const lld::File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000177 virtual StringRef name() const;
Sid Manning2a590242012-10-18 17:16:19 +0000178 virtual Scope scope() const {
179 const NativeAtomAttributesV1& attr = absAttributes();
180 return (Scope)(attr.scope);
181 }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000182 virtual uint64_t value() const {
183 return _ivarData->value;
184 }
185
186private:
Sid Manning2a590242012-10-18 17:16:19 +0000187 const NativeAtomAttributesV1& absAttributes() const;
Nick Kledzikabb69812012-05-31 22:34:00 +0000188 const File *_file;
189 const NativeAbsoluteAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000190};
191
192
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000193
194//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000195// An object of this class is instantied for each NativeReferenceIvarsV1
196// struct in the NCS_ReferencesArrayV1 chunk.
197//
198class NativeReferenceV1 : public Reference {
199public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000200 NativeReferenceV1(const File& f,
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000201 const NativeReferenceIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000202 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000203
204 virtual uint64_t offsetInAtom() const {
205 return _ivarData->offsetInAtom;
206 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000207
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000208 virtual Kind kind() const {
209 return _ivarData->kind;
210 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000211
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000212 virtual void setKind(Kind);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000213 virtual const Atom* target() const;
214 virtual Addend addend() const;
215 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000216 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000217
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000218private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000219 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000220 // since ivar data is mapped read-only.
221 void cloneIvarData() {
222 // TODO: do nothing on second call
223 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000224 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000225 std::nothrow));
226 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
227 }
228
Nick Kledzikabb69812012-05-31 22:34:00 +0000229 const File *_file;
230 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000231};
232
233
234
235//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000236// lld::File object for native llvm object file
237//
Nick Kledzikabb69812012-05-31 22:34:00 +0000238class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000239public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000240
241 /// Instantiates a File object from a native object file. Ownership
242 /// of the MemoryBuffer is transfered to the resulting File object.
Nick Kledzikabb69812012-05-31 22:34:00 +0000243 static error_code make(std::unique_ptr<llvm::MemoryBuffer> &mb,
Michael J. Spencere6203a52012-04-03 18:39:40 +0000244 StringRef path,
Nick Kledzikabb69812012-05-31 22:34:00 +0000245 std::vector<std::unique_ptr<lld::File>> &result) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000246 const uint8_t* const base =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000247 reinterpret_cast<const uint8_t*>(mb->getBufferStart());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000248 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000249 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000250 const NativeChunk *const chunks =
251 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000252 // make sure magic matches
253 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000254 return make_error_code(native_reader_error::unknown_file_format);
255
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000256 // make sure mapped file contains all needed data
257 const size_t fileSize = mb->getBufferSize();
258 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000259 return make_error_code(native_reader_error::file_too_short);
260
Nick Kledzikabb69812012-05-31 22:34:00 +0000261 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
262 << " Native File Header:"
263 << " fileSize=" << header->fileSize
264 << " chunkCount=" << header->chunkCount
265 << "\n");
266
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000267 // instantiate NativeFile object and add values to it as found
Nick Kledzikabb69812012-05-31 22:34:00 +0000268 std::unique_ptr<File> file(new File(std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000269
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000270 // process each chunk
271 for(uint32_t i=0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000272 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000273 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000274 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000275 if ( chunk->fileOffset > fileSize )
276 return make_error_code(native_reader_error::file_malformed);
277 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
278 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000279 // process chunk, based on signature
280 switch ( chunk->signature ) {
281 case NCS_DefinedAtomsV1:
282 ec = file->processDefinedAtomsV1(base, chunk);
283 break;
284 case NCS_AttributesArrayV1:
285 ec = file->processAttributesV1(base, chunk);
286 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000287 case NCS_UndefinedAtomsV1:
288 ec = file->processUndefinedAtomsV1(base, chunk);
289 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000290 case NCS_SharedLibraryAtomsV1:
291 ec = file->processSharedLibraryAtomsV1(base, chunk);
292 break;
293 case NCS_AbsoluteAtomsV1:
294 ec = file->processAbsoluteAtomsV1(base, chunk);
295 break;
Sid Manning2a590242012-10-18 17:16:19 +0000296 case NCS_AbsoluteAttributesV1:
297 ec = file->processAbsoluteAttributesV1(base, chunk);
298 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000299 case NCS_ReferencesArrayV1:
300 ec = file->processReferencesV1(base, chunk);
301 break;
302 case NCS_TargetsTable:
303 ec = file->processTargetsTable(base, chunk);
304 break;
305 case NCS_AddendsTable:
306 ec = file->processAddendsTable(base, chunk);
307 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000308 case NCS_Content:
309 ec = file->processContent(base, chunk);
310 break;
311 case NCS_Strings:
312 ec = file->processStrings(base, chunk);
313 break;
314 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000315 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000316 }
317 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000318 return ec;
319 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000320 }
321 // TO DO: validate enough chunks were used
322
323 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
324 << " ReaderNative DefinedAtoms:\n");
325 for (const DefinedAtom *a : file->defined() ) {
326 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
327 << llvm::format(" 0x%09lX", a)
328 << ", name=" << a->name()
329 << ", size=" << a->size()
330 << "\n");
331 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000332 (void)r;
333 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000334 << " offset="
335 << llvm::format("0x%03X", r->offsetInAtom())
336 << ", kind=" << r->kind()
337 << ", target=" << r->target()
338 << "\n");
339 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000340 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000341
Nick Kledzikabb69812012-05-31 22:34:00 +0000342 result.push_back(std::move(file));
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000343 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000344 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000345
Nick Kledzikabb69812012-05-31 22:34:00 +0000346 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000347 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000348
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000349 // All other ivar pointers are pointers into the MemoryBuffer, except
350 // the _definedAtoms array which was allocated to contain an array
351 // of Atom objects. The atoms have empty destructors, so it is ok
352 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000353 delete _definedAtoms._arrayStart;
354 delete _undefinedAtoms._arrayStart;
355 delete _sharedLibraryAtoms._arrayStart;
356 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000357 delete _references.arrayStart;
358 delete _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000359 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000360
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000361 virtual const atom_collection<DefinedAtom>& defined() const {
362 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000363 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000364 virtual const atom_collection<UndefinedAtom>& undefined() const {
365 return _undefinedAtoms;
366 }
367 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
368 return _sharedLibraryAtoms;
369 }
370 virtual const atom_collection<AbsoluteAtom>& absolute() const {
371 return _absoluteAtoms;
372 }
373
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000374private:
375 friend class NativeDefinedAtomV1;
Nick Kledzik23384e82012-02-07 02:59:54 +0000376 friend class NativeUndefinedAtomV1;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000377 friend class NativeSharedLibraryAtomV1;
378 friend class NativeAbsoluteAtomV1;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000379 friend class NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000380
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000381 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000382 error_code processDefinedAtomsV1(const uint8_t *base,
383 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000384 const size_t atomSize = sizeof(NativeDefinedAtomV1);
385 size_t atomsArraySize = chunk->elementCount * atomSize;
386 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
387 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000388 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000389 return make_error_code(native_reader_error::memory_error);
390 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000391 / chunk->elementCount;
392 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000393 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000394 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000395 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000396 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
397 (base + chunk->fileOffset);
398 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000399 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000400 reinterpret_cast<NativeDefinedAtomV1*>(s);
401 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
402 ++ivarData;
403 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000404 this->_definedAtoms._arrayStart = atomsStart;
405 this->_definedAtoms._arrayEnd = atomsEnd;
406 this->_definedAtoms._elementSize = atomSize;
407 this->_definedAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000408 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
409 << " chunk DefinedAtomsV1: "
410 << " count=" << chunk->elementCount
411 << " chunkSize=" << chunk->fileSize
412 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000413 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000414 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000415
Nick Kledzikabb69812012-05-31 22:34:00 +0000416
417
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000418 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000419 error_code processAttributesV1(const uint8_t *base,
420 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000421 this->_attributes = base + chunk->fileOffset;
422 this->_attributesMaxOffset = chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000423 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
424 << " chunk AttributesV1: "
425 << " count=" << chunk->elementCount
426 << " chunkSize=" << chunk->fileSize
427 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000428 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000429 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000430
Sid Manning2a590242012-10-18 17:16:19 +0000431 // set up pointers to attributes array
432 error_code processAbsoluteAttributesV1(const uint8_t *base,
433 const NativeChunk *chunk) {
434 this->_absAttributes = base + chunk->fileOffset;
435 this->_absAbsoluteMaxOffset = chunk->fileSize;
436 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
437 << " chunk AbsoluteAttributesV1: "
438 << " count=" << chunk->elementCount
439 << " chunkSize=" << chunk->fileSize
440 << "\n");
441 return make_error_code(native_reader_error::success);
442 }
443
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000444 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000445 error_code processUndefinedAtomsV1(const uint8_t *base,
446 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000447 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
448 size_t atomsArraySize = chunk->elementCount * atomSize;
449 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
450 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000451 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000452 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000453 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000454 / chunk->elementCount;
455 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
456 return make_error_code(native_reader_error::file_malformed);
457 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000458 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000459 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
460 (base + chunk->fileOffset);
461 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000462 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000463 reinterpret_cast<NativeUndefinedAtomV1*>(s);
464 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
465 ++ivarData;
466 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000467 this->_undefinedAtoms._arrayStart = atomsStart;
468 this->_undefinedAtoms._arrayEnd = atomsEnd;
469 this->_undefinedAtoms._elementSize = atomSize;
470 this->_undefinedAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000471 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
472 << " chunk UndefinedAtomsV1:"
473 << " count=" << chunk->elementCount
474 << " chunkSize=" << chunk->fileSize
475 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000476 return make_error_code(native_reader_error::success);
477 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000478
479
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000480 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000481 error_code processSharedLibraryAtomsV1(const uint8_t *base,
482 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000483 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
484 size_t atomsArraySize = chunk->elementCount * atomSize;
485 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
486 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000487 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000488 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000489 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000490 / chunk->elementCount;
491 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
492 return make_error_code(native_reader_error::file_malformed);
493 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000494 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000495 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
496 (base + chunk->fileOffset);
497 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000498 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000499 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
500 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
501 ++ivarData;
502 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000503 this->_sharedLibraryAtoms._arrayStart = atomsStart;
504 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
505 this->_sharedLibraryAtoms._elementSize = atomSize;
506 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000507 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
508 << " chunk SharedLibraryAtomsV1:"
509 << " count=" << chunk->elementCount
510 << " chunkSize=" << chunk->fileSize
511 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000512 return make_error_code(native_reader_error::success);
513 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000514
515
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000516 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000517 error_code processAbsoluteAtomsV1(const uint8_t *base,
518 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000519 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
520 size_t atomsArraySize = chunk->elementCount * atomSize;
521 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
522 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000523 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000524 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000525 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000526 / chunk->elementCount;
527 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
528 return make_error_code(native_reader_error::file_malformed);
529 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000530 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000531 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
532 (base + chunk->fileOffset);
533 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000534 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000535 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
536 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
537 ++ivarData;
538 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000539 this->_absoluteAtoms._arrayStart = atomsStart;
540 this->_absoluteAtoms._arrayEnd = atomsEnd;
541 this->_absoluteAtoms._elementSize = atomSize;
542 this->_absoluteAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000543 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
544 << " chunk AbsoluteAtomsV1: "
545 << " count=" << chunk->elementCount
546 << " chunkSize=" << chunk->fileSize
547 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000548 return make_error_code(native_reader_error::success);
549 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000550
551
552
553
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000554 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000555 error_code processReferencesV1(const uint8_t *base,
556 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000557 if ( chunk->elementCount == 0 )
558 return make_error_code(native_reader_error::success);
559 const size_t refSize = sizeof(NativeReferenceV1);
560 size_t refsArraySize = chunk->elementCount * refSize;
561 uint8_t* refsStart = reinterpret_cast<uint8_t*>
562 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000563 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000564 return make_error_code(native_reader_error::memory_error);
565 const size_t ivarElementSize = chunk->fileSize
566 / chunk->elementCount;
567 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
568 return make_error_code(native_reader_error::file_malformed);
569 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000570 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000571 reinterpret_cast<const NativeReferenceIvarsV1*>
572 (base + chunk->fileOffset);
573 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000574 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000575 reinterpret_cast<NativeReferenceV1*>(s);
576 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
577 ++ivarData;
578 }
579 this->_references.arrayStart = refsStart;
580 this->_references.arrayEnd = refsEnd;
581 this->_references.elementSize = refSize;
582 this->_references.elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000583 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
584 << " chunk ReferencesV1: "
585 << " count=" << chunk->elementCount
586 << " chunkSize=" << chunk->fileSize
587 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000588 return make_error_code(native_reader_error::success);
589 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000590
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000591 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000592 error_code processTargetsTable(const uint8_t *base,
593 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000594 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
595 (base + chunk->fileOffset);
596 this->_targetsTableCount = chunk->elementCount;
597 this->_targetsTable = new const Atom*[chunk->elementCount];
598 for (uint32_t i=0; i < chunk->elementCount; ++i) {
599 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000600 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000601 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000602 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000603 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
604 continue;
605 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000606 const uint32_t undefIndex = index - _definedAtoms._elementCount;
607 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000608 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000609 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000610 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
611 continue;
612 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000613 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000614 - _undefinedAtoms._elementCount;
615 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000616 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000617 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000618 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
619 continue;
620 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000621 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000622 - _undefinedAtoms._elementCount
623 - _sharedLibraryAtoms._elementCount;
624 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000625 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000626 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000627 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
628 continue;
629 }
630 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000631 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000632 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
633 << " chunk Targets Table: "
634 << " count=" << chunk->elementCount
635 << " chunkSize=" << chunk->fileSize
636 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000637 return make_error_code(native_reader_error::success);
638 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000639
640
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000641 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000642 error_code processAddendsTable(const uint8_t *base,
643 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000644 this->_addends = reinterpret_cast<const Reference::Addend*>
645 (base + chunk->fileOffset);
646 this->_addendsMaxIndex = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000647 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
648 << " chunk Addends: "
649 << " count=" << chunk->elementCount
650 << " chunkSize=" << chunk->fileSize
651 << "\n");
Nick Kledzik23384e82012-02-07 02:59:54 +0000652 return make_error_code(native_reader_error::success);
653 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000654
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000655 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000656 error_code processStrings(const uint8_t *base,
657 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000658 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
659 this->_stringsMaxOffset = chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000660 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
661 << " chunk Strings: "
662 << " chunkSize=" << chunk->fileSize
663 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000664 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000665 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000666
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000667 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000668 error_code processContent(const uint8_t *base,
669 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000670 this->_contentStart = base + chunk->fileOffset;
671 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000672 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
673 << " chunk content: "
674 << " chunkSize=" << chunk->fileSize
675 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000676 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000677 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000678
Michael J. Spencere6203a52012-04-03 18:39:40 +0000679 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000680 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000681 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000682 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000683
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000684 Reference::Addend addend(uint32_t index) const {
685 if ( index == 0 )
686 return 0; // addend index zero is used to mean "no addend"
687 assert(index <= _addendsMaxIndex);
688 return _addends[index-1]; // one-based indexing
689 }
690
691 const NativeAtomAttributesV1& attribute(uint32_t off) const {
692 assert(off < _attributesMaxOffset);
693 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000694 }
695
Sid Manning2a590242012-10-18 17:16:19 +0000696 const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
697 assert(off < _absAbsoluteMaxOffset);
698 return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
699 }
700
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000701 const uint8_t* content(uint32_t offset, uint32_t size) const {
702 const uint8_t* result = _contentStart + offset;
703 assert((result+size) <= _contentEnd);
704 return result;
705 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000706
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000707 const Reference* referenceByIndex(uintptr_t index) const {
708 assert(index < _references.elementCount);
709 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
710 return reinterpret_cast<const NativeReferenceV1*>(p);
711 }
712
Nick Kledzikb334be12012-04-07 01:31:00 +0000713 const Atom* target(uint16_t index) const {
714 if ( index == NativeReferenceIvarsV1::noTarget )
715 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000716 assert(index < _targetsTableCount);
717 return _targetsTable[index];
718 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000719
Nick Kledzikb334be12012-04-07 01:31:00 +0000720 void setTarget(uint16_t index, const Atom* newAtom) const {
721 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000722 assert(index > _targetsTableCount);
723 _targetsTable[index] = newAtom;
724 }
Nick Kledzikb334be12012-04-07 01:31:00 +0000725
Michael J. Spencer765792d2012-04-03 18:40:27 +0000726
727
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000728 // private constructor, only called by make()
Nick Kledzikabb69812012-05-31 22:34:00 +0000729 File(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
730 lld::File(path),
731 _buffer(std::move(mb)), // Reader now takes ownership of buffer
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000732 _header(nullptr),
733 _targetsTable(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000734 _targetsTableCount(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000735 _strings(nullptr),
Nick Kledzik23384e82012-02-07 02:59:54 +0000736 _stringsMaxOffset(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000737 _addends(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000738 _addendsMaxIndex(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000739 _contentStart(nullptr),
740 _contentEnd(nullptr)
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000741 {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000742 _header = reinterpret_cast<const NativeFileHeader*>
743 (_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000744 }
745
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000746 template <typename T>
747 class AtomArray : public File::atom_collection<T> {
748 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000749 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000750 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000751
752 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000753 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
754 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000755 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000756 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
757 }
758 virtual const T* deref(const void* it) const {
759 return reinterpret_cast<const T*>(it);
760 }
761 virtual void next(const void*& it) const {
762 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
763 p += _elementSize;
764 it = reinterpret_cast<const void*>(p);
765 }
766 const uint8_t* _arrayStart;
767 const uint8_t* _arrayEnd;
768 uint32_t _elementSize;
769 uint32_t _elementCount;
770 };
771
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000772 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000773 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000774 arrayStart(nullptr),
775 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000776 elementSize(0),
777 elementCount(0) { }
778
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000779 const uint8_t* arrayStart;
780 const uint8_t* arrayEnd;
781 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000782 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000783 };
784
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000785
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000786 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000787 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000788 AtomArray<DefinedAtom> _definedAtoms;
789 AtomArray<UndefinedAtom> _undefinedAtoms;
790 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
791 AtomArray<AbsoluteAtom> _absoluteAtoms;
Sid Manning2a590242012-10-18 17:16:19 +0000792 const uint8_t* _absAttributes;
793 uint32_t _absAbsoluteMaxOffset;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000794 const uint8_t* _attributes;
795 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000796 IvarArray _references;
797 const Atom** _targetsTable;
798 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000799 const char* _strings;
800 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000801 const Reference::Addend* _addends;
802 uint32_t _addendsMaxIndex;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000803 const uint8_t* _contentStart;
804 const uint8_t* _contentEnd;
805};
806
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000807
Nick Kledzikabb69812012-05-31 22:34:00 +0000808inline const class lld::File& NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000809 return *_file;
810}
811
812inline uint64_t NativeDefinedAtomV1:: ordinal() const {
813 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000814 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000815}
816
Michael J. Spencere6203a52012-04-03 18:39:40 +0000817inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000818 return _file->string(_ivarData->nameOffset);
819}
820
821inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
822 return _file->attribute(_ivarData->attributesOffset);
823}
824
Michael J. Spencere6203a52012-04-03 18:39:40 +0000825inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000826 if ( this->contentType() == DefinedAtom::typeZeroFill )
Michael J. Spencere6203a52012-04-03 18:39:40 +0000827 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000828 const uint8_t* p = _file->content(_ivarData->contentOffset,
829 _ivarData->contentSize);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000830 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000831}
832
Michael J. Spencere6203a52012-04-03 18:39:40 +0000833inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000834 uint32_t offset = attributes().sectionNameOffset;
835 return _file->string(offset);
836}
837
Nick Kledzik062a98c2012-04-08 23:52:13 +0000838DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000839 uintptr_t index = _ivarData->referencesStartIndex;
840 const void* it = reinterpret_cast<const void*>(index);
841 return reference_iterator(*this, it);
842}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000843
Nick Kledzik062a98c2012-04-08 23:52:13 +0000844DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000845 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
846 const void* it = reinterpret_cast<const void*>(index);
847 return reference_iterator(*this, it);
848}
849
850const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
851 uintptr_t index = reinterpret_cast<uintptr_t>(it);
852 return _file->referenceByIndex(index);
853}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000854
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000855void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
856 uintptr_t index = reinterpret_cast<uintptr_t>(it);
857 ++index;
858 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000859}
Nick Kledzik23384e82012-02-07 02:59:54 +0000860
Nick Kledzikabb69812012-05-31 22:34:00 +0000861inline const class lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000862 return *_file;
863}
864
Michael J. Spencere6203a52012-04-03 18:39:40 +0000865inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000866 return _file->string(_ivarData->nameOffset);
867}
868
869
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000870
871
Nick Kledzikabb69812012-05-31 22:34:00 +0000872inline const class lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000873 return *_file;
874}
875
Michael J. Spencere6203a52012-04-03 18:39:40 +0000876inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000877 return _file->string(_ivarData->nameOffset);
878}
879
Michael J. Spencere6203a52012-04-03 18:39:40 +0000880inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000881 return _file->string(_ivarData->loadNameOffset);
882}
883
884
885
Nick Kledzikabb69812012-05-31 22:34:00 +0000886inline const class lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000887 return *_file;
888}
889
Michael J. Spencere6203a52012-04-03 18:39:40 +0000890inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000891 return _file->string(_ivarData->nameOffset);
892}
893
Sid Manning2a590242012-10-18 17:16:19 +0000894inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
895 return _file->absAttribute(_ivarData->attributesOffset);
896}
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000897
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000898inline const Atom* NativeReferenceV1::target() const {
899 return _file->target(_ivarData->targetIndex);
900}
901
902inline Reference::Addend NativeReferenceV1::addend() const {
903 return _file->addend(_ivarData->addendIndex);
904}
905
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000906inline void NativeReferenceV1::setKind(Kind k) {
907 this->cloneIvarData();
908 const_cast<NativeReferenceIvarsV1*>(_ivarData)->kind = k;
909}
910
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000911inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
912 return _file->setTarget(_ivarData->targetIndex, newAtom);
913}
Nick Kledzik23384e82012-02-07 02:59:54 +0000914
Nick Kledzikb334be12012-04-07 01:31:00 +0000915inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000916 // Do nothing if addend value is not being changed.
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000917 if (addend() == a)
Nick Kledzikabb69812012-05-31 22:34:00 +0000918 return;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000919 llvm_unreachable("setAddend() not supported");
Nick Kledzikb334be12012-04-07 01:31:00 +0000920}
921
Nick Kledzikabb69812012-05-31 22:34:00 +0000922class Reader : public lld::Reader {
923public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000924 Reader(const TargetInfo &ti)
925 : lld::Reader(ti) {}
Nick Kledzikabb69812012-05-31 22:34:00 +0000926
927 virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
928 std::vector<std::unique_ptr<lld::File>> &result) {
929 return File::make(mb, mb->getBufferIdentifier(), result);
930 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000931};
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000932} // end namespace native
Nick Kledzikabb69812012-05-31 22:34:00 +0000933
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000934std::unique_ptr<Reader> createReaderNative(const TargetInfo &ti) {
935 return std::unique_ptr<Reader>(new lld::native::Reader(ti));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000936}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000937} // end namespace lld