xref: /netbsd-src/external/bsd/elftosb/dist/common/GHSSecInfo.cpp (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
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