OpenASIP  2.0
TPEFRelocSectionReader.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 TPEFRelocSectionReader.cc
26  *
27  * Definition of TPEFRelocSectionReader class.
28  *
29  * @author Mikael Lepistö 2003 (tmlepist-no.spam-cs.tut.fi)
30  *
31  * @note rating: yellow
32  */
33 
34 #include <cmath> // ceil()
35 
36 #include "boost/format.hpp"
37 
39 #include "SafePointer.hh"
40 #include "Exception.hh"
41 #include "ReferenceKey.hh"
42 #include "SectionReader.hh"
43 #include "TPEFBaseType.hh"
44 #include "BinaryStream.hh"
45 #include "RelocSection.hh"
46 #include "RelocElement.hh"
47 #include "ImmediateElement.hh"
48 
49 #include "TPEFHeaders.hh"
50 #include "ASpaceSection.hh"
51 #include "CodeSection.hh"
52 #include "DataSection.hh"
53 #include "LEDataSection.hh"
54 
55 #include "TPEFBaseType.hh"
56 #include "Locator.hh"
57 
58 #include "Swapper.hh"
59 
60 #include "MathTools.hh"
61 
62 namespace TPEF {
63 
64 using ReferenceManager::SafePointer;
65 using ReferenceManager::SectionKey;
66 using ReferenceManager::SectionIndexKey;
67 using ReferenceManager::SectionOffsetKey;
68 
69 TPEFRelocSectionReader TPEFRelocSectionReader::proto_;
71 
72 /**
73  * Constructor.
74  *
75  * Registers itself to SectionReader.
76  */
79 }
80 
81 /**
82  * Destructor.
83  */
85 }
86 
87 /**
88  * Returns the type of section which the reader can read.
89  *
90  * @return The type of section which reader can read.
91  */
94  return Section::ST_RELOC;
95 }
96 
97 /**
98  * Reads section data from TPEF binary file.
99  *
100  * @param stream Stream to be read from.
101  * @param section Section where the information is to be stored.
102  * @exception UnreachableStream If reading of section fails.
103  * @exception KeyAlreadyExists Key was in use when trying to register object.
104  * @exception EndOfFile If end of file were reached while it shouldn't.
105  * @exception OutOfRange Some of read values were out of range.
106  * @exception WrongSubclass Some class couldn't do what it was asked for.
107  * @exception UnexpectedValue Ift here was unexpected value when reading.
108  */
109 void
111  // base classes implementation must be called with these.
112  TPEFSectionReader::readData(stream, section);
113 
114  RelocSection* relocSection = dynamic_cast<RelocSection*>(section);
115  assert(relocSection != NULL);
116 
117  // check that link section is defined properly
118  assert(header().linkId != 0);
119 
120  if (!section->noBits()) {
121 
122  // store start of first element
123  SectionOffset elementStart = header().bodyOffset;
124  SectionIndex id = 0;
125 
126  while (elementStart + header().elementSize <=
127  header().bodyOffset + header().bodyLength) {
128 
129  RelocElement *elem = new RelocElement();
130 
131  SectionIndexKey sectionIndexKey(header().sectionId, id);
132  SafePointer::addObjectReference(sectionIndexKey, elem);
133 
134  // r_offset is source element section offset
135  Word rOffset = stream.readWord();
136  SectionOffsetKey sKey(refSectionId_, rOffset);
137  elem->setLocation(CREATE_SAFEPOINTER(sKey));
138 
139  // r_symbol
140  Word rSymbol = stream.readWord();
141  SectionIndexKey indexKey(header().linkId, rSymbol);
142  elem->setSymbol(CREATE_SAFEPOINTER(indexKey));
143 
144  // r_type
145  Byte rType = stream.readByte();
146  elem->setType(
147  static_cast<RelocElement::RelocType>(
149 
150  elem->setChunked(rType & TPEFHeaders::STF_CHUNK);
151 
152  // r_asp
153  Byte rASP = stream.readByte();
154  SectionIndexKey aSpaceIndexKey(
155  dynamic_cast<TPEFReader*>(parent())->aSpaceId(), rASP);
156  elem->setASpace(CREATE_SAFEPOINTER(aSpaceIndexKey));
157 
158  // r_size
159  elem->setSize(stream.readByte());
160 
161  // r_bitpos skipped for now
162  elem->setBitOffset(stream.readByte());
163 
164  section->addElement(elem);
165 
166  elementStart += header().elementSize;
167  stream.setReadPosition(elementStart);
168 
169  id++;
170  }
171  }
172 }
173 
174 /**
175  * Finalizer method for TPEF relocation sections.
176  *
177  * Resolves destination fields of relocation elements.
178  *
179  * @param section Section to finalize.
180  */
181 void
183 
184  Section *refSection =
185  dynamic_cast<RelocSection*>(section)->referencedSection();
186 
187  TPEFReader* tpefReader = dynamic_cast<TPEFReader*>(parent());
188 
189  for (Word i = 0; i < section->elementCount(); i++) {
190 
191  RelocElement *elem =
192  dynamic_cast<RelocElement*>(section->element(i));
193 
194  assert(elem->location() != NULL);
195 
196  // file offset of destination element to find
197  AddressImage address = 0;
198 
199  // should we dig up code or data section
200  if (refSection->isCodeSection()) {
201 
202  // value of immediate element, is an address to that element,
203  // which to immediate refers
204  ImmediateElement *imm =
205  dynamic_cast<ImmediateElement*>(elem->location());
206 
207  // relocation must have Immediate or Chunk element as location
208  assert(imm != NULL);
209  assert(imm->length() <= sizeof(address));
210 
211  // read destination address of relocation
212  unsigned int neededBits = MathTools::requiredBits(imm->word());
213  if (neededBits > elem->size()) {
214  throw OutOfRange(
215  __FILE__, __LINE__, __func__,
216  (boost::format(
217  "Destination address width %d of relocation is "
218  "bigger than the field size %d.")
219  % neededBits % elem->size()).str());
220  }
221 
222  address = imm->word();
223 
224 
225  } else if (refSection->type() == Section::ST_DATA) {
226 
227  try {
228  DataSection *dataSect =
229  dynamic_cast<DataSection*>(refSection);
230 
231  int startIndex =
232  dataSect->chunkToMAUIndex(
233  dynamic_cast<Chunk*>(elem->location()));
234 
235  int mauSize = dataSect->aSpace()->MAU();
236 
237  // BE
238  for (int i = 0; i < elem->size() / mauSize; i++) {
239  address = address << mauSize;
240  address = address | dataSect->MAU(startIndex+i);
241  }
242 
243  } catch (const OutOfRange &e) {
244  bool requestedChunkWasOutOfRange = false;
245  assert(requestedChunkWasOutOfRange);
246  }
247 
248  } else if (refSection->type() == Section::ST_LEDATA) {
249 
250  try {
251  LEDataSection *dataSect =
252  dynamic_cast<LEDataSection*>(refSection);
253 
254  int startIndex =
255  dataSect->chunkToMAUIndex(
256  dynamic_cast<Chunk*>(elem->location()));
257 
258  int mauSize = dataSect->aSpace()->MAU();
259 
260  // LE
261  for (int i = 0; i < elem->size() / mauSize; i++) {
262  address |= (dataSect->MAU(startIndex+i) << (mauSize*i));
263  }
264 
265  } catch (const OutOfRange &e) {
266  bool requestedChunkWasOutOfRange = false;
267  assert(requestedChunkWasOutOfRange);
268  }
269 
270 
271 
272  } else {
273  bool referencedSectionMustBeEitherCodeOrData = false;
274  assert(referencedSectionMustBeEitherCodeOrData);
275  }
276 
277  // if unresolved relocation leave destination to undefined
278  if (tpefReader->aSpaceSection()->isUndefined(elem->aSpace())) {
279  continue;
280  }
281 
282  // absolute address depending on relocation type and value
283  AddressImage absoluteAddress =
284  Locator::absoluteAddress(address, elem->type());
285 
286  // here we need to resolve section of section referenced
287  // by value of location
288  Section *destSection =
289  tpefReader->sectionOfAddress(elem->aSpace(), absoluteAddress);
290 
291  assert(destSection != NULL);
292 
293  // do the magic!
294 
295  // find section identification code
296  SectionId destSectionId =
297  SafePointer::sectionKeyFor(destSection).sectionId();
298 
299  SectionOffset sectOffsetOfElement;
300 
301  // if code section check instructionsize and encoding from
302  // refSection...
303  if (destSection->isCodeSection()) {
304  CodeSection *codeSection =
305  dynamic_cast<CodeSection*>(destSection);
306 
307  // find instruction number of absolute address
308  Word instructionNumber =
309  absoluteAddress - codeSection->startingAddress();
310 
311  // every index is stored for every instruction element that is
312  // start of instruction
313  SectionIndexKey sectIndexKey(destSectionId, instructionNumber);
314  elem->setDestination(CREATE_SAFEPOINTER(sectIndexKey));
315 
316  } else {
317 
318  Word mauInBytes =
319  static_cast<Word>(
320  ceil(static_cast<double>(elem->aSpace()->MAU()) /
321  static_cast<double>(BYTE_BITWIDTH)));
322 
323  // else find just section offset
324  sectOffsetOfElement =
325  (absoluteAddress - destSection->startingAddress()) *
326  mauInBytes;
327 
328  SectionOffsetKey sectOffKey(destSectionId, sectOffsetOfElement);
329  elem->setDestination(CREATE_SAFEPOINTER(sectOffKey));
330  }
331  }
332 }
333 
334 /**
335  * Reads info field of section header.
336  *
337  * Read position of stream will be moved 4 bytes forward.
338  *
339  * @param stream Stream where from info word is read.
340  * @param section Reloc section whose info field is read.
341  */
342 void
344  Section* sect) const {
345 
346  // referenced section identifier is in first 2 bytes of info field
347  refSectionId_ = stream.readHalfWord();
348 
349  if (refSectionId_ != 0) {
351  dynamic_cast<RelocSection*>(sect)->setReferencedSection(
352  CREATE_SAFEPOINTER(sKey));
353  } else {
354  bool referencedSectionOfRelocationMustNotBeNullSection = false;
355  assert(referencedSectionOfRelocationMustNotBeNullSection);
356  }
357 
358  // skip rest 2 of 4 bytes
359  stream.readHalfWord();
360 }
361 
362 }
TPEF::SectionId
HalfWord SectionId
Type for storing binary file section ids.
Definition: TPEFBaseType.hh:43
LEDataSection.hh
TPEF::Section::aSpace
ASpaceElement * aSpace() const
TPEF::DataSection::MAU
virtual MinimumAddressableUnit MAU(Word index) const
Definition: DataSection.cc:125
TPEF::TPEFSectionReader::Header::bodyOffset
Word bodyOffset
Definition: TPEFSectionReader.hh:69
TPEF::TPEFRelocSectionReader::readInfo
void readInfo(BinaryStream &stream, Section *sect) const
Definition: TPEFRelocSectionReader.cc:343
TPEF::BinaryStream::setReadPosition
void setReadPosition(unsigned int position)
Definition: BinaryStream.cc:629
Exception.hh
TPEF::TPEFReader::aSpaceSection
ASpaceSection * aSpaceSection() const
Definition: TPEFReader.cc:351
TPEF::TPEFRelocSectionReader::refSectionId_
static SectionId refSectionId_
Section id of last referenced section.
Definition: TPEFRelocSectionReader.hh:71
TPEF::LEDataSection
Definition: LEDataSection.hh:52
OutOfRange
Definition: Exception.hh:320
TPEF::TPEFRelocSectionReader::readData
virtual void readData(BinaryStream &stream, Section *section) const
Definition: TPEFRelocSectionReader.cc:110
TPEF::Section::type
virtual SectionType type() const =0
Returns SectioType of actual section instance.
TPEF::BinaryStream
Definition: BinaryStream.hh:59
TPEF::TPEFRelocSectionReader::finalize
virtual void finalize(Section *section) const
Definition: TPEFRelocSectionReader.cc:182
TPEF::ASpaceSection::isUndefined
bool isUndefined(ASpaceElement *aSpace) const
Definition: ASpaceSection.cc:93
TPEF::ImmediateElement::word
Word word() const
TPEF::TPEFHeaders::STF_RELOCATION_TYPE_MASK
@ STF_RELOCATION_TYPE_MASK
Mask for getting reloc type.
Definition: TPEFHeaders.hh:104
SafePointer.hh
TPEFHeaders.hh
TPEF::DataSection
Definition: DataSection.hh:52
TPEF::ImmediateElement
Definition: ImmediateElement.hh:49
TPEF::ASpaceElement::MAU
Byte MAU() const
TPEF::ReferenceManager::SectionKey::sectionId
SectionId sectionId() const
Byte
unsigned char Byte
Definition: BaseType.hh:116
Locator.hh
TPEF::ReferenceManager::SectionIndexKey
Definition: ReferenceKey.hh:65
TPEF::RelocElement::size
Byte size() const
TPEF::ReferenceManager::SafePointer::addObjectReference
static void addObjectReference(SectionIndexKey key, const SafePointable *obj)
Definition: SafePointer.cc:306
TPEFRelocSectionReader.hh
ImmediateElement.hh
TPEF::RelocSection
Definition: RelocSection.hh:47
TPEF::Section
Definition: Section.hh:64
TPEF::TPEFRelocSectionReader::proto_
static TPEFRelocSectionReader proto_
Prototype instance of TPEFRelocSectionReader to be registered to SectionReader.
Definition: TPEFRelocSectionReader.hh:68
TPEF::TPEFSectionReader::Header::elementSize
Word elementSize
Definition: TPEFSectionReader.hh:68
TPEF::Section::element
SectionElement * element(Word index) const
assert
#define assert(condition)
Definition: Application.hh:86
TPEF::TPEFRelocSectionReader::~TPEFRelocSectionReader
virtual ~TPEFRelocSectionReader()
Definition: TPEFRelocSectionReader.cc:84
TPEF::Section::addElement
virtual void addElement(SectionElement *element)
Definition: Section.cc:133
TPEF::TPEFReader::sectionOfAddress
Section * sectionOfAddress(const ASpaceElement *aSpaceId, AddressImage address) const
Definition: TPEFReader.cc:277
RelocSection.hh
TPEF::RelocElement::aSpace
ASpaceElement * aSpace() const
TPEF::Section::ST_DATA
@ ST_DATA
Initialized data section.
Definition: Section.hh:80
TPEF::RelocElement::setType
void setType(RelocType aType)
TPEF::Section::ST_LEDATA
@ ST_LEDATA
Initialized little endian data section.
Definition: Section.hh:82
TPEF::Locator::absoluteAddress
static AddressImage absoluteAddress(AddressImage relocationValue, RelocElement::RelocType relocType)
Definition: Locator.cc:46
TPEF::RelocElement::setSize
void setSize(Byte aSize)
TPEF::ReferenceManager::SafePointer::sectionKeyFor
static SectionKey sectionKeyFor(const SafePointable *obj)
Definition: SafePointer.cc:408
SectionReader.hh
__func__
#define __func__
Definition: Application.hh:67
TPEF::RelocElement::type
RelocType type() const
TPEF::RelocElement::setChunked
void setChunked(bool isChunked)
RelocElement.hh
TPEF::RelocElement::setSymbol
void setSymbol(SymbolElement *aSymbol)
TPEF::SectionReader::registerSectionReader
static void registerSectionReader(const SectionReader *sReader)
Definition: SectionReader.cc:145
DataSection.hh
MathTools::requiredBits
static int requiredBits(unsigned long int number)
TPEF::BinaryStream::readHalfWord
HalfWord readHalfWord()
Definition: BinaryStream.cc:150
TPEF::RelocElement::setLocation
void setLocation(SectionElement *aLocation)
TPEF::TPEFSectionReader
Definition: TPEFSectionReader.hh:48
TPEF::BinaryStream::readByte
Byte readByte()
Definition: BinaryStream.cc:120
TPEF::TPEFHeaders::STF_CHUNK
@ STF_CHUNK
Relocation applied to chunk(1) or complete address(0).
Definition: TPEFHeaders.hh:105
TPEF::CodeSection
Definition: CodeSection.hh:44
ASpaceSection.hh
TPEF::TPEFRelocSectionReader::type
virtual Section::SectionType type() const
Definition: TPEFRelocSectionReader.cc:93
TPEF::RelocElement
Definition: RelocElement.hh:51
TPEF::Section::noBits
bool noBits() const
AddressImage
UInt32 AddressImage
Type for storing addresses to memory image.
Definition: BaseType.hh:179
TPEF::TPEFSectionReader::parent
virtual BinaryReader * parent() const
Definition: TPEFSectionReader.cc:65
TPEF::SectionOffset
Word SectionOffset
Type for storing offsets relative to a given base offset value.
Definition: TPEFBaseType.hh:49
TPEF::ReferenceManager::SectionKey
Definition: ReferenceKey.hh:145
TPEF::TPEFSectionReader::readData
virtual void readData(BinaryStream &stream, Section *section) const
Definition: TPEFSectionReader.cc:86
TPEF::RelocElement::setBitOffset
void setBitOffset(Byte anOffset)
TPEF::TPEFReader
Definition: TPEFReader.hh:52
Swapper.hh
BYTE_BITWIDTH
const Byte BYTE_BITWIDTH
Definition: BaseType.hh:136
TPEF::TPEFRelocSectionReader::TPEFRelocSectionReader
TPEFRelocSectionReader()
Definition: TPEFRelocSectionReader.cc:77
TPEF::Section::ST_RELOC
@ ST_RELOC
Relocation section.
Definition: Section.hh:74
TPEF::ReferenceManager::SectionOffsetKey
Definition: ReferenceKey.hh:93
TPEF::RelocElement::setASpace
void setASpace(ASpaceElement *anASpace)
BinaryStream.hh
TPEF::Section::SectionType
SectionType
Definition: Section.hh:69
TPEF::RelocElement::RelocType
RelocType
Definition: RelocElement.hh:56
TPEF::RelocElement::setDestination
void setDestination(SectionElement *aDestination)
MathTools.hh
TPEFBaseType.hh
TPEF::RelocElement::location
SectionElement * location() const
TPEF::SectionIndex
Word SectionIndex
Type for storing section indexes.
Definition: TPEFBaseType.hh:46
TPEF::Section::isCodeSection
virtual bool isCodeSection() const
Definition: Section.hh:143
TPEF::ImmediateElement::length
unsigned int length() const
ReferenceKey.hh
TPEF::BinaryStream::readWord
Word readWord()
Definition: BinaryStream.cc:187
TPEF::Section::startingAddress
AddressImage startingAddress() const
TPEF::RawSection::chunkToMAUIndex
virtual Word chunkToMAUIndex(const Chunk *chunk) const
Definition: Section.cc:341
TPEF::Chunk
Definition: Chunk.hh:45
CodeSection.hh
TPEF::Section::elementCount
Word elementCount() const
TPEF::TPEFSectionReader::header
static const Header & header()
Definition: TPEFSectionReader.cc:174
TPEF
Definition: Assembler.hh:43