@@ -85,6 +85,25 @@ static uint64_t (*r8)(const uint64_t *);
static void (*w)(uint32_t, uint32_t *);
typedef void (*table_sort_t)(char *, int);
+static struct elf_funcs {
+ int (*compare_extable)(const void *a, const void *b);
+ uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
+ uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
+ uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
+ uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
+ uint64_t (*shdr_addr)(Elf_Shdr *shdr);
+ uint64_t (*shdr_offset)(Elf_Shdr *shdr);
+ uint64_t (*shdr_size)(Elf_Shdr *shdr);
+ uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
+ uint32_t (*shdr_link)(Elf_Shdr *shdr);
+ uint32_t (*shdr_name)(Elf_Shdr *shdr);
+ uint32_t (*shdr_type)(Elf_Shdr *shdr);
+ uint8_t (*sym_type)(Elf_Sym *sym);
+ uint32_t (*sym_name)(Elf_Sym *sym);
+ uint64_t (*sym_value)(Elf_Sym *sym);
+ uint16_t (*sym_shndx)(Elf_Sym *sym);
+} e;
+
static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
{
return r8(&ehdr->e64.e_shoff);
@@ -95,6 +114,11 @@ static uint64_t ehdr32_shoff(Elf_Ehdr *ehdr)
return r(&ehdr->e32.e_shoff);
}
+static uint64_t ehdr_shoff(Elf_Ehdr *ehdr)
+{
+ return e.ehdr_shoff(ehdr);
+}
+
#define EHDR_HALF(fn_name) \
static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \
{ \
@@ -104,6 +128,11 @@ static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \
static uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \
{ \
return r2(&ehdr->e32.e_##fn_name); \
+} \
+ \
+static uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \
+{ \
+ return e.ehdr_##fn_name(ehdr); \
}
EHDR_HALF(shentsize)
@@ -119,6 +148,11 @@ static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
{ \
return r(&shdr->e32.sh_##fn_name); \
+} \
+ \
+static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return e.shdr_##fn_name(shdr); \
}
#define SHDR_ADDR(fn_name) \
@@ -130,6 +164,11 @@ static uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \
static uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \
{ \
return r(&shdr->e32.sh_##fn_name); \
+} \
+ \
+static uint64_t shdr_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return e.shdr_##fn_name(shdr); \
}
#define SHDR_WORD(fn_name) \
@@ -141,6 +180,10 @@ static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
{ \
return r(&shdr->e32.sh_##fn_name); \
+} \
+static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return e.shdr_##fn_name(shdr); \
}
SHDR_ADDR(addr)
@@ -161,6 +204,11 @@ static uint64_t sym64_##fn_name(Elf_Sym *sym) \
static uint64_t sym32_##fn_name(Elf_Sym *sym) \
{ \
return r(&sym->e32.st_##fn_name); \
+} \
+ \
+static uint64_t sym_##fn_name(Elf_Sym *sym) \
+{ \
+ return e.sym_##fn_name(sym); \
}
#define SYM_WORD(fn_name) \
@@ -172,6 +220,11 @@ static uint32_t sym64_##fn_name(Elf_Sym *sym) \
static uint32_t sym32_##fn_name(Elf_Sym *sym) \
{ \
return r(&sym->e32.st_##fn_name); \
+} \
+ \
+static uint32_t sym_##fn_name(Elf_Sym *sym) \
+{ \
+ return e.sym_##fn_name(sym); \
}
#define SYM_HALF(fn_name) \
@@ -183,6 +236,11 @@ static uint16_t sym64_##fn_name(Elf_Sym *sym) \
static uint16_t sym32_##fn_name(Elf_Sym *sym) \
{ \
return r2(&sym->e32.st_##fn_name); \
+} \
+ \
+static uint16_t sym_##fn_name(Elf_Sym *sym) \
+{ \
+ return e.sym_##fn_name(sym); \
}
static uint8_t sym64_type(Elf_Sym *sym)
@@ -195,6 +253,11 @@ static uint8_t sym32_type(Elf_Sym *sym)
return ELF32_ST_TYPE(sym->e32.st_info);
}
+static uint8_t sym_type(Elf_Sym *sym)
+{
+ return e.sym_type(sym);
+}
+
SYM_ADDR(value)
SYM_WORD(name)
SYM_HALF(shndx)
@@ -322,29 +385,16 @@ static int compare_extable_64(const void *a, const void *b)
return av > bv;
}
+static int compare_extable(const void *a, const void *b)
+{
+ return e.compare_extable(a, b);
+}
+
static inline void *get_index(void *start, int entsize, int index)
{
return start + (entsize * index);
}
-
-static int (*compare_extable)(const void *a, const void *b);
-static uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
-static uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
-static uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
-static uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
-static uint64_t (*shdr_addr)(Elf_Shdr *shdr);
-static uint64_t (*shdr_offset)(Elf_Shdr *shdr);
-static uint64_t (*shdr_size)(Elf_Shdr *shdr);
-static uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
-static uint32_t (*shdr_link)(Elf_Shdr *shdr);
-static uint32_t (*shdr_name)(Elf_Shdr *shdr);
-static uint32_t (*shdr_type)(Elf_Shdr *shdr);
-static uint8_t (*sym_type)(Elf_Sym *sym);
-static uint32_t (*sym_name)(Elf_Sym *sym);
-static uint64_t (*sym_value)(Elf_Sym *sym);
-static uint16_t (*sym_shndx)(Elf_Sym *sym);
-
static int extable_ent_size;
static int long_size;
@@ -864,7 +914,30 @@ static int do_file(char const *const fname, void *addr)
}
switch (ehdr->e32.e_ident[EI_CLASS]) {
- case ELFCLASS32:
+ case ELFCLASS32: {
+ struct elf_funcs efuncs = {
+ .compare_extable = compare_extable_32,
+ .ehdr_shoff = ehdr32_shoff,
+ .ehdr_shentsize = ehdr32_shentsize,
+ .ehdr_shstrndx = ehdr32_shstrndx,
+ .ehdr_shnum = ehdr32_shnum,
+ .shdr_addr = shdr32_addr,
+ .shdr_offset = shdr32_offset,
+ .shdr_link = shdr32_link,
+ .shdr_size = shdr32_size,
+ .shdr_name = shdr32_name,
+ .shdr_type = shdr32_type,
+ .shdr_entsize = shdr32_entsize,
+ .sym_type = sym32_type,
+ .sym_name = sym32_name,
+ .sym_value = sym32_value,
+ .sym_shndx = sym32_shndx,
+ };
+
+ e = efuncs;
+ long_size = 4;
+ extable_ent_size = 8;
+
if (r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) ||
r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) {
fprintf(stderr,
@@ -872,26 +945,32 @@ static int do_file(char const *const fname, void *addr)
return -1;
}
- compare_extable = compare_extable_32;
- ehdr_shoff = ehdr32_shoff;
- ehdr_shentsize = ehdr32_shentsize;
- ehdr_shstrndx = ehdr32_shstrndx;
- ehdr_shnum = ehdr32_shnum;
- shdr_addr = shdr32_addr;
- shdr_offset = shdr32_offset;
- shdr_link = shdr32_link;
- shdr_size = shdr32_size;
- shdr_name = shdr32_name;
- shdr_type = shdr32_type;
- shdr_entsize = shdr32_entsize;
- sym_type = sym32_type;
- sym_name = sym32_name;
- sym_value = sym32_value;
- sym_shndx = sym32_shndx;
- long_size = 4;
- extable_ent_size = 8;
+ }
break;
- case ELFCLASS64:
+ case ELFCLASS64: {
+ struct elf_funcs efuncs = {
+ .compare_extable = compare_extable_64,
+ .ehdr_shoff = ehdr64_shoff,
+ .ehdr_shentsize = ehdr64_shentsize,
+ .ehdr_shstrndx = ehdr64_shstrndx,
+ .ehdr_shnum = ehdr64_shnum,
+ .shdr_addr = shdr64_addr,
+ .shdr_offset = shdr64_offset,
+ .shdr_link = shdr64_link,
+ .shdr_size = shdr64_size,
+ .shdr_name = shdr64_name,
+ .shdr_type = shdr64_type,
+ .shdr_entsize = shdr64_entsize,
+ .sym_type = sym64_type,
+ .sym_name = sym64_name,
+ .sym_value = sym64_value,
+ .sym_shndx = sym64_shndx,
+ };
+
+ e = efuncs;
+ long_size = 8;
+ extable_ent_size = 16;
+
if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) ||
r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) {
fprintf(stderr,
@@ -900,25 +979,7 @@ static int do_file(char const *const fname, void *addr)
return -1;
}
- compare_extable = compare_extable_64;
- ehdr_shoff = ehdr64_shoff;
- ehdr_shentsize = ehdr64_shentsize;
- ehdr_shstrndx = ehdr64_shstrndx;
- ehdr_shnum = ehdr64_shnum;
- shdr_addr = shdr64_addr;
- shdr_offset = shdr64_offset;
- shdr_link = shdr64_link;
- shdr_size = shdr64_size;
- shdr_name = shdr64_name;
- shdr_type = shdr64_type;
- shdr_entsize = shdr64_entsize;
- sym_type = sym64_type;
- sym_name = sym64_name;
- sym_value = sym64_value;
- sym_shndx = sym64_shndx;
- long_size = 8;
- extable_ent_size = 16;
-
+ }
break;
default:
fprintf(stderr, "unrecognized ELF class %d %s\n",