working on ELF identification

This commit is contained in:
mykola2312 2024-08-25 08:08:52 +03:00
parent 8a3ea5b2b2
commit bc2f89b039
2 changed files with 102 additions and 0 deletions

View file

@ -1 +1,61 @@
#include "relf/relf.h" #include "relf/relf.h"
#include "blackjack/debug.h"
#include <elf.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
relf_value_t relf_open(relf_t* relf, const char* path)
{
// reset struct
memset(relf, '\0', sizeof(relf_t));
// try stat file
struct stat st = {0};
if (stat(path, &stat))
return RELF_ERROR(RELF_FAILED_OPEN);
// open file and read ELF header
relf->fd = open(path, O_RDONLY);
if (relf->fd < 0)
return RELF_ERROR(RELF_FAILED_OPEN);
union {
Elf64_Ehdr hdr64;
Elf32_Ehdr hdr32;
} e;
// read biggest value by default
if (read(relf->fd, &e.hdr64, sizeof(e.hdr64)) < sizeof(e.hdr64))
{
close(relf->fd);
return RELF_ERROR(RELF_FAILED_OPEN);
}
// check magic and decide ELF type
// we operate here ELF64 variant since it same as in ELF32
if (!memcmp(e.hdr64.e_ident, ELFMAG, sizeof(ELFMAG)))
{
// not an ELF file at all
close(relf->fd);
return RELF_ERROR(RELF_NOT_AN_ELF);
}
// 32 bit or 64 bit
switch (e.hdr64.e_ident[EI_CLASS])
{
case ELFCLASS32: relf->type = RELF_32BIT; break;
case ELFCLASS64: relf->type = RELF_64BIT; break;
default:
close(relf->fd);
return RELF_ERROR(RELF_UNSUPPORTED);
}
if (e.hdr64.e_ident[EI_DATA] != ELFDATA2LSB)
{
// not little endian, we can't work with that
close(relf->fd);
return RELF_ERROR(RELF_UNSUPPORTED);
}
}

View file

@ -1,4 +1,46 @@
#ifndef __RELF_H #ifndef __RELF_H
#define __RELF_H #define __RELF_H
#include <stdint.h>
// composite error type
typedef enum {
RELF_MMAP_FAILED = -4, // file memory mapping failed
RELF_UNSUPPORTED = -3, // big endian or not x86/x86-64 architecture
RELF_NOT_AN_ELF = -2, // wrong magic
RELF_FAILED_OPEN = -1, // failed to stat or open file
RELF_OK = 0,
} relf_error_t;
typedef union {
relf_error_t error;
uintptr_t value;
} relf_value_t;
// supply relf_value_t type here
#define RELF_IS_ERROR(v) (v.error < 0)
#define RELF_ERROR(e) ((relf_value_t) {.error = e})
typedef enum {
RELF_64BIT,
RELF_32BIT
} relf_type_t;
// relf instance
typedef struct {
int fd;
void* image;
// is it 64 or 32 bit mode
relf_type_t type;
} relf_t;
// opens ELF file, checks ELF magic and maps it into memory
// may load additional info like string table
relf_value_t relf_open(relf_t* relf, const char* path);
// closes mapping and file, frees any allocated memory in relf instance
void relf_close(relf_t* relf);
#endif #endif