Skip to content

Commit 8226269

Browse files
Reimplementation of Elf Writer
- remove is_initialize pattern - add RAII - replace dynamic arrays with std::vector<char> - use fixed width integer types - remove c-style casting - reducing the number of code checks - add camelCase style Change-Id: If24a595f03865c59c86fed29db280de0084b5663
1 parent 392277f commit 8226269

File tree

14 files changed

+294
-666
lines changed

14 files changed

+294
-666
lines changed

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!groovy
22
neoDependenciesRev='787198-1060'
33
strategy='EQUAL'
4-
allowedCD=294
4+
allowedCD=283

elf/writer.cpp

Lines changed: 76 additions & 243 deletions
Original file line numberDiff line numberDiff line change
@@ -20,266 +20,99 @@
2020
* OTHER DEALINGS IN THE SOFTWARE.
2121
*/
2222
#include "writer.h"
23-
#include "runtime/helpers/string.h"
2423
#include <cstring>
2524

26-
namespace CLElfLib {
27-
/******************************************************************************\
28-
Constructor: CElfWriter::CElfWriter
29-
\******************************************************************************/
30-
CElfWriter::CElfWriter(
31-
E_EH_TYPE type,
32-
E_EH_MACHINE machine,
33-
Elf64_Xword flags) {
34-
m_type = type;
35-
m_machine = machine;
36-
m_flags = flags;
37-
}
38-
39-
/******************************************************************************\
40-
Destructor: CElfWriter::~CElfWriter
41-
\******************************************************************************/
42-
CElfWriter::~CElfWriter() {
43-
SSectionNode *pNode = nullptr;
44-
45-
// Walk through the section nodes
46-
while (m_nodeQueue.empty() == false) {
47-
pNode = m_nodeQueue.front();
48-
m_nodeQueue.pop();
49-
50-
// delete the node and it's data
51-
if (pNode) {
52-
if (pNode->pData) {
53-
delete[] pNode->pData;
54-
pNode->pData = nullptr;
55-
}
56-
57-
delete pNode;
58-
pNode = nullptr;
59-
}
60-
}
61-
}
62-
63-
/******************************************************************************\
64-
Member Function: CElfWriter::Create
65-
\******************************************************************************/
66-
CElfWriter *CElfWriter::create(
67-
E_EH_TYPE type,
68-
E_EH_MACHINE machine,
69-
Elf64_Xword flags) {
70-
CElfWriter *pWriter = new CElfWriter(type, machine, flags);
71-
72-
if (!pWriter->initialize()) {
73-
destroy(pWriter);
74-
}
75-
76-
return pWriter;
77-
}
78-
79-
/******************************************************************************\
80-
Member Function: CElfWriter::Delete
81-
\******************************************************************************/
82-
void CElfWriter::destroy(
83-
CElfWriter *&pWriter) {
84-
if (pWriter) {
85-
delete pWriter;
86-
pWriter = nullptr;
87-
}
88-
}
89-
90-
/******************************************************************************\
91-
Member Function: CElfWriter::AddSection
92-
\******************************************************************************/
93-
bool CElfWriter::addSection(
94-
SSectionNode *pSectionNode) {
95-
bool retVal = true;
96-
SSectionNode *pNode = nullptr;
97-
size_t nameSize = 0;
98-
unsigned int dataSize = 0;
99-
100-
// The section header must be non-NULL
101-
if (pSectionNode) {
102-
pNode = new SSectionNode();
103-
if (!pNode)
104-
return false;
105-
} else {
106-
return false;
107-
}
108-
109-
pNode->Flags = pSectionNode->Flags;
110-
pNode->Type = pSectionNode->Type;
111-
112-
nameSize = pSectionNode->Name.size() + 1;
113-
dataSize = pSectionNode->DataSize;
114-
115-
pNode->Name = pSectionNode->Name;
116-
117-
// ok to have NULL data
118-
if (dataSize > 0) {
119-
pNode->pData = new char[dataSize];
120-
if (pNode->pData) {
121-
memcpy_s(pNode->pData, dataSize, pSectionNode->pData, dataSize);
122-
pNode->DataSize = dataSize;
123-
} else {
124-
retVal = false;
125-
}
126-
}
127-
128-
if (retVal) {
129-
// push the node onto the queue
130-
m_nodeQueue.push(pNode);
25+
// Need for linux compatibility with memcpy_s
26+
#include "runtime/helpers/string.h"
13127

132-
// increment the sizes for each section
133-
m_dataSize += dataSize;
134-
m_stringTableSize += nameSize;
135-
m_numSections++;
136-
} else {
137-
delete pNode;
138-
pNode = nullptr;
28+
namespace CLElfLib {
29+
void CElfWriter::resolveBinary(ElfBinaryStorage &binary) {
30+
SElf64SectionHeader *curSectionHeader = nullptr;
31+
char *data = nullptr;
32+
char *stringTable = nullptr;
33+
char *curString = nullptr;
34+
35+
if (binary.size() < getTotalBinarySize()) {
36+
binary.resize(getTotalBinarySize());
13937
}
14038

141-
return retVal;
142-
}
143-
144-
/******************************************************************************\
145-
Member Function: CElfWriter::ResolveBinary
146-
\******************************************************************************/
147-
bool CElfWriter::resolveBinary(
148-
char *const pBinary,
149-
size_t &binarySize) {
150-
bool retVal = true;
151-
SSectionNode *pNode = nullptr;
152-
SElf64SectionHeader *pCurSectionHeader = nullptr;
153-
char *pData = nullptr;
154-
char *pStringTable = nullptr;
155-
char *pCurString = nullptr;
156-
157-
m_totalBinarySize =
158-
sizeof(SElf64Header) +
159-
((m_numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
160-
m_dataSize +
161-
m_stringTableSize;
162-
163-
if (pBinary) {
164-
// get a pointer to the first section header
165-
pCurSectionHeader = reinterpret_cast<SElf64SectionHeader *>(pBinary + sizeof(SElf64Header));
166-
167-
// get a pointer to the data
168-
pData = pBinary +
169-
sizeof(SElf64Header) +
170-
((m_numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry
171-
172-
// get a pointer to the string table
173-
pStringTable = pBinary + sizeof(SElf64Header) +
174-
((m_numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
175-
m_dataSize;
176-
177-
pCurString = pStringTable;
178-
179-
// Walk through the section nodes
180-
while (m_nodeQueue.empty() == false) {
181-
pNode = m_nodeQueue.front();
182-
183-
if (pNode) {
184-
m_nodeQueue.pop();
39+
// get a pointer to the first section header
40+
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(binary.data() + sizeof(SElf64Header));
18541

186-
// Copy data into the section header
187-
memset(pCurSectionHeader, 0, sizeof(SElf64SectionHeader));
188-
pCurSectionHeader->Type = pNode->Type;
189-
pCurSectionHeader->Flags = pNode->Flags;
190-
pCurSectionHeader->DataSize = pNode->DataSize;
191-
pCurSectionHeader->DataOffset = pData - pBinary;
192-
pCurSectionHeader->Name = static_cast<Elf64_Word>(pCurString - pStringTable);
193-
pCurSectionHeader = reinterpret_cast<SElf64SectionHeader *>(reinterpret_cast<unsigned char *>(pCurSectionHeader) + sizeof(SElf64SectionHeader));
42+
// get a pointer to the data
43+
data = binary.data() +
44+
sizeof(SElf64Header) +
45+
((numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry
19446

195-
// copy the data, move the data pointer
196-
memcpy_s(pData, pNode->DataSize, pNode->pData, pNode->DataSize);
197-
pData += pNode->DataSize;
47+
// get a pointer to the string table
48+
stringTable = binary.data() + sizeof(SElf64Header) +
49+
((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
50+
dataSize;
19851

199-
// copy the name into the string table, move the string pointer
200-
if (pNode->Name.size() > 0) {
201-
memcpy_s(pCurString, pNode->Name.size(), pNode->Name.c_str(), pNode->Name.size());
202-
pCurString += pNode->Name.size();
203-
}
204-
*(pCurString++) = '\0'; // NOLINT
52+
curString = stringTable;
20553

206-
// delete the node and it's data
207-
if (pNode->pData) {
208-
delete[] pNode->pData;
209-
pNode->pData = nullptr;
210-
}
211-
212-
delete pNode;
213-
pNode = nullptr;
214-
}
54+
// Walk through the section nodes
55+
while (nodeQueue.empty() == false) {
56+
// Copy data into the section header
57+
const auto &queueFront = nodeQueue.front();
58+
59+
curSectionHeader->Type = queueFront.type;
60+
curSectionHeader->Flags = queueFront.flag;
61+
curSectionHeader->DataSize = queueFront.dataSize;
62+
curSectionHeader->DataOffset = data - binary.data();
63+
curSectionHeader->Name = static_cast<Elf64_Word>(curString - stringTable);
64+
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(reinterpret_cast<unsigned char *>(curSectionHeader) + sizeof(SElf64SectionHeader));
65+
66+
// copy the data, move the data pointer
67+
memcpy_s(data, queueFront.dataSize, queueFront.data.c_str(), queueFront.dataSize);
68+
data += queueFront.dataSize;
69+
70+
// copy the name into the string table, move the string pointer
71+
if (queueFront.name.size() > 0) {
72+
memcpy_s(curString, queueFront.name.size(), queueFront.name.c_str(), queueFront.name.size());
73+
curString += queueFront.name.size();
21574
}
75+
*(curString++) = '\0'; // NOLINT
21676

217-
// add the string table section header
218-
SElf64SectionHeader stringSectionHeader = {0};
219-
stringSectionHeader.Type = E_SH_TYPE::SH_TYPE_STR_TBL;
220-
stringSectionHeader.Flags = E_SH_FLAG::SH_FLAG_NONE;
221-
stringSectionHeader.DataOffset = pStringTable - pBinary;
222-
stringSectionHeader.DataSize = m_stringTableSize;
223-
stringSectionHeader.Name = 0;
224-
225-
// Copy into the last section header
226-
memcpy_s(pCurSectionHeader, sizeof(SElf64SectionHeader),
227-
&stringSectionHeader, sizeof(SElf64SectionHeader));
228-
229-
// Add to our section number
230-
m_numSections++;
231-
232-
// patch up the ELF header
233-
retVal = patchElfHeader(pBinary);
77+
nodeQueue.pop();
23478
}
23579

236-
if (retVal) {
237-
binarySize = m_totalBinarySize;
238-
}
80+
// add the string table section header
81+
SElf64SectionHeader stringSectionHeader = {0};
82+
stringSectionHeader.Type = E_SH_TYPE::SH_TYPE_STR_TBL;
83+
stringSectionHeader.Flags = E_SH_FLAG::SH_FLAG_NONE;
84+
stringSectionHeader.DataOffset = stringTable - &binary[0];
85+
stringSectionHeader.DataSize = stringTableSize;
86+
stringSectionHeader.Name = 0;
23987

240-
return retVal;
241-
}
88+
// Copy into the last section header
89+
memcpy_s(curSectionHeader, sizeof(SElf64SectionHeader),
90+
&stringSectionHeader, sizeof(SElf64SectionHeader));
24291

243-
/******************************************************************************\
244-
Member Function: CElfWriter::Initialize
245-
\******************************************************************************/
246-
bool CElfWriter::initialize() {
247-
SSectionNode emptySection;
92+
// Add to our section number
93+
numSections++;
24894

249-
// Add an empty section 0 (points to "no-bits")
250-
return addSection(&emptySection);
95+
// patch up the ELF header
96+
patchElfHeader(*reinterpret_cast<SElf64Header *>(binary.data()));
25197
}
25298

253-
/******************************************************************************\
254-
Member Function: CElfWriter::PatchElfHeader
255-
\******************************************************************************/
256-
bool CElfWriter::patchElfHeader(char *const pBinary) {
257-
SElf64Header *pElfHeader = reinterpret_cast<SElf64Header *>(pBinary);
258-
259-
if (pElfHeader) {
260-
// Setup the identity
261-
memset(pElfHeader, 0x00, sizeof(SElf64Header));
262-
pElfHeader->Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0;
263-
pElfHeader->Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1;
264-
pElfHeader->Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2;
265-
pElfHeader->Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3;
266-
pElfHeader->Identity[ELFConstants::idIdxClass] = static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64);
267-
pElfHeader->Identity[ELFConstants::idIdxVersion] = static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT);
268-
269-
// Add other non-zero info
270-
pElfHeader->Type = m_type;
271-
pElfHeader->Machine = m_machine;
272-
pElfHeader->Flags = static_cast<uint32_t>(m_flags);
273-
pElfHeader->ElfHeaderSize = static_cast<uint32_t>(sizeof(SElf64Header));
274-
pElfHeader->SectionHeaderEntrySize = static_cast<uint32_t>(sizeof(SElf64SectionHeader));
275-
pElfHeader->NumSectionHeaderEntries = m_numSections;
276-
pElfHeader->SectionHeadersOffset = static_cast<uint32_t>(sizeof(SElf64Header));
277-
pElfHeader->SectionNameTableIndex = m_numSections - 1; // last index
278-
279-
return true;
280-
}
281-
282-
return false;
99+
void CElfWriter::patchElfHeader(SElf64Header &binary) {
100+
// Setup the identity
101+
binary.Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0;
102+
binary.Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1;
103+
binary.Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2;
104+
binary.Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3;
105+
binary.Identity[ELFConstants::idIdxClass] = static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64);
106+
binary.Identity[ELFConstants::idIdxVersion] = static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT);
107+
108+
// Add other non-zero info
109+
binary.Type = type;
110+
binary.Machine = machine;
111+
binary.Flags = static_cast<uint32_t>(flag);
112+
binary.ElfHeaderSize = static_cast<uint32_t>(sizeof(SElf64Header));
113+
binary.SectionHeaderEntrySize = static_cast<uint32_t>(sizeof(SElf64SectionHeader));
114+
binary.NumSectionHeaderEntries = numSections;
115+
binary.SectionHeadersOffset = static_cast<uint32_t>(sizeof(SElf64Header));
116+
binary.SectionNameTableIndex = numSections - 1; // last index
283117
}
284-
285118
} // namespace CLElfLib

0 commit comments

Comments
 (0)