OpenASIP 2.2
Loading...
Searching...
No Matches
AOutSymbolSectionReader.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file AOutSymbolSectionReader.cc
26 *
27 * Definition of class AOutSymbolSectionReader.
28 *
29 * @author Jussi Nykänen 2003 (nykanen-no.spam-cs.tut.fi)
30 * @author Mikael Lepistö 18.12.2003 (tmlepist-no.spam-cs.tut.fi)
31 * @note reviewed 23 October 2003 by pj, am, ll, jn
32 *
33 * @note rating: yellow
34 */
35
37#include "AOutReader.hh"
38#include "ReferenceKey.hh"
39#include "SafePointer.hh"
40#include "SectionReader.hh"
41#include "NoTypeSymElement.hh"
42#include "DataSymElement.hh"
43#include "CodeSymElement.hh"
44#include "ProcedSymElement.hh"
45#include "SectionSymElement.hh"
46#include "FileSymElement.hh"
47#include "ResourceSection.hh"
48#include "ResourceElement.hh"
49#include "StringSection.hh"
50#include "DebugStabElem.hh"
51#include "CodeSection.hh"
52#include "InstructionElement.hh"
53#include "MoveElement.hh"
54#include "NullSection.hh"
55#include "DebugSection.hh"
56#include "CodeSection.hh"
57
58namespace TPEF {
59
60using ReferenceManager::SectionKey;
61using ReferenceManager::SectionOffsetKey;
62using ReferenceManager::SectionIndexKey;
63using ReferenceManager::SafePointer;
64
65AOutSymbolSectionReader AOutSymbolSectionReader::proto_;
67
68const std::string
70
71const std::string
73
74/**
75 * Constructor.
76 *
77 * Registers itself to SectionReader.
78 */
82
83/**
84 * Destructor.
85 */
88
89/**
90 * Returns the type of section that this reader reads.
91 *
92 * @return The type of section this reader can read.
93 */
98
99/**
100 * Reads a.out symbol section out of stream and stores it in section.
101 *
102 * @param stream The stream to be read from.
103 * @param section The section in which data is stored.
104 * @exception UnreachableStream If reading of section fails.
105 * @exception KeyAlreadyExists Key was in use when trying to register object.
106 * @exception EndOfFile If end of file were reached while it shouldn't.
107 * @exception OutOfRange Some of read values were out of range.
108 * @exception WrongSubclass Some class couldn't do what it was asked for.
109 * @exception UnexpectedValue If there was unexpected value when reading.
110 */
111void
113 BinaryStream& stream, Section* section) const {
114 StringSection* stringSection =
115 dynamic_cast<AOutReader*>(parent())->stringSection();
116
117 FileOffset offset = stream.readPosition();
118 AOutReader* reader = dynamic_cast<AOutReader*>(parent());
119 assert(reader != NULL);
120
121 // create undef symbol to start of section (needed by TPEF)
122 SymbolElement *undefSymbol = new NoTypeSymElement();
123
124 SectionOffsetKey nullStringKey =
126
127 undefSymbol->setName(CREATE_SAFEPOINTER(nullStringKey));
128 undefSymbol->setSection(reader->nullSection());
129
130 SectionIndexKey undefSymbolKey =
132 SafePointer::addObjectReference(undefSymbolKey, undefSymbol);
133
134 section->addElement(undefSymbol);
135
136 // in this point there is no recources added yet
137 resolvedResources_.clear();
138 addedResources_.clear();
139
140 // symbols start in a.out with index 0
141 int symIndex = 0;
142 while (stream.readPosition() <
143 offset + reader->header().sectionSizeSymbol()) {
144
145 SectionOffset sectionOffset = stream.readPosition() - offset;
146
147 SymbolElement* elem =
148 initializeSymbol(stream, sectionOffset, reader);
149
150 if (elem != NULL) {
151 SectionIndexKey symIndexKey =
153 SafePointer::addObjectReference(symIndexKey, elem);
154
155 section->addElement(elem);
156
157 }
158
159 // always remember to increment index counter, even if symbol is not
160 // created
161 symIndex++;
162 }
163
164
165 // ----------------------------------------------------------------------
166 // write resource table out of N_PRTAB stabs collected from symbol table
167 // ----------------------------------------------------------------------
168
169 ResourceSection* resourceTable =
170 dynamic_cast<AOutReader*>(parent())->resourceTable();
171
172 ResourceElement *resource = NULL;
173
174 while (!resolvedResources_.empty()) {
175 Word value = (*(resolvedResources_.begin())).second;
176 Chunk* name =
177 stringSection->string2Chunk(
178 (*(resolvedResources_.begin())).first);
179
180 // if operation register, make entry to resource table
181 if (value > AOutReader::FIRST_FU_REGISTER) {
182
183 resource = new ResourceElement();
184 resource->setId(value);
186
187 resource->setName(
188 CREATE_SAFEPOINTER(
190
191 resourceTable->addElement(resource);
192
193 // the very first of FU registers in a.out is
194 // "return-address" special register
195 } else if (value == AOutReader::FIRST_FU_REGISTER) {
196
197 resource = new ResourceElement();
198 resource->setId(value);
200
201 resource->setName(
202 CREATE_SAFEPOINTER(
204
205 resourceTable->addElement(resource);
206 }
207
209 }
210
211 // add int register file
212 resource = new ResourceElement();
215 resource->setName(CREATE_SAFEPOINTER(nullStringKey));
216 resourceTable->addElement(resource);
217
218 // add fp registerfile
219 resource = new ResourceElement();
220 resource->setId(ResourceElement::FP_RF);
222 resource->setName(CREATE_SAFEPOINTER(nullStringKey));
223 resourceTable->addElement(resource);
224
225 // add bool register file
226 resource = new ResourceElement();
229 resource->setName(CREATE_SAFEPOINTER(nullStringKey));
230 resourceTable->addElement(resource);
231
232 // add unit
233 resource = new ResourceElement();
236 resource->setName(CREATE_SAFEPOINTER(nullStringKey));
237 resourceTable->addElement(resource);
238
239 // add bus
240 resource = new ResourceElement();
243 resource->setName(CREATE_SAFEPOINTER(nullStringKey));
244 resourceTable->addElement(resource);
245}
246
247/**
248 * Creates and initilizes one symbol element.
249 *
250 * Now only non-stabb symbols are read.
251 *
252 * @param stream The stream to be read from.
253 * @param sectionOffset The offset of the element in section.
254 * @param reader The base reader for a.out.
255 * @return Newly created symbol.
256 * @exception KeyAlreadyExists If key used to register object is in use.
257 * @exception UnreachableStream If there occurs problems with stream.
258 * @exception OutOfRange If offset read is out of the section.
259 */
262 BinaryStream& stream, SectionOffset sectionOffset,
263 AOutReader* reader) const {
264 StringSection* stringSection =
265 dynamic_cast<AOutReader*>(parent())->stringSection();
266
267 SymbolElement *element = NULL;
268
269 // first there is an offset to string in string table
270 Word strtabOff = stream.readWord();
271
272 // type of symbol
273 Byte type = stream.readByte();
274
275 // not used
276 Byte other = stream.readByte();
277
278 // description of the symbol, reserved for debugger use
279 // not needed in tpef (there is debug section for that)
280 HalfWord desc = stream.readHalfWord();
281
282 // offset of the value of the symbol
283 Word value = stream.readWord();
284
285 // key to string of symbol
286 SectionOffsetKey strOffKey =
288
289
290 // create element of right type
291 switch (type&(~AOutReader::N_EXT)) {
292
293 case AOutReader::N_UNDF: {
294 element = new NoTypeSymElement();
295 element->setSection(reader->nullSection());
296 break;
297 }
298
299 case AOutReader::N_TEXT: {
300 // create code symbols only if there really is code section
301 if (reader->header().sectionSizeText() != 0) {
302
303 // if new compilation module start symbol, start new module for
304 // resource id resolving...
305 std::string symbolName =
306 stringSection->chunk2String(stringSection->chunk(strtabOff));
307
308 if (GCC_MODULE_START_SYMBOL1 == symbolName) {
309 Word tpefAddress = value/8;
310 addedResources_.push_back(CompilationModule(tpefAddress));
311 }
312
313 element = new CodeSymElement();
314
315 // convert a.out address to suitable for section offset key..
316 value = reader->sectionOffsetOfAddress(value);
317
318 SectionOffsetKey valueKey(AOutReader::ST_TEXT, value);
319 CodeSymElement *elem = dynamic_cast<CodeSymElement*>(element);
320 elem->setReference(CREATE_SAFEPOINTER(valueKey));
321
323 element->setSection(CREATE_SAFEPOINTER(sKey));
324
325 } else { // otherwise create no type symbol
326 element = new NoTypeSymElement();
327 element->setSection(reader->nullSection());
328 }
329
330 break;
331 }
332
334 case AOutReader::N_BSS: {
335 element = new DataSymElement();
336
337 value = reader->sectionOffsetOfAddress(value);
338
339 SectionOffsetKey valueKey(type&(~AOutReader::N_EXT), value);
340 DataSymElement *elem = dynamic_cast<DataSymElement*>(element);
341 elem->setReference(CREATE_SAFEPOINTER(valueKey));
342
343
345
347 element->setSection(CREATE_SAFEPOINTER(sKey));
348 break;
349 }
350
351 case AOutReader::N_FN: {
352 element = new FileSymElement();
353 element->setSection(reader->nullSection());
354 break;
355 }
356
357 case AOutReader::N_PRTAB: {
358 std::string symbolName =
359 stringSection->chunk2String(stringSection->chunk(strtabOff));
360
361 if (!MapTools::containsKey(resolvedResources_, symbolName)) {
362 resolvedResources_[symbolName] = value;
363 } else {
364 // if symbol with same name has different value
365 // add replacement entry
366 Word resolvedValue = resolvedResources_[symbolName];
367 if (value != resolvedValue) {
368 addedResources_[addedResources_.size()-1].resources_[value] =
369 resolvedValue;
370 }
371 }
372
373 return NULL;
374 }
375
376 case AOutReader::N_ANN: {
377
378 std::string symbolName =
379 stringSection->chunk2String(stringSection->chunk(strtabOff));
380
381 // value - address of instruction, symbolName - all the data
382 Word numberOfInstruction = value / 8;
383 annotationes_.push_back(std::pair<Word, std::string>(numberOfInstruction, symbolName));
384 return NULL;
385 }
386
387 // rest of symbols are stored as stabs
388 default: {
389 DebugStabElem* stab =
390 new DebugStabElem(type, other, desc, value);
391
392 stab->setDebugString(CREATE_SAFEPOINTER(strOffKey));
393
394 reader->debugSection()->addElement(stab);
395
396 return NULL;
397 } break;
398
399 }
400
401 // inform ReferenceManager about new symbol
402 SectionOffsetKey offKey =
404 SafePointer::addObjectReference(offKey, element);
405
406 // figure out symbol linkage scope (local/global)
407 if (static_cast<Byte>(type) & static_cast<Byte>(AOutReader::N_EXT)) {
409 } else {
411 }
412
413 // symbol name string
414 element->setName(CREATE_SAFEPOINTER(strOffKey));
415
416 return element;
417}
418
419/**
420 * Finalizer method for AOut symbol sections.
421 *
422 * Removes reserved gcc code symbols and converts compilation unit code label
423 * to file symbol.
424 *
425 * Fixes resource references of special operations to use same id in all
426 * compilation units.
427 *
428 * Adds annotationes to needed moves.
429 *
430 * @param section Section to finalize.
431 */
432void
434
435 StringSection *strTab = dynamic_cast<StringSection*>(section->link());
436
437 NullSection* nullSection =
438 dynamic_cast<AOutReader*>(parent())->nullSection();
439
440 assert(nullSection);
441
442 // make file symbols to tpef
443 for (Word i = 0; i < section->elementCount(); i++) {
444
445 SymbolElement *sym =
446 dynamic_cast<SymbolElement*>(section->element(i));
447
448 if (sym->type() == SymbolElement::STT_CODE) {
449
450 std::string symName = strTab->chunk2String(sym->name());
451
452 // if read a.out is linked and compilation unit's start
453 // symbol is found (i == 1 and GCC_MODULE_START_SYMBOL1 is
454 // found it means that first read symbol from a.out was
455 // GCC_MODULE_START_SYMBOL1. In linked a.out there is always
456 // symbol for each compilation module before
457 // GCC_MODULE_START_SYMBOL1)
458
459
460 if (i > 1 && symName == GCC_MODULE_START_SYMBOL1) {
461
462 SymbolElement *prevSymbol =
463 dynamic_cast<SymbolElement*>(section->element(i - 1));
464
465 // previous symbol can be either code symbol or no type,
466 // if there is no instructions in compilation modulex
467 assert(prevSymbol->type() == SymbolElement::STT_CODE ||
468 prevSymbol->type() == SymbolElement::STT_NOTYPE);
469
470 FileSymElement *newFileSym = new FileSymElement();
471 newFileSym->setName(prevSymbol->name());
472
473 newFileSym->setSection(nullSection);
474
475 CodeSymElement *codeSym =
476 dynamic_cast<CodeSymElement*>(prevSymbol);
477
478 if (codeSym != NULL) {
479 // TODO: set value and section to be same that in code
480 // section newFileSym->setSection(codeSym->section());
481 // newFileSym->setValue();
482 }
483
484 section->setElement(i - 1, newFileSym);
485
486 // replace all references to prevSymbol with
487 // newFileSym reference.
488 SafePointer::replaceAllReferences(newFileSym, prevSymbol);
489 delete prevSymbol;
490 prevSymbol = NULL;
491 }
492
493 if (symName == GCC_MODULE_START_SYMBOL1 ||
494 symName == GCC_MODULE_START_SYMBOL2) {
495
496 NoTypeSymElement *replacingSymbol = new NoTypeSymElement();
497 replacingSymbol->setName(sym->name());
498 replacingSymbol->setSection(nullSection);
499
500 section->setElement(i, replacingSymbol);
501
502 // replace all references to sym with replacing symbol
503 // reference
504 SafePointer::replaceAllReferences(replacingSymbol, sym);
505 delete sym;
506 sym = NULL;
507
508 } else {
509 // create corresponding STT_PROCEDURE symbol for each code
510 // symbol
511 ProcedSymElement *newSym = new ProcedSymElement();
512 CodeSymElement *codeSym = dynamic_cast<CodeSymElement*>(sym);
513 assert(codeSym != NULL);
514
515 newSym->setAbsolute(codeSym->absolute());
517 newSym->setName(codeSym->name());
518 newSym->setSection(codeSym->section());
519 newSym->setReference(codeSym->reference());
520 newSym->setSize(codeSym->size());
521
522 section->addElement(newSym);
523 }
524 }
525 }
526
527 // fix operand references from code section with information gathered from
528 // symbol table.
529
530 CodeSection* textSection =
531 dynamic_cast<AOutReader*>(parent())->textSection();
532
533 for (unsigned int i = 0; i < addedResources_.size(); i++) {
534 CompilationModule& module = addedResources_[i];
535
536 // resolve address slice to convert...
537 Word lastAddress = textSection->instructionCount();
538
539 if (i < addedResources_.size() - 1) {
540 lastAddress = addedResources_[i+1].startAddress_;
541 }
542
543 // fix the stuff...
544 for (unsigned int j = module.startAddress_; j < lastAddress; j++) {
545
546 // get move to check
547 InstructionElement* instr = &textSection->instruction(j);
548
549 MoveElement* move = NULL;
550
551 // check only move's
552 if (instr->isImmediate()) {
553 Word sectionIndex = textSection->instructionToSectionIndex(j);
554 instr = dynamic_cast<InstructionElement*>(
555 textSection->element(sectionIndex + 1));
556 }
557
558 move = dynamic_cast<MoveElement*>(instr);
559
560 // if source is universal FU port, replace if updating is needed
561 if (move->sourceType() == MoveElement::MF_UNIT &&
564 module.resources_, move->sourceIndex())) {
565
566 move->setSourceIndex(module.resources_[move->sourceIndex()]);
567 }
568
569 // if destination is universal FU port,
570 // replace if updating is needed
571 if (move->destinationType() == MoveElement::MF_UNIT &&
574 module.resources_, move->destinationIndex())) {
575
577 module.resources_[move->destinationIndex()]);
578 }
579 }
580
581 }
582
583 // Add annotations to instruction elements
584 for (Word i = 0; i < annotationes_.size(); i++) {
585
586 InstructionElement* instr = dynamic_cast<InstructionElement*>(
587 textSection->element(annotationes_[i].first));
588
589 std::string annString = annotationes_[i].second;
590
591 // first 10 letters are annotation ID
592 if (annString.at(10) != ':') {
593 throw IllegalProgram(
594 __FILE__, __LINE__, __func__,
595 "11 first characters of annotation stab must contain "
596 "annotation ID ending with ':' e.g. '0x00011000:'");
597 }
598
599 Word annId = Conversion::toInt(annString.substr(0,10));
600
601 std::string payString = annString.substr(11,annString.length() - 10);
602 std::vector<Byte> payload;
603
604 for (unsigned int j = 0; j < payString.length(); j++) {
605 payload.push_back(payString.at(j));
606 }
607
608 instr->addAnnotation(new InstructionAnnotation(annId, payload));
609 }
610}
611
612} // namespace TPEF
#define __func__
#define assert(condition)
unsigned char Byte
Definition BaseType.hh:116
static int toInt(const T &source)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
Word sectionSizeText() const
Word sectionSizeSymbol() const
@ ST_SYMBOL
Symbol table.
@ ST_STRING
String table.
@ ST_TEXT
Text section.
SectionOffset sectionOffsetOfAddress(AddressImage address) const
NullSection * nullSection() const
DebugSection * debugSection() const
@ N_ANN
TCE annotation entry.
@ N_UNDF
Undefined.
Definition AOutReader.hh:62
@ N_PRTAB
TCE processors resource entry.
@ N_FN
File name.
Definition AOutReader.hh:68
@ N_EXT
Mask bit for external.
Definition AOutReader.hh:69
static const Word FIRST_FU_REGISTER
Index of the first function unit register.
static const Header & header()
virtual BinaryReader * parent() const
static const std::string GCC_MODULE_START_SYMBOL1
One of the symbols that are used to indicate start of new compilation module in a....
SymbolElement * initializeSymbol(BinaryStream &stream, SectionOffset sectionOffset, AOutReader *reader) const
static AOutSymbolSectionReader proto_
Class-wide (unique) prototype instance of AOutSymbolSectionReader registered into SectionReader.
virtual void finalize(Section *section) const
static const Word DATA_SYMBOL_SIZE
Data symbol size in bytes.
std::vector< CompilationModule > addedResources_
List of compilation modules of a.out.
std::vector< std::pair< Word, std::string > > annotationes_
virtual Section::SectionType type() const
std::map< std::string, Word > resolvedResources_
Resource id:s for strings.
static const std::string GCC_MODULE_START_SYMBOL2
One of the symbols that are used to indicate start of new compilation module in a....
virtual void readData(BinaryStream &stream, Section *section) const
unsigned int readPosition()
HalfWord readHalfWord()
SectionOffset offset() const
virtual InstructionElement * element(Word index) const
InstructionElement & instruction(Word index) const
Word instructionToSectionIndex(Word index) const
Word instructionCount() const
InstructionElement * reference() const
void setSize(Word aSize)
void setReference(InstructionElement *aReference)
void setReference(Chunk *aReference)
void setSize(Word aSize)
void setDebugString(const ReferenceManager::SafePointer *aString)
void addAnnotation(InstructionAnnotation *anAnnotation)
FieldType destinationType() const
HalfWord destinationIndex() const
HalfWord destinationUnit() const
void setSourceIndex(HalfWord aSourceIndex)
HalfWord sourceUnit() const
HalfWord sourceIndex() const
void setDestinationIndex(HalfWord aDestinationIndex)
FieldType sourceType() const
@ MF_UNIT
Function unit.
virtual Chunk * chunk(SectionOffset offset) const
Definition Section.cc:212
static void addObjectReference(SectionIndexKey key, const SafePointable *obj)
static void replaceAllReferences(SafePointable *newObj, SafePointable *oldObj)
void setId(HalfWord aId)
void setName(ReferenceManager::SafePointer *aName)
@ MRT_BUS
Transport bus.
@ MRT_SR
Special register.
@ MRT_UNIT
Function unit.
@ MRT_OP
Operation operand or function unit register.
@ UNIVERSAL_BUS
Universal bus.
@ UNIVERSAL_FU
Universal function unit.
@ INT_RF
Universal integer register file.
@ BOOL_RF
Universal boolean register file.
@ FP_RF
Universal floating point register file.
void setType(ResourceType aType)
static void registerSectionReader(const SectionReader *sReader)
virtual void setElement(Word index, SectionElement *element)
Definition Section.cc:145
virtual void addElement(SectionElement *element)
Definition Section.cc:133
Section * link() const
@ ST_SYMTAB
Symbol table.
Definition Section.hh:72
SectionElement * element(Word index) const
Word elementCount() const
std::string chunk2String(const Chunk *chunk) const
Chunk * string2Chunk(const std::string &str)
@ STT_CODE
Associated with executable code.
@ STT_NOTYPE
Type is not defined.
virtual SymbolType type() const =0
Returns type of symbol.
void setAbsolute(bool anAbsoluteness)
void setName(Chunk *aName)
void setBinding(SymbolBinding aBinding)
bool absolute() const
Section * section() const
void setSection(Section *aSect)
Chunk * name() const
@ STB_LOCAL
Not visible outside the object file that contains it's definition.
@ STB_GLOBAL
Visible to all files that are combined in TPEF file.
Word SectionOffset
Type for storing offsets relative to a given base offset value.
Word FileOffset
Type for storing absolute file offsets.