Skip to content

Instantly share code, notes, and snippets.

@hbobenicio
Created September 5, 2022 20:18
Show Gist options
  • Save hbobenicio/acac299f6f421ad2e1e1cfef3e590a4a to your computer and use it in GitHub Desktop.
Save hbobenicio/acac299f6f421ad2e1e1cfef3e590a4a to your computer and use it in GitHub Desktop.
Print elf 64 header info
#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