Skip to content

Michael elf parsing - LSDA parsing #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
cmake_minimum_required(VERSION 3.27)
project(safe LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # Ensure only standard C++ features


set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_custom_target(copy_compile_commands ALL
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_BINARY_DIR}/compile_commands.json
${CMAKE_SOURCE_DIR}/compile_commands.json
DEPENDS ${CMAKE_BINARY_DIR}/compile_commands.json)

# Find package dependancies
#TODO: Remove due to this being a temporary patch for libraries to work
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/build/Debug/generators")
find_package(libelf REQUIRED)

# Create the executable target
add_executable(${PROJECT_NAME} src/main.cpp)
add_executable(${PROJECT_NAME} src/main.cpp src/elf_parser.cpp)

#Linking Libraries
target_link_libraries(${PROJECT_NAME} libelf::libelf)


# Add include directories
target_include_directories(${PROJECT_NAME} PUBLIC include/)
Expand Down
Binary file added binary/lsda
Binary file not shown.
Binary file added binary/lsda_objcopy_onlysection
Binary file not shown.
5 changes: 2 additions & 3 deletions conanfile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from conan import ConanFile
from conan.errors import ConanException
from conan.tools.cmake import CMake, cmake_layout
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
from conan.tools.files import copy
from conan.tools.build import check_min_cppstd
import os
Expand All @@ -27,13 +27,12 @@ def _min_cppstd(self) -> str:
format: `self.requires(<package_name_on_conancenter>)`
"""
def requirements(self):
pass
self.requires("libelf/0.8.13")

def generate(self):
c = CMake(self)
c.configure()
c.build(target="copy_compile_commands")

"""
Manage requirements to build our project, this includes all build tools.
"""
Expand Down
83 changes: 83 additions & 0 deletions include/elf_parser.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#pragma once
#include <err.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sysexits.h>
#include <unistd.h>

#include <gelf.h>
#include <libelf.h>

#include <print>
#include <string>
#include <unordered_map>
#include <vector>
class ElfParser
{
public:
ElfParser(std::string_view p_file_name)
: m_file(p_file_name)
{
if (elf_version(EV_CURRENT) == EV_NONE) {
std::println(
stderr, "ELF library initialization failed : {}", elf_errmsg(-1));
}

if ((m_fd = open(m_file.c_str(), O_RDONLY, 0)) < 0) {
std::println(stderr, "\{} failed to open", elf_errmsg(-1));
fileOpened = false;
} else {
fileOpened = true;
}

if ((m_elf = elf_begin(m_fd, ELF_C_READ, NULL)) == NULL) {
std::println(
stderr, "Elf file failed to load : {}.", elf_errmsg(-1));
fileLoaded = false;
} else {
fileLoaded = true;
}

if (fileLoaded && fileOpened) {
if (elf_kind(m_elf) != ELF_K_ELF) {
std::println(stderr, "\{} is not an ELF object. ", m_file);
}
std::println("{} {}-bit ELF object\n",
m_file,
m_elf_class == ELFCLASS32 ? 32 : 64);
loadElfHeader();
loadSectionHeader();
loadProgramHeader();
}
};

~ElfParser()
{
close(m_fd);
std::println("ELF file closed");
}

void printElfHeader();
void printSectionHeader();
void printProgramHeader();

void getSection(std::string_view const& section);

private:
int m_elf_class;
int m_fd;
std::string m_file;

Elf* m_elf;
GElf_Ehdr m_elfHeader;
std::vector<GElf_Phdr> m_programHeader;
std::unordered_map<std::string, GElf_Shdr> m_sectionHeader;

bool elfHeaderLoaded;
bool fileOpened;
bool fileLoaded;

void loadElfHeader();
void loadSectionHeader();
void loadProgramHeader();
};
132 changes: 132 additions & 0 deletions src/elf_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include "../include/elf_parser.hpp"

void ElfParser::loadElfHeader()
{
if ((gelf_getehdr(m_elf, &m_elfHeader)) == NULL) {
std::print(stderr, "Elf header failed to load: {}.", elf_errmsg(-1));
elfHeaderLoaded = false;
} else {
elfHeaderLoaded = true;
}
}

void ElfParser::loadSectionHeader()
{
if (!elfHeaderLoaded) {
std::print(stderr, "Elf header was not previously loaded: {}.", elf_errmsg(-1));
} else {
char* sectionName;
Elf_Scn* scn = nullptr;
GElf_Shdr tempSectionHeader;
while ((scn = elf_nextscn(m_elf, scn)) != NULL) {
if (gelf_getshdr(scn, &tempSectionHeader) != &tempSectionHeader) {
std::print(
stderr, "Unable to get section header: {}.", elf_errmsg(-1));
}

if ((sectionName = elf_strptr(m_elf,
m_elfHeader.e_shstrndx,
tempSectionHeader.sh_name)) == NULL) {
std::print(
stderr, "Unable to get section name: {}.", elf_errmsg(-1));
}

m_sectionHeader.emplace(sectionName, tempSectionHeader);
}
}
}

void ElfParser::loadProgramHeader()
{
if (!elfHeaderLoaded) {
std::print(
stderr, "Elf header was not previously loaded: {}.", elf_errmsg(-1));
} else {
GElf_Phdr tempProgramHeader;
for (int i = 0; i < m_elfHeader.e_phnum; i++) {
if (gelf_getphdr(m_elf, i, &tempProgramHeader) !=
&tempProgramHeader) {
std::print(
stderr, "Unable to get program header: {}.", elf_errmsg(-1));
}
m_programHeader.emplace_back(tempProgramHeader);
}
}
}

void ElfParser::printElfHeader()
{
if (!elfHeaderLoaded) {
std::print(
stderr, "Elf header was not previously loaded: {}.", elf_errmsg(-1));
} else {
std::println("ELF Header");
std::println("====================");
std::print("ident: ");
for (int i = 0; i < 16; i++) {
std::print("0x{:X}, ", m_elfHeader.e_ident[i]);
}
std::println("");
std::println("type: 0x{:X}", m_elfHeader.e_type);
std::println("machine: 0x{:X}", m_elfHeader.e_machine);
std::println("version: 0x{:X}", m_elfHeader.e_version);
std::println("entry: 0x{:X}", m_elfHeader.e_entry);
std::println("phoff: 0x{:X}", m_elfHeader.e_phoff);
std::println("shoff: 0x{:X}", m_elfHeader.e_shoff);
std::println("flags: 0x{:X}", m_elfHeader.e_flags);
std::println("ehsize: 0x{:X}", m_elfHeader.e_ehsize);
std::println("phentsize: 0x{:X}", m_elfHeader.e_phentsize);
std::println("shentsize: 0x{:X}", m_elfHeader.e_shentsize);
std::println("shnum: 0x{:X}", m_elfHeader.e_shnum);
std::println("phnum: 0x{:X}", m_elfHeader.e_phnum);
}
}

void ElfParser::printSectionHeader()
{
if(m_sectionHeader.empty())
{
std::print(stderr, "No section headers exists.");
} else {
std::println("Section Header: ({})", m_elfHeader.e_shnum);
std::println("====================");
for(const auto& section : m_sectionHeader)
{
std::println(
"Section: {}", section.first);
std::println(" type : 0x{:X}", section.second.sh_type);
std::println(" flags : 0x{:X}", section.second.sh_flags);
std::println(" addr : 0x{:X}", section.second.sh_addr);
std::println(" offset : 0x{:X}", section.second.sh_offset);
std::println(" size : 0x{:X}", section.second.sh_size);
std::println(" link : 0x{:X}", section.second.sh_link);
std::println(" info : 0x{:X}", section.second.sh_info);
std::println(" addralign : 0x{:X}", section.second.sh_addralign);
std::println(" entsize : 0x{:X}", section.second.sh_entsize);
std::println("====================");
}
}
}

void ElfParser::printProgramHeader()
{
if(m_programHeader.empty())
{
std::print(stderr, "No program headers exists.");
} else {
for(int i = 0; i < m_elfHeader.e_phnum; i++)
{
std::println("Program Header: {}", i);
std::println("====================");
std::println("type : 0x{:X}", m_programHeader[i].p_type);
std::println("flags : 0x{:X}", m_programHeader[i].p_flags);
std::println("offset : 0x{:X}", m_programHeader[i].p_offset);
std::println("vaddr : 0x{:X}", m_programHeader[i].p_vaddr);
std::println("paddr : 0x{:X}", m_programHeader[i].p_paddr);
std::println("filez : 0x{:X}", m_programHeader[i].p_filesz);
std::println("memz : 0x{:X}", m_programHeader[i].p_memsz);
std::println("align : 0x{:X}", m_programHeader[i].p_align);
std::println("====================");
}
}
}
18 changes: 16 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
#include <bitset>
#include <print>
#include <string>

int main()
#include "../include/elf_parser.hpp"
int main(int argc, char* argv[])
{
std::println("yeet: {}", __cplusplus);
//const std::string_view lsda = ".gcc_except_table";

if (argc < 2)
{
std::print(stderr, "usage : %s file - name {}", argv[0]);
}

ElfParser elf(argv[1]);
elf.printElfHeader();
//elf.printSectionHeader();
elf.printProgramHeader();

return 0;
}