From nobody Fri Oct 3 20:53:45 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B276529BDA9; Mon, 25 Aug 2025 23:13:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756163621; cv=none; b=GCGyQL4ZscAic26KFQ4ar//F2T0wM6YfVU0pv7MiXdwzSRlDcL3gZjgOww9FnyAj8vjLACP6Jpu4vB/UQf1OMRCPSidixwwHrXC2WuH2BLnF58noINycBDO+2TqA2lAnWM7iZc4bW+a8bws8pp4EskwejEM45ipaOs00qUbCgUY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756163621; c=relaxed/simple; bh=fvlK/CP9POePs20mWrbHwSGPI0YoV4r06wrbRbmWQ5c=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=IHxAI6PbhfoXIpd8KdY3TFdk1Ds5qwfQxO3e4xqF06ovg1navyIThDl80DGqZ4mFUmw2r6qhFE4Sc8Gi4zOiLSQknuq/0nkUTo/I1eAs54zdfZgYz8SoOvSn41BxyZ5eEOTC3nCqGcYA8LtUfPFISBeQcyA7vMBB8ovPl9K7OOk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oMZk0WA/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oMZk0WA/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 264E5C4CEF4; Mon, 25 Aug 2025 23:13:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1756163621; bh=fvlK/CP9POePs20mWrbHwSGPI0YoV4r06wrbRbmWQ5c=; h=Date:From:To:Cc:Subject:References:From; b=oMZk0WA/A1TmEMPR3APFEmJVRI8+3VMDxfnd6he9rH6rhRBFRnTslQiiQFdbsaVGF rR/ugQk3IrPbqQsFgVbZNWPYAQYcKUY049vEi+ykaZ7j9uPMVkzxwadabIXsX+UMfH iY2lgfGp3Rbnw6qL7r4+ONwgKdc+DT+WZMzhFY2eXpmwe5ZgZrjAIxf1pxYOsjRl/3 WhIZT3GCqqOVVx7hV/kiJ07NNa3H8U8NHvQ0WYtpvOD08G/Eb3ys8tGpu3pOyVeVws eNwsr/RcWYlay/Z4JmZeFDTMCHCipEcl0/wpOpfhtjwPminVMAG2IH0TuzQk/+PzYH 97VkDd/GiHnxQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1uqgNv-00000002tFk-38Rq; Mon, 25 Aug 2025 19:13:55 -0400 Message-ID: <20250825231355.597630284@kernel.org> User-Agent: quilt/0.68 Date: Mon, 25 Aug 2025 19:13:02 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Arnd Bergmann , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Nick Desaulniers , Catalin Marinas , Linus Torvalds , Randy Dunlap Subject: [PATCH v7 1/3] sorttable: Move ELF parsing into scripts/elf-parse.[ch] References: <20250825231301.433412523@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Steven Rostedt In order to share the elf parsing that is in sorttable.c so that other programs could use the same code, move it into elf-parse.c and elf-parse.h. Signed-off-by: Steven Rostedt (Google) --- Changes since v6: https://lore.kernel.org/20250820174827.916211576@kernel.o= rg - Fixed cut and paste error of elf_map_long_size() using wrong field scripts/Makefile | 3 + scripts/Makefile.vmlinux | 2 + scripts/elf-parse.c | 198 ++++++++++++++++ scripts/elf-parse.h | 305 +++++++++++++++++++++++++ scripts/sorttable.c | 477 +++------------------------------------ 5 files changed, 542 insertions(+), 443 deletions(-) create mode 100644 scripts/elf-parse.c create mode 100644 scripts/elf-parse.h diff --git a/scripts/Makefile b/scripts/Makefile index 46f860529df5..f19624b3ed92 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -12,6 +12,8 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) +=3D = insert-sys-cert hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) +=3D rustdoc_test_builder hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) +=3D rustdoc_test_gen =20 +sorttable-objs :=3D sorttable.o elf-parse.o + ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),) always-$(CONFIG_RUST) +=3D target.json filechk_rust_target =3D $< < include/config/auto.conf @@ -25,6 +27,7 @@ generate_rust_target-rust :=3D y rustdoc_test_builder-rust :=3D y rustdoc_test_gen-rust :=3D y =20 +HOSTCFLAGS_elf-parse.o =3D -I$(srctree)/tools/include HOSTCFLAGS_sorttable.o =3D -I$(srctree)/tools/include HOSTLDLIBS_sorttable =3D -lpthread HOSTCFLAGS_asn1_compiler.o =3D -I$(srctree)/include diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux index b64862dc6f08..ebbb8b5aca83 100644 --- a/scripts/Makefile.vmlinux +++ b/scripts/Makefile.vmlinux @@ -97,6 +97,8 @@ ifdef CONFIG_BUILDTIME_TABLE_SORT $(vmlinux-final): scripts/sorttable endif =20 +.PRECIOUS: $(vmlinux-final) + # modules.builtin.ranges # ------------------------------------------------------------------------= --- ifdef CONFIG_BUILTIN_MODULE_RANGES diff --git a/scripts/elf-parse.c b/scripts/elf-parse.c new file mode 100644 index 000000000000..99869ff91a8c --- /dev/null +++ b/scripts/elf-parse.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "elf-parse.h" + +struct elf_funcs elf_parser; + +/* + * Get the whole file as a programming convenience in order to avoid + * malloc+lseek+read+free of many pieces. If successful, then mmap + * avoids copying unused pieces; else just read the whole file. + * Open for both read and write. + */ +static void *map_file(char const *fname, size_t *size) +{ + int fd; + struct stat sb; + void *addr =3D NULL; + + fd =3D open(fname, O_RDWR); + if (fd < 0) { + perror(fname); + return NULL; + } + if (fstat(fd, &sb) < 0) { + perror(fname); + goto out; + } + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, "not a regular file: %s\n", fname); + goto out; + } + + addr =3D mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (addr =3D=3D MAP_FAILED) { + fprintf(stderr, "Could not mmap file: %s\n", fname); + goto out; + } + + *size =3D sb.st_size; + +out: + close(fd); + return addr; +} + +static int elf_parse(const char *fname, void *addr, uint32_t types) +{ + Elf_Ehdr *ehdr =3D addr; + uint16_t type; + + switch (ehdr->e32.e_ident[EI_DATA]) { + case ELFDATA2LSB: + elf_parser.r =3D rle; + elf_parser.r2 =3D r2le; + elf_parser.r8 =3D r8le; + elf_parser.w =3D wle; + elf_parser.w8 =3D w8le; + break; + case ELFDATA2MSB: + elf_parser.r =3D rbe; + elf_parser.r2 =3D r2be; + elf_parser.r8 =3D r8be; + elf_parser.w =3D wbe; + elf_parser.w8 =3D w8be; + break; + default: + fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", + ehdr->e32.e_ident[EI_DATA], fname); + return -1; + } + + if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) !=3D 0 || + ehdr->e32.e_ident[EI_VERSION] !=3D EV_CURRENT) { + fprintf(stderr, "unrecognized ELF file %s\n", fname); + return -1; + } + + type =3D elf_parser.r2(&ehdr->e32.e_type); + if (!((1 << type) & types)) { + fprintf(stderr, "Invalid ELF type file %s\n", fname); + return -1; + } + + switch (ehdr->e32.e_ident[EI_CLASS]) { + case ELFCLASS32: { + elf_parser.ehdr_shoff =3D ehdr32_shoff; + elf_parser.ehdr_shentsize =3D ehdr32_shentsize; + elf_parser.ehdr_shstrndx =3D ehdr32_shstrndx; + elf_parser.ehdr_shnum =3D ehdr32_shnum; + elf_parser.shdr_addr =3D shdr32_addr; + elf_parser.shdr_offset =3D shdr32_offset; + elf_parser.shdr_link =3D shdr32_link; + elf_parser.shdr_size =3D shdr32_size; + elf_parser.shdr_name =3D shdr32_name; + elf_parser.shdr_type =3D shdr32_type; + elf_parser.shdr_entsize =3D shdr32_entsize; + elf_parser.sym_type =3D sym32_type; + elf_parser.sym_name =3D sym32_name; + elf_parser.sym_value =3D sym32_value; + elf_parser.sym_shndx =3D sym32_shndx; + elf_parser.rela_offset =3D rela32_offset; + elf_parser.rela_info =3D rela32_info; + elf_parser.rela_addend =3D rela32_addend; + elf_parser.rela_write_addend =3D rela32_write_addend; + + if (elf_parser.r2(&ehdr->e32.e_ehsize) !=3D sizeof(Elf32_Ehdr) || + elf_parser.r2(&ehdr->e32.e_shentsize) !=3D sizeof(Elf32_Shdr)) { + fprintf(stderr, + "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); + return -1; + } + + } + break; + case ELFCLASS64: { + elf_parser.ehdr_shoff =3D ehdr64_shoff; + elf_parser.ehdr_shentsize =3D ehdr64_shentsize; + elf_parser.ehdr_shstrndx =3D ehdr64_shstrndx; + elf_parser.ehdr_shnum =3D ehdr64_shnum; + elf_parser.shdr_addr =3D shdr64_addr; + elf_parser.shdr_offset =3D shdr64_offset; + elf_parser.shdr_link =3D shdr64_link; + elf_parser.shdr_size =3D shdr64_size; + elf_parser.shdr_name =3D shdr64_name; + elf_parser.shdr_type =3D shdr64_type; + elf_parser.shdr_entsize =3D shdr64_entsize; + elf_parser.sym_type =3D sym64_type; + elf_parser.sym_name =3D sym64_name; + elf_parser.sym_value =3D sym64_value; + elf_parser.sym_shndx =3D sym64_shndx; + elf_parser.rela_offset =3D rela64_offset; + elf_parser.rela_info =3D rela64_info; + elf_parser.rela_addend =3D rela64_addend; + elf_parser.rela_write_addend =3D rela64_write_addend; + + if (elf_parser.r2(&ehdr->e64.e_ehsize) !=3D sizeof(Elf64_Ehdr) || + elf_parser.r2(&ehdr->e64.e_shentsize) !=3D sizeof(Elf64_Shdr)) { + fprintf(stderr, + "unrecognized ET_EXEC/ET_DYN file: %s\n", + fname); + return -1; + } + + } + break; + default: + fprintf(stderr, "unrecognized ELF class %d %s\n", + ehdr->e32.e_ident[EI_CLASS], fname); + return -1; + } + return 0; +} + +int elf_map_machine(void *addr) +{ + Elf_Ehdr *ehdr =3D addr; + + return elf_parser.r2(&ehdr->e32.e_machine); +} + +int elf_map_long_size(void *addr) +{ + Elf_Ehdr *ehdr =3D addr; + + return ehdr->e32.e_ident[EI_CLASS] =3D=3D ELFCLASS32 ? 4 : 8; +} + +void *elf_map(char const *fname, size_t *size, uint32_t types) +{ + void *addr; + int ret; + + addr =3D map_file(fname, size); + if (!addr) + return NULL; + + ret =3D elf_parse(fname, addr, types); + if (ret < 0) { + elf_unmap(addr, *size); + return NULL; + } + + return addr; +} + +void elf_unmap(void *addr, size_t size) +{ + munmap(addr, size); +} diff --git a/scripts/elf-parse.h b/scripts/elf-parse.h new file mode 100644 index 000000000000..f4411e03069d --- /dev/null +++ b/scripts/elf-parse.h @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _SCRIPTS_ELF_PARSE_H +#define _SCRIPTS_ELF_PARSE_H + +#include + +#include +#include + +typedef union { + Elf32_Ehdr e32; + Elf64_Ehdr e64; +} Elf_Ehdr; + +typedef union { + Elf32_Shdr e32; + Elf64_Shdr e64; +} Elf_Shdr; + +typedef union { + Elf32_Sym e32; + Elf64_Sym e64; +} Elf_Sym; + +typedef union { + Elf32_Rela e32; + Elf64_Rela e64; +} Elf_Rela; + +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); + uint64_t (*rela_offset)(Elf_Rela *rela); + uint64_t (*rela_info)(Elf_Rela *rela); + uint64_t (*rela_addend)(Elf_Rela *rela); + void (*rela_write_addend)(Elf_Rela *rela, uint64_t val); + uint32_t (*r)(const uint32_t *); + uint16_t (*r2)(const uint16_t *); + uint64_t (*r8)(const uint64_t *); + void (*w)(uint32_t, uint32_t *); + void (*w8)(uint64_t, uint64_t *); +}; + +extern struct elf_funcs elf_parser; + +static inline uint64_t ehdr64_shoff(Elf_Ehdr *ehdr) +{ + return elf_parser.r8(&ehdr->e64.e_shoff); +} + +static inline uint64_t ehdr32_shoff(Elf_Ehdr *ehdr) +{ + return elf_parser.r(&ehdr->e32.e_shoff); +} + +static inline uint64_t ehdr_shoff(Elf_Ehdr *ehdr) +{ + return elf_parser.ehdr_shoff(ehdr); +} + +#define EHDR_HALF(fn_name) \ +static inline uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \ +{ \ + return elf_parser.r2(&ehdr->e64.e_##fn_name); \ +} \ + \ +static inline uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \ +{ \ + return elf_parser.r2(&ehdr->e32.e_##fn_name); \ +} \ + \ +static inline uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \ +{ \ + return elf_parser.ehdr_##fn_name(ehdr); \ +} + +EHDR_HALF(shentsize) +EHDR_HALF(shstrndx) +EHDR_HALF(shnum) + +#define SHDR_WORD(fn_name) \ +static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.r(&shdr->e64.sh_##fn_name); \ +} \ + \ +static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.r(&shdr->e32.sh_##fn_name); \ +} \ + \ +static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.shdr_##fn_name(shdr); \ +} + +#define SHDR_ADDR(fn_name) \ +static inline uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.r8(&shdr->e64.sh_##fn_name); \ +} \ + \ +static inline uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.r(&shdr->e32.sh_##fn_name); \ +} \ + \ +static inline uint64_t shdr_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.shdr_##fn_name(shdr); \ +} + +#define SHDR_WORD(fn_name) \ +static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.r(&shdr->e64.sh_##fn_name); \ +} \ + \ +static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.r(&shdr->e32.sh_##fn_name); \ +} \ +static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ +{ \ + return elf_parser.shdr_##fn_name(shdr); \ +} + +SHDR_ADDR(addr) +SHDR_ADDR(offset) +SHDR_ADDR(size) +SHDR_ADDR(entsize) + +SHDR_WORD(link) +SHDR_WORD(name) +SHDR_WORD(type) + +#define SYM_ADDR(fn_name) \ +static inline uint64_t sym64_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.r8(&sym->e64.st_##fn_name); \ +} \ + \ +static inline uint64_t sym32_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.r(&sym->e32.st_##fn_name); \ +} \ + \ +static inline uint64_t sym_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.sym_##fn_name(sym); \ +} + +#define SYM_WORD(fn_name) \ +static inline uint32_t sym64_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.r(&sym->e64.st_##fn_name); \ +} \ + \ +static inline uint32_t sym32_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.r(&sym->e32.st_##fn_name); \ +} \ + \ +static inline uint32_t sym_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.sym_##fn_name(sym); \ +} + +#define SYM_HALF(fn_name) \ +static inline uint16_t sym64_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.r2(&sym->e64.st_##fn_name); \ +} \ + \ +static inline uint16_t sym32_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.r2(&sym->e32.st_##fn_name); \ +} \ + \ +static inline uint16_t sym_##fn_name(Elf_Sym *sym) \ +{ \ + return elf_parser.sym_##fn_name(sym); \ +} + +static inline uint8_t sym64_type(Elf_Sym *sym) +{ + return ELF64_ST_TYPE(sym->e64.st_info); +} + +static inline uint8_t sym32_type(Elf_Sym *sym) +{ + return ELF32_ST_TYPE(sym->e32.st_info); +} + +static inline uint8_t sym_type(Elf_Sym *sym) +{ + return elf_parser.sym_type(sym); +} + +SYM_ADDR(value) +SYM_WORD(name) +SYM_HALF(shndx) + +#define __maybe_unused __attribute__((__unused__)) + +#define RELA_ADDR(fn_name) \ +static inline uint64_t rela64_##fn_name(Elf_Rela *rela) \ +{ \ + return elf_parser.r8((uint64_t *)&rela->e64.r_##fn_name); \ +} \ + \ +static inline uint64_t rela32_##fn_name(Elf_Rela *rela) \ +{ \ + return elf_parser.r((uint32_t *)&rela->e32.r_##fn_name); \ +} \ + \ +static inline uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \ +{ \ + return elf_parser.rela_##fn_name(rela); \ +} + +RELA_ADDR(offset) +RELA_ADDR(info) +RELA_ADDR(addend) + +static inline void rela64_write_addend(Elf_Rela *rela, uint64_t val) +{ + elf_parser.w8(val, (uint64_t *)&rela->e64.r_addend); +} + +static inline void rela32_write_addend(Elf_Rela *rela, uint64_t val) +{ + elf_parser.w(val, (uint32_t *)&rela->e32.r_addend); +} + +static inline uint32_t rbe(const uint32_t *x) +{ + return get_unaligned_be32(x); +} + +static inline uint16_t r2be(const uint16_t *x) +{ + return get_unaligned_be16(x); +} + +static inline uint64_t r8be(const uint64_t *x) +{ + return get_unaligned_be64(x); +} + +static inline uint32_t rle(const uint32_t *x) +{ + return get_unaligned_le32(x); +} + +static inline uint16_t r2le(const uint16_t *x) +{ + return get_unaligned_le16(x); +} + +static inline uint64_t r8le(const uint64_t *x) +{ + return get_unaligned_le64(x); +} + +static inline void wbe(uint32_t val, uint32_t *x) +{ + put_unaligned_be32(val, x); +} + +static inline void wle(uint32_t val, uint32_t *x) +{ + put_unaligned_le32(val, x); +} + +static inline void w8be(uint64_t val, uint64_t *x) +{ + put_unaligned_be64(val, x); +} + +static inline void w8le(uint64_t val, uint64_t *x) +{ + put_unaligned_le64(val, x); +} + +void *elf_map(char const *fname, size_t *size, uint32_t types); +void elf_unmap(void *addr, size_t size); +int elf_map_machine(void *addr); +int elf_map_long_size(void *addr); + +#endif /* _SCRIPTS_ELF_PARSE_H */ diff --git a/scripts/sorttable.c b/scripts/sorttable.c index deed676bfe38..e8ed11c680c6 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -21,10 +21,8 @@ */ =20 #include -#include #include #include -#include #include #include #include @@ -34,8 +32,7 @@ #include #include =20 -#include -#include +#include "elf-parse.h" =20 #ifndef EM_ARCOMPACT #define EM_ARCOMPACT 93 @@ -65,335 +62,8 @@ #define EM_LOONGARCH 258 #endif =20 -typedef union { - Elf32_Ehdr e32; - Elf64_Ehdr e64; -} Elf_Ehdr; - -typedef union { - Elf32_Shdr e32; - Elf64_Shdr e64; -} Elf_Shdr; - -typedef union { - Elf32_Sym e32; - Elf64_Sym e64; -} Elf_Sym; - -typedef union { - Elf32_Rela e32; - Elf64_Rela e64; -} Elf_Rela; - -static uint32_t (*r)(const uint32_t *); -static uint16_t (*r2)(const uint16_t *); -static uint64_t (*r8)(const uint64_t *); -static void (*w)(uint32_t, uint32_t *); -static void (*w8)(uint64_t, uint64_t *); typedef void (*table_sort_t)(char *, int); =20 -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); - uint64_t (*rela_offset)(Elf_Rela *rela); - uint64_t (*rela_info)(Elf_Rela *rela); - uint64_t (*rela_addend)(Elf_Rela *rela); - void (*rela_write_addend)(Elf_Rela *rela, uint64_t val); -} e; - -static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr) -{ - return r8(&ehdr->e64.e_shoff); -} - -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) \ -{ \ - return r2(&ehdr->e64.e_##fn_name); \ -} \ - \ -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) -EHDR_HALF(shstrndx) -EHDR_HALF(shnum) - -#define SHDR_WORD(fn_name) \ -static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ -{ \ - return r(&shdr->e64.sh_##fn_name); \ -} \ - \ -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) \ -static uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \ -{ \ - return r8(&shdr->e64.sh_##fn_name); \ -} \ - \ -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) \ -static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ -{ \ - return r(&shdr->e64.sh_##fn_name); \ -} \ - \ -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) -SHDR_ADDR(offset) -SHDR_ADDR(size) -SHDR_ADDR(entsize) - -SHDR_WORD(link) -SHDR_WORD(name) -SHDR_WORD(type) - -#define SYM_ADDR(fn_name) \ -static uint64_t sym64_##fn_name(Elf_Sym *sym) \ -{ \ - return r8(&sym->e64.st_##fn_name); \ -} \ - \ -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) \ -static uint32_t sym64_##fn_name(Elf_Sym *sym) \ -{ \ - return r(&sym->e64.st_##fn_name); \ -} \ - \ -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) \ -static uint16_t sym64_##fn_name(Elf_Sym *sym) \ -{ \ - return r2(&sym->e64.st_##fn_name); \ -} \ - \ -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) -{ - return ELF64_ST_TYPE(sym->e64.st_info); -} - -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) - -#define __maybe_unused __attribute__((__unused__)) - -#define RELA_ADDR(fn_name) \ -static uint64_t rela64_##fn_name(Elf_Rela *rela) \ -{ \ - return r8((uint64_t *)&rela->e64.r_##fn_name); \ -} \ - \ -static uint64_t rela32_##fn_name(Elf_Rela *rela) \ -{ \ - return r((uint32_t *)&rela->e32.r_##fn_name); \ -} \ - \ -static uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \ -{ \ - return e.rela_##fn_name(rela); \ -} - -RELA_ADDR(offset) -RELA_ADDR(info) -RELA_ADDR(addend) - -static void rela64_write_addend(Elf_Rela *rela, uint64_t val) -{ - w8(val, (uint64_t *)&rela->e64.r_addend); -} - -static void rela32_write_addend(Elf_Rela *rela, uint64_t val) -{ - w(val, (uint32_t *)&rela->e32.r_addend); -} - -/* - * Get the whole file as a programming convenience in order to avoid - * malloc+lseek+read+free of many pieces. If successful, then mmap - * avoids copying unused pieces; else just read the whole file. - * Open for both read and write. - */ -static void *mmap_file(char const *fname, size_t *size) -{ - int fd; - struct stat sb; - void *addr =3D NULL; - - fd =3D open(fname, O_RDWR); - if (fd < 0) { - perror(fname); - return NULL; - } - if (fstat(fd, &sb) < 0) { - perror(fname); - goto out; - } - if (!S_ISREG(sb.st_mode)) { - fprintf(stderr, "not a regular file: %s\n", fname); - goto out; - } - - addr =3D mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (addr =3D=3D MAP_FAILED) { - fprintf(stderr, "Could not mmap file: %s\n", fname); - goto out; - } - - *size =3D sb.st_size; - -out: - close(fd); - return addr; -} - -static uint32_t rbe(const uint32_t *x) -{ - return get_unaligned_be32(x); -} - -static uint16_t r2be(const uint16_t *x) -{ - return get_unaligned_be16(x); -} - -static uint64_t r8be(const uint64_t *x) -{ - return get_unaligned_be64(x); -} - -static uint32_t rle(const uint32_t *x) -{ - return get_unaligned_le32(x); -} - -static uint16_t r2le(const uint16_t *x) -{ - return get_unaligned_le16(x); -} - -static uint64_t r8le(const uint64_t *x) -{ - return get_unaligned_le64(x); -} - -static void wbe(uint32_t val, uint32_t *x) -{ - put_unaligned_be32(val, x); -} - -static void wle(uint32_t val, uint32_t *x) -{ - put_unaligned_le32(val, x); -} - -static void w8be(uint64_t val, uint64_t *x) -{ - put_unaligned_be64(val, x); -} - -static void w8le(uint64_t val, uint64_t *x) -{ - put_unaligned_le64(val, x); -} - /* * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of * the way to -256..-1, to avoid conflicting with real section @@ -415,13 +85,13 @@ static inline unsigned int get_secindex(unsigned int s= hndx, return SPECIAL(shndx); if (shndx !=3D SHN_XINDEX) return shndx; - return r(&symtab_shndx_start[sym_offs]); + return elf_parser.r(&symtab_shndx_start[sym_offs]); } =20 static int compare_extable_32(const void *a, const void *b) { - Elf32_Addr av =3D r(a); - Elf32_Addr bv =3D r(b); + Elf32_Addr av =3D elf_parser.r(a); + Elf32_Addr bv =3D elf_parser.r(b); =20 if (av < bv) return -1; @@ -430,18 +100,15 @@ static int compare_extable_32(const void *a, const vo= id *b) =20 static int compare_extable_64(const void *a, const void *b) { - Elf64_Addr av =3D r8(a); - Elf64_Addr bv =3D r8(b); + Elf64_Addr av =3D elf_parser.r8(a); + Elf64_Addr bv =3D elf_parser.r8(b); =20 if (av < bv) return -1; return av > bv; } =20 -static int compare_extable(const void *a, const void *b) -{ - return e.compare_extable(a, b); -} +static int (*compare_extable)(const void *a, const void *b); =20 static inline void *get_index(void *start, int entsize, int index) { @@ -577,7 +244,7 @@ static int (*compare_values)(const void *a, const void = *b); /* Only used for sorting mcount table */ static void rela_write_addend(Elf_Rela *rela, uint64_t val) { - e.rela_write_addend(rela, val); + elf_parser.rela_write_addend(rela, val); } =20 struct func_info { @@ -792,9 +459,9 @@ static int fill_addrs(void *ptr, uint64_t size, void *a= ddrs) =20 for (; ptr < end; ptr +=3D long_size, addrs +=3D long_size, count++) { if (long_size =3D=3D 4) - *(uint32_t *)ptr =3D r(addrs); + *(uint32_t *)ptr =3D elf_parser.r(addrs); else - *(uint64_t *)ptr =3D r8(addrs); + *(uint64_t *)ptr =3D elf_parser.r8(addrs); } return count; } @@ -805,9 +472,9 @@ static void replace_addrs(void *ptr, uint64_t size, voi= d *addrs) =20 for (; ptr < end; ptr +=3D long_size, addrs +=3D long_size) { if (long_size =3D=3D 4) - w(*(uint32_t *)ptr, addrs); + elf_parser.w(*(uint32_t *)ptr, addrs); else - w8(*(uint64_t *)ptr, addrs); + elf_parser.w8(*(uint64_t *)ptr, addrs); } } =20 @@ -1111,7 +778,7 @@ static int do_sort(Elf_Ehdr *ehdr, sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec); =20 /* extable has been sorted, clear the flag */ - w(0, sort_needed_loc); + elf_parser.w(0, sort_needed_loc); rc =3D 0; =20 out: @@ -1155,8 +822,8 @@ static int do_sort(Elf_Ehdr *ehdr, =20 static int compare_relative_table(const void *a, const void *b) { - int32_t av =3D (int32_t)r(a); - int32_t bv =3D (int32_t)r(b); + int32_t av =3D (int32_t)elf_parser.r(a); + int32_t bv =3D (int32_t)elf_parser.r(b); =20 if (av < bv) return -1; @@ -1175,7 +842,7 @@ static void sort_relative_table(char *extab_image, int= image_size) */ while (i < image_size) { uint32_t *loc =3D (uint32_t *)(extab_image + i); - w(r(loc) + i, loc); + elf_parser.w(elf_parser.r(loc) + i, loc); i +=3D 4; } =20 @@ -1185,7 +852,7 @@ static void sort_relative_table(char *extab_image, int= image_size) i =3D 0; while (i < image_size) { uint32_t *loc =3D (uint32_t *)(extab_image + i); - w(r(loc) - i, loc); + elf_parser.w(elf_parser.r(loc) - i, loc); i +=3D 4; } } @@ -1197,8 +864,8 @@ static void sort_relative_table_with_data(char *extab_= image, int image_size) while (i < image_size) { uint32_t *loc =3D (uint32_t *)(extab_image + i); =20 - w(r(loc) + i, loc); - w(r(loc + 1) + i + 4, loc + 1); + elf_parser.w(elf_parser.r(loc) + i, loc); + elf_parser.w(elf_parser.r(loc + 1) + i + 4, loc + 1); /* Don't touch the fixup type or data */ =20 i +=3D sizeof(uint32_t) * 3; @@ -1210,8 +877,8 @@ static void sort_relative_table_with_data(char *extab_= image, int image_size) while (i < image_size) { uint32_t *loc =3D (uint32_t *)(extab_image + i); =20 - w(r(loc) - i, loc); - w(r(loc + 1) - (i + 4), loc + 1); + elf_parser.w(elf_parser.r(loc) - i, loc); + elf_parser.w(elf_parser.r(loc + 1) - (i + 4), loc + 1); /* Don't touch the fixup type or data */ =20 i +=3D sizeof(uint32_t) * 3; @@ -1223,35 +890,7 @@ static int do_file(char const *const fname, void *add= r) Elf_Ehdr *ehdr =3D addr; table_sort_t custom_sort =3D NULL; =20 - switch (ehdr->e32.e_ident[EI_DATA]) { - case ELFDATA2LSB: - r =3D rle; - r2 =3D r2le; - r8 =3D r8le; - w =3D wle; - w8 =3D w8le; - break; - case ELFDATA2MSB: - r =3D rbe; - r2 =3D r2be; - r8 =3D r8be; - w =3D wbe; - w8 =3D w8be; - break; - default: - fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", - ehdr->e32.e_ident[EI_DATA], fname); - return -1; - } - - if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) !=3D 0 || - (r2(&ehdr->e32.e_type) !=3D ET_EXEC && r2(&ehdr->e32.e_type) !=3D ET_= DYN) || - ehdr->e32.e_ident[EI_VERSION] !=3D EV_CURRENT) { - fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname); - return -1; - } - - switch (r2(&ehdr->e32.e_machine)) { + switch (elf_map_machine(ehdr)) { case EM_AARCH64: #ifdef MCOUNT_SORT_ENABLED sort_reloc =3D true; @@ -1281,85 +920,37 @@ static int do_file(char const *const fname, void *ad= dr) break; default: fprintf(stderr, "unrecognized e_machine %d %s\n", - r2(&ehdr->e32.e_machine), fname); + elf_parser.r2(&ehdr->e32.e_machine), fname); return -1; } =20 - switch (ehdr->e32.e_ident[EI_CLASS]) { - case ELFCLASS32: { - struct elf_funcs efuncs =3D { - .compare_extable =3D compare_extable_32, - .ehdr_shoff =3D ehdr32_shoff, - .ehdr_shentsize =3D ehdr32_shentsize, - .ehdr_shstrndx =3D ehdr32_shstrndx, - .ehdr_shnum =3D ehdr32_shnum, - .shdr_addr =3D shdr32_addr, - .shdr_offset =3D shdr32_offset, - .shdr_link =3D shdr32_link, - .shdr_size =3D shdr32_size, - .shdr_name =3D shdr32_name, - .shdr_type =3D shdr32_type, - .shdr_entsize =3D shdr32_entsize, - .sym_type =3D sym32_type, - .sym_name =3D sym32_name, - .sym_value =3D sym32_value, - .sym_shndx =3D sym32_shndx, - .rela_offset =3D rela32_offset, - .rela_info =3D rela32_info, - .rela_addend =3D rela32_addend, - .rela_write_addend =3D rela32_write_addend, - }; - - e =3D efuncs; + switch (elf_map_long_size(addr)) { + case 4: + compare_extable =3D compare_extable_32, long_size =3D 4; extable_ent_size =3D 8; =20 - if (r2(&ehdr->e32.e_ehsize) !=3D sizeof(Elf32_Ehdr) || - r2(&ehdr->e32.e_shentsize) !=3D sizeof(Elf32_Shdr)) { + if (elf_parser.r2(&ehdr->e32.e_ehsize) !=3D sizeof(Elf32_Ehdr) || + elf_parser.r2(&ehdr->e32.e_shentsize) !=3D sizeof(Elf32_Shdr)) { fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); return -1; } =20 - } break; - case ELFCLASS64: { - struct elf_funcs efuncs =3D { - .compare_extable =3D compare_extable_64, - .ehdr_shoff =3D ehdr64_shoff, - .ehdr_shentsize =3D ehdr64_shentsize, - .ehdr_shstrndx =3D ehdr64_shstrndx, - .ehdr_shnum =3D ehdr64_shnum, - .shdr_addr =3D shdr64_addr, - .shdr_offset =3D shdr64_offset, - .shdr_link =3D shdr64_link, - .shdr_size =3D shdr64_size, - .shdr_name =3D shdr64_name, - .shdr_type =3D shdr64_type, - .shdr_entsize =3D shdr64_entsize, - .sym_type =3D sym64_type, - .sym_name =3D sym64_name, - .sym_value =3D sym64_value, - .sym_shndx =3D sym64_shndx, - .rela_offset =3D rela64_offset, - .rela_info =3D rela64_info, - .rela_addend =3D rela64_addend, - .rela_write_addend =3D rela64_write_addend, - }; - - e =3D efuncs; + case 8: + compare_extable =3D compare_extable_64, long_size =3D 8; extable_ent_size =3D 16; =20 - if (r2(&ehdr->e64.e_ehsize) !=3D sizeof(Elf64_Ehdr) || - r2(&ehdr->e64.e_shentsize) !=3D sizeof(Elf64_Shdr)) { + if (elf_parser.r2(&ehdr->e64.e_ehsize) !=3D sizeof(Elf64_Ehdr) || + elf_parser.r2(&ehdr->e64.e_shentsize) !=3D sizeof(Elf64_Shdr)) { fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); return -1; } =20 - } break; default: fprintf(stderr, "unrecognized ELF class %d %s\n", @@ -1398,7 +989,7 @@ int main(int argc, char *argv[]) =20 /* Process each file in turn, allowing deep failure. */ for (i =3D optind; i < argc; i++) { - addr =3D mmap_file(argv[i], &size); + addr =3D elf_map(argv[i], &size, (1 << ET_EXEC) | (1 << ET_DYN)); if (!addr) { ++n_error; continue; @@ -1407,7 +998,7 @@ int main(int argc, char *argv[]) if (do_file(argv[i], addr)) ++n_error; =20 - munmap(addr, size); + elf_unmap(addr, size); } =20 return !!n_error; --=20 2.50.1