28 #pragma warning(disable : 4996)
29 #pragma warning(disable : 4355)
30 #pragma warning(disable : 4244)
42 #include "elf_types.hpp"
43 #include "elfio_utils.hpp"
44 #include "elfio_header.hpp"
45 #include "elfio_section.hpp"
46 #include "elfio_segment.hpp"
47 #include "elfio_strings.hpp"
49 #define ELFIO_HEADER_ACCESS_GET(TYPE, FNAME) \
50 TYPE get_##FNAME() const { return header->get_##FNAME(); }
52 #define ELFIO_HEADER_ACCESS_GET_SET(TYPE, FNAME) \
53 TYPE get_##FNAME() const { return header->get_##FNAME(); } \
54 void set_##FNAME(TYPE val) { header->set_##FNAME(val); }
62 elfio() : sections(
this), segments(
this) {
65 create(ELFCLASS32, ELFDATA2LSB);
72 void create(
unsigned char file_class,
unsigned char encoding) {
74 convertor.setup(encoding);
75 header = create_header(file_class, encoding);
76 create_mandatory_sections();
80 bool load(
const std::string& file_name) {
82 stream.open(file_name.c_str(), std::ios::in | std::ios::binary);
91 bool load(std::istream& stream) {
94 unsigned char e_ident[EI_NIDENT];
98 stream.read(
reinterpret_cast<char*
>(&e_ident),
sizeof(e_ident));
101 if (stream.gcount() !=
sizeof(e_ident) || e_ident[EI_MAG0] != ELFMAG0 ||
102 e_ident[EI_MAG1] != ELFMAG1 || e_ident[EI_MAG2] != ELFMAG2 ||
103 e_ident[EI_MAG3] != ELFMAG3) {
107 if ((e_ident[EI_CLASS] != ELFCLASS64) && (e_ident[EI_CLASS] != ELFCLASS32)) {
111 convertor.setup(e_ident[EI_DATA]);
113 header = create_header(e_ident[EI_CLASS], e_ident[EI_DATA]);
117 if (!header->load(stream)) {
121 load_sections(stream);
122 load_segments(stream);
128 bool save(
const std::string& file_name) {
129 std::ofstream f(file_name.c_str(), std::ios::out | std::ios::binary);
135 bool is_still_good =
true;
141 header->set_segments_num(segments.size());
142 header->set_segments_offset(segments.size() ? header->get_header_size() : 0);
143 header->set_sections_num(sections.size());
144 header->set_sections_offset(0);
147 current_file_pos = header->get_header_size() +
148 header->get_segment_entry_size() * header->get_segments_num();
150 is_still_good = layout_segments_and_their_sections();
151 is_still_good = is_still_good && layout_sections_without_segments();
152 is_still_good = is_still_good && layout_section_table();
154 is_still_good = is_still_good && save_header(f);
155 is_still_good = is_still_good && save_sections(f);
156 is_still_good = is_still_good && save_segments(f);
160 return is_still_good;
165 ELFIO_HEADER_ACCESS_GET(
unsigned char,
class);
166 ELFIO_HEADER_ACCESS_GET(
unsigned char, elf_version);
167 ELFIO_HEADER_ACCESS_GET(
unsigned char, encoding);
168 ELFIO_HEADER_ACCESS_GET(Elf_Word, version);
169 ELFIO_HEADER_ACCESS_GET(Elf_Half, header_size);
170 ELFIO_HEADER_ACCESS_GET(Elf_Half, section_entry_size);
171 ELFIO_HEADER_ACCESS_GET(Elf_Half, segment_entry_size);
173 ELFIO_HEADER_ACCESS_GET_SET(
unsigned char, os_abi);
174 ELFIO_HEADER_ACCESS_GET_SET(
unsigned char, abi_version);
175 ELFIO_HEADER_ACCESS_GET_SET(Elf_Half, type);
176 ELFIO_HEADER_ACCESS_GET_SET(Elf_Half, machine);
177 ELFIO_HEADER_ACCESS_GET_SET(Elf_Word, flags);
178 ELFIO_HEADER_ACCESS_GET_SET(Elf64_Addr, entry);
179 ELFIO_HEADER_ACCESS_GET_SET(Elf64_Off, sections_offset);
180 ELFIO_HEADER_ACCESS_GET_SET(Elf64_Off, segments_offset);
181 ELFIO_HEADER_ACCESS_GET_SET(Elf_Half, section_name_str_index);
187 Elf_Xword get_default_entry_size(Elf_Word section_type)
const {
188 switch (section_type) {
190 if (header->get_class() == ELFCLASS64) {
196 if (header->get_class() == ELFCLASS64) {
202 if (header->get_class() == ELFCLASS64) {
208 if (header->get_class() == ELFCLASS64) {
225 std::vector<section*>::const_iterator it;
226 for (it = sections_.begin(); it != sections_.end(); ++it) {
231 std::vector<segment*>::const_iterator it1;
232 for (it1 = segments_.begin(); it1 != segments_.end(); ++it1) {
239 elf_header* create_header(
unsigned char file_class,
unsigned char encoding) {
242 if (file_class == ELFCLASS64) {
244 }
else if (file_class == ELFCLASS32) {
256 unsigned char file_class = get_class();
258 if (file_class == ELFCLASS64) {
260 }
else if (file_class == ELFCLASS32) {
266 new_section->set_index((Elf_Half)sections_.size());
267 sections_.push_back(new_section);
276 unsigned char file_class = header->get_class();
278 if (file_class == ELFCLASS64) {
280 }
else if (file_class == ELFCLASS32) {
286 new_segment->set_index((Elf_Half)segments_.size());
287 segments_.push_back(new_segment);
293 void create_mandatory_sections() {
296 section* sec0 = create_section();
299 sec0->set_name_string_offset(0);
301 set_section_name_str_index(1);
302 section* shstrtab = sections.add(
".shstrtab");
303 shstrtab->set_type(SHT_STRTAB);
304 shstrtab->set_addr_align(1);
308 Elf_Half load_sections(std::istream& stream) {
309 Elf_Half entry_size = header->get_section_entry_size();
310 Elf_Half num = header->get_sections_num();
311 Elf64_Off offset = header->get_sections_offset();
313 for (Elf_Half i = 0; i < num; ++i) {
314 section* sec = create_section();
315 sec->load(stream, (std::streamoff)offset + i * entry_size);
319 sec->set_address(sec->get_address());
322 Elf_Half shstrndx = get_section_name_str_index();
324 if (SHN_UNDEF != shstrndx) {
326 for (Elf_Half i = 0; i < num; ++i) {
327 Elf_Word offset = sections[i]->get_name_string_offset();
328 const char* p = str_reader.get_string(offset);
330 sections[i]->set_name(p);
339 bool load_segments(std::istream& stream) {
340 Elf_Half entry_size = header->get_segment_entry_size();
341 Elf_Half num = header->get_segments_num();
342 Elf64_Off offset = header->get_segments_offset();
344 for (Elf_Half i = 0; i < num; ++i) {
346 unsigned char file_class = header->get_class();
348 if (file_class == ELFCLASS64) {
350 }
else if (file_class == ELFCLASS32) {
356 seg->load(stream, (std::streamoff)offset + i * entry_size);
360 Elf64_Off segBaseOffset = seg->get_offset();
361 Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size();
362 Elf64_Off segVBaseAddr = seg->get_virtual_address();
363 Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size();
364 for (Elf_Half j = 0; j < sections.size(); ++j) {
365 const section* psec = sections[j];
369 if (psec->get_flags() & SHF_ALLOC
370 ? (segVBaseAddr <= psec->get_address() &&
371 psec->get_address() + psec->get_size() <= segVEndAddr)
372 : (segBaseOffset <= psec->get_offset() &&
373 psec->get_offset() + psec->get_size() <= segEndOffset)) {
374 seg->add_section_index(psec->get_index(), psec->get_addr_align());
379 segments_.push_back(seg);
386 bool save_header(std::ofstream& f) {
return header->save(f); }
389 bool save_sections(std::ofstream& f) {
390 for (
unsigned int i = 0; i < sections_.size(); ++i) {
391 section* sec = sections_.at(i);
393 std::streampos headerPosition = (std::streamoff)header->get_sections_offset() +
394 header->get_section_entry_size() * sec->get_index();
396 sec->save(f, headerPosition, sec->get_offset());
402 bool save_segments(std::ofstream& f) {
403 for (
unsigned int i = 0; i < segments_.size(); ++i) {
404 segment* seg = segments_.at(i);
406 std::streampos headerPosition =
407 header->get_segments_offset() + header->get_segment_entry_size() * seg->get_index();
409 seg->save(f, headerPosition, seg->get_offset());
415 bool is_section_without_segment(
unsigned int section_index) {
418 for (
unsigned int j = 0; !found && (j < segments.size()); ++j) {
419 for (
unsigned int k = 0; !found && (k < segments[j]->get_sections_num()); ++k) {
420 found = segments[j]->get_section_index_at(k) == section_index;
430 const std::vector<Elf_Half>& sections1 = seg1->get_sections();
431 const std::vector<Elf_Half>& sections2 = seg2->get_sections();
434 if (sections1.size() < sections2.size()) {
435 found = std::includes(sections2.begin(), sections2.end(), sections1.begin(),
443 std::vector<segment*> get_ordered_segments() {
444 std::vector<segment*> res;
445 std::deque<segment*> worklist;
447 res.reserve(segments.size());
448 std::copy(segments_.begin(), segments_.end(), std::back_inserter(worklist));
452 for (
size_t i = 0; i < worklist.size(); ++i) {
453 if (i != nextSlot && worklist[i]->is_offset_initialized() &&
454 worklist[i]->get_offset() == 0) {
455 std::swap(worklist[i], worklist[nextSlot]);
460 while (!worklist.empty()) {
461 segment* seg = worklist.front();
462 worklist.pop_front();
465 for (; i < worklist.size(); ++i) {
466 if (is_subsequence_of(seg, worklist[i])) {
471 if (i < worklist.size())
472 worklist.push_back(seg);
482 bool layout_sections_without_segments() {
483 for (
unsigned int i = 0; i < sections_.size(); ++i) {
484 if (is_section_without_segment(i)) {
487 Elf_Xword section_align = sec->get_addr_align();
488 if (section_align > 1 && current_file_pos % section_align != 0) {
489 current_file_pos += section_align - current_file_pos % section_align;
492 if (0 != sec->get_index()) sec->set_offset(current_file_pos);
494 if (SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type()) {
495 current_file_pos += sec->get_size();
505 bool layout_segments_and_their_sections() {
506 std::vector<segment*> worklist;
507 std::vector<bool> section_generated(sections.size(),
false);
511 worklist = get_ordered_segments();
513 for (
unsigned int i = 0; i < worklist.size(); ++i) {
514 Elf_Xword segment_memory = 0;
515 Elf_Xword segment_filesize = 0;
516 Elf_Xword seg_start_pos = current_file_pos;
521 if (seg->get_type() == PT_PHDR && seg->get_sections_num() == 0) {
522 seg_start_pos = header->get_segments_offset();
523 segment_memory = segment_filesize =
524 header->get_segment_entry_size() * header->get_segments_num();
528 else if (seg->get_sections_num() > 1 &&
529 sections[seg->get_section_index_at(0)]->get_type() == SHT_NULL) {
531 if (seg->get_sections_num()) {
532 segment_memory = segment_filesize = current_file_pos;
537 else if (seg->get_sections_num() && !section_generated[seg->get_section_index_at(0)]) {
538 Elf64_Off cur_page_alignment = current_file_pos % seg->get_align();
539 Elf64_Off req_page_alignment = seg->get_virtual_address() % seg->get_align();
540 Elf64_Off error = req_page_alignment - cur_page_alignment;
542 current_file_pos += (seg->get_align() + error) % seg->get_align();
543 seg_start_pos = current_file_pos;
544 }
else if (seg->get_sections_num()) {
545 seg_start_pos = sections[seg->get_section_index_at(0)]->get_offset();
549 for (
unsigned int j = 0; j < seg->get_sections_num(); ++j) {
550 Elf_Half index = seg->get_section_index_at(j);
552 section* sec = sections[index];
555 if (SHT_NULL == sec->get_type()) {
556 section_generated[index] =
true;
560 Elf_Xword secAlign = 0;
562 if (!section_generated[index] && sec->is_address_initialized() &&
563 SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type()) {
566 Elf64_Off req_offset = sec->get_address() - seg->get_virtual_address();
567 Elf64_Off cur_offset = current_file_pos - seg_start_pos;
568 secAlign = req_offset - cur_offset;
569 }
else if (!section_generated[index]) {
572 Elf_Xword align = sec->get_addr_align();
576 Elf64_Off error = current_file_pos % align;
577 secAlign = (align - error) % align;
580 secAlign = sec->get_offset() - seg_start_pos - segment_filesize;
585 if ((sec->get_flags() & SHF_ALLOC) &&
586 !((sec->get_flags() & SHF_TLS) && (seg->get_type() != PT_TLS) &&
587 (SHT_NOBITS == sec->get_type())))
588 segment_memory += sec->get_size() + secAlign;
589 if (SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type())
590 segment_filesize += sec->get_size() + secAlign;
593 if (section_generated[index]) {
597 current_file_pos += secAlign;
600 if (!sec->is_address_initialized())
601 sec->set_address(seg->get_virtual_address() + current_file_pos - seg_start_pos);
603 if (0 != sec->get_index()) sec->set_offset(current_file_pos);
605 if (SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type())
606 current_file_pos += sec->get_size();
607 section_generated[index] =
true;
610 seg->set_file_size(segment_filesize);
611 seg->set_memory_size(segment_memory);
612 seg->set_offset(seg_start_pos);
619 bool layout_section_table() {
621 Elf64_Off alignmentError = current_file_pos % 4;
622 current_file_pos += (4 - alignmentError) % 4;
623 header->set_sections_offset(current_file_pos);
637 Elf_Half size()
const {
return (Elf_Half)parent->sections_.size(); }
640 section* operator[](
unsigned int index)
const {
643 if (index < parent->sections_.size()) {
644 sec = parent->sections_[index];
651 section* operator[](
const std::string& name)
const {
654 std::vector<section*>::const_iterator it;
655 for (it = parent->sections_.begin(); it != parent->sections_.end(); ++it) {
656 if ((*it)->get_name() == name) {
666 section* add(
const std::string& name) {
667 section* new_section = parent->create_section();
668 new_section->set_name(name);
670 Elf_Half str_index = parent->get_section_name_str_index();
671 section* string_table(parent->sections_[str_index]);
673 Elf_Word pos = str_writer.add_string(name);
674 new_section->set_name_string_offset(pos);
680 std::vector<section*>::iterator begin() {
return parent->sections_.begin(); }
683 std::vector<section*>::iterator end() {
return parent->sections_.end(); }
699 Elf_Half size()
const {
return (Elf_Half)parent->segments_.size(); }
702 segment* operator[](
unsigned int index)
const {
return parent->segments_[index]; }
706 segment* add() {
return parent->create_segment(); }
709 std::vector<segment*>::iterator begin() {
return parent->segments_.begin(); }
712 std::vector<segment*>::iterator end() {
return parent->segments_.end(); }
722 std::vector<section*> sections_;
723 std::vector<segment*> segments_;
726 Elf_Xword current_file_pos;
731 #include "elfio_symbols.hpp"
732 #include "elfio_note.hpp"
733 #include "elfio_relocation.hpp"
734 #include "elfio_dynamic.hpp"