/* * File: GHSSecInfo.cpp * * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. * See included license file for license details. */ #include "GHSSecInfo.h" #include <stdexcept> #include "Logging.h" #include "EndianUtilities.h" //! The name of the GHS-specific section info table ELF section. const char * const kSecInfoSectionName = ".secinfo"; using namespace elftosb; //! The ELF file passed into this constructor as the \a elf argument must remain //! valid for the life of this object. //! //! \param elf The ELF file parser. An assertion is raised if this is NULL. GHSSecInfo::GHSSecInfo(StELFFile * elf) : m_elf(elf), m_hasInfo(false), m_info(0), m_entryCount(0) { assert(elf); // look up the section. if it's not there just leave m_info and m_entryCount to 0 unsigned sectionIndex = m_elf->getIndexOfSectionWithName(kSecInfoSectionName); if (sectionIndex == SHN_UNDEF) { return; } // get the section data const Elf32_Shdr & secInfo = m_elf->getSectionAtIndex(sectionIndex); if (secInfo.sh_type != SHT_PROGBITS) { // .secinfo section isn't the right type, so something is wrong return; } m_hasInfo = true; m_info = (ghs_secinfo_t *)m_elf->getSectionDataAtIndex(sectionIndex); m_entryCount = secInfo.sh_size / sizeof(ghs_secinfo_t); } //! Looks up \a addr for \a length in the .secinfo array. Only if that address is in the //! .secinfo array does this section need to be filled. If the section is found but the //! length does not match the \a length argument, a message is logged at the //! #Logger::WARNING level. //! //! If the .secinfo section is not present in the ELF file, this method always returns //! true. //! //! \param addr The start address of the section to query. //! \param length The length of the section. If a section with a start address matching //! \a addr is found, its length must match \a length to be considered. //! //! \retval true The section matching \a addr and \a length was found and should be filled. //! True is also returned when the ELF file does not have a .secinfo section. //! \retval false The section was not found and should not be filled. bool GHSSecInfo::isSectionFilled(uint32_t addr, uint32_t length) { if (!m_hasInfo) { return true; } unsigned i; for (i = 0; i < m_entryCount; ++i) { // byte swap these values into host endianness uint32_t clearAddr = ENDIAN_LITTLE_TO_HOST_U32(m_info[i].m_clearAddr); uint32_t numBytesToClear = ENDIAN_LITTLE_TO_HOST_U32(m_info[i].m_numBytesToClear); // we only consider non-zero length clear regions if ((addr == clearAddr) && (numBytesToClear != 0)) { // it is an error if the address matches but the length does not if (length != numBytesToClear) { Log::log(Logger::WARNING, "ELF Error: Size mismatch @ sect=%u, .secinfo=%u at addr 0x%08X\n", length, numBytesToClear, addr); } return true; } } return false; } //! Simply calls through to isSectionFilled(uint32_t, uint32_t) to determine //! if \a section should be filled. //! //! If the .secinfo section is not present in the ELF file, this method always returns //! true. bool GHSSecInfo::isSectionFilled(const Elf32_Shdr & section) { return isSectionFilled(section.sh_addr, section.sh_size); } |