#include "libkmod.h"
#include "libkmod-internal.h"
-enum kmod_elf_class {
- KMOD_ELF_32 = (1 << 1),
- KMOD_ELF_64 = (1 << 2),
- KMOD_ELF_LSB = (1 << 3),
- KMOD_ELF_MSB = (1 << 4),
-};
-
/* as defined in module-init-tools */
struct kmod_modversion32 {
uint32_t crc;
struct kmod_elf {
const uint8_t *memory;
uint64_t size;
- enum kmod_elf_class class;
+ bool x32;
+ bool msb;
struct kmod_elf_header {
struct {
uint64_t offset;
{
va_list args;
- fprintf(stderr, "ELFDBG-%d%c: %s:%u %s() ", (elf->class & KMOD_ELF_32) ? 32 : 64,
- (elf->class & KMOD_ELF_MSB) ? 'M' : 'L', fname, line, func);
+ fprintf(stderr, "ELFDBG-%d%c: %s:%u %s() ", elf->x32 ? 32 : 64,
+ elf->msb ? 'M' : 'L', fname, line, func);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
-static int elf_identify(const void *memory, uint64_t size)
+static int elf_identify(struct kmod_elf *elf, const void *memory, uint64_t size)
{
const uint8_t *p = memory;
- int class = 0;
if (size <= EI_NIDENT || memcmp(p, ELFMAG, SELFMAG) != 0)
return -ENOEXEC;
case ELFCLASS32:
if (size <= sizeof(Elf32_Ehdr))
return -EINVAL;
- class |= KMOD_ELF_32;
+ elf->x32 = true;
break;
case ELFCLASS64:
if (size <= sizeof(Elf64_Ehdr))
return -EINVAL;
- class |= KMOD_ELF_64;
+ elf->x32 = false;
break;
default:
return -EINVAL;
switch (p[EI_DATA]) {
case ELFDATA2LSB:
- class |= KMOD_ELF_LSB;
+ elf->msb = false;
break;
case ELFDATA2MSB:
- class |= KMOD_ELF_MSB;
+ elf->msb = true;
break;
default:
return -EINVAL;
}
- return class;
+ return 0;
}
static inline uint64_t elf_get_uint(const struct kmod_elf *elf, uint64_t offset,
}
p = elf->memory + offset;
- if (elf->class & KMOD_ELF_MSB) {
+ if (elf->msb) {
for (i = 0; i < size; i++)
ret = (ret << 8) | p[i];
} else {
}
p = changed + offset;
- if (elf->class & KMOD_ELF_MSB) {
+ if (elf->msb) {
for (i = 1; i <= size; i++) {
p[size - i] = value & 0xff;
value = (value & 0xffffffffffffff00) >> 8;
#define READV(field) \
elf_get_uint(elf, off + offsetof(typeof(*hdr), field), sizeof(hdr->field))
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
Elf32_Shdr *hdr;
*size = READV(sh_size);
*offset = READV(sh_offset);
struct kmod_elf *elf;
uint64_t min_size;
size_t shdrs_size, shdr_size;
- int class;
+ int err;
assert_cc(sizeof(uint16_t) == sizeof(Elf32_Half));
assert_cc(sizeof(uint16_t) == sizeof(Elf64_Half));
return NULL;
}
- class = elf_identify(memory, size);
- if (class < 0) {
- errno = -class;
+ elf = malloc(sizeof(struct kmod_elf));
+ if (elf == NULL) {
return NULL;
}
- elf = malloc(sizeof(struct kmod_elf));
- if (elf == NULL) {
+ err = elf_identify(elf, memory, size);
+ if (err < 0) {
+ free(elf);
+ errno = -err;
return NULL;
}
elf->memory = memory;
elf->size = size;
- elf->class = class;
#define READV(field) elf_get_uint(elf, offsetof(typeof(*hdr), field), sizeof(hdr->field))
elf->header.section.entry_size = READV(e_shentsize); \
elf->header.strings.section = READV(e_shstrndx); \
elf->header.machine = READV(e_machine)
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
Elf32_Ehdr *hdr;
LOAD_HEADER;
shdr_size = sizeof(Elf32_Shdr);
assert_cc(sizeof(struct kmod_modversion64) == sizeof(struct kmod_modversion32));
- if (elf->class & KMOD_ELF_32)
+ if (elf->x32)
offcrc = sizeof(uint32_t);
else
offcrc = sizeof(uint64_t);
buf = elf_get_section_header(elf, idx);
off = (const uint8_t *)buf - elf->memory;
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
off += offsetof(Elf32_Shdr, sh_flags);
size = sizeof(((Elf32_Shdr *)buf)->sh_flags);
} else {
goto fallback;
}
- if (elf->class & KMOD_ELF_32)
+ if (elf->x32)
symlen = sizeof(Elf32_Sym);
else
symlen = sizeof(Elf64_Sym);
#define READV(field) \
elf_get_uint(elf, sym_off + offsetof(typeof(*s), field), sizeof(s->field))
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
Elf32_Sym *s;
name_off = READV(st_name);
} else {
#define READV(field) \
elf_get_uint(elf, sym_off + offsetof(typeof(*s), field), sizeof(s->field))
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
Elf32_Sym *s;
name_off = READV(st_name);
crc = READV(st_value);
continue;
name += crc_strlen;
- if (elf->class & KMOD_ELF_32)
+ if (elf->x32)
bind = ELF32_ST_BIND(info);
else
bind = ELF64_ST_BIND(info);
size_t verlen, crclen, off;
uint64_t i;
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
struct kmod_modversion32 *mv;
verlen = sizeof(*mv);
crclen = sizeof(mv->crc);
verlen = 0;
crclen = 0;
} else {
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
struct kmod_modversion32 *mv;
verlen = sizeof(*mv);
crclen = sizeof(mv->crc);
return -EINVAL;
}
- if (elf->class & KMOD_ELF_32)
+ if (elf->x32)
symlen = sizeof(Elf32_Sym);
else
symlen = sizeof(Elf64_Sym);
#define READV(field) \
elf_get_uint(elf, sym_off + offsetof(typeof(*s), field), sizeof(s->field))
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
Elf32_Sym *s;
name_off = READV(st_name);
secidx = READV(st_shndx);
if (handle_register_symbols) {
uint8_t type;
- if (elf->class & KMOD_ELF_32)
+ if (elf->x32)
type = ELF32_ST_TYPE(info);
else
type = ELF64_ST_TYPE(info);
#define READV(field) \
elf_get_uint(elf, sym_off + offsetof(typeof(*s), field), sizeof(s->field))
- if (elf->class & KMOD_ELF_32) {
+ if (elf->x32) {
Elf32_Sym *s;
name_off = READV(st_name);
secidx = READV(st_shndx);
if (handle_register_symbols) {
uint8_t type;
- if (elf->class & KMOD_ELF_32)
+ if (elf->x32)
type = ELF32_ST_TYPE(info);
else
type = ELF64_ST_TYPE(info);
continue;
}
- if (elf->class & KMOD_ELF_32)
+ if (elf->x32)
bind = ELF32_ST_BIND(info);
else
bind = ELF64_ST_BIND(info);