1*993229b6Sjkunz /*
2*993229b6Sjkunz * File: GHSSecInfo.cpp
3*993229b6Sjkunz *
4*993229b6Sjkunz * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5*993229b6Sjkunz * See included license file for license details.
6*993229b6Sjkunz */
7*993229b6Sjkunz
8*993229b6Sjkunz #include "GHSSecInfo.h"
9*993229b6Sjkunz #include <stdexcept>
10*993229b6Sjkunz #include "Logging.h"
11*993229b6Sjkunz #include "EndianUtilities.h"
12*993229b6Sjkunz
13*993229b6Sjkunz //! The name of the GHS-specific section info table ELF section.
14*993229b6Sjkunz const char * const kSecInfoSectionName = ".secinfo";
15*993229b6Sjkunz
16*993229b6Sjkunz using namespace elftosb;
17*993229b6Sjkunz
18*993229b6Sjkunz //! The ELF file passed into this constructor as the \a elf argument must remain
19*993229b6Sjkunz //! valid for the life of this object.
20*993229b6Sjkunz //!
21*993229b6Sjkunz //! \param elf The ELF file parser. An assertion is raised if this is NULL.
GHSSecInfo(StELFFile * elf)22*993229b6Sjkunz GHSSecInfo::GHSSecInfo(StELFFile * elf)
23*993229b6Sjkunz : m_elf(elf), m_hasInfo(false), m_info(0), m_entryCount(0)
24*993229b6Sjkunz {
25*993229b6Sjkunz assert(elf);
26*993229b6Sjkunz
27*993229b6Sjkunz // look up the section. if it's not there just leave m_info and m_entryCount to 0
28*993229b6Sjkunz unsigned sectionIndex = m_elf->getIndexOfSectionWithName(kSecInfoSectionName);
29*993229b6Sjkunz if (sectionIndex == SHN_UNDEF)
30*993229b6Sjkunz {
31*993229b6Sjkunz return;
32*993229b6Sjkunz }
33*993229b6Sjkunz
34*993229b6Sjkunz // get the section data
35*993229b6Sjkunz const Elf32_Shdr & secInfo = m_elf->getSectionAtIndex(sectionIndex);
36*993229b6Sjkunz if (secInfo.sh_type != SHT_PROGBITS)
37*993229b6Sjkunz {
38*993229b6Sjkunz // .secinfo section isn't the right type, so something is wrong
39*993229b6Sjkunz return;
40*993229b6Sjkunz }
41*993229b6Sjkunz
42*993229b6Sjkunz m_hasInfo = true;
43*993229b6Sjkunz m_info = (ghs_secinfo_t *)m_elf->getSectionDataAtIndex(sectionIndex);
44*993229b6Sjkunz m_entryCount = secInfo.sh_size / sizeof(ghs_secinfo_t);
45*993229b6Sjkunz }
46*993229b6Sjkunz
47*993229b6Sjkunz //! Looks up \a addr for \a length in the .secinfo array. Only if that address is in the
48*993229b6Sjkunz //! .secinfo array does this section need to be filled. If the section is found but the
49*993229b6Sjkunz //! length does not match the \a length argument, a message is logged at the
50*993229b6Sjkunz //! #Logger::WARNING level.
51*993229b6Sjkunz //!
52*993229b6Sjkunz //! If the .secinfo section is not present in the ELF file, this method always returns
53*993229b6Sjkunz //! true.
54*993229b6Sjkunz //!
55*993229b6Sjkunz //! \param addr The start address of the section to query.
56*993229b6Sjkunz //! \param length The length of the section. If a section with a start address matching
57*993229b6Sjkunz //! \a addr is found, its length must match \a length to be considered.
58*993229b6Sjkunz //!
59*993229b6Sjkunz //! \retval true The section matching \a addr and \a length was found and should be filled.
60*993229b6Sjkunz //! True is also returned when the ELF file does not have a .secinfo section.
61*993229b6Sjkunz //! \retval false The section was not found and should not be filled.
isSectionFilled(uint32_t addr,uint32_t length)62*993229b6Sjkunz bool GHSSecInfo::isSectionFilled(uint32_t addr, uint32_t length)
63*993229b6Sjkunz {
64*993229b6Sjkunz if (!m_hasInfo)
65*993229b6Sjkunz {
66*993229b6Sjkunz return true;
67*993229b6Sjkunz }
68*993229b6Sjkunz
69*993229b6Sjkunz unsigned i;
70*993229b6Sjkunz for (i = 0; i < m_entryCount; ++i)
71*993229b6Sjkunz {
72*993229b6Sjkunz // byte swap these values into host endianness
73*993229b6Sjkunz uint32_t clearAddr = ENDIAN_LITTLE_TO_HOST_U32(m_info[i].m_clearAddr);
74*993229b6Sjkunz uint32_t numBytesToClear = ENDIAN_LITTLE_TO_HOST_U32(m_info[i].m_numBytesToClear);
75*993229b6Sjkunz
76*993229b6Sjkunz // we only consider non-zero length clear regions
77*993229b6Sjkunz if ((addr == clearAddr) && (numBytesToClear != 0))
78*993229b6Sjkunz {
79*993229b6Sjkunz // it is an error if the address matches but the length does not
80*993229b6Sjkunz if (length != numBytesToClear)
81*993229b6Sjkunz {
82*993229b6Sjkunz Log::log(Logger::WARNING, "ELF Error: Size mismatch @ sect=%u, .secinfo=%u at addr 0x%08X\n", length, numBytesToClear, addr);
83*993229b6Sjkunz }
84*993229b6Sjkunz return true;
85*993229b6Sjkunz }
86*993229b6Sjkunz }
87*993229b6Sjkunz
88*993229b6Sjkunz return false;
89*993229b6Sjkunz }
90*993229b6Sjkunz
91*993229b6Sjkunz //! Simply calls through to isSectionFilled(uint32_t, uint32_t) to determine
92*993229b6Sjkunz //! if \a section should be filled.
93*993229b6Sjkunz //!
94*993229b6Sjkunz //! If the .secinfo section is not present in the ELF file, this method always returns
95*993229b6Sjkunz //! true.
isSectionFilled(const Elf32_Shdr & section)96*993229b6Sjkunz bool GHSSecInfo::isSectionFilled(const Elf32_Shdr & section)
97*993229b6Sjkunz {
98*993229b6Sjkunz return isSectionFilled(section.sh_addr, section.sh_size);
99*993229b6Sjkunz }
100*993229b6Sjkunz
101