1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/*
* 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);
}
|