1 /* 2 * File: ELFSourceFile.cpp 3 * 4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. 5 * See included license file for license details. 6 */ 7 8 #include "ELFSourceFile.h" 9 #include "Logging.h" 10 #include "GHSSecInfo.h" 11 #include <ctype.h> 12 #include <algorithm> 13 #include "string.h" 14 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" 21 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" 28 29 using namespace elftosb; 30 31 ELFSourceFile::ELFSourceFile(const std::string & path) 32 : SourceFile(path), 33 m_toolset(kUnknownToolset), 34 m_secinfoOption(kSecinfoDefault) 35 { 36 } 37 38 ELFSourceFile::~ELFSourceFile() 39 { 40 } 41 42 bool ELFSourceFile::isELFFile(std::istream & stream) 43 { 44 try 45 { 46 StELFFile elf(stream); 47 return true; 48 } 49 catch (...) 50 { 51 return false; 52 } 53 } 54 55 void ELFSourceFile::open() 56 { 57 // Read toolset option 58 m_toolset = readToolsetOption(); 59 60 // Read option and select default value 61 m_secinfoOption = readSecinfoClearOption(); 62 if (m_secinfoOption == kSecinfoDefault) 63 { 64 m_secinfoOption = kSecinfoCStartupClear; 65 } 66 67 // Open the stream 68 SourceFile::open(); 69 70 m_file = new StELFFile(*m_stream); 71 // m_file->dumpSections(); 72 73 // Set toolset in elf file object 74 switch (m_toolset) 75 { 76 // default toolset is GHS 77 case kGHSToolset: 78 case kUnknownToolset: 79 m_file->setELFVariant(eGHSVariant); 80 break; 81 case kGCCToolset: 82 m_file->setELFVariant(eGCCVariant); 83 break; 84 case kADSToolset: 85 m_file->setELFVariant(eARMVariant); 86 break; 87 } 88 } 89 90 void ELFSourceFile::close() 91 { 92 SourceFile::close(); 93 94 m_file.safe_delete(); 95 } 96 97 elf_toolset_t ELFSourceFile::readToolsetOption() 98 { 99 do { 100 const OptionContext * options = getOptions(); 101 if (!options || !options->hasOption(kToolsetOptionName)) 102 { 103 break; 104 } 105 106 const Value * value = options->getOption(kToolsetOptionName); 107 const StringValue * stringValue = dynamic_cast<const StringValue*>(value); 108 if (!stringValue) 109 { 110 // Not a string value, warn the user. 111 Log::log(Logger::WARNING, "invalid type for 'toolset' option\n"); 112 break; 113 } 114 115 std::string toolsetName = *stringValue; 116 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); 119 120 if (toolsetName == kGHSToolsetName) 121 { 122 return kGHSToolset; 123 } 124 else if (toolsetName == kGCCToolsetName || toolsetName == kGNUToolsetName) 125 { 126 return kGCCToolset; 127 } 128 else if (toolsetName == kADSToolsetName) 129 { 130 return kADSToolset; 131 } 132 133 // Unrecognized option value, log a warning. 134 Log::log(Logger::WARNING, "unrecognized value for 'toolset' option\n"); 135 } while (0); 136 137 return kUnknownToolset; 138 } 139 140 //! It is up to the caller to convert from kSecinfoDefault to the actual default 141 //! value. 142 secinfo_clear_t ELFSourceFile::readSecinfoClearOption() 143 { 144 do { 145 const OptionContext * options = getOptions(); 146 if (!options || !options->hasOption(kSecinfoClearOptionName)) 147 { 148 break; 149 } 150 151 const Value * value = options->getOption(kSecinfoClearOptionName); 152 const StringValue * stringValue = dynamic_cast<const StringValue*>(value); 153 if (!stringValue) 154 { 155 // Not a string value, warn the user. 156 Log::log(Logger::WARNING, "invalid type for 'secinfoClear' option\n"); 157 break; 158 } 159 160 std::string secinfoOption = *stringValue; 161 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); 164 165 if (secinfoOption == kSecinfoDefaultName) 166 { 167 return kSecinfoDefault; 168 } 169 else if (secinfoOption == kSecinfoIgnoreName) 170 { 171 return kSecinfoIgnore; 172 } 173 else if (secinfoOption == kSecinfoROMName) 174 { 175 return kSecinfoROMClear; 176 } 177 else if (secinfoOption == kSecinfoCName) 178 { 179 return kSecinfoCStartupClear; 180 } 181 182 // Unrecognized option value, log a warning. 183 Log::log(Logger::WARNING, "unrecognized value for 'secinfoClear' option\n"); 184 } while (0); 185 186 return kSecinfoDefault; 187 } 188 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() 192 { 193 WildcardMatcher matcher; 194 return createDataSource(matcher); 195 } 196 197 DataSource * ELFSourceFile::createDataSource(StringMatcher & matcher) 198 { 199 assert(m_file); 200 ELFDataSource * source = new ELFDataSource(m_file); 201 source->setSecinfoOption(m_secinfoOption); 202 203 Log::log(Logger::DEBUG2, "filtering sections of file: %s\n", getPath().c_str()); 204 205 // We start at section 1 to skip the null section that is always first. 206 unsigned index = 1; 207 for (; index < m_file->getSectionCount(); ++index) 208 { 209 const Elf32_Shdr & header = m_file->getSectionAtIndex(index); 210 std::string name = m_file->getSectionNameAtIndex(header.sh_name); 211 212 // Ignore most section types 213 if (!(header.sh_type == SHT_PROGBITS || header.sh_type == SHT_NOBITS)) 214 { 215 continue; 216 } 217 218 // Ignore sections that don't have the allocate flag set. 219 if ((header.sh_flags & SHF_ALLOC) == 0) 220 { 221 continue; 222 } 223 224 if (matcher.match(name)) 225 { 226 Log::log(Logger::DEBUG2, "creating segment for section %s\n", name.c_str()); 227 source->addSection(index); 228 } 229 else 230 { 231 Log::log(Logger::DEBUG2, "section %s did not match\n", name.c_str()); 232 } 233 } 234 235 return source; 236 } 237 238 //! It is assumed that all ELF files have an entry point. 239 //! 240 bool ELFSourceFile::hasEntryPoint() 241 { 242 return true; 243 } 244 245 //! The StELFFile::getTypeOfSymbolAtIndex() method uses different methods of determining 246 //! ARM/Thumb mode depending on the toolset. 247 uint32_t ELFSourceFile::getEntryPointAddress() 248 { 249 uint32_t entryPoint = 0; 250 251 // get entry point address 252 const Elf32_Ehdr & header = m_file->getFileHeader(); 253 254 // find symbol corresponding to entry point and determine if 255 // it is arm or thumb mode 256 unsigned symbolIndex = m_file->getIndexOfSymbolAtAddress(header.e_entry); 257 if (symbolIndex != 0) 258 { 259 ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(symbolIndex); 260 bool entryPointIsThumb = (symbolType == eThumbSymbol); 261 const Elf32_Sym & symbol = m_file->getSymbolAtIndex(symbolIndex); 262 std::string symbolName = m_file->getSymbolName(symbol); 263 264 Log::log(Logger::DEBUG2, "Entry point is %s@0x%08x (%s)\n", symbolName.c_str(), symbol.st_value, entryPointIsThumb ? "Thumb" : "ARM"); 265 266 // set entry point, setting the low bit if it is thumb mode 267 entryPoint = header.e_entry + (entryPointIsThumb ? 1 : 0); 268 } 269 else 270 { 271 entryPoint = header.e_entry; 272 } 273 274 return entryPoint; 275 } 276 277 //! \return A DataTarget that describes the named section. 278 //! \retval NULL There was no section with the requested name. 279 DataTarget * ELFSourceFile::createDataTargetForSection(const std::string & section) 280 { 281 assert(m_file); 282 unsigned index = m_file->getIndexOfSectionWithName(section); 283 if (index == SHN_UNDEF) 284 { 285 return NULL; 286 } 287 288 const Elf32_Shdr & sectionHeader = m_file->getSectionAtIndex(index); 289 uint32_t beginAddress = sectionHeader.sh_addr; 290 uint32_t endAddress = beginAddress + sectionHeader.sh_size; 291 ConstantDataTarget * target = new ConstantDataTarget(beginAddress, endAddress); 292 return target; 293 } 294 295 //! \return A DataTarget instance pointing at the requested symbol. 296 //! \retval NULL No symbol matching the requested name was found. 297 DataTarget * ELFSourceFile::createDataTargetForSymbol(const std::string & symbol) 298 { 299 assert(m_file); 300 unsigned symbolCount = m_file->getSymbolCount(); 301 unsigned i; 302 303 for (i=0; i < symbolCount; ++i) 304 { 305 const Elf32_Sym & symbolHeader = m_file->getSymbolAtIndex(i); 306 std::string symbolName = m_file->getSymbolName(symbolHeader); 307 if (symbolName == symbol) 308 { 309 ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i); 310 bool symbolIsThumb = (symbolType == eThumbSymbol); 311 312 uint32_t beginAddress = symbolHeader.st_value + (symbolIsThumb ? 1 : 0); 313 uint32_t endAddress = beginAddress + symbolHeader.st_size; 314 ConstantDataTarget * target = new ConstantDataTarget(beginAddress, endAddress); 315 return target; 316 } 317 } 318 319 // didn't find a matching symbol 320 return NULL; 321 } 322 323 bool ELFSourceFile::hasSymbol(const std::string & name) 324 { 325 Elf32_Sym symbol; 326 return lookupSymbol(name, symbol); 327 } 328 329 uint32_t ELFSourceFile::getSymbolValue(const std::string & name) 330 { 331 unsigned symbolCount = m_file->getSymbolCount(); 332 unsigned i; 333 334 for (i=0; i < symbolCount; ++i) 335 { 336 const Elf32_Sym & symbolHeader = m_file->getSymbolAtIndex(i); 337 std::string symbolName = m_file->getSymbolName(symbolHeader); 338 if (symbolName == name) 339 { 340 // If the symbol is a function, then we check to see if it is Thumb code and set bit 0 if so. 341 if (ELF32_ST_TYPE(symbolHeader.st_info) == STT_FUNC) 342 { 343 ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i); 344 bool symbolIsThumb = (symbolType == eThumbSymbol); 345 return symbolHeader.st_value + (symbolIsThumb ? 1 : 0); 346 } 347 else 348 { 349 return symbolHeader.st_value; 350 } 351 } 352 } 353 354 // Couldn't find the symbol, so return 0. 355 return 0; 356 } 357 358 unsigned ELFSourceFile::getSymbolSize(const std::string & name) 359 { 360 Elf32_Sym symbol; 361 if (!lookupSymbol(name, symbol)) 362 { 363 return 0; 364 } 365 366 return symbol.st_size; 367 } 368 369 //! \param name The name of the symbol on which info is wanted. 370 //! \param[out] info Upon succssful return this is filled in with the symbol's information. 371 //! 372 //! \retval true The symbol was found and \a info is valid. 373 //! \retval false No symbol with \a name was found in the file. 374 bool ELFSourceFile::lookupSymbol(const std::string & name, Elf32_Sym & info) 375 { 376 assert(m_file); 377 unsigned symbolCount = m_file->getSymbolCount(); 378 unsigned i; 379 380 for (i=0; i < symbolCount; ++i) 381 { 382 const Elf32_Sym & symbol = m_file->getSymbolAtIndex(i); 383 std::string thisSymbolName = m_file->getSymbolName(symbol); 384 385 // Is this the symbol we're looking for? 386 if (thisSymbolName == name) 387 { 388 info = symbol; 389 return true; 390 } 391 } 392 393 // Didn't file the symbol. 394 return false; 395 } 396 397 ELFSourceFile::ELFDataSource::~ELFDataSource() 398 { 399 segment_vector_t::iterator it = m_segments.begin(); 400 for (; it != m_segments.end(); ++it) 401 { 402 delete *it; 403 } 404 } 405 406 //! Not all sections will actually result in a new segment being created. Only 407 //! those sections whose type is #SHT_PROGBITS or #SHT_NOBITS will create 408 //! a new segment. Also, only sections whose size is non-zero will actually 409 //! create a segment. 410 //! 411 //! In addition to this, ELF files that have been marked as being created by 412 //! the Green Hills Software toolset have an extra step. #SHT_NOBITS sections 413 //! are looked up in the .secinfo section to determine if they really 414 //! should be filled. If not in the .secinfo table, no segment will be 415 //! created for the section. 416 void ELFSourceFile::ELFDataSource::addSection(unsigned sectionIndex) 417 { 418 // get section info 419 const Elf32_Shdr & section = m_elf->getSectionAtIndex(sectionIndex); 420 if (section.sh_size == 0) 421 { 422 // empty section, so ignore it 423 return; 424 } 425 426 // create the right segment subclass based on the section type 427 DataSource::Segment * segment = NULL; 428 if (section.sh_type == SHT_PROGBITS) 429 { 430 segment = new ProgBitsSegment(*this, m_elf, sectionIndex); 431 } 432 else if (section.sh_type == SHT_NOBITS) 433 { 434 // Always add NOBITS sections by default. 435 bool addNobits = true; 436 437 // For GHS ELF files, we use the secinfoClear option to figure out what to do. 438 // If set to ignore, treat like a normal ELF file and always add. If set to 439 // ROM, then only clear if the section is listed in .secinfo. Otherwise if set 440 // to C startup, then let the C startup do all clearing. 441 if (m_elf->ELFVariant() == eGHSVariant) 442 { 443 GHSSecInfo secinfo(m_elf); 444 445 // If there isn't a .secinfo section present then use the normal ELF rules 446 // and always add NOBITS sections. 447 if (secinfo.hasSecinfo() && m_secinfoOption != kSecinfoIgnore) 448 { 449 switch (m_secinfoOption) 450 { 451 case kSecinfoROMClear: 452 addNobits = secinfo.isSectionFilled(section); 453 break; 454 455 case kSecinfoCStartupClear: 456 addNobits = false; 457 break; 458 } 459 } 460 } 461 462 if (addNobits) 463 { 464 segment = new NoBitsSegment(*this, m_elf, sectionIndex); 465 } 466 else 467 { 468 std::string name = m_elf->getSectionNameAtIndex(section.sh_name); 469 Log::log(Logger::DEBUG2, "..section %s is not filled\n", name.c_str()); 470 } 471 } 472 473 // add segment if one was created 474 if (segment) 475 { 476 m_segments.push_back(segment); 477 } 478 } 479 480 ELFSourceFile::ELFDataSource::ProgBitsSegment::ProgBitsSegment(ELFDataSource & source, StELFFile * elf, unsigned index) 481 : DataSource::Segment(source), m_elf(elf), m_sectionIndex(index) 482 { 483 } 484 485 unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getData(unsigned offset, unsigned maxBytes, uint8_t * buffer) 486 { 487 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex); 488 uint8_t * data = m_elf->getSectionDataAtIndex(m_sectionIndex); 489 490 assert(offset < section.sh_size); 491 492 unsigned copyBytes = std::min<unsigned>(section.sh_size - offset, maxBytes); 493 if (copyBytes) 494 { 495 memcpy(buffer, &data[offset], copyBytes); 496 } 497 498 return copyBytes; 499 } 500 501 unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getLength() 502 { 503 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex); 504 return section.sh_size; 505 } 506 507 uint32_t ELFSourceFile::ELFDataSource::ProgBitsSegment::getBaseAddress() 508 { 509 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex); 510 return section.sh_addr; 511 } 512 513 ELFSourceFile::ELFDataSource::NoBitsSegment::NoBitsSegment(ELFDataSource & source, StELFFile * elf, unsigned index) 514 : DataSource::PatternSegment(source), m_elf(elf), m_sectionIndex(index) 515 { 516 } 517 518 unsigned ELFSourceFile::ELFDataSource::NoBitsSegment::getLength() 519 { 520 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex); 521 return section.sh_size; 522 } 523 524 uint32_t ELFSourceFile::ELFDataSource::NoBitsSegment::getBaseAddress() 525 { 526 const Elf32_Shdr & section = m_elf->getSectionAtIndex(m_sectionIndex); 527 return section.sh_addr; 528 } 529 530