2 * File: ELFSourceFile.cpp
4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5 * See included license file for license details.
8 #include "ELFSourceFile.h"
10 #include "GHSSecInfo.h"
15 //! The name of the toolset option.
16 #define kToolsetOptionName "toolset"
17 #define kGHSToolsetName "GHS"
18 #define kGCCToolsetName "GCC"
19 #define kGNUToolsetName "GNU"
20 #define kADSToolsetName "ADS"
22 //! Name of the option to control .secinfo action.
23 #define kSecinfoClearOptionName "secinfoClear"
24 #define kSecinfoDefaultName "DEFAULT"
25 #define kSecinfoIgnoreName "IGNORE"
26 #define kSecinfoROMName "ROM"
27 #define kSecinfoCName "C"
29 using namespace elftosb;
31 ELFSourceFile::ELFSourceFile(const std::string & path)
33 m_toolset(kUnknownToolset),
34 m_secinfoOption(kSecinfoDefault)
38 ELFSourceFile::~ELFSourceFile()
42 bool ELFSourceFile::isELFFile(std::istream & stream)
46 StELFFile elf(stream);
55 void ELFSourceFile::open()
57 // Read toolset option
58 m_toolset = readToolsetOption();
60 // Read option and select default value
61 m_secinfoOption = readSecinfoClearOption();
62 if (m_secinfoOption == kSecinfoDefault)
64 m_secinfoOption = kSecinfoCStartupClear;
70 m_file = new StELFFile(*m_stream);
71 // m_file->dumpSections();
73 // Set toolset in elf file object
76 // default toolset is GHS
79 m_file->setELFVariant(eGHSVariant);
82 m_file->setELFVariant(eGCCVariant);
85 m_file->setELFVariant(eARMVariant);
90 void ELFSourceFile::close()
97 elf_toolset_t ELFSourceFile::readToolsetOption()
100 const OptionContext * options = getOptions();
101 if (!options || !options->hasOption(kToolsetOptionName))
106 const Value * value = options->getOption(kToolsetOptionName);
107 const StringValue * stringValue = dynamic_cast<const StringValue*>(value);
110 // Not a string value, warn the user.
111 Log::log(Logger::WARNING, "invalid type for 'toolset' option\n");
115 std::string toolsetName = *stringValue;
117 // convert option value to uppercase
118 std::transform<std::string::const_iterator, std::string::iterator, int (*)(int)>(toolsetName.begin(), toolsetName.end(), toolsetName.begin(), toupper);
120 if (toolsetName == kGHSToolsetName)
124 else if (toolsetName == kGCCToolsetName || toolsetName == kGNUToolsetName)
128 else if (toolsetName == kADSToolsetName)
133 // Unrecognized option value, log a warning.
134 Log::log(Logger::WARNING, "unrecognized value for 'toolset' option\n");
137 return kUnknownToolset;
140 //! It is up to the caller to convert from kSecinfoDefault to the actual default
142 secinfo_clear_t ELFSourceFile::readSecinfoClearOption()
145 const OptionContext * options = getOptions();
146 if (!options || !options->hasOption(kSecinfoClearOptionName))
151 const Value * value = options->getOption(kSecinfoClearOptionName);
152 const StringValue * stringValue = dynamic_cast<const StringValue*>(value);
155 // Not a string value, warn the user.
156 Log::log(Logger::WARNING, "invalid type for 'secinfoClear' option\n");
160 std::string secinfoOption = *stringValue;
162 // convert option value to uppercase
163 std::transform<std::string::const_iterator, std::string::iterator, int (*)(int)>(secinfoOption.begin(), secinfoOption.end(), secinfoOption.begin(), toupper);
165 if (secinfoOption == kSecinfoDefaultName)
167 return kSecinfoDefault;
169 else if (secinfoOption == kSecinfoIgnoreName)
171 return kSecinfoIgnore;
173 else if (secinfoOption == kSecinfoROMName)
175 return kSecinfoROMClear;
177 else if (secinfoOption == kSecinfoCName)
179 return kSecinfoCStartupClear;
182 // Unrecognized option value, log a warning.
183 Log::log(Logger::WARNING, "unrecognized value for 'secinfoClear' option\n");
186 return kSecinfoDefault;
189 //! To create a data source for all sections of the ELF file, a WildcardMatcher
190 //! is instantiated and passed to createDataSource(StringMatcher&).
191 DataSource * ELFSourceFile::createDataSource()
193 WildcardMatcher matcher;
194 return createDataSource(matcher);
197 DataSource * ELFSourceFile::createDataSource(StringMatcher & matcher)
200 ELFDataSource * source = new ELFDataSource(m_file);
201 source->setSecinfoOption(m_secinfoOption);
203 Log::log(Logger::DEBUG2, "filtering sections of file: %s\n", getPath().c_str());
205 // We start at section 1 to skip the null section that is always first.
207 for (; index < m_file->getSectionCount(); ++index)
209 const Elf32_Shdr & header = m_file->getSectionAtIndex(index);
210 std::string name = m_file->getSectionNameAtIndex(header.sh_name);
212 // Ignore most section types
213 switch (header.sh_type) {
224 // Ignore sections that don't have the allocate flag set.
225 if ((header.sh_flags & SHF_ALLOC) == 0)
230 if (matcher.match(name))
232 Log::log(Logger::DEBUG2, "creating segment for section %s\n", name.c_str());
233 source->addSection(index);
237 Log::log(Logger::DEBUG2, "section %s did not match\n", name.c_str());
244 //! It is assumed that all ELF files have an entry point.
246 bool ELFSourceFile::hasEntryPoint()
251 //! The StELFFile::getTypeOfSymbolAtIndex() method uses different methods of determining
252 //! ARM/Thumb mode depending on the toolset.
253 uint32_t ELFSourceFile::getEntryPointAddress()
255 uint32_t entryPoint = 0;
257 // get entry point address
258 const Elf32_Ehdr & header = m_file->getFileHeader();
260 // find symbol corresponding to entry point and determine if
261 // it is arm or thumb mode
262 unsigned symbolIndex = m_file->getIndexOfSymbolAtAddress(header.e_entry);
263 if (symbolIndex != 0)
265 ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(symbolIndex);
266 bool entryPointIsThumb = (symbolType == eThumbSymbol);
267 const Elf32_Sym & symbol = m_file->getSymbolAtIndex(symbolIndex);
268 std::string symbolName = m_file->getSymbolName(symbol);
270 Log::log(Logger::DEBUG2, "Entry point is %s@0x%08x (%s)\n", symbolName.c_str(), symbol.st_value, entryPointIsThumb ? "Thumb" : "ARM");
272 // set entry point, setting the low bit if it is thumb mode
273 entryPoint = header.e_entry + (entryPointIsThumb ? 1 : 0);
277 entryPoint = header.e_entry;
283 //! \return A DataTarget that describes the named section.
284 //! \retval NULL There was no section with the requested name.
285 DataTarget * ELFSourceFile::createDataTargetForSection(const std::string & section)
288 unsigned index = m_file->getIndexOfSectionWithName(section);
289 if (index == SHN_UNDEF)
294 const Elf32_Shdr & sectionHeader = m_file->getSectionAtIndex(index);
295 uint32_t beginAddress = sectionHeader.sh_addr;
296 uint32_t endAddress = beginAddress + sectionHeader.sh_size;
297 ConstantDataTarget * target = new ConstantDataTarget(beginAddress, endAddress);
301 //! \return A DataTarget instance pointing at the requested symbol.
302 //! \retval NULL No symbol matching the requested name was found.
303 DataTarget * ELFSourceFile::createDataTargetForSymbol(const std::string & symbol)
306 unsigned symbolCount = m_file->getSymbolCount();
309 for (i=0; i < symbolCount; ++i)
311 const Elf32_Sym & symbolHeader = m_file->getSymbolAtIndex(i);
312 std::string symbolName = m_file->getSymbolName(symbolHeader);
313 if (symbolName == symbol)
315 ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i);
316 bool symbolIsThumb = (symbolType == eThumbSymbol);
318 uint32_t beginAddress = symbolHeader.st_value + (symbolIsThumb ? 1 : 0);
319 uint32_t endAddress = beginAddress + symbolHeader.st_size;
320 ConstantDataTarget * target = new ConstantDataTarget(beginAddress, endAddress);
325 // didn't find a matching symbol
329 bool ELFSourceFile::hasSymbol(const std::string & name)
332 return lookupSymbol(name, symbol);
335 uint32_t ELFSourceFile::getSymbolValue(const std::string & name)
337 unsigned symbolCount = m_file->getSymbolCount();
340 for (i=0; i < symbolCount; ++i)
342 const Elf32_Sym & symbolHeader = m_file->getSymbolAtIndex(i);
343 std::string symbolName = m_file->getSymbolName(symbolHeader);
344 if (symbolName == name)
346 // If the symbol is a function, then we check to see if it is Thumb code and set bit 0 if so.
347 if (ELF32_ST_TYPE(symbolHeader.st_info) == STT_FUNC)
349 ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i);
350 bool symbolIsThumb = (symbolType == eThumbSymbol);
351 return symbolHeader.st_value + (symbolIsThumb ? 1 : 0);
355 return symbolHeader.st_value;
360 // Couldn't find the symbol, so return 0.
364 unsigned ELFSourceFile::getSymbolSize(const std::string & name)
367 if (!lookupSymbol(name, symbol))
372 return symbol.st_size;
375 //! \param name The name of the symbol on which info is wanted.
376 //! \param[out] info Upon succssful return this is filled in with the symbol's information.
378 //! \retval true The symbol was found and \a info is valid.
379 //! \retval false No symbol with \a name was found in the file.
380 bool ELFSourceFile::lookupSymbol(const std::string & name, Elf32_Sym & info)
383 unsigned symbolCount = m_file->getSymbolCount();
386 for (i=0; i < symbolCount; ++i)
388 const Elf32_Sym & symbol = m_file->getSymbolAtIndex(i);
389 std::string thisSymbolName = m_file->getSymbolName(symbol);
391 // Is this the symbol we're looking for?
392 if (thisSymbolName == name)
399 // Didn't file the symbol.
403 ELFSourceFile::ELFDataSource::~ELFDataSource()
405 segment_vector_t::iterator it = m_segments.begin();
406 for (; it != m_segments.end(); ++it)
412 //! Not all sections will actually result in a new segment being created. Only
413 //! those sections whose type is #SHT_PROGBITS or #SHT_NOBITS will create
414 //! a new segment. Also, only sections whose size is non-zero will actually
415 //! create a segment.
417 //! In addition to this, ELF files that have been marked as being created by
418 //! the Green Hills Software toolset have an extra step. #SHT_NOBITS sections
419 //! are looked up in the .secinfo section to determine if they really
420 //! should be filled. If not in the .secinfo table, no segment will be
421 //! created for the section.
422 void ELFSourceFile::ELFDataSource::addSection(unsigned sectionIndex)
425 const Elf32_Shdr & section = m_elf->getSectionAtIndex(sectionIndex);
426 if (section.sh_size == 0)
428 // empty section, so ignore it
432 // create the right segment subclass based on the section type
433 DataSource::Segment * segment = NULL;
434 switch (section.sh_type) {
438 segment = new ProgBitsSegment(*this, m_elf, sectionIndex);
443 // Always add NOBITS sections by default.
444 bool addNobits = true;
446 // For GHS ELF files, we use the secinfoClear option to figure out what to do.
447 // If set to ignore, treat like a normal ELF file and always add. If set to
448 // ROM, then only clear if the section is listed in .secinfo. Otherwise if set
449 // to C startup, then let the C startup do all clearing.
451 if (m_elf->ELFVariant() == eGHSVariant)
453 GHSSecInfo secinfo(m_elf);
455 // If there isn't a .secinfo section present then use the normal ELF rules
456 // and always add NOBITS sections.
457 if (secinfo.hasSecinfo() && m_secinfoOption != kSecinfoIgnore)
459 switch (m_secinfoOption)
461 case kSecinfoROMClear:
462 addNobits = secinfo.isSectionFilled(section);
465 case kSecinfoCStartupClear:
474 segment = new NoBitsSegment(*this, m_elf, sectionIndex);
478 std::string name = m_elf->getSectionNameAtIndex(section.sh_name);
479 Log::log(Logger::DEBUG2, "..section %s is not filled\n", name.c_str());
484 // add segment if one was created
487 m_segments.push_back(segment);
491 ELFSourceFile::ELFDataSource::ProgBitsSegment::ProgBitsSegment(ELFDataSource & source, StELFFile * elf, unsigned index)
492 : DataSource::Segment(source), m_elf(elf), m_sectionIndex(index)
496 unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer)
498 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
499 uint8_t * data = m_elf->getSectionDataAtIndex(m_sectionIndex);
501 assert(offset < section.sh_size);
503 unsigned copyBytes = std::min<unsigned>(section.sh_size - offset, maxBytes);
506 memcpy(buffer, &data[offset], copyBytes);
512 unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getLength()
514 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
515 return section.sh_size;
518 uint32_t ELFSourceFile::ELFDataSource::ProgBitsSegment::getBaseAddress()
520 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
521 return section.sh_addr;
524 ELFSourceFile::ELFDataSource::NoBitsSegment::NoBitsSegment(ELFDataSource & source, StELFFile * elf, unsigned index)
525 : DataSource::PatternSegment(source), m_elf(elf), m_sectionIndex(index)
529 unsigned ELFSourceFile::ELFDataSource::NoBitsSegment::getLength()
531 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
532 return section.sh_size;
535 uint32_t ELFSourceFile::ELFDataSource::NoBitsSegment::getBaseAddress()
537 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex);
538 return section.sh_addr;