Skip to content

Commit 8d8acdb

Browse files
committedApr 18, 2018
(elfcpp) use elfcpp instead of custom lib for loading elves
1 parent 35299b1 commit 8d8acdb

8 files changed

+312
-13
lines changed
 

‎config.cmake

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Generating config.h
2-
# (Required for elfcpp)
2+
# (Required by elfcpp)
33

44
include(CheckIncludeFiles)
55
include(TestBigEndian)

‎config.in

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
# include <clocale>
1111
#else
1212
# include <clocale>
13-
# define gettext(aMsgId) (aMsgId)
13+
# define _(aString) (aString)
1414
#endif
1515

16-
#define _(aString) gettext(aString)
17-
1816
#endif // LYN_SYS_CONFIG

‎core/binary_file.h

+50-3
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,62 @@
44
#include <iostream>
55
#include <vector>
66
#include <cstdint>
7+
#include <cstdarg>
78

89
namespace lyn {
910

10-
class binary_file {
11-
public:
11+
struct binary_file {
1212
using byte_t = unsigned char;
1313
using size_t = std::size_t;
1414

15-
public:
15+
struct Location {
16+
Location(size_t off, size_t len)
17+
: file_offset(off), data_size(len) {}
18+
19+
size_t file_offset, data_size;
20+
};
21+
22+
struct View : public Location {
23+
View(const binary_file* file, size_t off, size_t len)
24+
: Location(off, len), pFile(file) {}
25+
26+
const byte_t* data() const {
27+
return pFile->data().data() + file_offset;
28+
}
29+
30+
private:
31+
const binary_file* pFile;
32+
};
33+
34+
View view(size_t offset, size_t size) const {
35+
return View(this, offset, size);
36+
}
37+
38+
View view(const Location& location) const {
39+
return View(this, location.file_offset, location.data_size);
40+
}
41+
42+
void error(const char* format, ...) {
43+
std::va_list args;
44+
45+
va_start(args, format);
46+
47+
int strSize; {
48+
std::va_list argsCpy;
49+
va_copy(argsCpy, args);
50+
51+
strSize = std::vsnprintf(nullptr, 0, format, argsCpy);
52+
va_end(argsCpy);
53+
}
54+
55+
std::vector<char> buf(strSize + 1);
56+
std::vsnprintf(buf.data(), buf.size(), format, args);
57+
58+
va_end(args);
59+
60+
throw std::runtime_error(std::string(buf.begin(), buf.end())); // TODO: better error
61+
}
62+
1663
void load_from_stream(std::istream& input);
1764
void load_from_other(const binary_file& other, unsigned int start = 0, int size = -1);
1865

‎core/event_object.cpp

+254-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,266 @@
11
#include "event_object.h"
22

3+
#include <fstream>
4+
35
#include <iomanip>
46
#include <algorithm>
57

6-
#include "../ea/event_section.h"
8+
#include "elfcpp/elfcpp_file.h"
9+
10+
#include "ea/event_section.h"
711
#include "util/hex_write.h"
812

13+
namespace elfcpp {
14+
15+
// for some reason this is required in order to make the whole thing work
16+
17+
template<int Size, bool BigEndian, typename File>
18+
const int Elf_file<Size, BigEndian, File>::ehdr_size;
19+
20+
template<int Size, bool BigEndian, typename File>
21+
const int Elf_file<Size, BigEndian, File>::phdr_size;
22+
23+
template<int Size, bool BigEndian, typename File>
24+
const int Elf_file<Size, BigEndian, File>::shdr_size;
25+
26+
template<int Size, bool BigEndian, typename File>
27+
const int Elf_file<Size, BigEndian, File>::sym_size;
28+
29+
template<int Size, bool BigEndian, typename File>
30+
const int Elf_file<Size, BigEndian, File>::rel_size;
31+
32+
template<int Size, bool BigEndian, typename File>
33+
const int Elf_file<Size, BigEndian, File>::rela_size;
34+
35+
} // namespace elfcpp
36+
937
namespace lyn {
1038

39+
void event_object::append_from_elf(const char* fileName) {
40+
binary_file file; {
41+
std::ifstream fileStream;
42+
43+
fileStream.open(fileName, std::ios::in | std::ios::binary);
44+
45+
if (!fileStream.is_open())
46+
throw std::runtime_error(std::string("Couldn't open file for read: ").append(fileName)); // TODO: better error
47+
48+
file.load_from_stream(fileStream);
49+
fileStream.close();
50+
}
51+
52+
elfcpp::Elf_file<32, false, lyn::binary_file> elfFile(&file);
53+
54+
auto readString = [&file] (elfcpp::Shdr<32, false> section, unsigned offset) -> std::string {
55+
return file.cstr_at(section.get_sh_offset() + offset);
56+
};
57+
58+
std::vector<section_data> newSections(elfFile.shnum());
59+
std::vector<bool> outMap(elfFile.shnum(), false);
60+
61+
auto getLocalSymbolName = [this] (int section, int index) -> std::string {
62+
std::string result;
63+
result.reserve(4 + 8 + 4 + 4);
64+
65+
result.append("_L");
66+
67+
util::append_hex(result, size());
68+
result.append("_");
69+
util::append_hex(result, section);
70+
result.append("_");
71+
util::append_hex(result, index);
72+
73+
return result;
74+
};
75+
76+
auto getGlobalSymbolName = [this] (const char* name) -> std::string {
77+
std::string result(name);
78+
int find = 0;
79+
80+
while ((find = result.find('.')) != std::string::npos)
81+
result[find] = '_';
82+
83+
return result;
84+
};
85+
86+
for (unsigned i = 0; i < elfFile.shnum(); ++i) {
87+
auto flags = elfFile.section_flags(i);
88+
89+
if ((flags & elfcpp::SHF_ALLOC) && !(flags & elfcpp::SHF_WRITE)) {
90+
auto& section = newSections.at(i);
91+
auto loc = elfFile.section_contents(i);
92+
93+
section.set_name(elfFile.section_name(i));
94+
section.load_from_other(file, loc.file_offset, loc.data_size);
95+
96+
outMap[i] = true;
97+
}
98+
}
99+
100+
for (unsigned si = 0; si < elfFile.shnum(); ++si) {
101+
elfcpp::Shdr<32, false> header(&file, elfFile.section_header(si));
102+
103+
switch (header.get_sh_type()) {
104+
105+
case elfcpp::SHT_SYMTAB: {
106+
const unsigned count = header.get_sh_size() / header.get_sh_entsize();
107+
const elfcpp::Shdr<32, false> nameShdr(&file, elfFile.section_header(header.get_sh_link()));
108+
109+
for (unsigned i = 0; i < count; ++i) {
110+
elfcpp::Sym<32, false> sym(&file, binary_file::Location(
111+
header.get_sh_offset() + i * header.get_sh_entsize(),
112+
header.get_sh_entsize()
113+
));
114+
115+
switch (sym.get_st_shndx()) {
116+
117+
case elfcpp::SHN_ABS: {
118+
if (sym.get_st_bind() != elfcpp::STB_GLOBAL)
119+
break;
120+
121+
mAbsoluteSymbols.push_back(symbol {
122+
readString(nameShdr, sym.get_st_name()),
123+
sym.get_st_value(),
124+
false
125+
});
126+
127+
break;
128+
} // case elfcpp::SHN_ABS
129+
130+
default: {
131+
if (!outMap.at(sym.get_st_shndx()))
132+
break;
133+
134+
auto& section = newSections.at(sym.get_st_shndx());
135+
136+
std::string name = readString(nameShdr, sym.get_st_name());
137+
138+
if (sym.get_st_type() == elfcpp::STT_NOTYPE && sym.get_st_bind() == elfcpp::STB_LOCAL) {
139+
std::string subString = name.substr(0, 3);
140+
141+
if ((name == "$t") || (subString == "$t.")) {
142+
section.set_mapping(sym.get_st_value(), mapping::Thumb);
143+
break;
144+
} else if ((name == "$a") || (subString == "$a.")) {
145+
section.set_mapping(sym.get_st_value(), mapping::ARM);
146+
break;
147+
} else if ((name == "$d") || (subString == "$d.")) {
148+
section.set_mapping(sym.get_st_value(), mapping::Data);
149+
break;
150+
}
151+
}
152+
153+
if (sym.get_st_bind() == elfcpp::STB_LOCAL)
154+
name = getLocalSymbolName(si, i);
155+
else
156+
name = getGlobalSymbolName(name.c_str());
157+
158+
section.symbols().push_back(symbol {
159+
name,
160+
sym.get_st_value(),
161+
(sym.get_st_bind() == elfcpp::STB_LOCAL)
162+
});
163+
164+
break;
165+
} // default
166+
167+
} // switch (sym.get_st_shndx())
168+
}
169+
170+
break;
171+
} // case elfcpp::SHT_SYMTAB
172+
173+
case elfcpp::SHT_REL: {
174+
if (!outMap.at(header.get_sh_info()))
175+
break;
176+
177+
const unsigned count = header.get_sh_size() / header.get_sh_entsize();
178+
179+
const elfcpp::Shdr<32, false> symShdr(&file, elfFile.section_header(header.get_sh_link()));
180+
const elfcpp::Shdr<32, false> symNameShdr(&file, elfFile.section_header(symShdr.get_sh_link()));
181+
182+
auto& section = newSections.at(header.get_sh_info());
183+
184+
for (unsigned i = 0; i < count; ++i) {
185+
const elfcpp::Rel<32, false> rel(&file, binary_file::Location(
186+
header.get_sh_offset() + i * header.get_sh_entsize(),
187+
header.get_sh_entsize()
188+
));
189+
190+
const elfcpp::Sym<32, false> sym(&file, binary_file::Location(
191+
symShdr.get_sh_offset() + elfcpp::elf_r_sym<32>(rel.get_r_info()) * symShdr.get_sh_entsize(),
192+
symShdr.get_sh_entsize()
193+
));
194+
195+
const std::string name = (sym.get_st_bind() == elfcpp::STB_LOCAL)
196+
? getLocalSymbolName(header.get_sh_link(), elfcpp::elf_r_sym<32>(rel.get_r_info()))
197+
: getGlobalSymbolName(readString(symNameShdr, sym.get_st_name()).c_str());
198+
199+
section.relocations().push_back(relocation {
200+
name,
201+
0,
202+
elfcpp::elf_r_type<32>(rel.get_r_info()),
203+
rel.get_r_offset()
204+
});
205+
}
206+
207+
break;
208+
} // case elfcpp::SHT_REL
209+
210+
case elfcpp::SHT_RELA: {
211+
if (!outMap.at(header.get_sh_info()))
212+
break;
213+
214+
const unsigned count = header.get_sh_size() / header.get_sh_entsize();
215+
216+
const elfcpp::Shdr<32, false> symShdr(&file, elfFile.section_header(header.get_sh_link()));
217+
const elfcpp::Shdr<32, false> symNameShdr(&file, elfFile.section_header(symShdr.get_sh_link()));
218+
219+
auto& section = newSections.at(header.get_sh_info());
220+
221+
for (unsigned i = 0; i < count; ++i) {
222+
const elfcpp::Rela<32, false> rela(&file, binary_file::Location(
223+
header.get_sh_offset() + i * header.get_sh_entsize(),
224+
header.get_sh_entsize()
225+
));
226+
227+
const elfcpp::Sym<32, false> sym(&file, binary_file::Location(
228+
symShdr.get_sh_offset() + elfcpp::elf_r_sym<32>(rela.get_r_info()) * symShdr.get_sh_entsize(),
229+
symShdr.get_sh_entsize()
230+
));
231+
232+
const std::string name = (sym.get_st_bind() == elfcpp::STB_LOCAL)
233+
? getLocalSymbolName(header.get_sh_link(), elfcpp::elf_r_sym<32>(rela.get_r_info()))
234+
: getGlobalSymbolName(readString(symNameShdr, sym.get_st_name()).c_str());
235+
236+
section.relocations().push_back(relocation {
237+
name,
238+
rela.get_r_addend(),
239+
elfcpp::elf_r_type<32>(rela.get_r_info()),
240+
rela.get_r_offset()
241+
});
242+
}
243+
244+
break;
245+
} // case elfcpp::SHT_RELA
246+
247+
} // switch (header.get_sh_type())
248+
}
249+
250+
// Remove empty sections
251+
252+
newSections.erase(std::remove_if(newSections.begin(), newSections.end(), [] (const section_data& section) {
253+
return (section.size()==0);
254+
}), newSections.end());
255+
256+
// Create the ultimate lifeform
257+
258+
for (auto& section : newSections) {
259+
combine_with(std::move(section));
260+
ensure_aligned(4);
261+
}
262+
}
263+
11264
void event_object::append_from_elf(const elf_file& elfFile) {
12265
std::vector<section_data> newSections(elfFile.sections().size());
13266
std::vector<bool> outMap(elfFile.sections().size(), false);

‎core/event_object.h

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class event_object : public section_data {
1616
};
1717

1818
public:
19+
void append_from_elf(const char* fName);
1920
void append_from_elf(const lyn::elf_file& elfFile);
2021

2122
void try_transform_relatives();

‎core/section_data.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ class section_data : public binary_file {
3131
std::string symbolName;
3232
int addend;
3333

34-
int type;
35-
unsigned int offset;
34+
unsigned type;
35+
unsigned offset;
3636
};
3737

3838
enum output_type {

‎elf/raw_elf.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,15 @@ struct symbol {
144144
std::uint8_t st_other;
145145
std::uint16_t st_shndx;
146146

147-
constexpr int type() const { return st_info & 0xF; }
147+
constexpr unsigned type() const { return st_info & 0xF; }
148148
constexpr int bind() const { return st_info >> 4; }
149149
};
150150

151151
struct rel {
152152
std::uint32_t r_offset;
153153
std::uint32_t r_info;
154154

155-
constexpr int type() const { return r_info & 0xFF; }
155+
constexpr unsigned type() const { return r_info & 0xFF; }
156156
constexpr int symId() const { return r_info >> 8; }
157157
};
158158

‎main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ int main(int argc, char** argv) {
6969
lyn::event_object object;
7070

7171
for (auto& elf : elves)
72-
object.append_from_elf(make_elf(elf));
72+
object.append_from_elf(elf.c_str());
7373

7474
if (options.doLink)
7575
object.try_relocate_relatives();

0 commit comments

Comments
 (0)
Please sign in to comment.