working on ELF identification
This commit is contained in:
parent
8a3ea5b2b2
commit
bc2f89b039
2 changed files with 102 additions and 0 deletions
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
Loading…
Add table
Reference in a new issue