blob: 29935e3d88c92727ce08c81c6071f54cd8812d79 [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
Nick Kledzikabb69812012-05-31 22:34:00 +000010#include "lld/ReaderWriter/ReaderNative.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;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000178
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000179 virtual uint64_t value() const {
180 return _ivarData->value;
181 }
182
183private:
Nick Kledzikabb69812012-05-31 22:34:00 +0000184 const File *_file;
185 const NativeAbsoluteAtomIvarsV1 *_ivarData;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000186};
187
188
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000189
190//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000191// An object of this class is instantied for each NativeReferenceIvarsV1
192// struct in the NCS_ReferencesArrayV1 chunk.
193//
194class NativeReferenceV1 : public Reference {
195public:
Nick Kledzikabb69812012-05-31 22:34:00 +0000196 NativeReferenceV1(const File& f,
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000197 const NativeReferenceIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000198 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000199
200 virtual uint64_t offsetInAtom() const {
201 return _ivarData->offsetInAtom;
202 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000203
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000204 virtual Kind kind() const {
205 return _ivarData->kind;
206 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000207
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000208 virtual void setKind(Kind);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000209 virtual const Atom* target() const;
210 virtual Addend addend() const;
211 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000212 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000213
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000214private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000215 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000216 // since ivar data is mapped read-only.
217 void cloneIvarData() {
218 // TODO: do nothing on second call
219 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000220 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000221 std::nothrow));
222 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
223 }
224
Nick Kledzikabb69812012-05-31 22:34:00 +0000225 const File *_file;
226 const NativeReferenceIvarsV1 *_ivarData;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000227};
228
229
230
231//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000232// lld::File object for native llvm object file
233//
Nick Kledzikabb69812012-05-31 22:34:00 +0000234class File : public lld::File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000235public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000236
237 /// Instantiates a File object from a native object file. Ownership
238 /// of the MemoryBuffer is transfered to the resulting File object.
Nick Kledzikabb69812012-05-31 22:34:00 +0000239 static error_code make(std::unique_ptr<llvm::MemoryBuffer> &mb,
Michael J. Spencere6203a52012-04-03 18:39:40 +0000240 StringRef path,
Nick Kledzikabb69812012-05-31 22:34:00 +0000241 std::vector<std::unique_ptr<lld::File>> &result) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000242 const uint8_t* const base =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000243 reinterpret_cast<const uint8_t*>(mb->getBufferStart());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000244 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000245 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000246 const NativeChunk *const chunks =
247 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000248 // make sure magic matches
249 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000250 return make_error_code(native_reader_error::unknown_file_format);
251
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000252 // make sure mapped file contains all needed data
253 const size_t fileSize = mb->getBufferSize();
254 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000255 return make_error_code(native_reader_error::file_too_short);
256
Nick Kledzikabb69812012-05-31 22:34:00 +0000257 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
258 << " Native File Header:"
259 << " fileSize=" << header->fileSize
260 << " chunkCount=" << header->chunkCount
261 << "\n");
262
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000263 // instantiate NativeFile object and add values to it as found
Nick Kledzikabb69812012-05-31 22:34:00 +0000264 std::unique_ptr<File> file(new File(std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000265
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000266 // process each chunk
267 for(uint32_t i=0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000268 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000269 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000270 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000271 if ( chunk->fileOffset > fileSize )
272 return make_error_code(native_reader_error::file_malformed);
273 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
274 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000275 // process chunk, based on signature
276 switch ( chunk->signature ) {
277 case NCS_DefinedAtomsV1:
278 ec = file->processDefinedAtomsV1(base, chunk);
279 break;
280 case NCS_AttributesArrayV1:
281 ec = file->processAttributesV1(base, chunk);
282 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000283 case NCS_UndefinedAtomsV1:
284 ec = file->processUndefinedAtomsV1(base, chunk);
285 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000286 case NCS_SharedLibraryAtomsV1:
287 ec = file->processSharedLibraryAtomsV1(base, chunk);
288 break;
289 case NCS_AbsoluteAtomsV1:
290 ec = file->processAbsoluteAtomsV1(base, chunk);
291 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000292 case NCS_ReferencesArrayV1:
293 ec = file->processReferencesV1(base, chunk);
294 break;
295 case NCS_TargetsTable:
296 ec = file->processTargetsTable(base, chunk);
297 break;
298 case NCS_AddendsTable:
299 ec = file->processAddendsTable(base, chunk);
300 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000301 case NCS_Content:
302 ec = file->processContent(base, chunk);
303 break;
304 case NCS_Strings:
305 ec = file->processStrings(base, chunk);
306 break;
307 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000308 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000309 }
310 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000311 return ec;
312 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000313 }
314 // TO DO: validate enough chunks were used
315
316 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
317 << " ReaderNative DefinedAtoms:\n");
318 for (const DefinedAtom *a : file->defined() ) {
319 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
320 << llvm::format(" 0x%09lX", a)
321 << ", name=" << a->name()
322 << ", size=" << a->size()
323 << "\n");
324 for (const Reference *r : *a ) {
Michael J. Spencerefcf0992012-06-21 22:41:46 +0000325 (void)r;
326 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
Nick Kledzikabb69812012-05-31 22:34:00 +0000327 << " offset="
328 << llvm::format("0x%03X", r->offsetInAtom())
329 << ", kind=" << r->kind()
330 << ", target=" << r->target()
331 << "\n");
332 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000333 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000334
Nick Kledzikabb69812012-05-31 22:34:00 +0000335 result.push_back(std::move(file));
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000336 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000337 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000338
Nick Kledzikabb69812012-05-31 22:34:00 +0000339 virtual ~File() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000340 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000341
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000342 // All other ivar pointers are pointers into the MemoryBuffer, except
343 // the _definedAtoms array which was allocated to contain an array
344 // of Atom objects. The atoms have empty destructors, so it is ok
345 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000346 delete _definedAtoms._arrayStart;
347 delete _undefinedAtoms._arrayStart;
348 delete _sharedLibraryAtoms._arrayStart;
349 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000350 delete _references.arrayStart;
351 delete _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000352 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000353
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000354 virtual const atom_collection<DefinedAtom>& defined() const {
355 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000356 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000357 virtual const atom_collection<UndefinedAtom>& undefined() const {
358 return _undefinedAtoms;
359 }
360 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
361 return _sharedLibraryAtoms;
362 }
363 virtual const atom_collection<AbsoluteAtom>& absolute() const {
364 return _absoluteAtoms;
365 }
366
367 virtual void addAtom(const Atom&) {
368 assert(0 && "cannot add atoms to native .o files");
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000369 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000370
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000371private:
372 friend class NativeDefinedAtomV1;
Nick Kledzik23384e82012-02-07 02:59:54 +0000373 friend class NativeUndefinedAtomV1;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000374 friend class NativeSharedLibraryAtomV1;
375 friend class NativeAbsoluteAtomV1;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000376 friend class NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000377
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000378 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000379 error_code processDefinedAtomsV1(const uint8_t *base,
380 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000381 const size_t atomSize = sizeof(NativeDefinedAtomV1);
382 size_t atomsArraySize = chunk->elementCount * atomSize;
383 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
384 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000385 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000386 return make_error_code(native_reader_error::memory_error);
387 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000388 / chunk->elementCount;
389 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000390 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000391 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000392 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000393 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
394 (base + chunk->fileOffset);
395 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000396 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000397 reinterpret_cast<NativeDefinedAtomV1*>(s);
398 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
399 ++ivarData;
400 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000401 this->_definedAtoms._arrayStart = atomsStart;
402 this->_definedAtoms._arrayEnd = atomsEnd;
403 this->_definedAtoms._elementSize = atomSize;
404 this->_definedAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000405 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
406 << " chunk DefinedAtomsV1: "
407 << " count=" << chunk->elementCount
408 << " chunkSize=" << chunk->fileSize
409 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000410 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000411 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000412
Nick Kledzikabb69812012-05-31 22:34:00 +0000413
414
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000415 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000416 error_code processAttributesV1(const uint8_t *base,
417 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000418 this->_attributes = base + chunk->fileOffset;
419 this->_attributesMaxOffset = chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000420 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
421 << " chunk AttributesV1: "
422 << " count=" << chunk->elementCount
423 << " chunkSize=" << chunk->fileSize
424 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000425 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000426 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000427
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000428 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000429 error_code processUndefinedAtomsV1(const uint8_t *base,
430 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000431 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
432 size_t atomsArraySize = chunk->elementCount * atomSize;
433 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
434 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000435 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000436 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000437 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000438 / chunk->elementCount;
439 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
440 return make_error_code(native_reader_error::file_malformed);
441 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000442 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000443 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
444 (base + chunk->fileOffset);
445 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000446 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000447 reinterpret_cast<NativeUndefinedAtomV1*>(s);
448 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
449 ++ivarData;
450 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000451 this->_undefinedAtoms._arrayStart = atomsStart;
452 this->_undefinedAtoms._arrayEnd = atomsEnd;
453 this->_undefinedAtoms._elementSize = atomSize;
454 this->_undefinedAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000455 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
456 << " chunk UndefinedAtomsV1:"
457 << " count=" << chunk->elementCount
458 << " chunkSize=" << chunk->fileSize
459 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000460 return make_error_code(native_reader_error::success);
461 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000462
463
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000464 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000465 error_code processSharedLibraryAtomsV1(const uint8_t *base,
466 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000467 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
468 size_t atomsArraySize = chunk->elementCount * atomSize;
469 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
470 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000471 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000472 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000473 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000474 / chunk->elementCount;
475 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
476 return make_error_code(native_reader_error::file_malformed);
477 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000478 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000479 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
480 (base + chunk->fileOffset);
481 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000482 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000483 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
484 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
485 ++ivarData;
486 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000487 this->_sharedLibraryAtoms._arrayStart = atomsStart;
488 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
489 this->_sharedLibraryAtoms._elementSize = atomSize;
490 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000491 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
492 << " chunk SharedLibraryAtomsV1:"
493 << " count=" << chunk->elementCount
494 << " chunkSize=" << chunk->fileSize
495 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000496 return make_error_code(native_reader_error::success);
497 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000498
499
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000500 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000501 error_code processAbsoluteAtomsV1(const uint8_t *base,
502 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000503 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
504 size_t atomsArraySize = chunk->elementCount * atomSize;
505 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
506 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000507 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000508 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000509 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000510 / chunk->elementCount;
511 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
512 return make_error_code(native_reader_error::file_malformed);
513 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000514 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000515 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
516 (base + chunk->fileOffset);
517 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000518 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000519 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
520 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
521 ++ivarData;
522 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000523 this->_absoluteAtoms._arrayStart = atomsStart;
524 this->_absoluteAtoms._arrayEnd = atomsEnd;
525 this->_absoluteAtoms._elementSize = atomSize;
526 this->_absoluteAtoms._elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000527 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
528 << " chunk AbsoluteAtomsV1: "
529 << " count=" << chunk->elementCount
530 << " chunkSize=" << chunk->fileSize
531 << "\n");
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000532 return make_error_code(native_reader_error::success);
533 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000534
535
536
537
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000538 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000539 error_code processReferencesV1(const uint8_t *base,
540 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000541 if ( chunk->elementCount == 0 )
542 return make_error_code(native_reader_error::success);
543 const size_t refSize = sizeof(NativeReferenceV1);
544 size_t refsArraySize = chunk->elementCount * refSize;
545 uint8_t* refsStart = reinterpret_cast<uint8_t*>
546 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000547 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000548 return make_error_code(native_reader_error::memory_error);
549 const size_t ivarElementSize = chunk->fileSize
550 / chunk->elementCount;
551 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
552 return make_error_code(native_reader_error::file_malformed);
553 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000554 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000555 reinterpret_cast<const NativeReferenceIvarsV1*>
556 (base + chunk->fileOffset);
557 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000558 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000559 reinterpret_cast<NativeReferenceV1*>(s);
560 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
561 ++ivarData;
562 }
563 this->_references.arrayStart = refsStart;
564 this->_references.arrayEnd = refsEnd;
565 this->_references.elementSize = refSize;
566 this->_references.elementCount = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000567 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
568 << " chunk ReferencesV1: "
569 << " count=" << chunk->elementCount
570 << " chunkSize=" << chunk->fileSize
571 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000572 return make_error_code(native_reader_error::success);
573 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000574
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000575 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000576 error_code processTargetsTable(const uint8_t *base,
577 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000578 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
579 (base + chunk->fileOffset);
580 this->_targetsTableCount = chunk->elementCount;
581 this->_targetsTable = new const Atom*[chunk->elementCount];
582 for (uint32_t i=0; i < chunk->elementCount; ++i) {
583 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000584 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000585 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000586 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000587 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
588 continue;
589 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000590 const uint32_t undefIndex = index - _definedAtoms._elementCount;
591 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000592 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000593 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000594 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
595 continue;
596 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000597 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000598 - _undefinedAtoms._elementCount;
599 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000600 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000601 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000602 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
603 continue;
604 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000605 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000606 - _undefinedAtoms._elementCount
607 - _sharedLibraryAtoms._elementCount;
608 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000609 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000610 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000611 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
612 continue;
613 }
614 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000615 }
Nick Kledzikabb69812012-05-31 22:34:00 +0000616 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
617 << " chunk Targets Table: "
618 << " count=" << chunk->elementCount
619 << " chunkSize=" << chunk->fileSize
620 << "\n");
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000621 return make_error_code(native_reader_error::success);
622 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000623
624
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000625 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000626 error_code processAddendsTable(const uint8_t *base,
627 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000628 this->_addends = reinterpret_cast<const Reference::Addend*>
629 (base + chunk->fileOffset);
630 this->_addendsMaxIndex = chunk->elementCount;
Nick Kledzikabb69812012-05-31 22:34:00 +0000631 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
632 << " chunk Addends: "
633 << " count=" << chunk->elementCount
634 << " chunkSize=" << chunk->fileSize
635 << "\n");
Nick Kledzik23384e82012-02-07 02:59:54 +0000636 return make_error_code(native_reader_error::success);
637 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000638
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000639 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000640 error_code processStrings(const uint8_t *base,
641 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000642 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
643 this->_stringsMaxOffset = chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000644 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
645 << " chunk Strings: "
646 << " chunkSize=" << chunk->fileSize
647 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000648 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000649 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000650
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000651 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000652 error_code processContent(const uint8_t *base,
653 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000654 this->_contentStart = base + chunk->fileOffset;
655 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Nick Kledzikabb69812012-05-31 22:34:00 +0000656 DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
657 << " chunk content: "
658 << " chunkSize=" << chunk->fileSize
659 << "\n");
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000660 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000661 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000662
Michael J. Spencere6203a52012-04-03 18:39:40 +0000663 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000664 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000665 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000666 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000667
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000668 Reference::Addend addend(uint32_t index) const {
669 if ( index == 0 )
670 return 0; // addend index zero is used to mean "no addend"
671 assert(index <= _addendsMaxIndex);
672 return _addends[index-1]; // one-based indexing
673 }
674
675 const NativeAtomAttributesV1& attribute(uint32_t off) const {
676 assert(off < _attributesMaxOffset);
677 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000678 }
679
680 const uint8_t* content(uint32_t offset, uint32_t size) const {
681 const uint8_t* result = _contentStart + offset;
682 assert((result+size) <= _contentEnd);
683 return result;
684 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000685
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000686 const Reference* referenceByIndex(uintptr_t index) const {
687 assert(index < _references.elementCount);
688 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
689 return reinterpret_cast<const NativeReferenceV1*>(p);
690 }
691
Nick Kledzikb334be12012-04-07 01:31:00 +0000692 const Atom* target(uint16_t index) const {
693 if ( index == NativeReferenceIvarsV1::noTarget )
694 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000695 assert(index < _targetsTableCount);
696 return _targetsTable[index];
697 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000698
Nick Kledzikb334be12012-04-07 01:31:00 +0000699 void setTarget(uint16_t index, const Atom* newAtom) const {
700 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000701 assert(index > _targetsTableCount);
702 _targetsTable[index] = newAtom;
703 }
Nick Kledzikb334be12012-04-07 01:31:00 +0000704
Michael J. Spencer765792d2012-04-03 18:40:27 +0000705
706
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000707 // private constructor, only called by make()
Nick Kledzikabb69812012-05-31 22:34:00 +0000708 File(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
709 lld::File(path),
710 _buffer(std::move(mb)), // Reader now takes ownership of buffer
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000711 _header(nullptr),
712 _targetsTable(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000713 _targetsTableCount(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000714 _strings(nullptr),
Nick Kledzik23384e82012-02-07 02:59:54 +0000715 _stringsMaxOffset(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000716 _addends(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000717 _addendsMaxIndex(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000718 _contentStart(nullptr),
719 _contentEnd(nullptr)
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000720 {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000721 _header = reinterpret_cast<const NativeFileHeader*>
722 (_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000723 }
724
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000725 template <typename T>
726 class AtomArray : public File::atom_collection<T> {
727 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000728 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000729 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000730
731 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000732 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
733 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000734 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000735 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
736 }
737 virtual const T* deref(const void* it) const {
738 return reinterpret_cast<const T*>(it);
739 }
740 virtual void next(const void*& it) const {
741 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
742 p += _elementSize;
743 it = reinterpret_cast<const void*>(p);
744 }
745 const uint8_t* _arrayStart;
746 const uint8_t* _arrayEnd;
747 uint32_t _elementSize;
748 uint32_t _elementCount;
749 };
750
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000751 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000752 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000753 arrayStart(nullptr),
754 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000755 elementSize(0),
756 elementCount(0) { }
757
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000758 const uint8_t* arrayStart;
759 const uint8_t* arrayEnd;
760 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000761 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000762 };
763
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000764
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000765 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000766 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000767 AtomArray<DefinedAtom> _definedAtoms;
768 AtomArray<UndefinedAtom> _undefinedAtoms;
769 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
770 AtomArray<AbsoluteAtom> _absoluteAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000771 const uint8_t* _attributes;
772 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000773 IvarArray _references;
774 const Atom** _targetsTable;
775 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000776 const char* _strings;
777 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000778 const Reference::Addend* _addends;
779 uint32_t _addendsMaxIndex;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000780 const uint8_t* _contentStart;
781 const uint8_t* _contentEnd;
782};
783
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000784
Nick Kledzikabb69812012-05-31 22:34:00 +0000785inline const class lld::File& NativeDefinedAtomV1::file() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000786 return *_file;
787}
788
789inline uint64_t NativeDefinedAtomV1:: ordinal() const {
790 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000791 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000792}
793
Michael J. Spencere6203a52012-04-03 18:39:40 +0000794inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000795 return _file->string(_ivarData->nameOffset);
796}
797
798inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
799 return _file->attribute(_ivarData->attributesOffset);
800}
801
Michael J. Spencere6203a52012-04-03 18:39:40 +0000802inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000803 if ( this->contentType() == DefinedAtom::typeZeroFill )
Michael J. Spencere6203a52012-04-03 18:39:40 +0000804 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000805 const uint8_t* p = _file->content(_ivarData->contentOffset,
806 _ivarData->contentSize);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000807 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000808}
809
Michael J. Spencere6203a52012-04-03 18:39:40 +0000810inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000811 uint32_t offset = attributes().sectionNameOffset;
812 return _file->string(offset);
813}
814
Nick Kledzik062a98c2012-04-08 23:52:13 +0000815DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000816 uintptr_t index = _ivarData->referencesStartIndex;
817 const void* it = reinterpret_cast<const void*>(index);
818 return reference_iterator(*this, it);
819}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000820
Nick Kledzik062a98c2012-04-08 23:52:13 +0000821DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000822 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
823 const void* it = reinterpret_cast<const void*>(index);
824 return reference_iterator(*this, it);
825}
826
827const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
828 uintptr_t index = reinterpret_cast<uintptr_t>(it);
829 return _file->referenceByIndex(index);
830}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000831
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000832void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
833 uintptr_t index = reinterpret_cast<uintptr_t>(it);
834 ++index;
835 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000836}
Nick Kledzik23384e82012-02-07 02:59:54 +0000837
Nick Kledzikabb69812012-05-31 22:34:00 +0000838inline const class lld::File& NativeUndefinedAtomV1::file() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000839 return *_file;
840}
841
Michael J. Spencere6203a52012-04-03 18:39:40 +0000842inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000843 return _file->string(_ivarData->nameOffset);
844}
845
846
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000847
848
Nick Kledzikabb69812012-05-31 22:34:00 +0000849inline const class lld::File& NativeSharedLibraryAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000850 return *_file;
851}
852
Michael J. Spencere6203a52012-04-03 18:39:40 +0000853inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000854 return _file->string(_ivarData->nameOffset);
855}
856
Michael J. Spencere6203a52012-04-03 18:39:40 +0000857inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000858 return _file->string(_ivarData->loadNameOffset);
859}
860
861
862
Nick Kledzikabb69812012-05-31 22:34:00 +0000863inline const class lld::File& NativeAbsoluteAtomV1::file() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000864 return *_file;
865}
866
Michael J. Spencere6203a52012-04-03 18:39:40 +0000867inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000868 return _file->string(_ivarData->nameOffset);
869}
870
871
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000872inline const Atom* NativeReferenceV1::target() const {
873 return _file->target(_ivarData->targetIndex);
874}
875
876inline Reference::Addend NativeReferenceV1::addend() const {
877 return _file->addend(_ivarData->addendIndex);
878}
879
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000880inline void NativeReferenceV1::setKind(Kind k) {
881 this->cloneIvarData();
882 const_cast<NativeReferenceIvarsV1*>(_ivarData)->kind = k;
883}
884
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000885inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
886 return _file->setTarget(_ivarData->targetIndex, newAtom);
887}
Nick Kledzik23384e82012-02-07 02:59:54 +0000888
Nick Kledzikb334be12012-04-07 01:31:00 +0000889inline void NativeReferenceV1::setAddend(Addend a) {
Nick Kledzikabb69812012-05-31 22:34:00 +0000890 // Do nothing if addend value is not being changed.
891 if ( this->addend() == a )
892 return;
Nick Kledzikb334be12012-04-07 01:31:00 +0000893 assert(0 && "setAddend() not supported");
894}
895
Nick Kledzik23384e82012-02-07 02:59:54 +0000896
Nick Kledzikabb69812012-05-31 22:34:00 +0000897class Reader : public lld::Reader {
898public:
899 Reader(const ReaderOptionsNative &options) : _options(options) {
900 }
901
902 virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
903 std::vector<std::unique_ptr<lld::File>> &result) {
904 return File::make(mb, mb->getBufferIdentifier(), result);
905 }
906
907private:
908 const ReaderOptionsNative &_options;
909};
910
911
912
913} // namespace native
914
915Reader* createReaderNative(const ReaderOptionsNative &options) {
916 return new lld::native::Reader(options);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000917}
918
Nick Kledzikabb69812012-05-31 22:34:00 +0000919ReaderOptionsNative::ReaderOptionsNative() {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000920}
921
Nick Kledzikabb69812012-05-31 22:34:00 +0000922ReaderOptionsNative::~ReaderOptionsNative() {
923}
924
925
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000926} // namespace lld
Nick Kledzikabb69812012-05-31 22:34:00 +0000927
928
929
930