Created
September 5, 2022 20:18
-
-
Save hbobenicio/acac299f6f421ad2e1e1cfef3e590a4a to your computer and use it in GitHub Desktop.
Print elf 64 header info
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
#include <elf.h> | |
using std::cout; | |
using std::cerr; | |
using std::string_view; | |
using std::array; | |
namespace elf::header | |
{ | |
void print(const Elf64_Ehdr& header); | |
void print_ident(const Elf64_Ehdr& header); | |
void print_ident_class(const Elf64_Ehdr& header); | |
void print_ident_data_encoding(const Elf64_Ehdr& header); | |
void print_ident_version(const Elf64_Ehdr& header); | |
void print_ident_os_abi(const Elf64_Ehdr& header); | |
void print_ident_abi_version(const Elf64_Ehdr& header); | |
void print_type(const Elf64_Ehdr& header); | |
void print_machine(const Elf64_Ehdr& header); | |
} | |
int main() | |
{ | |
static constexpr array<string_view, 2> file_paths = { | |
"/usr/bin/gcc", | |
"/home/hugo/repos/github/hbobenicio/my-compiler/target/hello-world.o", | |
}; | |
for (auto file_path: file_paths) { | |
cout << file_path << ":\n"; | |
Elf64_Ehdr header = {}; | |
{ | |
std::ifstream file; | |
file.open(file_path.data(), std::ios_base::in | std::ios_base::binary); | |
if (!file.good()) { | |
auto error_code = errno; | |
cerr << "error: failed to open file \"" << file_path << "\": " << strerror(error_code) << "\n"; | |
exit(1); | |
} | |
// TODO First, check only the ELF magic number. Then check its class format (32/64 bits). Only then assume the full Elf64_Ehdr | |
file.read(reinterpret_cast<char*>(&header), sizeof(header)); | |
if (std::streamsize bytes_read_count = file.gcount(); bytes_read_count != sizeof(header)) { | |
cerr << "error: failed to read elf 64 header. Is \"" << file_path << "\" an Elf64 encoded file?\n"; | |
exit(1); | |
} | |
} | |
elf::header::print(header); | |
cout << '\n'; | |
} | |
} | |
namespace elf::header | |
{ | |
void print(const Elf64_Ehdr& header) | |
{ | |
elf::header::print_ident(header); | |
elf::header::print_type(header); | |
elf::header::print_machine(header); | |
} | |
void print_ident(const Elf64_Ehdr& header) | |
{ | |
elf::header::print_ident_class(header); | |
elf::header::print_ident_data_encoding(header); | |
elf::header::print_ident_version(header); | |
elf::header::print_ident_os_abi(header); | |
//elf::header::print_ident_abi_version(header); | |
} | |
void print_ident_class(const Elf64_Ehdr& header) | |
{ | |
cout << "Elf Class: "; | |
switch (header.e_ident[EI_CLASS]) { | |
case ELFCLASSNONE: | |
cout << "None (ELFCLASSNONE). This class is invalid"; | |
break; | |
case ELFCLASS32: | |
cout << "32 bits (ELFCLASS32)"; | |
break; | |
case ELFCLASS64: | |
cout << "64 bits (ELFCLASS64)"; | |
break; | |
default: | |
cout << "Unknown"; | |
} | |
cout << '\n'; | |
} | |
void print_ident_data_encoding(const Elf64_Ehdr& header) | |
{ | |
cout << "Elf Data Encoding: "; | |
switch (header.e_ident[EI_DATA]) { | |
case ELFDATA2LSB: | |
cout << "Two's complement, little-endian (ELFDATA2LSB)"; | |
break; | |
case ELFDATA2MSB: | |
cout << "Two's complement, big-endian (ELFDATA2MSB)"; | |
break; | |
case ELFDATANONE: | |
default: | |
cout << "Unknown"; | |
} | |
cout << '\n'; | |
} | |
void print_ident_version(const Elf64_Ehdr& header) | |
{ | |
cout << "Elf Version: "; | |
switch (header.e_ident[EI_VERSION]) { | |
case EV_NONE: | |
cout << "Invalid version (EV_NONE)"; | |
break; | |
case EV_CURRENT: | |
cout << "Current version (EV_CURRENT)"; | |
break; | |
default: | |
cout << "Unknown"; | |
} | |
cout << '\n'; | |
} | |
void print_ident_os_abi(const Elf64_Ehdr& header) | |
{ | |
cout << "Elf OS ABI: "; | |
switch (header.e_ident[EI_OSABI]) { | |
case ELFOSABI_SYSV: | |
cout << "UNIX System V ABI (ELFOSABI_SYSV)"; | |
break; | |
case ELFOSABI_HPUX: | |
cout << "HP-UX ABI (ELFOSABI_HPUX)"; | |
break; | |
case ELFOSABI_NETBSD: | |
cout << "NetBSD ABI (ELFOSABI_NETBSD)"; | |
break; | |
case ELFOSABI_LINUX: | |
cout << "Linux ABI (ELFOSABI_LINUX)"; | |
break; | |
case ELFOSABI_SOLARIS: | |
cout << "Solaris ABI (ELFOSABI_SOLARIS)"; | |
break; | |
case ELFOSABI_IRIX: | |
cout << "IRIX ABI (ELFOSABI_IRIX)"; | |
break; | |
case ELFOSABI_FREEBSD: | |
cout << "FreeBSD ABI (ELFOSABI_FREEBSD)"; | |
break; | |
case ELFOSABI_TRU64: | |
cout << "TRU64 UNIX ABI (ELFOSABI_TRU64)"; | |
break; | |
case ELFOSABI_ARM: | |
cout << "ARM architecture ABI (ELFOSABI_ARM)"; | |
break; | |
case ELFOSABI_STANDALONE: | |
cout << "Stand-alone (embedded) ABI (ELFOSABI_STANDALONE)"; | |
break; | |
default: | |
cout << "Unknown"; | |
} | |
cout << '\n'; | |
} | |
void print_ident_abi_version(const Elf64_Ehdr& header) | |
{ | |
cout << "Elf ABI Version: " << header.e_ident[EI_ABIVERSION] << '\n'; | |
} | |
void print_type(const Elf64_Ehdr& header) | |
{ | |
cout << "Elf Type: "; | |
switch (header.e_type) { | |
case ET_REL: | |
cout << "Relocatable"; | |
break; | |
case ET_EXEC: | |
cout << "Executable"; | |
break; | |
case ET_DYN: | |
cout << "Shared Object"; | |
break; | |
case ET_CORE: | |
cout << "Core File"; | |
break; | |
case ET_NONE: | |
default: | |
cout << "Unknown"; | |
} | |
cout << '\n'; | |
} | |
void print_machine(const Elf64_Ehdr& header) | |
{ | |
cout << "Elf Machine (Arch): "; | |
switch (header.e_machine) { | |
case EM_M32: cout << "AT&T WE 32100"; break; | |
case EM_SPARC: cout << "Sun Microsystems SPARC"; break; | |
case EM_386: cout << "Intel 80386"; break; | |
case EM_68K: cout << "Motorola 68000"; break; | |
case EM_88K: cout << "Motorola 88000"; break; | |
case EM_860: cout << "Intel 80860"; break; | |
case EM_MIPS: cout << "MIPS RS3000 (big-endian only)"; break; | |
case EM_PARISC: cout << "HP/PA"; break; | |
case EM_SPARC32PLUS: cout << "SPARC with enhanced instruction set"; break; | |
case EM_PPC: cout << "PowerPC"; break; | |
case EM_PPC64: cout << "PowerPC 64-bit"; break; | |
case EM_S390: cout << "IBM S/390"; break; | |
case EM_ARM: cout << "Advanced RISC Machines"; break; | |
case EM_SH: cout << "Renesas SuperH"; break; | |
case EM_SPARCV9: cout << "SPARC v9 64-bit"; break; | |
case EM_IA_64: cout << "Intel Itanium"; break; | |
case EM_X86_64: cout << "AMD x86-64"; break; | |
case EM_VAX: cout << "DEC Vax"; break; | |
case EM_NONE: | |
default: | |
cout << "An unknown machine"; | |
} | |
cout << '\n'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment