]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
libkmod: Split elf->class into two booleans
authorTobias Stoeckmann <tobias@stoeckmann.org>
Wed, 16 Oct 2024 14:52:26 +0000 (16:52 +0200)
committerLucas De Marchi <lucas.de.marchi@gmail.com>
Fri, 18 Oct 2024 19:00:27 +0000 (14:00 -0500)
Compilers on x86_64 use two instructions to test value of class
variable, i.e. loading a mask and then comparing with value.

A boolean is faster, shows directly what it is about, and the struct
does not even grow.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://github.com/kmod-project/kmod/pull/187
Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
libkmod/libkmod-elf.c

index c90b66113fc87b3e18db15113dde0eb9008bbaec..9660bcd6b1482a308432d346f160dc15894430af 100644 (file)
 #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;
@@ -36,7 +29,8 @@ struct kmod_modversion64 {
 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;
@@ -68,17 +62,16 @@ _printf_format_(5, 6) static inline void _elf_dbg(const struct kmod_elf *elf,
 {
        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;
@@ -87,12 +80,12 @@ static int elf_identify(const void *memory, uint64_t size)
        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;
@@ -100,16 +93,16 @@ static int elf_identify(const void *memory, uint64_t size)
 
        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,
@@ -130,7 +123,7 @@ 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 {
@@ -165,7 +158,7 @@ static inline int elf_set_uint(const struct kmod_elf *elf, uint64_t offset, uint
        }
 
        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;
@@ -222,7 +215,7 @@ static inline int elf_get_section_info(const struct kmod_elf *elf, uint16_t idx,
 #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);
@@ -260,7 +253,7 @@ struct kmod_elf *kmod_elf_new(const void *memory, off_t size)
        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));
@@ -272,20 +265,20 @@ struct kmod_elf *kmod_elf_new(const void *memory, off_t size)
                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))
 
@@ -295,7 +288,7 @@ struct kmod_elf *kmod_elf_new(const void *memory, off_t size)
        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);
@@ -507,7 +500,7 @@ int kmod_elf_get_modversions(const struct kmod_elf *elf, struct kmod_modversion
 
        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);
@@ -577,7 +570,7 @@ static int elf_strip_versions_section(const struct kmod_elf *elf, uint8_t *chang
        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 {
@@ -820,7 +813,7 @@ int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **ar
                goto fallback;
        }
 
-       if (elf->class & KMOD_ELF_32)
+       if (elf->x32)
                symlen = sizeof(Elf32_Sym);
        else
                symlen = sizeof(Elf64_Sym);
@@ -844,7 +837,7 @@ int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **ar
 
 #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 {
@@ -889,7 +882,7 @@ int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **ar
 
 #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);
@@ -908,7 +901,7 @@ int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **ar
                        continue;
                name += crc_strlen;
 
-               if (elf->class & KMOD_ELF_32)
+               if (elf->x32)
                        bind = ELF32_ST_BIND(info);
                else
                        bind = ELF64_ST_BIND(info);
@@ -935,7 +928,7 @@ static int kmod_elf_crc_find(const struct kmod_elf *elf, const void *versions,
        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);
@@ -985,7 +978,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
                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);
@@ -1016,7 +1009,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
                return -EINVAL;
        }
 
-       if (elf->class & KMOD_ELF_32)
+       if (elf->x32)
                symlen = sizeof(Elf32_Sym);
        else
                symlen = sizeof(Elf64_Sym);
@@ -1064,7 +1057,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
 
 #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);
@@ -1081,7 +1074,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
 
                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);
@@ -1162,7 +1155,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
 
 #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);
@@ -1179,7 +1172,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
 
                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);
@@ -1199,7 +1192,7 @@ int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf,
                        continue;
                }
 
-               if (elf->class & KMOD_ELF_32)
+               if (elf->x32)
                        bind = ELF32_ST_BIND(info);
                else
                        bind = ELF64_ST_BIND(info);