|
2 | 2 | #include "ELFParser.h" |
3 | 3 | #include "Log.h" |
4 | 4 | #include "FileSystem.h" |
| 5 | +#include "KernelObject.h" |
5 | 6 |
|
6 | 7 | namespace core |
7 | 8 | { |
8 | | - ////////////////////////////////////////////////////////////////////////// |
9 | | - CELFParser::CELFParser(void) |
10 | | - : m_strFilePath() |
11 | | - , m_mapSection64() |
12 | | - { |
13 | | - |
14 | | - } |
| 9 | + static LPCSTR g_pszFileVersionName = "FileVersion"; |
| 10 | + static LPCSTR g_pszProductVersionName = "ProductVersion"; |
15 | 11 |
|
16 | 12 | ////////////////////////////////////////////////////////////////////////// |
17 | | - #define READ_BIN_FROM_FILE(TARGET) \ |
18 | | - {\ |
19 | | - size_t tRead = fread(&TARGET, 1, sizeof(TARGET), pFile);\ |
20 | | - if( tRead != sizeof(TARGET) )\ |
21 | | - throw exception_format("ELF %s read failure, try:%lu, read:%lu", #TARGET, sizeof(TARGET), tRead);\ |
22 | | - } |
23 | | - |
24 | | - ////////////////////////////////////////////////////////////////////////// |
25 | | - ECODE CELFParser::Parse(const char* pszFilePath) |
| 13 | + CELFParser::CELFParser(void) |
| 14 | + : m_mapSection64() |
26 | 15 | { |
27 | | - FILE* pFile = NULL; |
28 | | - |
29 | | - try |
30 | | - { |
31 | | - pFile = fopenA(pszFilePath, "rb"); |
32 | | - if( NULL == pFile ) |
33 | | - throw exception_format("file open failure, %s", pszFilePath); |
34 | | - |
35 | | - ST_ELF_IDENTITY stIdentity = { 0, }; |
36 | | - READ_BIN_FROM_FILE(stIdentity); |
37 | | - |
38 | | - if( 0x7F != stIdentity.ei_magic[0] |
39 | | - || 'E' != stIdentity.ei_magic[1] |
40 | | - || 'L' != stIdentity.ei_magic[2] |
41 | | - || 'F' != stIdentity.ei_magic[3] ) |
42 | | - throw exception_format("ELF magic is not matched"); |
43 | | - |
44 | | - ECODE nRet = EC_SUCCESS; |
45 | | - if( 1 == stIdentity.ei_class ) |
46 | | - nRet = Parse32Bit(pFile, stIdentity); |
47 | | - |
48 | | - if( 2 == stIdentity.ei_class ) |
49 | | - nRet = Parse64Bit(pFile, stIdentity); |
50 | | - |
51 | | - if( EC_SUCCESS != nRet ) |
52 | | - throw exception_format("ELF parsing failure, %d", nRet); |
53 | | - |
54 | | - fclose(pFile); |
55 | | - } |
56 | | - catch (std::exception& e) |
57 | | - { |
58 | | - e; // Declaration to resolve unused variable warning |
59 | | - //Log_Error("%s", e.what()); |
60 | | - if( pFile ) |
61 | | - fclose(pFile); |
62 | | - return EC_INTERNAL_ERROR; |
63 | | - } |
64 | | - |
65 | | - m_strFilePath = pszFilePath; |
66 | | - return EC_SUCCESS; |
67 | 16 | } |
68 | 17 |
|
69 | 18 | ////////////////////////////////////////////////////////////////////////// |
70 | | - ECODE CELFParser::QueryELFVersion(const char* pszSectioName, ST_VERSIONINFO& stVersionInfo) |
| 19 | + ECODE CELFParser::QueryVersion(HANDLE hFile, const char* pszSectionName, ST_VERSIONINFO& stVersionInfo) |
71 | 20 | { |
72 | 21 | ECODE nRet = EC_SUCCESS; |
73 | | - FILE* pFile = NULL; |
74 | 22 | try |
75 | 23 | { |
76 | | - CELFSectionHeader64It iter = m_mapSection64.find(pszSectioName); |
| 24 | + CELFSectionHeader64It iter = m_mapSection64.find(pszSectionName); |
77 | 25 |
|
78 | 26 | nRet = EC_NO_DATA; |
79 | 27 | if( iter == m_mapSection64.end() ) |
80 | 28 | throw exception_format("VersionInfo section is not found"); |
81 | 29 |
|
82 | 30 | const ST_ELF_SECTION_HEADER64& shVersionInfo = iter->second; |
83 | 31 |
|
84 | | - nRet = EC_INVALID_FILE; |
85 | | - pFile = fopenA(m_strFilePath.c_str(), "rb"); |
86 | | - if( NULL == pFile ) |
87 | | - throw exception_format("File(%s) open failure", m_strFilePath.c_str()); |
88 | | - |
89 | | - fseek(pFile, (long)shVersionInfo.sh_offset, SEEK_SET); |
| 32 | + SetFilePointer(hFile, (long)shVersionInfo.sh_offset, FILE_BEGIN_); |
90 | 33 |
|
91 | 34 | int nVersion[4]; |
92 | 35 | const size_t tVersionStructSize = sizeof(nVersion); |
93 | 36 | if( (shVersionInfo.sh_size > 0) && (shVersionInfo.sh_size%tVersionStructSize > 0) ) |
94 | 37 | throw exception_format("Section VersionInfo size is not matched, try:%lu, stored:%lu", sizeof(nVersion), shVersionInfo.sh_size); |
95 | 38 |
|
96 | | - size_t tRead = fread(nVersion, 1, sizeof(nVersion), pFile); |
97 | | - if( tRead != sizeof(nVersion) ) |
98 | | - throw exception_format("VersionInfo section read failure, try:%lu, read:%lu", sizeof(nVersion), tRead); |
| 39 | + DWORD dwReadSize = 0; |
| 40 | + if( !ReadFile(hFile, nVersion, sizeof(nVersion), &dwReadSize) ) |
| 41 | + throw exception_format("VersionInfo section read failure, try:%lu, read:%lu", sizeof(nVersion), dwReadSize); |
99 | 42 |
|
100 | 43 | stVersionInfo.dwMajor = nVersion[0]; |
101 | 44 | stVersionInfo.dwMinor = nVersion[1]; |
102 | 45 | stVersionInfo.dwPatch = nVersion[2]; |
103 | 46 | stVersionInfo.dwBuild = nVersion[3]; |
104 | | - fclose(pFile); |
105 | 47 | } |
106 | 48 | catch (std::exception& e) |
107 | 49 | { |
108 | | - e; // Declaration to resolve unused variable warning |
109 | | - //Log_Error("%s", e.what()); // skip for unexpected console output, caused by ConsolFramework |
110 | | - if( pFile ) |
111 | | - fclose(pFile); |
| 50 | + Log_Debug("%s", e.what()); |
112 | 51 | return nRet; |
113 | 52 | } |
114 | 53 |
|
115 | 54 | return EC_SUCCESS; |
116 | 55 | } |
117 | 56 |
|
118 | 57 | ////////////////////////////////////////////////////////////////////////// |
119 | | - ECODE CELFParser::QueryFileVersion(ST_VERSIONINFO& stVersionInfo) |
| 58 | + ECODE CELFParser::QueryFileVersion(ST_VERSIONINFO& outVersionInfo) |
120 | 59 | { |
121 | | - return QueryELFVersion("FileVersion", stVersionInfo); |
| 60 | + auto iter = m_mapVersionInfo.find(g_pszFileVersionName); |
| 61 | + if (iter == m_mapVersionInfo.end()) |
| 62 | + return EC_NO_DATA; |
| 63 | + |
| 64 | + outVersionInfo = iter->second; |
| 65 | + return EC_SUCCESS; |
122 | 66 | } |
123 | 67 |
|
124 | 68 | ////////////////////////////////////////////////////////////////////////// |
125 | | - ECODE CELFParser::QueryProductVersion(ST_VERSIONINFO& stVersionInfo) |
| 69 | + ECODE CELFParser::QueryProductVersion(ST_VERSIONINFO& outVersionInfo) |
126 | 70 | { |
127 | | - return QueryELFVersion("ProductVersion", stVersionInfo); |
| 71 | + auto iter = m_mapVersionInfo.find(g_pszProductVersionName); |
| 72 | + if (iter == m_mapVersionInfo.end()) |
| 73 | + return EC_NO_DATA; |
| 74 | + |
| 75 | + outVersionInfo = iter->second; |
| 76 | + return EC_SUCCESS; |
128 | 77 | } |
129 | 78 |
|
130 | 79 | ////////////////////////////////////////////////////////////////////////// |
131 | | - ECODE CELFParser::Parse32Bit(FILE* pFile, const ST_ELF_IDENTITY& stIdentity) |
| 80 | + ECODE CELFParser::Parse32Bit(HANDLE hFile, const ST_ELF_IDENTITY& stIdentity) |
132 | 81 | { |
| 82 | + DWORD dwRead = 0; |
| 83 | + |
133 | 84 | ST_ELF_HEADER32 stHeader = { 0, }; |
134 | | - READ_BIN_FROM_FILE(stHeader); |
| 85 | + if (!ReadFile(hFile, &stHeader, sizeof(stHeader), &dwRead)) |
| 86 | + return EC_READ_FAILURE; |
135 | 87 |
|
136 | 88 | return EC_SUCCESS; |
137 | 89 | } |
138 | 90 |
|
139 | 91 | ////////////////////////////////////////////////////////////////////////// |
140 | | - ECODE CELFParser::Parse64Bit(FILE* pFile, const ST_ELF_IDENTITY& stIdentity) |
| 92 | + ECODE CELFParser::Parse64Bit(HANDLE hFile, const ST_ELF_IDENTITY& stIdentity) |
141 | 93 | { |
| 94 | + ECODE nRet = EC_SUCCESS; |
142 | 95 | try |
143 | 96 | { |
| 97 | + DWORD dwRead = 0; |
| 98 | + |
144 | 99 | ST_ELF_HEADER64 stHeader = { 0, }; |
145 | | - READ_BIN_FROM_FILE(stHeader); |
| 100 | + nRet = EC_READ_FAILURE; |
| 101 | + if (!ReadFile(hFile, &stHeader, sizeof(stHeader), &dwRead)) |
| 102 | + throw exception_format(TEXT("Reading ELF header has failed.")); |
146 | 103 |
|
147 | | - fseek(pFile, (long)stHeader.e_phoff, SEEK_SET); |
| 104 | + SetFilePointer(hFile, (long)stHeader.e_phoff, FILE_BEGIN_); |
148 | 105 | std::vector<ST_ELF_PROGRAM_HEADER64> vecPHTable; |
149 | 106 | size_t i; |
150 | 107 | for(i=0; i<stHeader.e_phnum; i++) |
151 | 108 | { |
152 | 109 | ST_ELF_PROGRAM_HEADER64 stPH; |
153 | | - READ_BIN_FROM_FILE(stPH); |
| 110 | + nRet = EC_READ_FAILURE; |
| 111 | + if (!ReadFile(hFile, &stPH, sizeof(stPH), &dwRead)) |
| 112 | + throw exception_format(TEXT("Reading ELF PH has failed.")); |
154 | 113 |
|
155 | 114 | vecPHTable.push_back(stPH); |
156 | 115 | } |
157 | 116 |
|
158 | | - fseek(pFile, (long)stHeader.e_shoff, SEEK_SET); |
| 117 | + SetFilePointer(hFile, (long)stHeader.e_shoff, FILE_BEGIN_); |
159 | 118 | std::vector<ST_ELF_SECTION_HEADER64> vecSHTable; |
160 | 119 | for(i=0; i<stHeader.e_shnum; i++) |
161 | 120 | { |
162 | | - ST_ELF_SECTION_HEADER64 stPH; |
163 | | - READ_BIN_FROM_FILE(stPH); |
| 121 | + ST_ELF_SECTION_HEADER64 stSH; |
| 122 | + nRet = EC_READ_FAILURE; |
| 123 | + if (!ReadFile(hFile, &stSH, sizeof(stSH), &dwRead)) |
| 124 | + throw exception_format(TEXT("Reading ELF SH has failed.")); |
164 | 125 |
|
165 | | - vecSHTable.push_back(stPH); |
| 126 | + vecSHTable.push_back(stSH); |
166 | 127 | } |
167 | 128 |
|
168 | 129 | std::vector<char> vecStringTable; |
| 130 | + nRet = EC_INVALID_DATA; |
169 | 131 | if( vecSHTable.size() < stHeader.e_shstrndx ) |
170 | 132 | throw exception_format("Invalid ELF string table index"); |
171 | 133 |
|
| 134 | + nRet = EC_INVALID_DATA; |
172 | 135 | if( SHT_STRTAB != vecSHTable[stHeader.e_shstrndx].sh_type ) |
173 | 136 | throw exception_format("Invalid ELF string table location"); |
174 | 137 |
|
175 | 138 | { |
176 | 139 | const ST_ELF_SECTION_HEADER64& shStringTable = vecSHTable[stHeader.e_shstrndx]; |
177 | | - fseek(pFile, (long)shStringTable.sh_offset, SEEK_SET); |
| 140 | + SetFilePointer(hFile, (long)shStringTable.sh_offset, FILE_BEGIN_); |
178 | 141 | vecStringTable.resize((size_t)shStringTable.sh_size); |
179 | | - fread(&vecStringTable[0], (size_t)shStringTable.sh_size, 1, pFile); |
| 142 | + |
| 143 | + nRet = EC_READ_FAILURE; |
| 144 | + if (!ReadFile(hFile, &vecStringTable[0], (size_t)shStringTable.sh_size, &dwRead)) |
| 145 | + throw exception_format("Reading ELF string table has failed"); |
180 | 146 | } |
181 | 147 |
|
182 | 148 | for(i=0; i<vecSHTable.size(); i++) |
183 | 149 | { |
184 | 150 | const ST_ELF_SECTION_HEADER64& curSectionHeader = vecSHTable[i]; |
185 | | - if( vecStringTable.size() <= curSectionHeader.sh_name ) |
186 | | - m_mapSection64.insert(std::make_pair("InvalidName", curSectionHeader)); |
187 | | - else |
| 151 | + if(curSectionHeader.sh_name < vecStringTable.size()) |
188 | 152 | { |
189 | 153 | std::string strName = &vecStringTable[curSectionHeader.sh_name]; |
190 | 154 | m_mapSection64.insert(std::make_pair(strName, curSectionHeader)); |
191 | 155 | } |
| 156 | + else |
| 157 | + m_mapSection64.insert(std::make_pair("InvalidName", curSectionHeader)); |
192 | 158 | } |
193 | 159 | } |
194 | 160 | catch (std::exception& e) |
195 | 161 | { |
196 | | - e; // Declaration to resolve unused variable warning |
197 | | - //Log_Error("%s", e.what()); |
198 | | - return EC_INTERNAL_ERROR; |
| 162 | + Log_Debug("%s", e.what()); |
| 163 | + return nRet; |
199 | 164 | } |
200 | 165 |
|
201 | 166 | return EC_SUCCESS; |
|
0 commit comments