OpenASIP  2.0
TPEFReader.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 TPEFReader.cc
26  *
27  * Definitions of class TPEFReader.
28  *
29  * @author Mikael Lepistö 2003 (tmlepist-no.spam-cs.tut.fi)
30  *
31  * @note rating: yellow
32  */
33 
34 #include <list>
35 #include <cmath>
36 
37 #include "TPEFReader.hh"
38 #include "Section.hh"
39 #include "TPEFBaseType.hh"
40 #include "SafePointer.hh"
41 #include "ReferenceKey.hh"
42 #include "SectionReader.hh"
43 #include "CodeSection.hh"
44 #include "BinaryStream.hh"
45 #include "Binary.hh"
46 #include "ASpaceSection.hh"
47 #include "TPEFHeaders.hh"
48 
49 namespace TPEF {
50 
51 using std::list;
52 using ReferenceManager::SafePointer;
53 
54 using ReferenceManager::FileOffsetKey;
55 using ReferenceManager::SectionOffsetKey;
56 using ReferenceManager::SectionKey;
57 using ReferenceManager::SectionIndexKey;
58 
59 TPEFReader* TPEFReader::proto_ = NULL;
60 
61 /**
62  * Constructor.
63  *
64  * Creates Header and registers itself to BinaryReader.
65  */
66 TPEFReader::TPEFReader() : BinaryReader(), aSpaceId_(0), strTableId_(0) {
68 }
69 
70 /**
71  * Destructor.
72  */
74  if (proto_ != NULL) {
75  auto proto = proto_;
76  proto_ = NULL;
77  delete proto;
78  }
79 }
80 
81 /**
82  * Does the actual work of reading binary file from stream.
83  *
84  * @param stream Stream to be read from.
85  * @return Pointer to the Binary object created.
86  * @exception UnreachableStream If reading of section fails.
87  * @exception KeyAlreadyExists Key was in use whent rying to register object.
88  * @exception EndOfFile If end of file were reached while it shouldn't.
89  * @exception OutOfRange Some of read values were out of range.
90  * @exception WrongSubclass Some class couldn't do what it was asked for.
91  * @exception UnexpectedValue If there was unexpected value when reading.
92  */
93 Binary*
95  binary_ = new Binary();
96  sectionSizes_.clear();
97 
98  // let's read file header stuff
99  FileOffset startOffset = stream.readPosition();
100 
101  // read file format identifier (including TPEF version number)
102  stream.setReadPosition(startOffset + TPEFHeaders::FH_ID);
103  for (Word i = 0; i < TPEFHeaders::FH_ID_SIZE; i++) {
104  // TPEF version number is located in the 9th Byte of FH_ID header
105  if (i == 8) {
106  TPEFHeaders::TPEFVersion version =
107  static_cast<TPEFHeaders::TPEFVersion>(stream.readByte());
108  stream.setTPEFVersion(version);
109  binary_->setTPEFVersion(version);
110  } else {
111  stream.readByte();
112  }
113  }
114 
115  stream.setReadPosition(startOffset + TPEFHeaders::FH_ARCH);
116  binary_->setArch(
117  static_cast<Binary::FileArchitecture>(stream.readByte()));
118 
119  stream.setReadPosition(startOffset + TPEFHeaders::FH_TYPE);
120  binary_->setType(
121  static_cast<Binary::FileType>(stream.readByte()));
122 
123  stream.setReadPosition(startOffset + TPEFHeaders::FH_SHOFF);
124  FileOffset offsetToHeader = stream.readWord();
125 
126  // skip size of file header
127 
128  stream.setReadPosition(startOffset + TPEFHeaders::FH_SHSIZE);
129  HalfWord sectionHeaderSize = stream.readHalfWord();
130 
131  stream.setReadPosition(startOffset + TPEFHeaders::FH_SHNUM);
132  HalfWord sectionHeaderCount = stream.readHalfWord();
133 
134  // string table of section names
135  stream.setReadPosition(startOffset + TPEFHeaders::FH_SHSTRTAB);
136  Word stringTableFileOffset = stream.readWord();
137 
138  if (stringTableFileOffset != 0) {
139  FileOffsetKey fKey(stringTableFileOffset);
140  binary_->setStrings(CREATE_SAFEPOINTER(fKey));
141  } else {
143  }
144 
145  // get identification code of string table section of binary
146  if (stringTableFileOffset != 0) {
147  stream.setReadPosition(stringTableFileOffset + TPEFHeaders::SH_ID);
148  SectionId stringTableSectionId = stream.readHalfWord();
149  strTableId_ = stringTableSectionId;
150  } else {
151  strTableId_ = 0;
152  }
153 
154  // get identification code of address space section of binary
155  SectionId aSpaceSectionId = 0;
156  bool programSectionWasFound = false;
157  for (Word i = offsetToHeader;
158  i < offsetToHeader + (sectionHeaderCount*sectionHeaderSize);
159  i += sectionHeaderSize) {
160 
161  // go to start of section header
163 
164  Section::SectionType sectionTypeToCheck =
165  static_cast<Section::SectionType>(stream.readByte());
166 
167  // if section is ASpaceSection
168  if (sectionTypeToCheck == Section::ST_ADDRSP) {
169  bool brokenBinaryMoreThanOneASpaceSection =
170  (aSpaceSectionId == 0);
171  assert(brokenBinaryMoreThanOneASpaceSection);
172 
174  aSpaceSectionId = stream.readHalfWord();
175 
176  } else if(Section::isProgramSection(sectionTypeToCheck)) {
177  programSectionWasFound = true;
178  }
179  }
180 
181  // there must be address space
182  assert(aSpaceSectionId != 0);
183  aSpaceId_ = aSpaceSectionId;
184 
185  // let's do some serious section-reading...
186  for (HalfWord i = 0; i < sectionHeaderCount; i++) {
187 
188  stream.setReadPosition(offsetToHeader + TPEFHeaders::SH_TYPE);
189 
191  static_cast<Section::SectionType>(stream.readByte()));
192 
193  FileOffsetKey sectionFileOffsetKey(offsetToHeader);
194  SafePointer::addObjectReference(sectionFileOffsetKey, sect);
195 
196  stream.setReadPosition(offsetToHeader);
197 
198  SectionReader::readSection(stream, sect, proto_);
199 
200  // next header
201  offsetToHeader += sectionHeaderSize;
202  binary_->addSection(sect);
203  }
204 
205  // NOTE: This check might be better to do in Binary classes addSection
206  // method. Because it's Binary classes job to prevent illegal
207  // section set. This check only prevents adding too many of these
208  // section while reading.
209 
210  // make sure that binary has needed sctions and do not have too many
211  // resource or address space sections
216  programSectionWasFound == false));
217 
218  return binary_;
219 }
220 
221 /**
222  * Checks if this reader is capable of reading the given stream.
223  *
224  * This method does not modify the stream pointer.
225  *
226  * @param stream The stream to test.
227  * @return True if stream contains data in expected format, false otherwise.
228  * @exception UnreachableStream If there occurs an exception with stream.
229  */
230 bool
232  unsigned long startPos = stream.readPosition();
233 
234  try {
235  if (stream.readByte() == 0x7f &&
236  stream.readByte() == 'T' &&
237  stream.readByte() == 'T' &&
238  stream.readByte() == 'A' &&
239  stream.readByte() == '-' &&
240  stream.readByte() == 'P' &&
241  stream.readByte() == 'F' &&
242  stream.readByte() == 0x00) {
243 
244  stream.setReadPosition(startPos);
245  return true;
246  }
247  } catch (EndOfFile& e) {
248  stream.setReadPosition(startPos);
249  return false;
250  }
251 
252  stream.setReadPosition(startPos);
253  return false;
254 }
255 
256 /**
257  * Returns instance of reader.
258  *
259  * @return Instance used for reading.
260  */
263  if (proto_ == NULL) {
264  proto_ = new TPEFReader();
265  }
266  return proto_;
267 }
268 
269 /**
270  * Resolves, which section is in given address in last read binary file.
271  *
272  * @param aSpace Address space in which section resides in memory image.
273  * @param address Address whose section is resolved.
274  * @return Section to which given offset refers.
275  */
276 Section*
278  const ASpaceElement* aSpace,
279  AddressImage address) const {
280 
281  assert(binary_ != NULL);
282 
283  for (Word i = 0; i < binary_->sectionCount(); i++) {
284 
285  Section *sect = binary_->section(i);
286 
287  // if section have same aSpace that in parameter
288  if (sect->aSpace() == aSpace) {
289 
290  Word lastSectionAddress = sect->startingAddress();
291 
292  if (sect->isCodeSection()) {
293  lastSectionAddress +=
294  dynamic_cast<CodeSection*>(sect)->instructionCount();
295 
296  } else {
297  lastSectionAddress +=
298  dynamic_cast<RawSection*>(sect)->lengthInMAUs();
299  }
300 
301  // test if address is inside base + sh_size
302  if (address < lastSectionAddress &&
303  address >= sect->startingAddress()) {
304 
305  return sect;
306  }
307  }
308  }
309 
310  return NULL;
311 }
312 
313 /**
314  * Stores size of a section as bytes.
315  *
316  * @param sect Section whose size is stored.
317  * @param length Section data size in addresses.
318  */
319 void
320 TPEFReader::addSectionSize(const Section* sect, Word length) {
321  sectionSizes_[sect] = length;
322 }
323 
324 /**
325  * Returns the identification code of the address space table section.
326  *
327  * @return Identification code of the address space table section.
328  */
329 SectionId
331  return aSpaceId_;
332 }
333 
334 /**
335  * Returns the identification code of string table section that contains the
336  * names of the sections.
337  *
338  * @return Identification code of a string table section.
339  */
340 SectionId
342  return strTableId_;
343 }
344 
345 /**
346  * Returns address space of file if already read.
347  *
348  * @return Address space of binary. NULL if there is no ASpace.
349  */
352  for (unsigned int i = 0; i < binary_->sectionCount(); i++) {
353  if (binary_->section(i)->type() == Section::ST_ADDRSP) {
354  return dynamic_cast<ASpaceSection*>(binary_->section(i));
355  }
356  }
357  return NULL;
358 }
359 
360 }
TPEF::SectionId
HalfWord SectionId
Type for storing binary file section ids.
Definition: TPEFBaseType.hh:43
TPEF::TPEFReader::instance
static BinaryReader * instance()
Definition: TPEFReader.cc:262
TPEF::TPEFHeaders::FH_TYPE
@ FH_TYPE
Type of TTA program.
Definition: TPEFHeaders.hh:67
TPEF::Section::aSpace
ASpaceElement * aSpace() const
TPEF::TPEFReader::addSectionSize
void addSectionSize(const Section *sect, Word length)
Definition: TPEFReader.cc:320
TPEF::BinaryStream::readPosition
unsigned int readPosition()
Definition: BinaryStream.cc:561
TPEF::Binary::FileArchitecture
FileArchitecture
Definition: Binary.hh:67
TPEF::TPEFHeaders::SH_TYPE
@ SH_TYPE
Type of section.
Definition: TPEFHeaders.hh:80
TPEF::Binary::setTPEFVersion
void setTPEFVersion(TPEFHeaders::TPEFVersion version)
TPEF::BinaryStream::setReadPosition
void setReadPosition(unsigned int position)
Definition: BinaryStream.cc:629
TPEF::TPEFReader::aSpaceSection
ASpaceSection * aSpaceSection() const
Definition: TPEFReader.cc:351
TPEFReader.hh
TPEF::TPEFReader::sectionSizes_
std::map< const Section *, Word > sectionSizes_
Cache of sizes in addresses of read sections.
Definition: TPEFReader.hh:97
TPEF::Binary
Definition: Binary.hh:49
TPEF::TPEFReader::proto_
static TPEFReader * proto_
Prototype instance registered into BinaryReader.
Definition: TPEFReader.hh:87
TPEF::Section::type
virtual SectionType type() const =0
Returns SectioType of actual section instance.
TPEF::BinaryStream
Definition: BinaryStream.hh:59
TPEF::ReferenceManager::SafePointer::null
static const SafePointer null
The default SafePointer that is used in null references.
Definition: SafePointer.hh:229
TPEF::TPEFHeaders::FH_ID_SIZE
const Byte FH_ID_SIZE
Size of file identification code.
Definition: TPEFHeaders.hh:50
TPEF::Binary::addSection
void addSection(Section *section)
SafePointer.hh
TPEFHeaders.hh
TPEF::Binary::setType
void setType(FileType type)
TPEF::Binary::section
Section * section(Word index) const
TPEF::Binary::sectionCount
Word sectionCount() const
TPEF::BinaryStream::setTPEFVersion
void setTPEFVersion(TPEFHeaders::TPEFVersion version)
Definition: BinaryStream.cc:86
TPEF::ReferenceManager::SafePointer::addObjectReference
static void addObjectReference(SectionIndexKey key, const SafePointable *obj)
Definition: SafePointer.cc:306
TPEF::TPEFHeaders::FH_SHSIZE
@ FH_SHSIZE
Size of section header entry.
Definition: TPEFHeaders.hh:70
TPEF::TPEFHeaders::FH_SHSTRTAB
@ FH_SHSTRTAB
Offset to header of string table.
Definition: TPEFHeaders.hh:72
TPEF::TPEFReader::TPEFReader
TPEFReader()
Definition: TPEFReader.cc:66
TPEF::BinaryReader
Definition: BinaryReader.hh:51
TPEF::Section
Definition: Section.hh:64
assert
#define assert(condition)
Definition: Application.hh:86
TPEF::TPEFReader::isMyStreamType
virtual bool isMyStreamType(BinaryStream &stream) const
Definition: TPEFReader.cc:231
TPEF::TPEFHeaders::TPEFVersion
TPEFVersion
Definition: TPEFHeaders.hh:56
TPEF::TPEFReader::sectionOfAddress
Section * sectionOfAddress(const ASpaceElement *aSpaceId, AddressImage address) const
Definition: TPEFReader.cc:277
TPEF::TPEFReader::strTableId_
SectionId strTableId_
Identification code of string table containing section name strings.
Definition: TPEFReader.hh:95
TPEF::Section::createSection
static Section * createSection(SectionType type)
Definition: Section.cc:91
TPEF::TPEFHeaders::FH_SHOFF
@ FH_SHOFF
Offset to first section header.
Definition: TPEFHeaders.hh:68
TPEF::ASpaceElement
Definition: ASpaceElement.hh:48
TPEF::Binary::FileType
FileType
Definition: Binary.hh:54
TPEF::TPEFHeaders::SH_ID
@ SH_ID
Section identification code.
Definition: TPEFHeaders.hh:85
SectionReader.hh
TPEF::TPEFHeaders::FH_SHNUM
@ FH_SHNUM
Number of section headers.
Definition: TPEFHeaders.hh:71
TPEF::FileOffset
Word FileOffset
Type for storing absolute file offsets.
Definition: TPEFBaseType.hh:52
TPEF::TPEFReader::binary_
Binary * binary_
Last or currently read binary.
Definition: TPEFReader.hh:90
TPEF::BinaryStream::readHalfWord
HalfWord readHalfWord()
Definition: BinaryStream.cc:150
TPEF::TPEFReader::readData
virtual Binary * readData(BinaryStream &stream) const
Definition: TPEFReader.cc:94
TPEF::BinaryStream::readByte
Byte readByte()
Definition: BinaryStream.cc:120
TPEF::CodeSection
Definition: CodeSection.hh:44
ASpaceSection.hh
TPEF::TPEFReader::aSpaceId
SectionId aSpaceId()
Definition: TPEFReader.cc:330
TPEF::TPEFReader::strTableId
SectionId strTableId()
Definition: TPEFReader.cc:341
AddressImage
UInt32 AddressImage
Type for storing addresses to memory image.
Definition: BaseType.hh:179
TPEF::ReferenceManager::FileOffsetKey
Definition: ReferenceKey.hh:121
TPEF::RawSection
Definition: Section.hh:196
Section.hh
BinaryStream.hh
TPEF::Section::SectionType
SectionType
Definition: Section.hh:69
TPEF::Section::isProgramSection
bool isProgramSection() const
TPEF::Section::ST_NULL
@ ST_NULL
NULL Section.
Definition: Section.hh:70
TPEFBaseType.hh
EndOfFile
Definition: Exception.hh:189
TPEF::Section::isCodeSection
virtual bool isCodeSection() const
Definition: Section.hh:143
TPEF::TPEFReader::aSpaceId_
SectionId aSpaceId_
Identification code of address space section (there is only one at maximum).
Definition: TPEFReader.hh:93
TPEF::Section::ST_MR
@ ST_MR
Machine resources section.
Definition: Section.hh:78
ReferenceKey.hh
TPEF::Binary::setStrings
void setStrings(StringSection *strTable)
TPEF::BinaryStream::readWord
Word readWord()
Definition: BinaryStream.cc:187
TPEF::ASpaceSection
Definition: ASpaceSection.hh:44
TPEF::TPEFHeaders::FH_ID
@ FH_ID
File identification code.
Definition: TPEFHeaders.hh:65
TPEF::TPEFReader::~TPEFReader
virtual ~TPEFReader()
Definition: TPEFReader.cc:73
TPEF::Section::startingAddress
AddressImage startingAddress() const
TPEF::TPEFHeaders::FH_ARCH
@ FH_ARCH
Architecture template.
Definition: TPEFHeaders.hh:66
CodeSection.hh
TPEF::Section::ST_ADDRSP
@ ST_ADDRSP
Address space section.
Definition: Section.hh:77
TPEF
Definition: Assembler.hh:43
Binary.hh
TPEF::SectionReader::readSection
static void readSection(BinaryStream &stream, Section *section, BinaryReader *reader)
Definition: SectionReader.cc:84
TPEF::Binary::setArch
void setArch(FileArchitecture arch)
TPEF::BinaryReader::registerBinaryReader
static void registerBinaryReader(BinaryReader *reader)
Definition: BinaryReader.cc:165