OpenASIP 2.2
Loading...
Searching...
No Matches
LabelManager.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 LabelManager.cc
26 *
27 * Definition of LabelManager class.
28 *
29 * @author Mikael Lepistö 2005 (tmlepist-no.spam-cs.tut.fi)
30 * @author Pekka Jääskeläinen 2006 (pekka.jaaskelainen-no.spam-tut.fi)
31 *
32 * @note rating: yellow
33 */
34
35#include "LabelManager.hh"
37
38#include "Binary.hh"
39#include "SymbolSection.hh"
40#include "RelocSection.hh"
41#include "RelocElement.hh"
42#include "ASpaceElement.hh"
43#include "DataSymElement.hh"
44#include "CodeSymElement.hh"
45#include "ProcedSymElement.hh"
46#include "NoTypeSymElement.hh"
47#include "StringSection.hh"
48#include "ContainerTools.hh"
49#include "SymbolElement.hh"
50#include "CodeSection.hh"
51#include "DataSection.hh"
52#include "UDataSection.hh"
53#include "SequenceTools.hh"
54#include "MapTools.hh"
55#include "Exception.hh"
56#include "TPEFTools.hh"
57
58using TPEF::Binary;
64using TPEF::Section;
74using TPEF::TPEFTools;
75
76/**
77 * Constructor.
78 *
79 * @param bin Binary containing data and code sections of relocations.
80 * @param resources Resource manager for getting TPEF resources.
81 * @param parent Assembler root class.
82 */
84 Binary& bin,
85 MachineResourceManager& resources,
86 AssemblyParserDiagnostic* /*parent*/) :
87 bin_(bin), resources_(resources) {
88}
89
90/**
91 * Destructor.
92 */
95
96 while (!relocs_.empty()) {
97 delete *relocs_.begin();
98 relocs_.erase(relocs_.begin());
99 }
100}
101
102/**
103 * Returns value of a label by name.
104 *
105 * @param name Name of the requested label.
106 * @return Value of the label.
107 * @exception SymbolNotFound If there is not symbol for requested name.
108 */
109UValue
110LabelManager::value(std::string& name) {
111 if(!MapTools::containsKey(labels_, name)) {
112
113 throw SymbolNotFound(
114 __FILE__, __LINE__, __func__,
115 "Can't find value for label: " + name);
116 }
117
118 return labels_[name]->value;
119}
120
121/**
122 * Returns a TPEF address space element for a label by name.
123 *
124 * @param labelName Name of the requested label.
125 * @return Address space of the label.
126 * @exception SymbolNotFound If there is not symbol for requested name.
127 */
129LabelManager::aSpaceElement(std::string& labelName) {
130 if(!MapTools::containsKey(labels_, labelName)) {
131 throw SymbolNotFound(
132 __FILE__, __LINE__, __func__,
133 "Can't find address address space for label: " + labelName);
134 }
135
136 return *labels_[labelName]->aSpace;
137}
138
139/**
140 * Returns the name of the address space for a label.
141 *
142 * @param labelName Name of the requested label.
143 * @return Name of the address space the label belongs in.
144 * @exception SymbolNotFound If there is not symbol for requested name.
145 */
146std::string
147LabelManager::aSpaceName(std::string& labelName) {
148 return TPEFTools::addressSpaceName(bin_, aSpaceElement(labelName));
149}
150
151/**
152 * Adds a label to manager.
153 *
154 * @param aSpace Address space of the label to add.
155 * @param name Name of the label.
156 * @param value Value for the label.
157 * @exception ObjectAlreadyExists Label by the same name already exists.
158 */
159void
160LabelManager::addLabel(ASpaceElement& aSpace, std::string& name, UValue value) {
161 if(MapTools::containsKey(labels_, name)) {
163 __FILE__, __LINE__, __func__,
164 "Multiply defined lablel: " + name);
165 }
166
167 InternalLabel *newElem = new InternalLabel();
168
169 newElem->name = name;
170 newElem->aSpace = &aSpace;
171 newElem->value = value;
172
173 labels_[name] = newElem;
174}
175
176/**
177 * Removes a label from manager.
178 *
179 * @param name Name of the label.
180 * @exception SymbolNotFound Label is not found.
181 */
182void
183LabelManager::removeLabel(std::string& name) {
184 if(!MapTools::containsKey(labels_, name)) {
185 throw SymbolNotFound(
186 __FILE__, __LINE__, __func__,
187 "Can't find label: " + name);
188 }
189
190 labels_.erase(name);
191}
192
193/**
194 * Adds a procedure to manager.
195 *
196 * @param name Name of the procedure
197 * @param address Start address of the procedure.
198 * @exception ObjectAlreadyExists Procedure with a same name is already added.
199 */
200void
201LabelManager::addProcedure(std::string& name, UValue address) {
204 __FILE__, __LINE__, __func__,
205 "Multiply defined procedure: " + name);
206 }
207
208 procedures_[name] = address;
209}
210
211/**
212 * Set's label to be global label.
213 *
214 * @param labelName Name of label to set global.
215 */
216void
217LabelManager::setGlobal(std::string &labelName) {
218 globals_.insert(labelName);
219}
220
221/**
222 * Adds relocated immediate or data chunk.
223 *
224 * @param locationSect Section where relocated element is stored.
225 * @param location Immediate or Chunk containing value to relocate.
226 * @param dstASpace Destination address space of relocation.
227 * @param destination Destination address of relocation.
228 * @param bitWidth Size of the relocated field.
229 */
230void
232 Section& locationSect,
233 SectionElement& location,
234 ASpaceElement& dstASpace,
235 UValue destination,
236 UValue bitWidth) {
237
238 InternalRelocation *newElem = new InternalRelocation();
239
240 newElem->locationSect = &locationSect;
241 newElem->location = &location;
242 newElem->dstASpace = &dstASpace;
243 newElem->destination = destination;
244 newElem->bitWidth = bitWidth;
245
246 uncommittedRelocs_.insert(newElem);
247}
248
249/**
250 * Removes relocations that are added but not committed to manager.
251 *
252 * Used for cleaning up in error cases.
253 */
254void
258
259/**
260 * Frees all internally allocated data.
261 */
262void
270
271/**
272 * Adds permanently relocations that are added but not yet
273 * committed to manager.
274 */
275void
277
278 // add last relocations for writing down
279 for (std::set<InternalRelocation*>::iterator iter =
280 uncommittedRelocs_.begin();
281 iter != uncommittedRelocs_.end(); iter++) {
282
283 relocs_.insert(*iter);
284 }
285
286 uncommittedRelocs_.clear();
287}
288
289/**
290 * Creates symbol and relocation tables corresponding to input information.
291 *
292 * All destinations must exist in TPEF before this method can be executed,
293 * otherwise finalize will throw exception. If exception is thrown finalize
294 * method will not do any changes to TPEF. When error that caused the
295 * exception is fixed, method can be re-executed and it continues from the
296 * same phase until the end.
297 *
298 * @exception CompileError There was problems during the resolving.
299 */
300void
302 SymbolSection* symbolSect = NULL;
303
304 // write labels
306 NoTypeSymElement* undefSymbol = NULL;
307
308 // create always symbol section with undefined symbol
309 symbolSect = dynamic_cast<SymbolSection*>(
310 Section::createSection(Section::ST_SYMTAB));
311
312 try {
314
315 symbolSect->setLink(strings);
316
317 undefSymbol = new NoTypeSymElement();
318 undefSymbol->setName(strings->string2Chunk(""));
319 symbolSect->addElement(undefSymbol);
320
321 // write code and data labels
322 for (SymbolMap::iterator iter = labels_.begin();
323 iter != labels_.end(); iter++) {
324
325 InternalLabel *currLabel = (*iter).second;
326
327 Section *ownerSection = findSectionByAddress(currLabel);
328 assert(ownerSection != NULL);
329
330 SymbolElement *symbol =
331 createSymbolWithReference(currLabel, ownerSection);
332 assert(symbol != NULL);
333
334 symbol->setSection(ownerSection);
335 symbol->setName(strings->string2Chunk(currLabel->name));
336 symbol->setAbsolute(false);
337
338 // check if global
340 symbol->setBinding(SymbolElement::STB_GLOBAL);
341 globals_.erase(currLabel->name);
342 } else {
343 symbol->setBinding(SymbolElement::STB_LOCAL);
344 }
345
346 symbolSect->addElement(symbol);
347 }
348
349 // if there is global definition without corresponding label
350 if (!globals_.empty()) {
351 throw CompileError(
352 __FILE__, __LINE__, __func__,
353 "Can't set label to be global. " +
354 *(globals_.begin()) + " is undefined.");
355 }
356
357 // write procedure symbols
358 if (bin_.sectionCount(Section::ST_CODE) != 0) {
359
360 CodeSection *codeSect =
361 dynamic_cast<CodeSection*>(
362 bin_.section(Section::ST_CODE, 0));
363
364 assert(codeSect != NULL);
365 writeProcedureSymbols(codeSect, symbolSect, strings);
366
367 } else if (procedures_.size() != 0) {
368 throw CompileError(
369 __FILE__, __LINE__, __func__,
370 "Invalid procedure declaration: " +
371 (*procedures_.begin()).first);
372 }
373
374 // write relocations
375 for (std::set<InternalRelocation*>::iterator iter = relocs_.begin();
376 iter != relocs_.end(); iter++) {
377
378 InternalRelocation *currReloc = *iter;
379
380 // find relocation section for corresponding location section
381 RelocSection* relocSect =
382 findOrCreateRelocationSection(currReloc, symbolSect);
383 assert(relocSect != NULL);
384
385 // find destination section
386 Section* dstSect = findRelocationDstSection(currReloc);
387
388 if (dstSect == NULL) {
389 throw CompileError(
390 __FILE__, __LINE__, __func__,
391 "Can't find destination section for address: "
392 + Conversion::toString(currReloc->destination) +
393 " of adress space: " +
394 TPEFTools::addressSpaceName(bin_, *currReloc->dstASpace));
395 }
396
397 RelocElement *newReloc = new RelocElement();
398
399 newReloc->setLocation(currReloc->location);
400
401 Word dstIndex =
402 currReloc->destination - dstSect->startingAddress();
403
404 // set destination element
405 if (dstSect->isCodeSection()) {
406 CodeSection* codeSect =
407 dynamic_cast<CodeSection*>(dstSect);
408
409 newReloc->setDestination(&codeSect->instruction(dstIndex));
410
411 } else if (dstSect->type() == Section::ST_DATA ||
412 dstSect->type() == Section::ST_LEDATA ||
413 dstSect->type() == Section::ST_UDATA) {
414
415 UDataSection* uDataSect =
416 dynamic_cast<UDataSection*>(dstSect);
417
418 Word byteOffset = uDataSect->MAUsToBytes(dstIndex);
419
420 newReloc->setDestination(uDataSect->chunk(byteOffset));
421
422 } else {
423 abortWithError("Unknown dst section of relocation.");
424 }
425
426 newReloc->setASpace(currReloc->dstASpace);
427 newReloc->setType(RelocElement::RT_SELF);
428 newReloc->setChunked(false);
429 newReloc->setSymbol(undefSymbol);
430 newReloc->setSize(currReloc->bitWidth);
431
432 relocSect->addElement(newReloc);
433 }
434
435 } catch(CompileError& e) {
436 delete symbolSect;
437 throw e;
438 }
439
440 bin_.addSection(symbolSect);
441
442 cleanup();
443}
444
445/**
446 * Returns section that contains the address stored in label.
447 *
448 * @param currLabel Label whose destination section is returned.
449 * @return Section that contains the address stored in label.
450 */
451Section*
453
454 // find section by address space
455 for (Word i = 0; i < bin_.sectionCount(); i++) {
456 Section *currSect = bin_.section(i);
457
458 if (currSect->aSpace() == currLabel->aSpace) {
459
460 // address must be found from section
461 if (currSect->type() == Section::ST_DATA ||
462 currSect->type() == Section::ST_LEDATA ||
463 currSect->type() == Section::ST_UDATA) {
464
465 UDataSection* sect =
466 dynamic_cast<UDataSection*>(currSect);
467
468 assert(sect != NULL);
469
470 if (currLabel->value >= sect->startingAddress() &&
471 currLabel->value - sect->startingAddress() <
472 sect->lengthInMAUs()) {
473
474 return currSect;
475 }
476
477 } else if (currSect->isCodeSection()) {
478
479 CodeSection* sect = dynamic_cast<CodeSection*>(currSect);
480
481 assert(sect != NULL);
482
483 if (currLabel->value >= sect->startingAddress() &&
484 currLabel->value - sect->startingAddress() <
485 sect->instructionCount()) {
486
487 return currSect;
488 }
489
490 } else {
491 abortWithError("Label must point to data or code section.");
492 }
493 }
494
495 }
496 return NULL;
497}
498
499/**
500 * Creates new TPEF SymbolElement and sets reference field of symbol.
501 *
502 * @param currLabel Label which for symbol element is created.
503 * @param ownerSection Section who contains element referred by label.
504 * @return Dynamically allocated TPEF symbol with reference field set.
505 */
508 InternalLabel *currLabel,
509 Section* ownerSection) {
510
511 SymbolElement *symbol = NULL;
512
513 if (ownerSection->isCodeSection()) {
514 CodeSymElement *codeSym = new CodeSymElement();
515 symbol = codeSym;
516
517 CodeSection *codeSection =
518 dynamic_cast<CodeSection*>(ownerSection);
519
520 codeSym->setReference(
521 &codeSection->instruction(currLabel->value));
522
523 } else {
524 DataSymElement *dataSym = new DataSymElement();
525 symbol = dataSym;
526
527 UDataSection *uDataSection =
528 dynamic_cast<UDataSection*>(ownerSection);
529
530 dataSym->setReference(
531 uDataSection->chunk(
532 uDataSection->MAUsToBytes(
533 currLabel->value - ownerSection->startingAddress())));
534 }
535
536 return symbol;
537}
538
539/**
540 * Writes all procedure symbols of code section to symbol section.
541 *
542 * @param codeSect Section whose symbols are written.
543 * @param symbolSect Section where to symbols are written.
544 * @param string Sectiong where symbol strings are stored.
545 * @exception CompileError Procedure declaration is is not in code section.
546 */
547void
549 CodeSection* codeSect, SymbolSection* symbolSect, StringSection* strings) {
550 for (std::map<std::string, UValue>::iterator
551 iter = procedures_.begin();
552 iter != procedures_.end(); iter++) {
553
554 std::string name = (*iter).first;
555 UValue address = (*iter).second;
556
557 if (address >=
558 codeSect->instructionCount() +
559 codeSect->startingAddress()) {
560
561 throw CompileError(
562 __FILE__, __LINE__, __func__,
563 "Invalid procedure declaration: " +
564 name);
565 }
566
567 ProcedSymElement *procedSym = new ProcedSymElement();
568
569 procedSym->setReference(
570 &codeSect->instruction(
571 address - codeSect->startingAddress()));
572
573 procedSym->setSection(codeSect);
574 procedSym->setName(strings->string2Chunk(name));
575 procedSym->setAbsolute(false);
576 procedSym->setBinding(SymbolElement::STB_LOCAL);
577
578 symbolSect->addElement(procedSym);
579 }
580}
581
582/**
583 * Finds or creates relocation section for relocation.
584 *
585 * @param currReloc Relocation whose section is looked for.
586 * @param symbolSect Strings for created section.
587 * @return Suitable relocation section for requested relocation.
588 */
591 InternalRelocation* currReloc, SymbolSection* symbolSect) {
592
593 RelocSection* relocSect = NULL;
594
595 for (Word j = 0; j < bin_.sectionCount(Section::ST_RELOC); j++) {
596 RelocSection* currSect =
597 dynamic_cast<RelocSection*>(
598 bin_.section(Section::ST_RELOC, j));
599
600 if (currSect->referencedSection() ==
601 currReloc->locationSect) {
602 return currSect;
603 }
604 }
605
606 // none found, create new reloc section
607 if (relocSect == NULL) {
608 relocSect = dynamic_cast<RelocSection*>(
609 Section::createSection(Section::ST_RELOC));
610
611 relocSect->setReferencedSection(currReloc->locationSect);
613 relocSect->setLink(symbolSect);
614
615 bin_.addSection(relocSect);
616 }
617
618 return relocSect;
619}
620
621/**
622 * Returns destination section of the relocation.
623 *
624 * @param currReloc Relocation whose destination is wanted.
625 * @return Destination section of the relocation.
626 */
627Section*
629
630 for (Word j = 0; j < bin_.sectionCount(); j++) {
631 Section* currSect = bin_.section(j);
632
633 // check address space and starting address
634 if (currSect->aSpace() == currReloc->dstASpace &&
635 currSect->startingAddress() <= currReloc->destination) {
636
637 if (currSect->isCodeSection()) {
638 CodeSection* codeSect = dynamic_cast<CodeSection*>(currSect);
639
640 // check that section is enough long
641 if (codeSect->instructionCount() +
642 codeSect->startingAddress() > currReloc->destination) {
643
644 return currSect;
645 }
646
647 } else if (currSect->type() == Section::ST_DATA ||
648 currSect->type() == Section::ST_LEDATA ||
649 currSect->type() == Section::ST_UDATA) {
650
651 UDataSection* uDataSect =
652 dynamic_cast<UDataSection*>(currSect);
653
654 // check that section is enough long
655 if (uDataSect->lengthInMAUs() +
656 uDataSect->startingAddress() > currReloc->destination) {
657
658 return currSect;
659 }
660 }
661 }
662 }
663
664 return NULL;
665}
666
667
668/**
669 * Resolves value of label expression.
670 *
671 * @param asmLineNumber Current assembly code line number error information.
672 * @param litOrExpr Expression whose value to resolve.
673 * @param labels Label manager for resolving label values.
674 * @return Value of expression.
675 * @exception CompileError There was error with resolving value.
676 */
677UValue
679 UValue asmLineNumber, LiteralOrExpression& litOrExpr) {
680 UValue retVal = 0;
681
682 try {
683 retVal = value(litOrExpr.expression.label);
684
685 } catch (SymbolNotFound& e) {
686 CompileError error(
687 __FILE__, __LINE__, __func__,
688 e.errorMessage());
689
690 error.setCause(e);
691 error.setCodeFileLineNumber(asmLineNumber);
692
693 throw error;
694 }
695
696 if (litOrExpr.expression.hasOffset) {
697 if (litOrExpr.expression.isMinus) {
698 retVal -= litOrExpr.expression.offset;
699 } else {
700 retVal += litOrExpr.expression.offset;
701 }
702 }
703
704 // check if value matches with label + offset
705 if(litOrExpr.expression.hasValue) {
706 if (litOrExpr.expression.value != retVal) {
707
708 CompileError error(
709 __FILE__, __LINE__, __func__,
710 "Defined expression value (" +
712 ") does not match with resolved (" +
713 Conversion::toString(retVal) +
714 ") one.");
715
716 error.setCodeFileLineNumber(asmLineNumber);
717
718 throw error;
719 }
720 }
721
722 return retVal;
723}
#define __func__
#define abortWithError(message)
#define assert(condition)
unsigned long UValue
void setCodeFileLineNumber(int lineNum)
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
static std::string toString(const T &source)
std::string errorMessage() const
Definition Exception.cc:123
void setCause(const Exception &cause)
Definition Exception.cc:75
bool hasOffset
Is offset defined.
bool isMinus
Is offset minus.
UValue value
Resolved value.
bool hasValue
Is resolved value defined in struct.
std::string label
Name of the label.
UValue offset
Value of offset.
TPEF::SymbolElement * createSymbolWithReference(InternalLabel *currLabel, TPEF::Section *ownerSection)
void removeLabel(std::string &name)
TPEF::RelocSection * findOrCreateRelocationSection(InternalRelocation *currReloc, TPEF::SymbolSection *symbolSect)
void clearLastRelocations()
UValue value(std::string &name)
void addProcedure(std::string &name, UValue value)
SymbolMap labels_
Contains stored symbols by their name.
TPEF::Section * findSectionByAddress(InternalLabel *currLabel)
UValue resolveExpressionValue(UValue asmLineNumber, LiteralOrExpression &litOrExpr)
void setGlobal(std::string &labelName)
std::string aSpaceName(std::string &labelName)
void writeProcedureSymbols(TPEF::CodeSection *codeSect, TPEF::SymbolSection *symbolSect, TPEF::StringSection *strings)
void commitLastRelocations()
TPEF::ASpaceElement & aSpaceElement(std::string &labelName)
std::set< InternalRelocation * > relocs_
Added relocations.
std::set< std::string > globals_
Names of global symbols.
TPEF::Binary & bin_
For finding sections containing relocated elements.
std::set< InternalRelocation * > uncommittedRelocs_
Uncommitted relocations.
void addRelocation(TPEF::Section &locationSect, TPEF::SectionElement &location, TPEF::ASpaceElement &dstASpace, UValue destination, UValue bitWidth)
LabelManager(TPEF::Binary &bin, MachineResourceManager &resources, AssemblyParserDiagnostic *parent)
void addLabel(TPEF::ASpaceElement &aSpace, std::string &name, UValue value)
MachineResourceManager & resources_
Common resources of TPEF.
std::map< std::string, UValue > procedures_
Names and addresses of procedure starts.
TPEF::Section * findRelocationDstSection(InternalRelocation *currReloc)
Expression expression
If expression the expression, Otherwise not used.
TPEF::StringSection * stringSection()
TPEF::ASpaceElement * undefinedAddressSpace()
static void deleteAllValues(MapType &aMap)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static void deleteAllItems(SequenceType &aSequence)
void addSection(Section *section)
Word sectionCount() const
Section * section(Word index) const
InstructionElement & instruction(Word index) const
Word instructionCount() const
void setReference(InstructionElement *aReference)
void setReference(Chunk *aReference)
virtual Chunk * chunk(SectionOffset offset) const
Definition Section.cc:212
virtual Word MAUsToBytes(Word mauCount) const
Definition Section.cc:320
virtual Word lengthInMAUs() const
Definition Section.cc:285
void setASpace(ASpaceElement *anASpace)
void setLocation(SectionElement *aLocation)
void setSize(Byte aSize)
void setSymbol(SymbolElement *aSymbol)
void setChunked(bool isChunked)
void setType(RelocType aType)
void setDestination(SectionElement *aDestination)
void setReferencedSection(Section *section)
Section * referencedSection() const
AddressImage startingAddress() const
virtual void addElement(SectionElement *element)
Definition Section.cc:133
virtual bool isCodeSection() const
Definition Section.hh:143
void setLink(const ReferenceManager::SafePointer *aLink)
void setASpace(const ReferenceManager::SafePointer *addrSpace)
virtual SectionType type() const =0
Returns SectioType of actual section instance.
ASpaceElement * aSpace() const
Chunk * string2Chunk(const std::string &str)
void setAbsolute(bool anAbsoluteness)
void setName(Chunk *aName)
void setBinding(SymbolBinding aBinding)
void setSection(Section *aSect)
TPEF::ASpaceElement * aSpace
Address space of the label.
std::string name
Name of the label.
UValue value
Address where label is located.
TPEF::SectionElement * location
Element that is reloacted.
TPEF::Section * locationSect
Section where relocated immediate or chunk is stored.
UValue bitWidth
Number of bits that are used to store the value.
UValue destination
Destination address.
TPEF::ASpaceElement * dstASpace
Address space of destination address.