104 lines
3.5 KiB
C++
104 lines
3.5 KiB
C++
/*
|
|
* 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 §ion)
|
|
{
|
|
return isSectionFilled(section.sh_addr, section.sh_size);
|
|
}
|