diff --git a/CMakeLists.txt b/CMakeLists.txt index e2ed707..e912356 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,11 @@ 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 @@ -8,9 +13,17 @@ add_custom_target(copy_compile_commands ALL ${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/) diff --git a/binary/lsda b/binary/lsda new file mode 100644 index 0000000..72aac90 Binary files /dev/null and b/binary/lsda differ diff --git a/binary/lsda_objcopy_onlysection b/binary/lsda_objcopy_onlysection new file mode 100755 index 0000000..72aac90 Binary files /dev/null and b/binary/lsda_objcopy_onlysection differ diff --git a/conanfile.py b/conanfile.py index d17d124..398b7c0 100644 --- a/conanfile.py +++ b/conanfile.py @@ -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 @@ -27,13 +27,12 @@ def _min_cppstd(self) -> str: format: `self.requires()` """ 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. """ diff --git a/include/elf_parser.hpp b/include/elf_parser.hpp new file mode 100644 index 0000000..92b5055 --- /dev/null +++ b/include/elf_parser.hpp @@ -0,0 +1,83 @@ +#pragma once +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +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 m_programHeader; + std::unordered_map m_sectionHeader; + + bool elfHeaderLoaded; + bool fileOpened; + bool fileLoaded; + + void loadElfHeader(); + void loadSectionHeader(); + void loadProgramHeader(); +}; diff --git a/src/elf_parser.cpp b/src/elf_parser.cpp new file mode 100644 index 0000000..a178cf6 --- /dev/null +++ b/src/elf_parser.cpp @@ -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("===================="); + } + } +} diff --git a/src/main.cpp b/src/main.cpp index cea7f40..a645238 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,21 @@ +#include #include +#include -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; } \ No newline at end of file