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