blob: d5e60eb21310056f25d4580fe03f5dcd895b4b3a [file] [log] [blame]
Michael J. Spencer773a8fb2011-12-18 08:27:59 +00001//===- Core/YamlReader.cpp - Reads YAML -----------------------------------===//
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
Nick Kledzik49d6cc82012-02-15 00:38:09 +000010#include <string.h>
11
Nick Kledzik7735a7d2012-01-04 23:58:17 +000012#include "YamlKeyValues.h"
13
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000014#include "lld/Core/YamlReader.h"
15#include "lld/Core/Atom.h"
Michael J. Spencer7aba8952012-01-31 21:47:13 +000016#include "lld/Core/Error.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000017#include "lld/Core/File.h"
18#include "lld/Core/Reference.h"
19
20#include "llvm/ADT/OwningPtr.h"
21#include "llvm/ADT/StringRef.h"
Nick Kledzikbfedfc12012-01-09 20:18:15 +000022#include "llvm/ADT/ArrayRef.h"
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000023#include "llvm/Support/DataTypes.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/MemoryBuffer.h"
26#include "llvm/Support/system_error.h"
27
28#include <vector>
29
Nick Kledzik7735a7d2012-01-04 23:58:17 +000030
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000031
32namespace lld {
33namespace yaml {
Nick Kledzik7735a7d2012-01-04 23:58:17 +000034
Nick Kledzik49d6cc82012-02-15 00:38:09 +000035namespace {
36
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000037class YAML {
38public:
39 struct Entry {
Nick Kledzikbfedfc12012-01-09 20:18:15 +000040 Entry(const char *k, const char *v, std::vector<uint8_t>* vs,
41 int d, bool bd, bool bs)
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000042 : key(strdup(k))
Nick Kledzikbfedfc12012-01-09 20:18:15 +000043 , value(v ? strdup(v) : NULL)
44 , valueSequenceBytes(vs)
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000045 , depth(d)
46 , beginSequence(bs)
47 , beginDocument(bd) {}
48
Nick Kledzikbfedfc12012-01-09 20:18:15 +000049 const char * key;
50 const char * value;
51 std::vector<uint8_t>* valueSequenceBytes;
52 int depth;
53 bool beginSequence;
54 bool beginDocument;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000055 };
56
57 static void parse(llvm::MemoryBuffer *mb, std::vector<const Entry *>&);
58
59private:
60 enum State {
61 start,
62 inHeaderComment,
63 inTripleDash,
64 inTriplePeriod,
65 inDocument,
66 inKey,
67 inSpaceBeforeValue,
68 inValue,
69 inValueSequence,
70 inValueSequenceEnd
71 };
72};
73
74
75void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &entries) {
76 State state = start;
77 char key[64];
78 char value[64];
79 char *p = NULL;
80 unsigned int lineNumber = 1;
81 int depth = 0;
82 bool nextKeyIsStartOfDocument = false;
83 bool nextKeyIsStartOfSequence = false;
Nick Kledzikbfedfc12012-01-09 20:18:15 +000084 std::vector<uint8_t>* sequenceBytes = NULL;
85 unsigned contentByte = 0;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +000086 for (const char *s = mb->getBufferStart(); s < mb->getBufferEnd(); ++s) {
87 char c = *s;
88 if (c == '\n')
89 ++lineNumber;
90 switch (state) {
91 case start:
92 if (c == '#')
93 state = inHeaderComment;
94 else if (c == '-') {
95 p = &key[0];
96 *p++ = c;
97 state = inTripleDash;
98 }
99 break;
100 case inHeaderComment:
101 if (c == '\n') {
102 state = start;
103 }
104 break;
105 case inTripleDash:
106 if (c == '-') {
107 *p++ = c;
108 } else if (c == '\n') {
109 *p = '\0';
110 if (strcmp(key, "---") != 0)
111 return;
112 depth = 0;
113 state = inDocument;
114 nextKeyIsStartOfDocument = true;
115 } else {
116 return;
117 }
118 break;
119 case inTriplePeriod:
120 if (c == '.') {
121 *p++ = c;
122 } else if (c == '\n') {
123 *p = '\0';
124 if (strcmp(key, "...") != 0)
125 return;
126 depth = 0;
127 state = inHeaderComment;
128 } else {
129 return;
130 }
131 break;
132 case inDocument:
133 if (isalnum(c)) {
134 state = inKey;
135 p = &key[0];
136 *p++ = c;
137 } else if (c == '-') {
138 if (depth == 0) {
139 p = &key[0];
140 *p++ = c;
141 state = inTripleDash;
142 } else {
143 nextKeyIsStartOfSequence = true;
144 ++depth;
145 }
146 } else if (c == ' ') {
147 ++depth;
148 } else if (c == '.') {
149 p = &key[0];
150 *p++ = c;
151 state = inTriplePeriod;
152 } else if (c == '\n') {
153 // ignore empty lines
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000154 depth = 0;
Nick Kledzik38eec3d2011-12-22 02:38:01 +0000155 } else if (c == '\t') {
156 llvm::report_fatal_error("TAB character found in yaml file");
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000157 } else {
158 return;
159 }
160 break;
161 case inKey:
162 if (isalnum(c) || (c == '-')) {
163 *p++ = c;
164 } else if (c == ':') {
165 *p = '\0';
166 state = inSpaceBeforeValue;
167 } else if (c == '\n') {
168 *p = '\0';
169 if (strcmp(key, "---") == 0)
170 state = inDocument;
171 else
172 return;
173 } else {
174 return;
175 }
176 break;
177 case inSpaceBeforeValue:
178 if (isalnum(c) || (c == '-') || (c == '_')) {
179 p = &value[0];
180 *p++ = c;
181 state = inValue;
182 } else if (c == '\n') {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000183 entries.push_back(new Entry(key, "", NULL, depth,
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000184 nextKeyIsStartOfDocument,
185 nextKeyIsStartOfSequence));
186 nextKeyIsStartOfSequence = false;
187 nextKeyIsStartOfDocument = false;
188 state = inDocument;
189 depth = 0;
190 } else if (c == '[') {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000191 contentByte = 0;
192 sequenceBytes = new std::vector<uint8_t>();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000193 state = inValueSequence;
194 } else if (c == ' ') {
195 // eat space
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000196 } else if (c == '\t') {
197 llvm::report_fatal_error("TAB character found in yaml file");
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000198 } else {
199 return;
200 }
201 break;
202 case inValue:
203 if (isalnum(c) || (c == '-') || (c == '_')) {
204 *p++ = c;
205 } else if (c == '\n') {
206 *p = '\0';
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000207 entries.push_back(new Entry(key, value, NULL, depth,
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000208 nextKeyIsStartOfDocument,
209 nextKeyIsStartOfSequence));
210 nextKeyIsStartOfSequence = false;
211 nextKeyIsStartOfDocument = false;
212 state = inDocument;
213 depth = 0;
214 }
215 break;
216 case inValueSequence:
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000217 if (c == ']') {
218 sequenceBytes->push_back(contentByte);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000219 state = inValueSequenceEnd;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000220 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000221 else if ( (c == ' ') || (c == '\n') ) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000222 // eat white space
223 }
224 else if (c == ',') {
225 sequenceBytes->push_back(contentByte);
226 }
227 else if ( isdigit(c) ) {
228 contentByte = (contentByte << 4) | (c-'0');
229 }
230 else if ( ('a' <= tolower(c)) && (tolower(c) <= 'f') ) {
231 contentByte = (contentByte << 4) | (tolower(c)-'a'+10);
232 }
233 else {
234 llvm::report_fatal_error("non-hex digit found in content [ ]");
235 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000236 break;
237 case inValueSequenceEnd:
238 if (c == '\n') {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000239 entries.push_back(new Entry(key, NULL, sequenceBytes, depth,
240 nextKeyIsStartOfDocument,
241 nextKeyIsStartOfSequence));
242 nextKeyIsStartOfSequence = false;
243 nextKeyIsStartOfDocument = false;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000244 state = inDocument;
245 depth = 0;
246 }
247 break;
248 }
249 }
250}
251
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000252
253
254class YAMLReference : public Reference {
255public:
256 YAMLReference() : _target(NULL), _targetName(NULL),
257 _offsetInAtom(0), _addend(0), _kind(0) { }
258
259 virtual uint64_t offsetInAtom() const {
260 return _offsetInAtom;
261 }
262
263 virtual Kind kind() const {
264 return _kind;
265 }
266
267 virtual const Atom* target() const {
268 return _target;
269 }
270
271 virtual Addend addend() const {
272 return _addend;
273 }
274
275 virtual void setTarget(const Atom* newAtom) {
276 _target = newAtom;
277 }
278
279 const Atom* _target;
280 const char* _targetName;
281 uint64_t _offsetInAtom;
282 Addend _addend;
283 Kind _kind;
284};
285
286
287
288class YAMLDefinedAtom;
289
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000290class YAMLFile : public File {
291public:
292 YAMLFile()
293 : File("path")
294 , _lastRefIndex(0) {}
295
296 virtual bool forEachAtom(File::AtomHandler &) const;
297 virtual bool justInTimeforEachAtom(llvm::StringRef name,
298 File::AtomHandler &) const;
299
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000300 void bindTargetReferences();
301 void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);
302 void addUndefinedAtom(UndefinedAtom* atom);
303 Atom* findAtom(const char* name);
304
305 struct NameAtomPair {
306 NameAtomPair(const char* n, Atom* a) : name(n), atom(a) {}
307 const char* name;
308 Atom* atom;
309 };
310
311 std::vector<YAMLDefinedAtom*> _definedAtoms;
312 std::vector<UndefinedAtom*> _undefinedAtoms;
313 std::vector<YAMLReference> _references;
314 std::vector<NameAtomPair> _nameToAtomMapping;
315 unsigned int _lastRefIndex;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000316};
317
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000318
319
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000320class YAMLDefinedAtom : public DefinedAtom {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000321public:
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000322 YAMLDefinedAtom( uint32_t ord
323 , YAMLFile& file
324 , DefinedAtom::Scope scope
325 , DefinedAtom::ContentType type
326 , DefinedAtom::SectionChoice sectionChoice
327 , DefinedAtom::Interposable interpose
328 , DefinedAtom::Merge merge
329 , DefinedAtom::DeadStripKind deadStrip
330 , DefinedAtom::ContentPermissions perms
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000331 , bool isThumb
332 , bool isAlias
333 , DefinedAtom::Alignment alignment
334 , const char* name
335 , const char* sectionName
336 , uint64_t size
337 , std::vector<uint8_t>* content)
338 : _file(file)
339 , _name(name)
340 , _sectionName(sectionName)
341 , _size(size)
342 , _ord(ord)
343 , _content(content)
344 , _alignment(alignment)
345 , _scope(scope)
346 , _type(type)
347 , _sectionChoice(sectionChoice)
348 , _interpose(interpose)
349 , _merge(merge)
350 , _deadStrip(deadStrip)
351 , _permissions(perms)
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000352 , _isThumb(isThumb)
353 , _isAlias(isAlias)
354 , _refStartIndex(file._lastRefIndex)
355 , _refEndIndex(file._references.size()) {
356 file._lastRefIndex = _refEndIndex;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000357 }
358
Nick Kledzikf46669c2011-12-21 23:29:36 +0000359 virtual const class File& file() const {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000360 return _file;
361 }
362
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000363 virtual llvm::StringRef name() const {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000364 if ( _name == NULL )
365 return llvm::StringRef();
366 else
367 return _name;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000368 }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000369
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000370 virtual uint64_t size() const {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000371 return (_content ? _content->size() : _size);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000372 }
373
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000374 virtual DefinedAtom::Scope scope() const {
375 return _scope;
376 }
377
378 virtual DefinedAtom::Interposable interposable() const {
379 return _interpose;
380 }
381
382 virtual DefinedAtom::Merge merge() const {
383 return _merge;
384 }
385
386 virtual DefinedAtom::ContentType contentType() const {
387 return _type;
388 }
389
390 virtual DefinedAtom::Alignment alignment() const {
391 return _alignment;
392 }
393
394 virtual DefinedAtom::SectionChoice sectionChoice() const {
395 return _sectionChoice;
396 }
397
398 virtual llvm::StringRef customSectionName() const {
399 return _sectionName;
400 }
401
402 virtual DefinedAtom::DeadStripKind deadStrip() const {
403 return _deadStrip;
404 }
405
406 virtual DefinedAtom::ContentPermissions permissions() const {
407 return _permissions;
408 }
409
410 virtual bool isThumb() const {
411 return _isThumb;
412 }
413
414 virtual bool isAlias() const {
415 return _isAlias;
416 }
417
418 llvm::ArrayRef<uint8_t> rawContent() const {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000419 if ( _content != NULL )
420 return llvm::ArrayRef<uint8_t>(*_content);
421 else
422 return llvm::ArrayRef<uint8_t>();
423 }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000424
425 virtual uint64_t ordinal() const {
426 return _ord;
427 }
428
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000429
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000430 virtual void forEachReference(ReferenceHandler& handler) const {
431 for (uint32_t i=_refStartIndex; i < _refEndIndex; ++i) {
432 handler.doReference(_file._references[i]);
433 }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000434 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000435
436 void bindTargetReferences() {
437 for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {
438 const char* targetName = _file._references[i]._targetName;
439 Atom* targetAtom = _file.findAtom(targetName);
440 _file._references[i]._target = targetAtom;
441 }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000442 }
443
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000444private:
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000445 YAMLFile& _file;
446 const char * _name;
447 const char * _sectionName;
448 unsigned long _size;
449 uint32_t _ord;
450 std::vector<uint8_t>* _content;
451 DefinedAtom::Alignment _alignment;
452 DefinedAtom::Scope _scope;
453 DefinedAtom::ContentType _type;
454 DefinedAtom::SectionChoice _sectionChoice;
455 DefinedAtom::Interposable _interpose;
456 DefinedAtom::Merge _merge;
457 DefinedAtom::DeadStripKind _deadStrip;
458 DefinedAtom::ContentPermissions _permissions;
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000459 bool _isThumb;
460 bool _isAlias;
461 unsigned int _refStartIndex;
462 unsigned int _refEndIndex;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000463};
464
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000465
Nick Kledzik23384e82012-02-07 02:59:54 +0000466class YAMLUndefinedAtom : public UndefinedAtom {
467public:
468 YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm, bool wi)
469 : _file(f), _name(nm), _ordinal(ord), _weakImport(wi) { }
470
471 virtual const class File& file() const {
472 return _file;
473 }
474
475 virtual llvm::StringRef name() const {
476 return _name;
477 }
478
479 virtual bool weakImport() const {
480 return _weakImport;
481 }
482
483private:
484 YAMLFile& _file;
485 const char * _name;
486 uint32_t _ordinal;
487 bool _weakImport;
488};
489
490
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000491bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
492 handler.doFile(*this);
493 for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();
494 it != _definedAtoms.end(); ++it) {
495 handler.doDefinedAtom(**it);
496 }
497 for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
498 it != _undefinedAtoms.end(); ++it) {
499 handler.doUndefinedAtom(**it);
500 }
501 return true;
502}
503
504bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
505 File::AtomHandler &handler) const {
506 return false;
507}
508
509void YAMLFile::bindTargetReferences() {
510 for (std::vector<YAMLDefinedAtom *>::const_iterator
511 it = _definedAtoms.begin(); it != _definedAtoms.end(); ++it) {
512 YAMLDefinedAtom* atom = *it;
513 atom->bindTargetReferences();
514 }
515}
516
517Atom* YAMLFile::findAtom(const char* name) {
518 for (std::vector<NameAtomPair>::const_iterator it = _nameToAtomMapping.begin();
519 it != _nameToAtomMapping.end(); ++it) {
520 if ( strcmp(name, it->name) == 0 )
521 return it->atom;
522 }
523 llvm::report_fatal_error("reference to atom that does not exist");
524}
525
526void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {
527 _definedAtoms.push_back(atom);
528 assert(refName != NULL);
529 _nameToAtomMapping.push_back(NameAtomPair(refName, atom));
530}
531
532void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {
533 _undefinedAtoms.push_back(atom);
534 _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));
535}
536
Nick Kledzik23384e82012-02-07 02:59:54 +0000537
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000538class YAMLAtomState {
539public:
540 YAMLAtomState();
541
542 void setName(const char *n);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000543 void setRefName(const char *n);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000544 void setAlign2(const char *n);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000545
546 void setFixupKind(const char *n);
547 void setFixupOffset(const char *n);
548 void setFixupTarget(const char *n);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000549 void setFixupAddend(const char *n);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000550 void addFixup(YAMLFile *f);
551
Nick Kledzikf46669c2011-12-21 23:29:36 +0000552 void makeAtom(YAMLFile&);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000553
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000554 const char * _name;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000555 const char * _refName;
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000556 const char * _sectionName;
557 unsigned long long _size;
558 uint32_t _ordinal;
559 std::vector<uint8_t>* _content;
560 DefinedAtom::Alignment _alignment;
561 Atom::Definition _definition;
562 DefinedAtom::Scope _scope;
563 DefinedAtom::ContentType _type;
564 DefinedAtom::SectionChoice _sectionChoice;
565 DefinedAtom::Interposable _interpose;
566 DefinedAtom::Merge _merge;
567 DefinedAtom::DeadStripKind _deadStrip;
568 DefinedAtom::ContentPermissions _permissions;
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000569 bool _isThumb;
570 bool _isAlias;
Nick Kledzik23384e82012-02-07 02:59:54 +0000571 bool _weakImport;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000572 YAMLReference _ref;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000573};
574
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000575
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000576YAMLAtomState::YAMLAtomState()
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000577 : _name(NULL)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000578 , _refName(NULL)
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000579 , _sectionName(NULL)
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000580 , _size(0)
581 , _ordinal(0)
582 , _content(NULL)
583 , _alignment(0, 0)
584 , _definition(KeyValues::definitionDefault)
585 , _scope(KeyValues::scopeDefault)
586 , _type(KeyValues::contentTypeDefault)
587 , _sectionChoice(KeyValues::sectionChoiceDefault)
588 , _interpose(KeyValues::interposableDefault)
589 , _merge(KeyValues::mergeDefault)
590 , _deadStrip(KeyValues::deadStripKindDefault)
591 , _permissions(KeyValues::permissionsDefault)
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000592 , _isThumb(KeyValues::isThumbDefault)
593 , _isAlias(KeyValues::isAliasDefault)
Nick Kledzik23384e82012-02-07 02:59:54 +0000594 , _weakImport(false)
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000595 {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000596 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000597
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000598
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000599void YAMLAtomState::makeAtom(YAMLFile& f) {
600 if ( _definition == Atom::definitionRegular ) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000601 YAMLDefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000602 _sectionChoice, _interpose, _merge, _deadStrip,
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000603 _permissions, _isThumb, _isAlias,
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000604 _alignment, _name, _sectionName, _size, _content);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000605 f.addDefinedAtom(a, _refName ? _refName : _name);
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000606 ++_ordinal;
607 }
Nick Kledzik23384e82012-02-07 02:59:54 +0000608 else if ( _definition == Atom::definitionUndefined ) {
609 UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport);
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000610 f.addUndefinedAtom(a);
Nick Kledzik23384e82012-02-07 02:59:54 +0000611 ++_ordinal;
612 }
Nick Kledzikf46669c2011-12-21 23:29:36 +0000613
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000614 // reset state for next atom
615 _name = NULL;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000616 _refName = NULL;
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000617 _sectionName = NULL;
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000618 _size = 0;
619 _ordinal = 0;
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000620 _content = NULL;
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000621 _alignment.powerOf2= 0;
622 _alignment.modulus = 0;
623 _definition = KeyValues::definitionDefault;
624 _scope = KeyValues::scopeDefault;
625 _type = KeyValues::contentTypeDefault;
626 _sectionChoice = KeyValues::sectionChoiceDefault;
627 _interpose = KeyValues::interposableDefault;
628 _merge = KeyValues::mergeDefault;
629 _deadStrip = KeyValues::deadStripKindDefault;
630 _permissions = KeyValues::permissionsDefault;
631 _isThumb = KeyValues::isThumbDefault;
632 _isAlias = KeyValues::isAliasDefault;
Nick Kledzik23384e82012-02-07 02:59:54 +0000633 _weakImport = KeyValues::weakImportDefault;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000634 _ref._target = NULL;
635 _ref._targetName = NULL;
636 _ref._addend = 0;
637 _ref._offsetInAtom = 0;
638 _ref._kind = 0;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000639}
640
641void YAMLAtomState::setName(const char *n) {
642 _name = n;
643}
644
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000645void YAMLAtomState::setRefName(const char *n) {
646 _refName = n;
647}
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000648
649void YAMLAtomState::setAlign2(const char *s) {
650 llvm::StringRef str(s);
651 uint32_t res;
652 str.getAsInteger(10, res);
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000653 _alignment.powerOf2 = static_cast<uint16_t>(res);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000654}
655
Nick Kledzik38eec3d2011-12-22 02:38:01 +0000656
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000657void YAMLAtomState::setFixupKind(const char *s) {
658 if (strcmp(s, "pcrel32") == 0)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000659 _ref._kind = 1;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000660 else if (strcmp(s, "call32") == 0)
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000661 _ref._kind = 2;
662 else {
663 int k;
664 llvm::StringRef(s).getAsInteger(10, k);
665 _ref._kind = k;
666 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000667}
668
669void YAMLAtomState::setFixupOffset(const char *s) {
670 if ((s[0] == '0') && (s[1] == 'x'))
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000671 llvm::StringRef(s).getAsInteger(16, _ref._offsetInAtom);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000672 else
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000673 llvm::StringRef(s).getAsInteger(10, _ref._offsetInAtom);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000674}
675
676void YAMLAtomState::setFixupTarget(const char *s) {
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000677 _ref._targetName = s;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000678}
679
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000680void YAMLAtomState::setFixupAddend(const char *s) {
681 if ((s[0] == '0') && (s[1] == 'x'))
682 llvm::StringRef(s).getAsInteger(16, _ref._addend);
683 else
684 llvm::StringRef(s).getAsInteger(10, _ref._addend);
685}
686
687
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000688void YAMLAtomState::addFixup(YAMLFile *f) {
689 f->_references.push_back(_ref);
690 // clear for next ref
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000691 _ref._target = NULL;
692 _ref._targetName = NULL;
693 _ref._addend = 0;
694 _ref._offsetInAtom = 0;
695 _ref._kind = 0;
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000696}
697
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000698
699} // anonymous namespace
700
701
702
703
704
705/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
706/// into lld::File object(s) and append each to the specified vector<File*>.
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000707llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
708 , std::vector<File *> &result) {
709 std::vector<const YAML::Entry *> entries;
710 YAML::parse(mb, entries);
711
712 YAMLFile *file = NULL;
713 YAMLAtomState atomState;
714 bool inAtoms = false;
715 bool inFixups = false;
716 int depthForAtoms = -1;
717 int depthForFixups = -1;
718 int lastDepth = -1;
719 bool haveAtom = false;
720 bool haveFixup = false;
721
722 for (std::vector<const YAML::Entry *>::iterator it = entries.begin();
723 it != entries.end(); ++it) {
724 const YAML::Entry *entry = *it;
725
726 if (entry->beginDocument) {
727 if (file != NULL) {
728 if (haveAtom) {
Nick Kledzikf46669c2011-12-21 23:29:36 +0000729 atomState.makeAtom(*file);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000730 haveAtom = false;
731 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000732 file->bindTargetReferences();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000733 result.push_back(file);
734 }
735 file = new YAMLFile();
736 inAtoms = false;
737 depthForAtoms = -1;
738 }
739 if (lastDepth > entry->depth) {
740 // end of fixup sequence
741 if (haveFixup) {
742 atomState.addFixup(file);
743 haveFixup = false;
744 }
745 }
746
747 if (inAtoms && (depthForAtoms == -1)) {
748 depthForAtoms = entry->depth;
749 }
750 if (inFixups && (depthForFixups == -1)) {
751 depthForFixups = entry->depth;
752 }
753 if (strcmp(entry->key, "atoms") == 0) {
754 inAtoms = true;
755 }
756 if (inAtoms) {
757 if (depthForAtoms == entry->depth) {
758 if (entry->beginSequence) {
759 if (haveAtom) {
Nick Kledzikf46669c2011-12-21 23:29:36 +0000760 atomState.makeAtom(*file);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000761 haveAtom = false;
762 }
763 }
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000764 if (strcmp(entry->key, KeyValues::nameKeyword) == 0) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000765 atomState.setName(entry->value);
766 haveAtom = true;
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000767 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000768 else if (strcmp(entry->key, KeyValues::refNameKeyword) == 0) {
769 atomState.setRefName(entry->value);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000770 haveAtom = true;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000771 }
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000772 else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000773 atomState._definition = KeyValues::definition(entry->value);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000774 haveAtom = true;
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000775 }
776 else if (strcmp(entry->key, KeyValues::scopeKeyword) == 0) {
777 atomState._scope = KeyValues::scope(entry->value);
778 haveAtom = true;
779 }
780 else if (strcmp(entry->key, KeyValues::contentTypeKeyword) == 0) {
781 atomState._type = KeyValues::contentType(entry->value);
782 haveAtom = true;
783 }
784 else if (strcmp(entry->key, KeyValues::deadStripKindKeyword) == 0) {
785 atomState._deadStrip = KeyValues::deadStripKind(entry->value);
786 haveAtom = true;
787 }
788 else if (strcmp(entry->key, KeyValues::sectionChoiceKeyword) == 0) {
789 atomState._sectionChoice = KeyValues::sectionChoice(entry->value);
790 haveAtom = true;
791 }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000792 else if (strcmp(entry->key, KeyValues::mergeKeyword) == 0) {
793 atomState._merge = KeyValues::merge(entry->value);
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000794 haveAtom = true;
795 }
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000796 else if (strcmp(entry->key, KeyValues::interposableKeyword) == 0) {
797 atomState._interpose = KeyValues::interposable(entry->value);
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000798 haveAtom = true;
799 }
800 else if (strcmp(entry->key, KeyValues::isThumbKeyword) == 0) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000801 atomState._isThumb = KeyValues::isThumb(entry->value);
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000802 haveAtom = true;
803 }
804 else if (strcmp(entry->key, KeyValues::isAliasKeyword) == 0) {
Nick Kledzikf4fb2c52012-01-11 01:06:19 +0000805 atomState._isAlias = KeyValues::isAlias(entry->value);
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000806 haveAtom = true;
807 }
Nick Kledzik23384e82012-02-07 02:59:54 +0000808 else if (strcmp(entry->key, KeyValues::weakImportKeyword) == 0) {
809 atomState._weakImport = KeyValues::weakImport(entry->value);
810 haveAtom = true;
811 }
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000812 else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) {
813 atomState._sectionName = entry->value;
814 haveAtom = true;
815 }
816 else if (strcmp(entry->key, KeyValues::sizeKeyword) == 0) {
817 llvm::StringRef val = entry->value;
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000818 if ( val.getAsInteger(0, atomState._size) )
819 return make_error_code(yaml_reader_error::illegal_value);
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000820 haveAtom = true;
821 }
822 else if (strcmp(entry->key, KeyValues::contentKeyword) == 0) {
Nick Kledzikbfedfc12012-01-09 20:18:15 +0000823 atomState._content = entry->valueSequenceBytes;
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000824 haveAtom = true;
825 }
826 else if (strcmp(entry->key, "align2") == 0) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000827 atomState.setAlign2(entry->value);
828 haveAtom = true;
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000829 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000830 else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000831 inFixups = true;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000832
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000833 }
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000834 else {
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000835 return make_error_code(yaml_reader_error::unknown_keyword);
Nick Kledzik7735a7d2012-01-04 23:58:17 +0000836 }
837 }
838 else if (depthForFixups == entry->depth) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000839 if (entry->beginSequence) {
840 if (haveFixup) {
841 atomState.addFixup(file);
842 haveFixup = false;
843 }
844 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000845 if (strcmp(entry->key, KeyValues::fixupsKindKeyword) == 0) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000846 atomState.setFixupKind(entry->value);
847 haveFixup = true;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000848 }
849 else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000850 atomState.setFixupOffset(entry->value);
851 haveFixup = true;
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000852 }
853 else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000854 atomState.setFixupTarget(entry->value);
855 haveFixup = true;
856 }
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000857 else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {
858 atomState.setFixupAddend(entry->value);
859 haveFixup = true;
860 }
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000861 }
862 }
863 lastDepth = entry->depth;
864 }
865 if (haveAtom) {
Nick Kledzikf46669c2011-12-21 23:29:36 +0000866 atomState.makeAtom(*file);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000867 }
868
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000869 file->bindTargetReferences();
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000870 result.push_back(file);
Michael J. Spencer7aba8952012-01-31 21:47:13 +0000871 return make_error_code(yaml_reader_error::success);
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000872}
Nick Kledzik070e1a72011-12-20 00:07:11 +0000873
Nick Kledzik49d6cc82012-02-15 00:38:09 +0000874
Nick Kledzik070e1a72011-12-20 00:07:11 +0000875//
876// Fill in vector<File*> from path to input text file.
877//
878llvm::error_code parseObjectTextFileOrSTDIN(llvm::StringRef path
879 , std::vector<File*>& result) {
880 llvm::OwningPtr<llvm::MemoryBuffer> mb;
881 llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
882 if ( ec )
883 return ec;
884
885 return parseObjectText(mb.get(), result);
886}
887
888
Michael J. Spencer773a8fb2011-12-18 08:27:59 +0000889} // namespace yaml
890} // namespace lld