Permit substitution of relocation entry by using set_entry() function call

This commit is contained in:
Serge Lamikhov-Center 2020-08-19 13:39:15 -07:00
parent 6037df883c
commit 6d3d5467a2
2 changed files with 243 additions and 1 deletions

View File

@ -200,6 +200,38 @@ class relocation_section_accessor_template
return ret;
}
//------------------------------------------------------------------------------
bool
set_entry(Elf_Xword index,
Elf64_Addr offset,
Elf_Word symbol,
Elf_Word type,
Elf_Sxword addend)
{
if (index >= get_entries_num()) { // Is index valid
return false;
}
if (elf_file.get_class() == ELFCLASS32) {
if (SHT_REL == relocation_section->get_type()) {
generic_set_entry_rel<Elf32_Rel>(index, offset, symbol, type, addend);
}
else if (SHT_RELA == relocation_section->get_type()) {
generic_set_entry_rela<Elf32_Rela>(index, offset, symbol, type, addend);
}
}
else {
if (SHT_REL == relocation_section->get_type()) {
generic_set_entry_rel<Elf64_Rel>(index, offset, symbol, type, addend);
}
else if (SHT_RELA == relocation_section->get_type()) {
generic_set_entry_rela<Elf64_Rela>(index, offset, symbol, type, addend);
}
}
return true;
}
//------------------------------------------------------------------------------
void
add_entry( Elf64_Addr offset, Elf_Xword info )
@ -325,6 +357,58 @@ class relocation_section_accessor_template
addend = convertor( pEntry->r_addend );
}
//------------------------------------------------------------------------------
template <class T>
void
generic_set_entry_rel(Elf_Xword index,
Elf64_Addr offset,
Elf_Word symbol,
Elf_Word type,
Elf_Sxword addend)
{
const endianess_convertor &convertor = elf_file.get_convertor();
T *pEntry = const_cast<T *>(reinterpret_cast<const T *>(relocation_section->get_data() +
index * relocation_section->get_entry_size()));
if (elf_file.get_class() == ELFCLASS32) {
pEntry->r_info = ELF32_R_INFO((Elf_Xword)symbol, type);
}
else {
pEntry->r_info = ELF64_R_INFO((Elf_Xword)symbol, type);
}
pEntry->r_offset = offset;
pEntry->r_offset = convertor(pEntry->r_offset);
pEntry->r_info = convertor(pEntry->r_info);
}
//------------------------------------------------------------------------------
template <class T>
void
generic_set_entry_rela(Elf_Xword index,
Elf64_Addr offset,
Elf_Word symbol,
Elf_Word type,
Elf_Sxword addend)
{
const endianess_convertor &convertor = elf_file.get_convertor();
T *pEntry = const_cast<T *>(reinterpret_cast<const T *>(relocation_section->get_data() +
index * relocation_section->get_entry_size()));
if (elf_file.get_class() == ELFCLASS32) {
pEntry->r_info = ELF32_R_INFO((Elf_Xword)symbol, type);
}
else {
pEntry->r_info = ELF64_R_INFO((Elf_Xword)symbol, type);
}
pEntry->r_offset = offset;
pEntry->r_addend = addend;
pEntry->r_offset = convertor(pEntry->r_offset);
pEntry->r_info = convertor(pEntry->r_info);
pEntry->r_addend = convertor(pEntry->r_addend);
}
//------------------------------------------------------------------------------
template< class T >
void

View File

@ -650,7 +650,7 @@ BOOST_AUTO_TEST_CASE(rearrange_local_symbols)
value = 8;
symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
symbols.arrange_local_symbols([symbols](Elf_Xword first, Elf_Xword second) -> void {
symbols.arrange_local_symbols([&](Elf_Xword first, Elf_Xword second) -> void {
static int counter = 0;
BOOST_CHECK_EQUAL(first, ++counter);
// std::string name = "";
@ -702,3 +702,161 @@ BOOST_AUTO_TEST_CASE(rearrange_local_symbols)
}
BOOST_CHECK_EQUAL(name, "Str8");
}
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(rearrange_local_symbols_with_reallocation)
{
std::string name = "";
ELFIO::Elf64_Addr value = 0;
ELFIO::Elf_Xword size = 0;
unsigned char bind = STB_LOCAL;
unsigned char type = STT_FUNC;
ELFIO::Elf_Half section_index = 0;
unsigned char other = 0;
const std::string file_name = "elf_examples/test_symbols_order.elf";
elfio writer;
writer.create(ELFCLASS64, ELFDATA2LSB);
writer.set_os_abi(ELFOSABI_LINUX);
writer.set_type(ET_EXEC);
writer.set_machine(EM_X86_64);
section *text_sec = writer.sections.add(".text");
text_sec->set_type(SHT_PROGBITS);
text_sec->set_flags(SHF_ALLOC | SHF_EXECINSTR);
text_sec->set_addr_align(0x10);
section* str_sec = writer.sections.add(".strtab");
str_sec->set_type(SHT_STRTAB);
str_sec->set_addr_align(0x1);
string_section_accessor str_writer(str_sec);
section* sym_sec = writer.sections.add(".symtab");
sym_sec->set_type(SHT_SYMTAB);
sym_sec->set_info(0);
sym_sec->set_link(str_sec->get_index());
sym_sec->set_addr_align(4);
sym_sec->set_entry_size(writer.get_default_entry_size(SHT_SYMTAB));
symbol_section_accessor symbols(writer, sym_sec);
name = "Str1";
bind = STB_GLOBAL;
value = 1;
Elf_Word sym1 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
name = "Str2";
bind = STB_LOCAL;
value = 2;
Elf_Word sym2 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
name = "Str3";
bind = STB_WEAK;
value = 3;
Elf_Word sym3 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
name = "Str4";
bind = STB_LOCAL;
value = 4;
Elf_Word sym4 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
name = "Str5";
bind = STB_LOCAL;
value = 5;
Elf_Word sym5 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
name = "Str6";
bind = STB_GLOBAL;
value = 6;
Elf_Word sym6 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
name = "Str7";
bind = STB_LOCAL;
value = 7;
Elf_Word sym7 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
name = "Str8";
bind = STB_WEAK;
value = 8;
Elf_Word sym8 = symbols.add_symbol(str_writer, name.c_str(), value, size, bind, type, other, section_index);
section* rel_sec = writer.sections.add(".rel.text");
rel_sec->set_type(SHT_REL);
rel_sec->set_info(text_sec->get_index());
rel_sec->set_addr_align(0x4);
rel_sec->set_entry_size(writer.get_default_entry_size(SHT_REL));
rel_sec->set_link(sym_sec->get_index());
relocation_section_accessor rela(writer, rel_sec);
// Add relocation entry (adjust address at offset 11)
rela.add_entry(1, sym1, (unsigned char)R_386_RELATIVE);
rela.add_entry(8, sym8, (unsigned char)R_386_RELATIVE);
rela.add_entry(6, sym6, (unsigned char)R_386_RELATIVE);
rela.add_entry(2, sym2, (unsigned char)R_386_RELATIVE);
rela.add_entry(3, sym3, (unsigned char)R_386_RELATIVE);
rela.add_entry(8, sym8, (unsigned char)R_386_RELATIVE);
rela.add_entry(7, sym7, (unsigned char)R_386_RELATIVE);
rela.add_entry(2, sym2, (unsigned char)R_386_RELATIVE);
rela.add_entry(11, sym1, (unsigned char)R_386_RELATIVE);
rela.add_entry(18, sym8, (unsigned char)R_386_RELATIVE);
rela.add_entry(16, sym6, (unsigned char)R_386_RELATIVE);
rela.add_entry(12, sym2, (unsigned char)R_386_RELATIVE);
rela.add_entry(13, sym3, (unsigned char)R_386_RELATIVE);
rela.add_entry(17, sym7, (unsigned char)R_386_RELATIVE);
rela.add_entry(14, sym4, (unsigned char)R_386_RELATIVE);
rela.add_entry(15, sym5, (unsigned char)R_386_RELATIVE);
std::vector<std::string> before;
for (Elf_Word i = 0; i < rela.get_entries_num(); i++)
{
Elf64_Addr offset;
Elf_Word symbol;
Elf_Word rtype;
Elf_Sxword addend;
rela.get_entry(i, offset, symbol, rtype, addend);
symbols.get_symbol(symbol, name, value, size, bind, type, section_index, other);
before.push_back(name);
}
symbols.arrange_local_symbols([&](Elf_Xword first, Elf_Xword second) -> void {
Elf64_Addr offset;
Elf_Word symbol;
Elf_Word rtype;
Elf_Sxword addend;
for (Elf_Word i = 0; i < rela.get_entries_num(); i++) {
rela.get_entry(i, offset, symbol, rtype, addend);
if (symbol == first) {
rela.set_entry(i, offset, second, rtype, addend);
}
if (symbol == second) {
rela.set_entry(i, offset, first, rtype, addend);
}
}
});
BOOST_REQUIRE_EQUAL(writer.save(file_name), true);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
elfio reader;
BOOST_REQUIRE_EQUAL(reader.load(file_name), true);
auto prelsec = reader.sections[".rel.text"];
auto psyms = reader.sections[".symtab"];
BOOST_REQUIRE_NE(prelsec, nullptr);
BOOST_REQUIRE_NE(psyms, nullptr);
const_relocation_section_accessor rel(reader, prelsec);
const_symbol_section_accessor syms(reader, psyms);
std::vector<std::string> after;
for (Elf_Word i = 0; i < rel.get_entries_num(); i++)
{
Elf64_Addr offset;
Elf_Word symbol;
Elf_Word rtype;
Elf_Sxword addend;
rel.get_entry(i, offset, symbol, rtype, addend);
syms.get_symbol(symbol, name, value, size, bind, type, section_index, other);
after.push_back(name);
}
BOOST_CHECK_EQUAL_COLLECTIONS(before.begin(), before.end(), after.begin(), after.end());
}