Skip to content

Commit

Permalink
Merge branch 'junghee/soname' into 'main'
Browse files Browse the repository at this point in the history
Add handling of SONAME dynamic-section entry

Closes #602

See merge request rewriting/ddisasm!1197
  • Loading branch information
junghee committed Apr 17, 2024
2 parents 813a66d + e031d94 commit fef6189
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 35 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* Generate GOT, PAGE and GOT, OFST symbolic expression attributes for split
.got loads on MIPS.
* Correct symbol_minus_symbol in lsda entries with a reference to the end of `.gcc_except_table`: add `boundary_sym_expr` for such reference
* Add `ElfSoname` aux-data for `SONAME` dynamic-section entry
* Requires gtirb >=2.1.0

# 1.8.0

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ endif()
# ---------------------------------------------------------------------------
# gtirb
# ---------------------------------------------------------------------------
find_package(gtirb 2.0.0 REQUIRED)
find_package(gtirb 2.1.0 REQUIRED)

# ---------------------------------------------------------------------------
# pretty-printer
Expand Down
4 changes: 3 additions & 1 deletion examples/asm_examples/ex_ifunc/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
CC="gcc"
CFLAGS=

all: ex_original.s
gcc -shared -Wl,--version-script=ex.map ex_original.s -o ex.so
$(CC) -shared -Wl,--version-script=ex.map $(CFLAGS) ex_original.s -o ex.so
clean:
rm -f ex.so ex.gtirb out.txt
1 change: 1 addition & 0 deletions src/Registration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ void registerAuxDataTypes()
gtirb::AuxDataContainer::registerAuxDataType<ElfDynamicFini>();
gtirb::AuxDataContainer::registerAuxDataType<ElfStackSize>();
gtirb::AuxDataContainer::registerAuxDataType<ElfStackExec>();
gtirb::AuxDataContainer::registerAuxDataType<ElfSoname>();
}

void registerDatalogLoaders()
Expand Down
114 changes: 81 additions & 33 deletions src/gtirb-builder/ElfReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,32 +304,72 @@ void ElfReader::createGPforMIPS(
SymbolTabIdxInfo[S->getUUID()] = Indexes;
}

void ElfReader::resurrectSymbols()
// Extract STRTAB bytes
LIEF::span<const uint8_t> ElfReader::getStrTabBytes()
{
// Get dynamic entries
std::map<std::string, uint64_t> DynamicEntries = getDynamicEntries();
static LIEF::span<const uint8_t> StrTabBytes;

// Extract bytes from STRTAB -------------------------------------
LIEF::span<const uint8_t> StrTabBytes;
auto It = DynamicEntries.find("STRTAB");
if(It == DynamicEntries.end())
{
std::cerr << "\nWARNING: resurrectSymbols: STRTAB not found.";
}
else
if(StrTabBytes.empty())
{
uint64_t StrTabAddr = It->second;
It = DynamicEntries.find("STRSZ");
std::map<std::string, uint64_t> DynamicEntries = getDynamicEntries();

auto It = DynamicEntries.find("STRTAB");
if(It == DynamicEntries.end())
{
std::cerr << "\nWARNING: resurrectSymbols: STRSZ not found.";
std::cerr << "\nWARNING: STRTAB not found.";
}
else
{
uint64_t StrTabSize = It->second;
StrTabBytes = Elf->get_content_from_virtual_address(StrTabAddr, StrTabSize);
uint64_t StrTabAddr = It->second;
It = DynamicEntries.find("STRSZ");
if(It == DynamicEntries.end())
{
std::cerr << "\nWARNING: STRSZ not found.";
}
else
{
uint64_t StrTabSize = It->second;
StrTabBytes = Elf->get_content_from_virtual_address(StrTabAddr, StrTabSize);
}
}
}
return StrTabBytes;
}

// Extract a string at the given Index in STRTAB
std::optional<std::string> ElfReader::getStringAt(uint32_t Index)
{
LIEF::span<const uint8_t> StrTabBytes = getStrTabBytes();
size_t StrTabSize = StrTabBytes.size();

if(StrTabSize == 0)
{
std::cerr << "getStringAt: STRSZ == 0\n";
return std::nullopt;
}
if(static_cast<size_t>(Index) >= StrTabSize)
{
std::cerr << "getStringAt: Index " << Index
<< " is greater than the STRTAB size: " << StrTabSize << std::endl;
return std::nullopt;
}

std::stringstream SS;
auto It = StrTabBytes.begin() + Index;
while(It != StrTabBytes.end())
{
uint8_t V = *It++;
if(V == 0)
break;
SS << V;
}
return SS.str();
};

void ElfReader::resurrectSymbols()
{
// Get dynamic entries
std::map<std::string, uint64_t> DynamicEntries = getDynamicEntries();

// Extract symbols -----------------------------------------------
// NOTE: The following code is specific to MIPS32 because it makes use of
Expand Down Expand Up @@ -366,20 +406,6 @@ void ElfReader::resurrectSymbols()
auto Bytes = Elf->get_content_from_virtual_address(Addr, Size);
auto Iter = Bytes.begin();

// Extract a string at the given Index in STRTAB
auto getStringAt = [&StrTabBytes](uint32_t Index) {
std::stringstream SS;
auto It = StrTabBytes.begin() + Index;
while(It != StrTabBytes.end())
{
uint8_t V = *It++;
if(V == 0)
break;
SS << V;
}
return SS.str();
};

for(uint64_t I = 0; I < DynSymNum; ++I)
{
// NOTE:
Expand All @@ -394,9 +420,16 @@ void ElfReader::resurrectSymbols()
LIEF::Convert::swap_endian<LIEF::ELF::details::Elf32_Sym>(P);
}
LIEF::ELF::Symbol Symbol(*P);
std::string Name = getStringAt(S.st_name);
Symbol.name(Name);
Elf->add_dynamic_symbol(Symbol);
std::optional<std::string> Name = getStringAt(S.st_name);
if(Name)
{
Symbol.name(Name.value());
Elf->add_dynamic_symbol(Symbol);
}
else
{
std::cerr << "resurrectSymbols: No string found for " << S.st_name << std::endl;
}
}
}
return;
Expand Down Expand Up @@ -1220,6 +1253,21 @@ void ElfReader::addAuxData()
}
Module->addAuxData<gtirb::schema::DynamicEntries>(std::move(DynamicEntryTuples));

// Add soname
auto SonameIt = DynamicEntries.find("SONAME");
if(SonameIt != DynamicEntries.end())
{
std::optional<std::string> Soname = getStringAt(SonameIt->second);
if(Soname)
{
Module->addAuxData<gtirb::schema::ElfSoname>(std::move(Soname.value()));
}
else
{
std::cerr << "\nWARNING: No string found for SONAME\n";
}
}

// Build segment auxdata
bool FoundStackSegment = false;
for(auto &Segment : Elf->segments())
Expand Down
3 changes: 3 additions & 0 deletions src/gtirb-builder/ElfReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class ElfReader : public GtirbBuilder
private:
uint64_t TlsBaseAddress = 0;

std::optional<std::string> getStringAt(uint32_t Index);
LIEF::span<const uint8_t> getStrTabBytes();

// For sectionless binaries
std::map<std::string, uint64_t> getDynamicEntries();
std::string inferDynMode();
Expand Down
1 change: 1 addition & 0 deletions src/tests/Main.Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void registerTestAuxDataTypes()
gtirb::AuxDataContainer::registerAuxDataType<DdisasmVersion>();
gtirb::AuxDataContainer::registerAuxDataType<ElfStackSize>();
gtirb::AuxDataContainer::registerAuxDataType<ElfStackExec>();
gtirb::AuxDataContainer::registerAuxDataType<ElfSoname>();
}

int main(int argc, char** argv)
Expand Down
17 changes: 17 additions & 0 deletions tests/misc_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,23 @@ def test_stack_exec(self):
# verify executable bit
self.assertEqual(m.aux_data["elfStackExec"].data, is_exec)

@unittest.skipUnless(
platform.system() == "Linux", "This test is linux only."
)
def test_soname(self):
"""
Test SONAME dynamic-section entry
"""
binary = "ex.so"
with cd(ex_asm_dir / "ex_ifunc"):
self.assertTrue(
compile("gcc", "g++", "-O0", [f"-Wl,-soname={binary}"])
)
ir = disassemble(Path(binary)).ir()
m = ir.modules[0]

self.assertEqual(m.aux_data["elfSoname"].data, binary)


class RawGtirbTests(unittest.TestCase):
@unittest.skipUnless(
Expand Down

0 comments on commit fef6189

Please sign in to comment.