blob: 01466d3e87e73fa9ea49c9f03305b95513e954ac [file] [log] [blame]
Nick Kledzik55fd6be2012-01-16 22:03:44 +00001//===- Core/NativeReader.cpp - reads native object file ------------------===//
2//
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. Spencercfd029f2012-03-28 19:04:02 +000010#include "NativeFileFormat.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"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/MemoryBuffer.h"
Nick Kledzik55fd6be2012-01-16 22:03:44 +000021
Michael J. Spencercfd029f2012-03-28 19:04:02 +000022#include <vector>
Nick Kledzikb334be12012-04-07 01:31:00 +000023#include <memory>
Nick Kledzik55fd6be2012-01-16 22:03:44 +000024
25namespace lld {
26
27// forward reference
28class NativeFile;
29
Nick Kledzik55fd6be2012-01-16 22:03:44 +000030//
31// An object of this class is instantied for each NativeDefinedAtomIvarsV1
32// struct in the NCS_DefinedAtomsV1 chunk.
33//
34class NativeDefinedAtomV1 : public DefinedAtom {
35public:
Michael J. Spencer765792d2012-04-03 18:40:27 +000036 NativeDefinedAtomV1(const NativeFile& f,
Nick Kledzik55fd6be2012-01-16 22:03:44 +000037 const NativeDefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +000038 : _file(&f), _ivarData(ivarData) { }
39
Nick Kledzik55fd6be2012-01-16 22:03:44 +000040 virtual const class File& file() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000041
42 virtual uint64_t ordinal() const;
43
Michael J. Spencere6203a52012-04-03 18:39:40 +000044 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000045
Nick Kledzik55fd6be2012-01-16 22:03:44 +000046 virtual uint64_t size() const {
47 return _ivarData->contentSize;
48 }
49
50 virtual DefinedAtom::Scope scope() const {
51 return (DefinedAtom::Scope)(attributes().scope);
52 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000053
Nick Kledzik55fd6be2012-01-16 22:03:44 +000054 virtual DefinedAtom::Interposable interposable() const {
55 return (DefinedAtom::Interposable)(attributes().interposable);
56 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000057
Nick Kledzik55fd6be2012-01-16 22:03:44 +000058 virtual DefinedAtom::Merge merge() const {
59 return (DefinedAtom::Merge)(attributes().merge);
60 }
61
62 virtual DefinedAtom::ContentType contentType() const {
Nick Kledzik23384e82012-02-07 02:59:54 +000063 const NativeAtomAttributesV1& attr = attributes();
64 return (DefinedAtom::ContentType)(attr.contentType);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000065 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000066
Nick Kledzik55fd6be2012-01-16 22:03:44 +000067 virtual DefinedAtom::Alignment alignment() const {
68 return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
69 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000070
Nick Kledzik55fd6be2012-01-16 22:03:44 +000071 virtual DefinedAtom::SectionChoice sectionChoice() const {
72 return (DefinedAtom::SectionChoice)(attributes().sectionChoice);
73 }
74
Michael J. Spencere6203a52012-04-03 18:39:40 +000075 virtual StringRef customSectionName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000076
Nick Kledzik55fd6be2012-01-16 22:03:44 +000077 virtual DefinedAtom::DeadStripKind deadStrip() const {
78 return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
Nick Kledzik6bc04c62012-02-22 21:56:59 +000079 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000080
Nick Kledzik55fd6be2012-01-16 22:03:44 +000081 virtual DefinedAtom::ContentPermissions permissions() const {
82 return (DefinedAtom::ContentPermissions)(attributes().permissions);
83 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000084
Nick Kledzik55fd6be2012-01-16 22:03:44 +000085 virtual bool isThumb() const {
Nick Kledzik49d6cc82012-02-15 00:38:09 +000086 return false; //(attributes().thumb != 0);
Nick Kledzik55fd6be2012-01-16 22:03:44 +000087 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000088
Nick Kledzik55fd6be2012-01-16 22:03:44 +000089 virtual bool isAlias() const {
90 return (attributes().alias != 0);
91 }
Michael J. Spencer765792d2012-04-03 18:40:27 +000092
Michael J. Spencere6203a52012-04-03 18:39:40 +000093 virtual ArrayRef<uint8_t> rawContent() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000094
Nick Kledzik1a6615d2012-03-08 00:18:30 +000095 virtual reference_iterator referencesBegin() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +000096
Nick Kledzik1a6615d2012-03-08 00:18:30 +000097 virtual reference_iterator referencesEnd() const;
98
99 virtual const Reference* derefIterator(const void*) const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000100
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000101 virtual void incrementIterator(const void*& it) const;
102
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000103private:
104 const NativeAtomAttributesV1& attributes() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000105
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000106 const NativeFile* _file;
107 const NativeDefinedAtomIvarsV1* _ivarData;
108};
109
110
111
Nick Kledzik23384e82012-02-07 02:59:54 +0000112//
113// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
114// struct in the NCS_UndefinedAtomsV1 chunk.
115//
116class NativeUndefinedAtomV1 : public UndefinedAtom {
117public:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000118 NativeUndefinedAtomV1(const NativeFile& f,
Nick Kledzik23384e82012-02-07 02:59:54 +0000119 const NativeUndefinedAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000120 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik23384e82012-02-07 02:59:54 +0000121
122 virtual const File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000123 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000124
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000125 virtual CanBeNull canBeNull() const {
126 return (CanBeNull)(_ivarData->flags & 0x3);
Nick Kledzik23384e82012-02-07 02:59:54 +0000127 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000128
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000129
Nick Kledzik23384e82012-02-07 02:59:54 +0000130private:
131 const NativeFile* _file;
132 const NativeUndefinedAtomIvarsV1* _ivarData;
133};
134
135
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000136//
137// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
138// struct in the NCS_SharedLibraryAtomsV1 chunk.
139//
140class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
141public:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000142 NativeSharedLibraryAtomV1(const NativeFile& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000143 const NativeSharedLibraryAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000144 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000145
146 virtual const File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000147 virtual StringRef name() const;
148 virtual StringRef loadName() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000149
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000150 virtual bool canBeNullAtRuntime() const {
151 return (_ivarData->flags & 0x1);
152 }
153
154private:
155 const NativeFile* _file;
156 const NativeSharedLibraryAtomIvarsV1* _ivarData;
157};
158
159
160//
161// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
162// struct in the NCS_AbsoluteAtomsV1 chunk.
163//
164class NativeAbsoluteAtomV1 : public AbsoluteAtom {
165public:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000166 NativeAbsoluteAtomV1(const NativeFile& f,
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000167 const NativeAbsoluteAtomIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000168 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000169
170 virtual const File& file() const;
Michael J. Spencere6203a52012-04-03 18:39:40 +0000171 virtual StringRef name() const;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000172
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000173 virtual uint64_t value() const {
174 return _ivarData->value;
175 }
176
177private:
178 const NativeFile* _file;
179 const NativeAbsoluteAtomIvarsV1* _ivarData;
180};
181
182
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000183
184//
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000185// An object of this class is instantied for each NativeReferenceIvarsV1
186// struct in the NCS_ReferencesArrayV1 chunk.
187//
188class NativeReferenceV1 : public Reference {
189public:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000190 NativeReferenceV1(const NativeFile& f,
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000191 const NativeReferenceIvarsV1* ivarData)
Michael J. Spencer765792d2012-04-03 18:40:27 +0000192 : _file(&f), _ivarData(ivarData) { }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000193
194 virtual uint64_t offsetInAtom() const {
195 return _ivarData->offsetInAtom;
196 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000197
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000198 virtual Kind kind() const {
199 return _ivarData->kind;
200 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000201
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000202 virtual void setKind(Kind);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000203 virtual const Atom* target() const;
204 virtual Addend addend() const;
205 virtual void setTarget(const Atom* newAtom);
Nick Kledzikb334be12012-04-07 01:31:00 +0000206 virtual void setAddend(Addend a);
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000207
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000208private:
Michael J. Spencer765792d2012-04-03 18:40:27 +0000209 // Used in rare cases when Reference is modified,
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000210 // since ivar data is mapped read-only.
211 void cloneIvarData() {
212 // TODO: do nothing on second call
213 NativeReferenceIvarsV1* niv = reinterpret_cast<NativeReferenceIvarsV1*>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000214 (operator new(sizeof(NativeReferenceIvarsV1),
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000215 std::nothrow));
216 memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
217 }
218
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000219 const NativeFile* _file;
220 const NativeReferenceIvarsV1* _ivarData;
221};
222
223
224
225//
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000226// lld::File object for native llvm object file
227//
228class NativeFile : public File {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000229public:
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000230
231 /// Instantiates a File object from a native object file. Ownership
232 /// of the MemoryBuffer is transfered to the resulting File object.
Michael J. Spencere6203a52012-04-03 18:39:40 +0000233 static error_code make(std::unique_ptr<llvm::MemoryBuffer> mb,
234 StringRef path,
235 std::unique_ptr<File> &result) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000236 const uint8_t* const base =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000237 reinterpret_cast<const uint8_t*>(mb->getBufferStart());
Michael J. Spencer765792d2012-04-03 18:40:27 +0000238 const NativeFileHeader* const header =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000239 reinterpret_cast<const NativeFileHeader*>(base);
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000240 const NativeChunk *const chunks =
241 reinterpret_cast<const NativeChunk*>(base + sizeof(NativeFileHeader));
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000242 // make sure magic matches
243 if ( memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 16) != 0 )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000244 return make_error_code(native_reader_error::unknown_file_format);
245
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000246 // make sure mapped file contains all needed data
247 const size_t fileSize = mb->getBufferSize();
248 if ( header->fileSize > fileSize )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000249 return make_error_code(native_reader_error::file_too_short);
250
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000251 // instantiate NativeFile object and add values to it as found
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000252 std::unique_ptr<NativeFile> file(new NativeFile(std::move(mb), path));
Michael J. Spencer765792d2012-04-03 18:40:27 +0000253
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000254 // process each chunk
255 for(uint32_t i=0; i < header->chunkCount; ++i) {
Michael J. Spencere6203a52012-04-03 18:39:40 +0000256 error_code ec;
Michael J. Spencerb2bd7332012-01-31 21:45:53 +0000257 const NativeChunk* chunk = &chunks[i];
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000258 // sanity check chunk is within file
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000259 if ( chunk->fileOffset > fileSize )
260 return make_error_code(native_reader_error::file_malformed);
261 if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
262 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000263 // process chunk, based on signature
264 switch ( chunk->signature ) {
265 case NCS_DefinedAtomsV1:
266 ec = file->processDefinedAtomsV1(base, chunk);
267 break;
268 case NCS_AttributesArrayV1:
269 ec = file->processAttributesV1(base, chunk);
270 break;
Nick Kledzik23384e82012-02-07 02:59:54 +0000271 case NCS_UndefinedAtomsV1:
272 ec = file->processUndefinedAtomsV1(base, chunk);
273 break;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000274 case NCS_SharedLibraryAtomsV1:
275 ec = file->processSharedLibraryAtomsV1(base, chunk);
276 break;
277 case NCS_AbsoluteAtomsV1:
278 ec = file->processAbsoluteAtomsV1(base, chunk);
279 break;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000280 case NCS_ReferencesArrayV1:
281 ec = file->processReferencesV1(base, chunk);
282 break;
283 case NCS_TargetsTable:
284 ec = file->processTargetsTable(base, chunk);
285 break;
286 case NCS_AddendsTable:
287 ec = file->processAddendsTable(base, chunk);
288 break;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000289 case NCS_Content:
290 ec = file->processContent(base, chunk);
291 break;
292 case NCS_Strings:
293 ec = file->processStrings(base, chunk);
294 break;
295 default:
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000296 return make_error_code(native_reader_error::unknown_chunk_type);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000297 }
298 if ( ec ) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000299 return ec;
300 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000301 // TO DO: validate enough chunks were used
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000302 }
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000303
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000304 result.reset(file.release());
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000305 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000306 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000307
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000308 virtual ~NativeFile() {
Nick Kledzik23384e82012-02-07 02:59:54 +0000309 // _buffer is automatically deleted because of OwningPtr<>
Michael J. Spencer765792d2012-04-03 18:40:27 +0000310
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000311 // All other ivar pointers are pointers into the MemoryBuffer, except
312 // the _definedAtoms array which was allocated to contain an array
313 // of Atom objects. The atoms have empty destructors, so it is ok
314 // to just delete the memory.
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000315 delete _definedAtoms._arrayStart;
316 delete _undefinedAtoms._arrayStart;
317 delete _sharedLibraryAtoms._arrayStart;
318 delete _absoluteAtoms._arrayStart;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000319 delete _references.arrayStart;
320 delete _targetsTable;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000321 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000322
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000323 virtual const atom_collection<DefinedAtom>& defined() const {
324 return _definedAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000325 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000326 virtual const atom_collection<UndefinedAtom>& undefined() const {
327 return _undefinedAtoms;
328 }
329 virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
330 return _sharedLibraryAtoms;
331 }
332 virtual const atom_collection<AbsoluteAtom>& absolute() const {
333 return _absoluteAtoms;
334 }
335
336 virtual void addAtom(const Atom&) {
337 assert(0 && "cannot add atoms to native .o files");
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000338 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000339
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000340private:
341 friend class NativeDefinedAtomV1;
Nick Kledzik23384e82012-02-07 02:59:54 +0000342 friend class NativeUndefinedAtomV1;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000343 friend class NativeSharedLibraryAtomV1;
344 friend class NativeAbsoluteAtomV1;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000345 friend class NativeReferenceV1;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000346
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000347 // instantiate array of DefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000348 error_code processDefinedAtomsV1(const uint8_t *base,
349 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000350 const size_t atomSize = sizeof(NativeDefinedAtomV1);
351 size_t atomsArraySize = chunk->elementCount * atomSize;
352 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
353 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000354 if (atomsStart == nullptr)
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000355 return make_error_code(native_reader_error::memory_error);
356 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000357 / chunk->elementCount;
358 if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000359 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000360 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000361 const NativeDefinedAtomIvarsV1* ivarData =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000362 reinterpret_cast<const NativeDefinedAtomIvarsV1*>
363 (base + chunk->fileOffset);
364 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000365 NativeDefinedAtomV1* atomAllocSpace =
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000366 reinterpret_cast<NativeDefinedAtomV1*>(s);
367 new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
368 ++ivarData;
369 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000370 this->_definedAtoms._arrayStart = atomsStart;
371 this->_definedAtoms._arrayEnd = atomsEnd;
372 this->_definedAtoms._elementSize = atomSize;
373 this->_definedAtoms._elementCount = chunk->elementCount;
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000374 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000375 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000376
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000377 // set up pointers to attributes array
Michael J. Spencere6203a52012-04-03 18:39:40 +0000378 error_code processAttributesV1(const uint8_t *base,
379 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000380 this->_attributes = base + chunk->fileOffset;
381 this->_attributesMaxOffset = chunk->fileSize;
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000382 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000383 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000384
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000385 // instantiate array of UndefinedAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000386 error_code processUndefinedAtomsV1(const uint8_t *base,
387 const NativeChunk *chunk) {
Nick Kledzik23384e82012-02-07 02:59:54 +0000388 const size_t atomSize = sizeof(NativeUndefinedAtomV1);
389 size_t atomsArraySize = chunk->elementCount * atomSize;
390 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
391 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000392 if (atomsStart == nullptr)
Nick Kledzik23384e82012-02-07 02:59:54 +0000393 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000394 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik23384e82012-02-07 02:59:54 +0000395 / chunk->elementCount;
396 if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
397 return make_error_code(native_reader_error::file_malformed);
398 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000399 const NativeUndefinedAtomIvarsV1* ivarData =
Nick Kledzik23384e82012-02-07 02:59:54 +0000400 reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
401 (base + chunk->fileOffset);
402 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000403 NativeUndefinedAtomV1* atomAllocSpace =
Nick Kledzik23384e82012-02-07 02:59:54 +0000404 reinterpret_cast<NativeUndefinedAtomV1*>(s);
405 new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
406 ++ivarData;
407 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000408 this->_undefinedAtoms._arrayStart = atomsStart;
409 this->_undefinedAtoms._arrayEnd = atomsEnd;
410 this->_undefinedAtoms._elementSize = atomSize;
411 this->_undefinedAtoms._elementCount = chunk->elementCount;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000412 return make_error_code(native_reader_error::success);
413 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000414
415
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000416 // instantiate array of ShareLibraryAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000417 error_code processSharedLibraryAtomsV1(const uint8_t *base,
418 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000419 const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
420 size_t atomsArraySize = chunk->elementCount * atomSize;
421 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
422 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000423 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000424 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000425 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000426 / chunk->elementCount;
427 if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
428 return make_error_code(native_reader_error::file_malformed);
429 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000430 const NativeSharedLibraryAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000431 reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
432 (base + chunk->fileOffset);
433 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000434 NativeSharedLibraryAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000435 reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
436 new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
437 ++ivarData;
438 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000439 this->_sharedLibraryAtoms._arrayStart = atomsStart;
440 this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
441 this->_sharedLibraryAtoms._elementSize = atomSize;
442 this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000443 return make_error_code(native_reader_error::success);
444 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000445
446
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000447 // instantiate array of AbsoluteAtoms from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000448 error_code processAbsoluteAtomsV1(const uint8_t *base,
449 const NativeChunk *chunk) {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000450 const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
451 size_t atomsArraySize = chunk->elementCount * atomSize;
452 uint8_t* atomsStart = reinterpret_cast<uint8_t*>
453 (operator new(atomsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000454 if (atomsStart == nullptr)
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000455 return make_error_code(native_reader_error::memory_error);
Michael J. Spencer765792d2012-04-03 18:40:27 +0000456 const size_t ivarElementSize = chunk->fileSize
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000457 / chunk->elementCount;
458 if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
459 return make_error_code(native_reader_error::file_malformed);
460 uint8_t* atomsEnd = atomsStart + atomsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000461 const NativeAbsoluteAtomIvarsV1* ivarData =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000462 reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
463 (base + chunk->fileOffset);
464 for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000465 NativeAbsoluteAtomV1* atomAllocSpace =
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000466 reinterpret_cast<NativeAbsoluteAtomV1*>(s);
467 new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
468 ++ivarData;
469 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000470 this->_absoluteAtoms._arrayStart = atomsStart;
471 this->_absoluteAtoms._arrayEnd = atomsEnd;
472 this->_absoluteAtoms._elementSize = atomSize;
473 this->_absoluteAtoms._elementCount = chunk->elementCount;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000474 return make_error_code(native_reader_error::success);
475 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000476
477
478
479
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000480 // instantiate array of Referemces from v1 ivar data in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000481 error_code processReferencesV1(const uint8_t *base,
482 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000483 if ( chunk->elementCount == 0 )
484 return make_error_code(native_reader_error::success);
485 const size_t refSize = sizeof(NativeReferenceV1);
486 size_t refsArraySize = chunk->elementCount * refSize;
487 uint8_t* refsStart = reinterpret_cast<uint8_t*>
488 (operator new(refsArraySize, std::nothrow));
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000489 if (refsStart == nullptr)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000490 return make_error_code(native_reader_error::memory_error);
491 const size_t ivarElementSize = chunk->fileSize
492 / chunk->elementCount;
493 if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )
494 return make_error_code(native_reader_error::file_malformed);
495 uint8_t* refsEnd = refsStart + refsArraySize;
Michael J. Spencer765792d2012-04-03 18:40:27 +0000496 const NativeReferenceIvarsV1* ivarData =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000497 reinterpret_cast<const NativeReferenceIvarsV1*>
498 (base + chunk->fileOffset);
499 for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000500 NativeReferenceV1* atomAllocSpace =
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000501 reinterpret_cast<NativeReferenceV1*>(s);
502 new (atomAllocSpace) NativeReferenceV1(*this, ivarData);
503 ++ivarData;
504 }
505 this->_references.arrayStart = refsStart;
506 this->_references.arrayEnd = refsEnd;
507 this->_references.elementSize = refSize;
508 this->_references.elementCount = chunk->elementCount;
509 return make_error_code(native_reader_error::success);
510 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000511
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000512 // set up pointers to target table
Michael J. Spencere6203a52012-04-03 18:39:40 +0000513 error_code processTargetsTable(const uint8_t *base,
514 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000515 const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
516 (base + chunk->fileOffset);
517 this->_targetsTableCount = chunk->elementCount;
518 this->_targetsTable = new const Atom*[chunk->elementCount];
519 for (uint32_t i=0; i < chunk->elementCount; ++i) {
520 const uint32_t index = targetIndexes[i];
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000521 if ( index < _definedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000522 const uint8_t* p = _definedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000523 + index * _definedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000524 this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
525 continue;
526 }
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000527 const uint32_t undefIndex = index - _definedAtoms._elementCount;
528 if ( undefIndex < _undefinedAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000529 const uint8_t* p = _undefinedAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000530 + undefIndex * _undefinedAtoms._elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000531 this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
532 continue;
533 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000534 const uint32_t slIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000535 - _undefinedAtoms._elementCount;
536 if ( slIndex < _sharedLibraryAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000537 const uint8_t* p = _sharedLibraryAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000538 + slIndex * _sharedLibraryAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000539 this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
540 continue;
541 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000542 const uint32_t abIndex = index - _definedAtoms._elementCount
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000543 - _undefinedAtoms._elementCount
544 - _sharedLibraryAtoms._elementCount;
545 if ( abIndex < _absoluteAtoms._elementCount ) {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000546 const uint8_t* p = _absoluteAtoms._arrayStart
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000547 + slIndex * _absoluteAtoms._elementSize;
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000548 this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
549 continue;
550 }
551 return make_error_code(native_reader_error::file_malformed);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000552 }
553 return make_error_code(native_reader_error::success);
554 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000555
556
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000557 // set up pointers to addend pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000558 error_code processAddendsTable(const uint8_t *base,
559 const NativeChunk *chunk) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000560 this->_addends = reinterpret_cast<const Reference::Addend*>
561 (base + chunk->fileOffset);
562 this->_addendsMaxIndex = chunk->elementCount;
Nick Kledzik23384e82012-02-07 02:59:54 +0000563 return make_error_code(native_reader_error::success);
564 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000565
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000566 // set up pointers to string pool in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000567 error_code processStrings(const uint8_t *base,
568 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000569 this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
570 this->_stringsMaxOffset = chunk->fileSize;
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000571 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000572 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000573
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000574 // set up pointers to content area in file
Michael J. Spencere6203a52012-04-03 18:39:40 +0000575 error_code processContent(const uint8_t *base,
576 const NativeChunk *chunk) {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000577 this->_contentStart = base + chunk->fileOffset;
578 this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000579 return make_error_code(native_reader_error::success);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000580 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000581
Michael J. Spencere6203a52012-04-03 18:39:40 +0000582 StringRef string(uint32_t offset) const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000583 assert(offset < _stringsMaxOffset);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000584 return StringRef(&_strings[offset]);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000585 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000586
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000587 Reference::Addend addend(uint32_t index) const {
588 if ( index == 0 )
589 return 0; // addend index zero is used to mean "no addend"
590 assert(index <= _addendsMaxIndex);
591 return _addends[index-1]; // one-based indexing
592 }
593
594 const NativeAtomAttributesV1& attribute(uint32_t off) const {
595 assert(off < _attributesMaxOffset);
596 return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000597 }
598
599 const uint8_t* content(uint32_t offset, uint32_t size) const {
600 const uint8_t* result = _contentStart + offset;
601 assert((result+size) <= _contentEnd);
602 return result;
603 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000604
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000605 const Reference* referenceByIndex(uintptr_t index) const {
606 assert(index < _references.elementCount);
607 const uint8_t* p = _references.arrayStart + index * _references.elementSize;
608 return reinterpret_cast<const NativeReferenceV1*>(p);
609 }
610
Nick Kledzikb334be12012-04-07 01:31:00 +0000611 const Atom* target(uint16_t index) const {
612 if ( index == NativeReferenceIvarsV1::noTarget )
613 return nullptr;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000614 assert(index < _targetsTableCount);
615 return _targetsTable[index];
616 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000617
Nick Kledzikb334be12012-04-07 01:31:00 +0000618 void setTarget(uint16_t index, const Atom* newAtom) const {
619 assert(index != NativeReferenceIvarsV1::noTarget);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000620 assert(index > _targetsTableCount);
621 _targetsTable[index] = newAtom;
622 }
Nick Kledzikb334be12012-04-07 01:31:00 +0000623
Michael J. Spencer765792d2012-04-03 18:40:27 +0000624
625
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000626 // private constructor, only called by make()
Michael J. Spencere6203a52012-04-03 18:39:40 +0000627 NativeFile(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
628 File(path),
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000629 _buffer(std::move(mb)), // NativeFile now takes ownership of buffer
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000630 _header(nullptr),
631 _targetsTable(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000632 _targetsTableCount(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000633 _strings(nullptr),
Nick Kledzik23384e82012-02-07 02:59:54 +0000634 _stringsMaxOffset(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000635 _addends(nullptr),
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000636 _addendsMaxIndex(0),
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000637 _contentStart(nullptr),
638 _contentEnd(nullptr)
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000639 {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000640 _header = reinterpret_cast<const NativeFileHeader*>
641 (_buffer->getBufferStart());
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000642 }
643
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000644 template <typename T>
645 class AtomArray : public File::atom_collection<T> {
646 public:
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000647 AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000648 _elementSize(0), _elementCount(0) { }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000649
650 virtual atom_iterator<T> begin() const {
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000651 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
652 }
Michael J. Spencer765792d2012-04-03 18:40:27 +0000653 virtual atom_iterator<T> end() const{
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000654 return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
655 }
656 virtual const T* deref(const void* it) const {
657 return reinterpret_cast<const T*>(it);
658 }
659 virtual void next(const void*& it) const {
660 const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
661 p += _elementSize;
662 it = reinterpret_cast<const void*>(p);
663 }
664 const uint8_t* _arrayStart;
665 const uint8_t* _arrayEnd;
666 uint32_t _elementSize;
667 uint32_t _elementCount;
668 };
669
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000670 struct IvarArray {
Michael J. Spencer765792d2012-04-03 18:40:27 +0000671 IvarArray() :
Michael J. Spencerc9d25062012-03-29 19:39:14 +0000672 arrayStart(nullptr),
673 arrayEnd(nullptr),
Michael J. Spencer765792d2012-04-03 18:40:27 +0000674 elementSize(0),
675 elementCount(0) { }
676
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000677 const uint8_t* arrayStart;
678 const uint8_t* arrayEnd;
679 uint32_t elementSize;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000680 uint32_t elementCount;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000681 };
682
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000683
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000684 std::unique_ptr<llvm::MemoryBuffer> _buffer;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000685 const NativeFileHeader* _header;
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000686 AtomArray<DefinedAtom> _definedAtoms;
687 AtomArray<UndefinedAtom> _undefinedAtoms;
688 AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
689 AtomArray<AbsoluteAtom> _absoluteAtoms;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000690 const uint8_t* _attributes;
691 uint32_t _attributesMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000692 IvarArray _references;
693 const Atom** _targetsTable;
694 uint32_t _targetsTableCount;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000695 const char* _strings;
696 uint32_t _stringsMaxOffset;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000697 const Reference::Addend* _addends;
698 uint32_t _addendsMaxIndex;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000699 const uint8_t* _contentStart;
700 const uint8_t* _contentEnd;
701};
702
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000703
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000704inline const class File& NativeDefinedAtomV1::file() const {
705 return *_file;
706}
707
708inline uint64_t NativeDefinedAtomV1:: ordinal() const {
709 const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000710 return p - _file->_definedAtoms._arrayStart;
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000711}
712
Michael J. Spencere6203a52012-04-03 18:39:40 +0000713inline StringRef NativeDefinedAtomV1::name() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000714 return _file->string(_ivarData->nameOffset);
715}
716
717inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
718 return _file->attribute(_ivarData->attributesOffset);
719}
720
Michael J. Spencere6203a52012-04-03 18:39:40 +0000721inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000722 if ( this->contentType() == DefinedAtom::typeZeroFill )
Michael J. Spencere6203a52012-04-03 18:39:40 +0000723 return ArrayRef<uint8_t>();
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000724 const uint8_t* p = _file->content(_ivarData->contentOffset,
725 _ivarData->contentSize);
Michael J. Spencere6203a52012-04-03 18:39:40 +0000726 return ArrayRef<uint8_t>(p, _ivarData->contentSize);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000727}
728
Michael J. Spencere6203a52012-04-03 18:39:40 +0000729inline StringRef NativeDefinedAtomV1::customSectionName() const {
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000730 uint32_t offset = attributes().sectionNameOffset;
731 return _file->string(offset);
732}
733
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000734DefinedAtom::reference_iterator NativeDefinedAtomV1::referencesBegin() const {
735 uintptr_t index = _ivarData->referencesStartIndex;
736 const void* it = reinterpret_cast<const void*>(index);
737 return reference_iterator(*this, it);
738}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000739
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000740DefinedAtom::reference_iterator NativeDefinedAtomV1::referencesEnd() const {
741 uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
742 const void* it = reinterpret_cast<const void*>(index);
743 return reference_iterator(*this, it);
744}
745
746const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
747 uintptr_t index = reinterpret_cast<uintptr_t>(it);
748 return _file->referenceByIndex(index);
749}
Michael J. Spencer765792d2012-04-03 18:40:27 +0000750
Nick Kledzik1a6615d2012-03-08 00:18:30 +0000751void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
752 uintptr_t index = reinterpret_cast<uintptr_t>(it);
753 ++index;
754 it = reinterpret_cast<const void*>(index);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000755}
Nick Kledzik23384e82012-02-07 02:59:54 +0000756
757inline const class File& NativeUndefinedAtomV1::file() const {
758 return *_file;
759}
760
Michael J. Spencere6203a52012-04-03 18:39:40 +0000761inline StringRef NativeUndefinedAtomV1::name() const {
Nick Kledzik23384e82012-02-07 02:59:54 +0000762 return _file->string(_ivarData->nameOffset);
763}
764
765
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000766
767
768inline const class File& NativeSharedLibraryAtomV1::file() const {
769 return *_file;
770}
771
Michael J. Spencere6203a52012-04-03 18:39:40 +0000772inline StringRef NativeSharedLibraryAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000773 return _file->string(_ivarData->nameOffset);
774}
775
Michael J. Spencere6203a52012-04-03 18:39:40 +0000776inline StringRef NativeSharedLibraryAtomV1::loadName() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000777 return _file->string(_ivarData->loadNameOffset);
778}
779
780
781
782inline const class File& NativeAbsoluteAtomV1::file() const {
783 return *_file;
784}
785
Michael J. Spencere6203a52012-04-03 18:39:40 +0000786inline StringRef NativeAbsoluteAtomV1::name() const {
Nick Kledzik6bc04c62012-02-22 21:56:59 +0000787 return _file->string(_ivarData->nameOffset);
788}
789
790
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000791inline const Atom* NativeReferenceV1::target() const {
792 return _file->target(_ivarData->targetIndex);
793}
794
795inline Reference::Addend NativeReferenceV1::addend() const {
796 return _file->addend(_ivarData->addendIndex);
797}
798
Nick Kledzikf4e2c732012-03-15 23:36:24 +0000799inline void NativeReferenceV1::setKind(Kind k) {
800 this->cloneIvarData();
801 const_cast<NativeReferenceIvarsV1*>(_ivarData)->kind = k;
802}
803
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000804inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
805 return _file->setTarget(_ivarData->targetIndex, newAtom);
806}
Nick Kledzik23384e82012-02-07 02:59:54 +0000807
Nick Kledzikb334be12012-04-07 01:31:00 +0000808inline void NativeReferenceV1::setAddend(Addend a) {
809 assert(0 && "setAddend() not supported");
810}
811
Nick Kledzik23384e82012-02-07 02:59:54 +0000812
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000813//
814// Instantiate an lld::File from the given native object file buffer
815//
Michael J. Spencere6203a52012-04-03 18:39:40 +0000816error_code parseNativeObjectFile(std::unique_ptr<llvm::MemoryBuffer> mb,
817 StringRef path,
818 std::unique_ptr<File> &result) {
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000819 return NativeFile::make(std::move(mb), path, result);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000820}
821
822
823
824//
825// Instantiate an lld::File from the given native object file path
826//
Michael J. Spencere6203a52012-04-03 18:39:40 +0000827error_code parseNativeObjectFileOrSTDIN(StringRef path,
828 std::unique_ptr<File>& result) {
829 OwningPtr<llvm::MemoryBuffer> mb;
830 error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
831 if ( ec )
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000832 return ec;
833
Michael J. Spencerd58cf032012-03-29 00:49:50 +0000834 return parseNativeObjectFile( std::unique_ptr<llvm::MemoryBuffer>(mb.take())
835 , path
836 , result);
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000837}
838
Nick Kledzik55fd6be2012-01-16 22:03:44 +0000839} // namespace lld