Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sorttable: Move ELF parsing into scripts/elf-parse.[ch]

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.

Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nicolas Schier <nicolas.schier@linux.dev>
Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Link: https://lore.kernel.org/20251022004452.752298788@kernel.org
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+540 -443
+3
scripts/Makefile
··· 12 12 hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_builder 13 13 hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_gen 14 14 15 + sorttable-objs := sorttable.o elf-parse.o 16 + 15 17 ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),) 16 18 always-$(CONFIG_RUST) += target.json 17 19 filechk_rust_target = $< < include/config/auto.conf ··· 27 25 rustdoc_test_builder-rust := y 28 26 rustdoc_test_gen-rust := y 29 27 28 + HOSTCFLAGS_elf-parse.o = -I$(srctree)/tools/include 30 29 HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include 31 30 HOSTLDLIBS_sorttable = -lpthread 32 31 HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
+198
scripts/elf-parse.c
··· 1 + #include <sys/types.h> 2 + #include <sys/mman.h> 3 + #include <sys/stat.h> 4 + #include <fcntl.h> 5 + #include <stdio.h> 6 + #include <stdlib.h> 7 + #include <stdbool.h> 8 + #include <string.h> 9 + #include <unistd.h> 10 + #include <errno.h> 11 + 12 + #include "elf-parse.h" 13 + 14 + struct elf_funcs elf_parser; 15 + 16 + /* 17 + * Get the whole file as a programming convenience in order to avoid 18 + * malloc+lseek+read+free of many pieces. If successful, then mmap 19 + * avoids copying unused pieces; else just read the whole file. 20 + * Open for both read and write. 21 + */ 22 + static void *map_file(char const *fname, size_t *size) 23 + { 24 + int fd; 25 + struct stat sb; 26 + void *addr = NULL; 27 + 28 + fd = open(fname, O_RDWR); 29 + if (fd < 0) { 30 + perror(fname); 31 + return NULL; 32 + } 33 + if (fstat(fd, &sb) < 0) { 34 + perror(fname); 35 + goto out; 36 + } 37 + if (!S_ISREG(sb.st_mode)) { 38 + fprintf(stderr, "not a regular file: %s\n", fname); 39 + goto out; 40 + } 41 + 42 + addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 43 + if (addr == MAP_FAILED) { 44 + fprintf(stderr, "Could not mmap file: %s\n", fname); 45 + goto out; 46 + } 47 + 48 + *size = sb.st_size; 49 + 50 + out: 51 + close(fd); 52 + return addr; 53 + } 54 + 55 + static int elf_parse(const char *fname, void *addr, uint32_t types) 56 + { 57 + Elf_Ehdr *ehdr = addr; 58 + uint16_t type; 59 + 60 + switch (ehdr->e32.e_ident[EI_DATA]) { 61 + case ELFDATA2LSB: 62 + elf_parser.r = rle; 63 + elf_parser.r2 = r2le; 64 + elf_parser.r8 = r8le; 65 + elf_parser.w = wle; 66 + elf_parser.w8 = w8le; 67 + break; 68 + case ELFDATA2MSB: 69 + elf_parser.r = rbe; 70 + elf_parser.r2 = r2be; 71 + elf_parser.r8 = r8be; 72 + elf_parser.w = wbe; 73 + elf_parser.w8 = w8be; 74 + break; 75 + default: 76 + fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", 77 + ehdr->e32.e_ident[EI_DATA], fname); 78 + return -1; 79 + } 80 + 81 + if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) != 0 || 82 + ehdr->e32.e_ident[EI_VERSION] != EV_CURRENT) { 83 + fprintf(stderr, "unrecognized ELF file %s\n", fname); 84 + return -1; 85 + } 86 + 87 + type = elf_parser.r2(&ehdr->e32.e_type); 88 + if (!((1 << type) & types)) { 89 + fprintf(stderr, "Invalid ELF type file %s\n", fname); 90 + return -1; 91 + } 92 + 93 + switch (ehdr->e32.e_ident[EI_CLASS]) { 94 + case ELFCLASS32: { 95 + elf_parser.ehdr_shoff = ehdr32_shoff; 96 + elf_parser.ehdr_shentsize = ehdr32_shentsize; 97 + elf_parser.ehdr_shstrndx = ehdr32_shstrndx; 98 + elf_parser.ehdr_shnum = ehdr32_shnum; 99 + elf_parser.shdr_addr = shdr32_addr; 100 + elf_parser.shdr_offset = shdr32_offset; 101 + elf_parser.shdr_link = shdr32_link; 102 + elf_parser.shdr_size = shdr32_size; 103 + elf_parser.shdr_name = shdr32_name; 104 + elf_parser.shdr_type = shdr32_type; 105 + elf_parser.shdr_entsize = shdr32_entsize; 106 + elf_parser.sym_type = sym32_type; 107 + elf_parser.sym_name = sym32_name; 108 + elf_parser.sym_value = sym32_value; 109 + elf_parser.sym_shndx = sym32_shndx; 110 + elf_parser.rela_offset = rela32_offset; 111 + elf_parser.rela_info = rela32_info; 112 + elf_parser.rela_addend = rela32_addend; 113 + elf_parser.rela_write_addend = rela32_write_addend; 114 + 115 + if (elf_parser.r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) || 116 + elf_parser.r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) { 117 + fprintf(stderr, 118 + "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); 119 + return -1; 120 + } 121 + 122 + } 123 + break; 124 + case ELFCLASS64: { 125 + elf_parser.ehdr_shoff = ehdr64_shoff; 126 + elf_parser.ehdr_shentsize = ehdr64_shentsize; 127 + elf_parser.ehdr_shstrndx = ehdr64_shstrndx; 128 + elf_parser.ehdr_shnum = ehdr64_shnum; 129 + elf_parser.shdr_addr = shdr64_addr; 130 + elf_parser.shdr_offset = shdr64_offset; 131 + elf_parser.shdr_link = shdr64_link; 132 + elf_parser.shdr_size = shdr64_size; 133 + elf_parser.shdr_name = shdr64_name; 134 + elf_parser.shdr_type = shdr64_type; 135 + elf_parser.shdr_entsize = shdr64_entsize; 136 + elf_parser.sym_type = sym64_type; 137 + elf_parser.sym_name = sym64_name; 138 + elf_parser.sym_value = sym64_value; 139 + elf_parser.sym_shndx = sym64_shndx; 140 + elf_parser.rela_offset = rela64_offset; 141 + elf_parser.rela_info = rela64_info; 142 + elf_parser.rela_addend = rela64_addend; 143 + elf_parser.rela_write_addend = rela64_write_addend; 144 + 145 + if (elf_parser.r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) || 146 + elf_parser.r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) { 147 + fprintf(stderr, 148 + "unrecognized ET_EXEC/ET_DYN file: %s\n", 149 + fname); 150 + return -1; 151 + } 152 + 153 + } 154 + break; 155 + default: 156 + fprintf(stderr, "unrecognized ELF class %d %s\n", 157 + ehdr->e32.e_ident[EI_CLASS], fname); 158 + return -1; 159 + } 160 + return 0; 161 + } 162 + 163 + int elf_map_machine(void *addr) 164 + { 165 + Elf_Ehdr *ehdr = addr; 166 + 167 + return elf_parser.r2(&ehdr->e32.e_machine); 168 + } 169 + 170 + int elf_map_long_size(void *addr) 171 + { 172 + Elf_Ehdr *ehdr = addr; 173 + 174 + return ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 175 + } 176 + 177 + void *elf_map(char const *fname, size_t *size, uint32_t types) 178 + { 179 + void *addr; 180 + int ret; 181 + 182 + addr = map_file(fname, size); 183 + if (!addr) 184 + return NULL; 185 + 186 + ret = elf_parse(fname, addr, types); 187 + if (ret < 0) { 188 + elf_unmap(addr, *size); 189 + return NULL; 190 + } 191 + 192 + return addr; 193 + } 194 + 195 + void elf_unmap(void *addr, size_t size) 196 + { 197 + munmap(addr, size); 198 + }
+305
scripts/elf-parse.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + #ifndef _SCRIPTS_ELF_PARSE_H 3 + #define _SCRIPTS_ELF_PARSE_H 4 + 5 + #include <elf.h> 6 + 7 + #include <tools/be_byteshift.h> 8 + #include <tools/le_byteshift.h> 9 + 10 + typedef union { 11 + Elf32_Ehdr e32; 12 + Elf64_Ehdr e64; 13 + } Elf_Ehdr; 14 + 15 + typedef union { 16 + Elf32_Shdr e32; 17 + Elf64_Shdr e64; 18 + } Elf_Shdr; 19 + 20 + typedef union { 21 + Elf32_Sym e32; 22 + Elf64_Sym e64; 23 + } Elf_Sym; 24 + 25 + typedef union { 26 + Elf32_Rela e32; 27 + Elf64_Rela e64; 28 + } Elf_Rela; 29 + 30 + struct elf_funcs { 31 + int (*compare_extable)(const void *a, const void *b); 32 + uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr); 33 + uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr); 34 + uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr); 35 + uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr); 36 + uint64_t (*shdr_addr)(Elf_Shdr *shdr); 37 + uint64_t (*shdr_offset)(Elf_Shdr *shdr); 38 + uint64_t (*shdr_size)(Elf_Shdr *shdr); 39 + uint64_t (*shdr_entsize)(Elf_Shdr *shdr); 40 + uint32_t (*shdr_link)(Elf_Shdr *shdr); 41 + uint32_t (*shdr_name)(Elf_Shdr *shdr); 42 + uint32_t (*shdr_type)(Elf_Shdr *shdr); 43 + uint8_t (*sym_type)(Elf_Sym *sym); 44 + uint32_t (*sym_name)(Elf_Sym *sym); 45 + uint64_t (*sym_value)(Elf_Sym *sym); 46 + uint16_t (*sym_shndx)(Elf_Sym *sym); 47 + uint64_t (*rela_offset)(Elf_Rela *rela); 48 + uint64_t (*rela_info)(Elf_Rela *rela); 49 + uint64_t (*rela_addend)(Elf_Rela *rela); 50 + void (*rela_write_addend)(Elf_Rela *rela, uint64_t val); 51 + uint32_t (*r)(const uint32_t *); 52 + uint16_t (*r2)(const uint16_t *); 53 + uint64_t (*r8)(const uint64_t *); 54 + void (*w)(uint32_t, uint32_t *); 55 + void (*w8)(uint64_t, uint64_t *); 56 + }; 57 + 58 + extern struct elf_funcs elf_parser; 59 + 60 + static inline uint64_t ehdr64_shoff(Elf_Ehdr *ehdr) 61 + { 62 + return elf_parser.r8(&ehdr->e64.e_shoff); 63 + } 64 + 65 + static inline uint64_t ehdr32_shoff(Elf_Ehdr *ehdr) 66 + { 67 + return elf_parser.r(&ehdr->e32.e_shoff); 68 + } 69 + 70 + static inline uint64_t ehdr_shoff(Elf_Ehdr *ehdr) 71 + { 72 + return elf_parser.ehdr_shoff(ehdr); 73 + } 74 + 75 + #define EHDR_HALF(fn_name) \ 76 + static inline uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \ 77 + { \ 78 + return elf_parser.r2(&ehdr->e64.e_##fn_name); \ 79 + } \ 80 + \ 81 + static inline uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \ 82 + { \ 83 + return elf_parser.r2(&ehdr->e32.e_##fn_name); \ 84 + } \ 85 + \ 86 + static inline uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \ 87 + { \ 88 + return elf_parser.ehdr_##fn_name(ehdr); \ 89 + } 90 + 91 + EHDR_HALF(shentsize) 92 + EHDR_HALF(shstrndx) 93 + EHDR_HALF(shnum) 94 + 95 + #define SHDR_WORD(fn_name) \ 96 + static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ 97 + { \ 98 + return elf_parser.r(&shdr->e64.sh_##fn_name); \ 99 + } \ 100 + \ 101 + static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ 102 + { \ 103 + return elf_parser.r(&shdr->e32.sh_##fn_name); \ 104 + } \ 105 + \ 106 + static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ 107 + { \ 108 + return elf_parser.shdr_##fn_name(shdr); \ 109 + } 110 + 111 + #define SHDR_ADDR(fn_name) \ 112 + static inline uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \ 113 + { \ 114 + return elf_parser.r8(&shdr->e64.sh_##fn_name); \ 115 + } \ 116 + \ 117 + static inline uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \ 118 + { \ 119 + return elf_parser.r(&shdr->e32.sh_##fn_name); \ 120 + } \ 121 + \ 122 + static inline uint64_t shdr_##fn_name(Elf_Shdr *shdr) \ 123 + { \ 124 + return elf_parser.shdr_##fn_name(shdr); \ 125 + } 126 + 127 + #define SHDR_WORD(fn_name) \ 128 + static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ 129 + { \ 130 + return elf_parser.r(&shdr->e64.sh_##fn_name); \ 131 + } \ 132 + \ 133 + static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ 134 + { \ 135 + return elf_parser.r(&shdr->e32.sh_##fn_name); \ 136 + } \ 137 + static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ 138 + { \ 139 + return elf_parser.shdr_##fn_name(shdr); \ 140 + } 141 + 142 + SHDR_ADDR(addr) 143 + SHDR_ADDR(offset) 144 + SHDR_ADDR(size) 145 + SHDR_ADDR(entsize) 146 + 147 + SHDR_WORD(link) 148 + SHDR_WORD(name) 149 + SHDR_WORD(type) 150 + 151 + #define SYM_ADDR(fn_name) \ 152 + static inline uint64_t sym64_##fn_name(Elf_Sym *sym) \ 153 + { \ 154 + return elf_parser.r8(&sym->e64.st_##fn_name); \ 155 + } \ 156 + \ 157 + static inline uint64_t sym32_##fn_name(Elf_Sym *sym) \ 158 + { \ 159 + return elf_parser.r(&sym->e32.st_##fn_name); \ 160 + } \ 161 + \ 162 + static inline uint64_t sym_##fn_name(Elf_Sym *sym) \ 163 + { \ 164 + return elf_parser.sym_##fn_name(sym); \ 165 + } 166 + 167 + #define SYM_WORD(fn_name) \ 168 + static inline uint32_t sym64_##fn_name(Elf_Sym *sym) \ 169 + { \ 170 + return elf_parser.r(&sym->e64.st_##fn_name); \ 171 + } \ 172 + \ 173 + static inline uint32_t sym32_##fn_name(Elf_Sym *sym) \ 174 + { \ 175 + return elf_parser.r(&sym->e32.st_##fn_name); \ 176 + } \ 177 + \ 178 + static inline uint32_t sym_##fn_name(Elf_Sym *sym) \ 179 + { \ 180 + return elf_parser.sym_##fn_name(sym); \ 181 + } 182 + 183 + #define SYM_HALF(fn_name) \ 184 + static inline uint16_t sym64_##fn_name(Elf_Sym *sym) \ 185 + { \ 186 + return elf_parser.r2(&sym->e64.st_##fn_name); \ 187 + } \ 188 + \ 189 + static inline uint16_t sym32_##fn_name(Elf_Sym *sym) \ 190 + { \ 191 + return elf_parser.r2(&sym->e32.st_##fn_name); \ 192 + } \ 193 + \ 194 + static inline uint16_t sym_##fn_name(Elf_Sym *sym) \ 195 + { \ 196 + return elf_parser.sym_##fn_name(sym); \ 197 + } 198 + 199 + static inline uint8_t sym64_type(Elf_Sym *sym) 200 + { 201 + return ELF64_ST_TYPE(sym->e64.st_info); 202 + } 203 + 204 + static inline uint8_t sym32_type(Elf_Sym *sym) 205 + { 206 + return ELF32_ST_TYPE(sym->e32.st_info); 207 + } 208 + 209 + static inline uint8_t sym_type(Elf_Sym *sym) 210 + { 211 + return elf_parser.sym_type(sym); 212 + } 213 + 214 + SYM_ADDR(value) 215 + SYM_WORD(name) 216 + SYM_HALF(shndx) 217 + 218 + #define __maybe_unused __attribute__((__unused__)) 219 + 220 + #define RELA_ADDR(fn_name) \ 221 + static inline uint64_t rela64_##fn_name(Elf_Rela *rela) \ 222 + { \ 223 + return elf_parser.r8((uint64_t *)&rela->e64.r_##fn_name); \ 224 + } \ 225 + \ 226 + static inline uint64_t rela32_##fn_name(Elf_Rela *rela) \ 227 + { \ 228 + return elf_parser.r((uint32_t *)&rela->e32.r_##fn_name); \ 229 + } \ 230 + \ 231 + static inline uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \ 232 + { \ 233 + return elf_parser.rela_##fn_name(rela); \ 234 + } 235 + 236 + RELA_ADDR(offset) 237 + RELA_ADDR(info) 238 + RELA_ADDR(addend) 239 + 240 + static inline void rela64_write_addend(Elf_Rela *rela, uint64_t val) 241 + { 242 + elf_parser.w8(val, (uint64_t *)&rela->e64.r_addend); 243 + } 244 + 245 + static inline void rela32_write_addend(Elf_Rela *rela, uint64_t val) 246 + { 247 + elf_parser.w(val, (uint32_t *)&rela->e32.r_addend); 248 + } 249 + 250 + static inline uint32_t rbe(const uint32_t *x) 251 + { 252 + return get_unaligned_be32(x); 253 + } 254 + 255 + static inline uint16_t r2be(const uint16_t *x) 256 + { 257 + return get_unaligned_be16(x); 258 + } 259 + 260 + static inline uint64_t r8be(const uint64_t *x) 261 + { 262 + return get_unaligned_be64(x); 263 + } 264 + 265 + static inline uint32_t rle(const uint32_t *x) 266 + { 267 + return get_unaligned_le32(x); 268 + } 269 + 270 + static inline uint16_t r2le(const uint16_t *x) 271 + { 272 + return get_unaligned_le16(x); 273 + } 274 + 275 + static inline uint64_t r8le(const uint64_t *x) 276 + { 277 + return get_unaligned_le64(x); 278 + } 279 + 280 + static inline void wbe(uint32_t val, uint32_t *x) 281 + { 282 + put_unaligned_be32(val, x); 283 + } 284 + 285 + static inline void wle(uint32_t val, uint32_t *x) 286 + { 287 + put_unaligned_le32(val, x); 288 + } 289 + 290 + static inline void w8be(uint64_t val, uint64_t *x) 291 + { 292 + put_unaligned_be64(val, x); 293 + } 294 + 295 + static inline void w8le(uint64_t val, uint64_t *x) 296 + { 297 + put_unaligned_le64(val, x); 298 + } 299 + 300 + void *elf_map(char const *fname, size_t *size, uint32_t types); 301 + void elf_unmap(void *addr, size_t size); 302 + int elf_map_machine(void *addr); 303 + int elf_map_long_size(void *addr); 304 + 305 + #endif /* _SCRIPTS_ELF_PARSE_H */
+34 -443
scripts/sorttable.c
··· 21 21 */ 22 22 23 23 #include <sys/types.h> 24 - #include <sys/mman.h> 25 24 #include <sys/stat.h> 26 25 #include <getopt.h> 27 - #include <elf.h> 28 26 #include <fcntl.h> 29 27 #include <stdio.h> 30 28 #include <stdlib.h> ··· 32 34 #include <errno.h> 33 35 #include <pthread.h> 34 36 35 - #include <tools/be_byteshift.h> 36 - #include <tools/le_byteshift.h> 37 + #include "elf-parse.h" 37 38 38 39 #ifndef EM_ARCOMPACT 39 40 #define EM_ARCOMPACT 93 ··· 62 65 #define EM_LOONGARCH 258 63 66 #endif 64 67 65 - typedef union { 66 - Elf32_Ehdr e32; 67 - Elf64_Ehdr e64; 68 - } Elf_Ehdr; 69 - 70 - typedef union { 71 - Elf32_Shdr e32; 72 - Elf64_Shdr e64; 73 - } Elf_Shdr; 74 - 75 - typedef union { 76 - Elf32_Sym e32; 77 - Elf64_Sym e64; 78 - } Elf_Sym; 79 - 80 - typedef union { 81 - Elf32_Rela e32; 82 - Elf64_Rela e64; 83 - } Elf_Rela; 84 - 85 - static uint32_t (*r)(const uint32_t *); 86 - static uint16_t (*r2)(const uint16_t *); 87 - static uint64_t (*r8)(const uint64_t *); 88 - static void (*w)(uint32_t, uint32_t *); 89 - static void (*w8)(uint64_t, uint64_t *); 90 68 typedef void (*table_sort_t)(char *, int); 91 - 92 - static struct elf_funcs { 93 - int (*compare_extable)(const void *a, const void *b); 94 - uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr); 95 - uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr); 96 - uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr); 97 - uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr); 98 - uint64_t (*shdr_addr)(Elf_Shdr *shdr); 99 - uint64_t (*shdr_offset)(Elf_Shdr *shdr); 100 - uint64_t (*shdr_size)(Elf_Shdr *shdr); 101 - uint64_t (*shdr_entsize)(Elf_Shdr *shdr); 102 - uint32_t (*shdr_link)(Elf_Shdr *shdr); 103 - uint32_t (*shdr_name)(Elf_Shdr *shdr); 104 - uint32_t (*shdr_type)(Elf_Shdr *shdr); 105 - uint8_t (*sym_type)(Elf_Sym *sym); 106 - uint32_t (*sym_name)(Elf_Sym *sym); 107 - uint64_t (*sym_value)(Elf_Sym *sym); 108 - uint16_t (*sym_shndx)(Elf_Sym *sym); 109 - uint64_t (*rela_offset)(Elf_Rela *rela); 110 - uint64_t (*rela_info)(Elf_Rela *rela); 111 - uint64_t (*rela_addend)(Elf_Rela *rela); 112 - void (*rela_write_addend)(Elf_Rela *rela, uint64_t val); 113 - } e; 114 - 115 - static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr) 116 - { 117 - return r8(&ehdr->e64.e_shoff); 118 - } 119 - 120 - static uint64_t ehdr32_shoff(Elf_Ehdr *ehdr) 121 - { 122 - return r(&ehdr->e32.e_shoff); 123 - } 124 - 125 - static uint64_t ehdr_shoff(Elf_Ehdr *ehdr) 126 - { 127 - return e.ehdr_shoff(ehdr); 128 - } 129 - 130 - #define EHDR_HALF(fn_name) \ 131 - static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \ 132 - { \ 133 - return r2(&ehdr->e64.e_##fn_name); \ 134 - } \ 135 - \ 136 - static uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \ 137 - { \ 138 - return r2(&ehdr->e32.e_##fn_name); \ 139 - } \ 140 - \ 141 - static uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \ 142 - { \ 143 - return e.ehdr_##fn_name(ehdr); \ 144 - } 145 - 146 - EHDR_HALF(shentsize) 147 - EHDR_HALF(shstrndx) 148 - EHDR_HALF(shnum) 149 - 150 - #define SHDR_WORD(fn_name) \ 151 - static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ 152 - { \ 153 - return r(&shdr->e64.sh_##fn_name); \ 154 - } \ 155 - \ 156 - static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ 157 - { \ 158 - return r(&shdr->e32.sh_##fn_name); \ 159 - } \ 160 - \ 161 - static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ 162 - { \ 163 - return e.shdr_##fn_name(shdr); \ 164 - } 165 - 166 - #define SHDR_ADDR(fn_name) \ 167 - static uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \ 168 - { \ 169 - return r8(&shdr->e64.sh_##fn_name); \ 170 - } \ 171 - \ 172 - static uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \ 173 - { \ 174 - return r(&shdr->e32.sh_##fn_name); \ 175 - } \ 176 - \ 177 - static uint64_t shdr_##fn_name(Elf_Shdr *shdr) \ 178 - { \ 179 - return e.shdr_##fn_name(shdr); \ 180 - } 181 - 182 - #define SHDR_WORD(fn_name) \ 183 - static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ 184 - { \ 185 - return r(&shdr->e64.sh_##fn_name); \ 186 - } \ 187 - \ 188 - static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ 189 - { \ 190 - return r(&shdr->e32.sh_##fn_name); \ 191 - } \ 192 - static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ 193 - { \ 194 - return e.shdr_##fn_name(shdr); \ 195 - } 196 - 197 - SHDR_ADDR(addr) 198 - SHDR_ADDR(offset) 199 - SHDR_ADDR(size) 200 - SHDR_ADDR(entsize) 201 - 202 - SHDR_WORD(link) 203 - SHDR_WORD(name) 204 - SHDR_WORD(type) 205 - 206 - #define SYM_ADDR(fn_name) \ 207 - static uint64_t sym64_##fn_name(Elf_Sym *sym) \ 208 - { \ 209 - return r8(&sym->e64.st_##fn_name); \ 210 - } \ 211 - \ 212 - static uint64_t sym32_##fn_name(Elf_Sym *sym) \ 213 - { \ 214 - return r(&sym->e32.st_##fn_name); \ 215 - } \ 216 - \ 217 - static uint64_t sym_##fn_name(Elf_Sym *sym) \ 218 - { \ 219 - return e.sym_##fn_name(sym); \ 220 - } 221 - 222 - #define SYM_WORD(fn_name) \ 223 - static uint32_t sym64_##fn_name(Elf_Sym *sym) \ 224 - { \ 225 - return r(&sym->e64.st_##fn_name); \ 226 - } \ 227 - \ 228 - static uint32_t sym32_##fn_name(Elf_Sym *sym) \ 229 - { \ 230 - return r(&sym->e32.st_##fn_name); \ 231 - } \ 232 - \ 233 - static uint32_t sym_##fn_name(Elf_Sym *sym) \ 234 - { \ 235 - return e.sym_##fn_name(sym); \ 236 - } 237 - 238 - #define SYM_HALF(fn_name) \ 239 - static uint16_t sym64_##fn_name(Elf_Sym *sym) \ 240 - { \ 241 - return r2(&sym->e64.st_##fn_name); \ 242 - } \ 243 - \ 244 - static uint16_t sym32_##fn_name(Elf_Sym *sym) \ 245 - { \ 246 - return r2(&sym->e32.st_##fn_name); \ 247 - } \ 248 - \ 249 - static uint16_t sym_##fn_name(Elf_Sym *sym) \ 250 - { \ 251 - return e.sym_##fn_name(sym); \ 252 - } 253 - 254 - static uint8_t sym64_type(Elf_Sym *sym) 255 - { 256 - return ELF64_ST_TYPE(sym->e64.st_info); 257 - } 258 - 259 - static uint8_t sym32_type(Elf_Sym *sym) 260 - { 261 - return ELF32_ST_TYPE(sym->e32.st_info); 262 - } 263 - 264 - static uint8_t sym_type(Elf_Sym *sym) 265 - { 266 - return e.sym_type(sym); 267 - } 268 - 269 - SYM_ADDR(value) 270 - SYM_WORD(name) 271 - SYM_HALF(shndx) 272 - 273 - #define __maybe_unused __attribute__((__unused__)) 274 - 275 - #define RELA_ADDR(fn_name) \ 276 - static uint64_t rela64_##fn_name(Elf_Rela *rela) \ 277 - { \ 278 - return r8((uint64_t *)&rela->e64.r_##fn_name); \ 279 - } \ 280 - \ 281 - static uint64_t rela32_##fn_name(Elf_Rela *rela) \ 282 - { \ 283 - return r((uint32_t *)&rela->e32.r_##fn_name); \ 284 - } \ 285 - \ 286 - static uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \ 287 - { \ 288 - return e.rela_##fn_name(rela); \ 289 - } 290 - 291 - RELA_ADDR(offset) 292 - RELA_ADDR(info) 293 - RELA_ADDR(addend) 294 - 295 - static void rela64_write_addend(Elf_Rela *rela, uint64_t val) 296 - { 297 - w8(val, (uint64_t *)&rela->e64.r_addend); 298 - } 299 - 300 - static void rela32_write_addend(Elf_Rela *rela, uint64_t val) 301 - { 302 - w(val, (uint32_t *)&rela->e32.r_addend); 303 - } 304 - 305 - /* 306 - * Get the whole file as a programming convenience in order to avoid 307 - * malloc+lseek+read+free of many pieces. If successful, then mmap 308 - * avoids copying unused pieces; else just read the whole file. 309 - * Open for both read and write. 310 - */ 311 - static void *mmap_file(char const *fname, size_t *size) 312 - { 313 - int fd; 314 - struct stat sb; 315 - void *addr = NULL; 316 - 317 - fd = open(fname, O_RDWR); 318 - if (fd < 0) { 319 - perror(fname); 320 - return NULL; 321 - } 322 - if (fstat(fd, &sb) < 0) { 323 - perror(fname); 324 - goto out; 325 - } 326 - if (!S_ISREG(sb.st_mode)) { 327 - fprintf(stderr, "not a regular file: %s\n", fname); 328 - goto out; 329 - } 330 - 331 - addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 332 - if (addr == MAP_FAILED) { 333 - fprintf(stderr, "Could not mmap file: %s\n", fname); 334 - goto out; 335 - } 336 - 337 - *size = sb.st_size; 338 - 339 - out: 340 - close(fd); 341 - return addr; 342 - } 343 - 344 - static uint32_t rbe(const uint32_t *x) 345 - { 346 - return get_unaligned_be32(x); 347 - } 348 - 349 - static uint16_t r2be(const uint16_t *x) 350 - { 351 - return get_unaligned_be16(x); 352 - } 353 - 354 - static uint64_t r8be(const uint64_t *x) 355 - { 356 - return get_unaligned_be64(x); 357 - } 358 - 359 - static uint32_t rle(const uint32_t *x) 360 - { 361 - return get_unaligned_le32(x); 362 - } 363 - 364 - static uint16_t r2le(const uint16_t *x) 365 - { 366 - return get_unaligned_le16(x); 367 - } 368 - 369 - static uint64_t r8le(const uint64_t *x) 370 - { 371 - return get_unaligned_le64(x); 372 - } 373 - 374 - static void wbe(uint32_t val, uint32_t *x) 375 - { 376 - put_unaligned_be32(val, x); 377 - } 378 - 379 - static void wle(uint32_t val, uint32_t *x) 380 - { 381 - put_unaligned_le32(val, x); 382 - } 383 - 384 - static void w8be(uint64_t val, uint64_t *x) 385 - { 386 - put_unaligned_be64(val, x); 387 - } 388 - 389 - static void w8le(uint64_t val, uint64_t *x) 390 - { 391 - put_unaligned_le64(val, x); 392 - } 393 69 394 70 /* 395 71 * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of ··· 85 415 return SPECIAL(shndx); 86 416 if (shndx != SHN_XINDEX) 87 417 return shndx; 88 - return r(&symtab_shndx_start[sym_offs]); 418 + return elf_parser.r(&symtab_shndx_start[sym_offs]); 89 419 } 90 420 91 421 static int compare_extable_32(const void *a, const void *b) 92 422 { 93 - Elf32_Addr av = r(a); 94 - Elf32_Addr bv = r(b); 423 + Elf32_Addr av = elf_parser.r(a); 424 + Elf32_Addr bv = elf_parser.r(b); 95 425 96 426 if (av < bv) 97 427 return -1; ··· 100 430 101 431 static int compare_extable_64(const void *a, const void *b) 102 432 { 103 - Elf64_Addr av = r8(a); 104 - Elf64_Addr bv = r8(b); 433 + Elf64_Addr av = elf_parser.r8(a); 434 + Elf64_Addr bv = elf_parser.r8(b); 105 435 106 436 if (av < bv) 107 437 return -1; 108 438 return av > bv; 109 439 } 110 440 111 - static int compare_extable(const void *a, const void *b) 112 - { 113 - return e.compare_extable(a, b); 114 - } 441 + static int (*compare_extable)(const void *a, const void *b); 115 442 116 443 static inline void *get_index(void *start, int entsize, int index) 117 444 { ··· 244 577 /* Only used for sorting mcount table */ 245 578 static void rela_write_addend(Elf_Rela *rela, uint64_t val) 246 579 { 247 - e.rela_write_addend(rela, val); 580 + elf_parser.rela_write_addend(rela, val); 248 581 } 249 582 250 583 struct func_info { ··· 459 792 460 793 for (; ptr < end; ptr += long_size, addrs += long_size, count++) { 461 794 if (long_size == 4) 462 - *(uint32_t *)ptr = r(addrs); 795 + *(uint32_t *)ptr = elf_parser.r(addrs); 463 796 else 464 - *(uint64_t *)ptr = r8(addrs); 797 + *(uint64_t *)ptr = elf_parser.r8(addrs); 465 798 } 466 799 return count; 467 800 } ··· 472 805 473 806 for (; ptr < end; ptr += long_size, addrs += long_size) { 474 807 if (long_size == 4) 475 - w(*(uint32_t *)ptr, addrs); 808 + elf_parser.w(*(uint32_t *)ptr, addrs); 476 809 else 477 - w8(*(uint64_t *)ptr, addrs); 810 + elf_parser.w8(*(uint64_t *)ptr, addrs); 478 811 } 479 812 } 480 813 ··· 778 1111 sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec); 779 1112 780 1113 /* extable has been sorted, clear the flag */ 781 - w(0, sort_needed_loc); 1114 + elf_parser.w(0, sort_needed_loc); 782 1115 rc = 0; 783 1116 784 1117 out: ··· 822 1155 823 1156 static int compare_relative_table(const void *a, const void *b) 824 1157 { 825 - int32_t av = (int32_t)r(a); 826 - int32_t bv = (int32_t)r(b); 1158 + int32_t av = (int32_t)elf_parser.r(a); 1159 + int32_t bv = (int32_t)elf_parser.r(b); 827 1160 828 1161 if (av < bv) 829 1162 return -1; ··· 842 1175 */ 843 1176 while (i < image_size) { 844 1177 uint32_t *loc = (uint32_t *)(extab_image + i); 845 - w(r(loc) + i, loc); 1178 + elf_parser.w(elf_parser.r(loc) + i, loc); 846 1179 i += 4; 847 1180 } 848 1181 ··· 852 1185 i = 0; 853 1186 while (i < image_size) { 854 1187 uint32_t *loc = (uint32_t *)(extab_image + i); 855 - w(r(loc) - i, loc); 1188 + elf_parser.w(elf_parser.r(loc) - i, loc); 856 1189 i += 4; 857 1190 } 858 1191 } ··· 864 1197 while (i < image_size) { 865 1198 uint32_t *loc = (uint32_t *)(extab_image + i); 866 1199 867 - w(r(loc) + i, loc); 868 - w(r(loc + 1) + i + 4, loc + 1); 1200 + elf_parser.w(elf_parser.r(loc) + i, loc); 1201 + elf_parser.w(elf_parser.r(loc + 1) + i + 4, loc + 1); 869 1202 /* Don't touch the fixup type or data */ 870 1203 871 1204 i += sizeof(uint32_t) * 3; ··· 877 1210 while (i < image_size) { 878 1211 uint32_t *loc = (uint32_t *)(extab_image + i); 879 1212 880 - w(r(loc) - i, loc); 881 - w(r(loc + 1) - (i + 4), loc + 1); 1213 + elf_parser.w(elf_parser.r(loc) - i, loc); 1214 + elf_parser.w(elf_parser.r(loc + 1) - (i + 4), loc + 1); 882 1215 /* Don't touch the fixup type or data */ 883 1216 884 1217 i += sizeof(uint32_t) * 3; ··· 890 1223 Elf_Ehdr *ehdr = addr; 891 1224 table_sort_t custom_sort = NULL; 892 1225 893 - switch (ehdr->e32.e_ident[EI_DATA]) { 894 - case ELFDATA2LSB: 895 - r = rle; 896 - r2 = r2le; 897 - r8 = r8le; 898 - w = wle; 899 - w8 = w8le; 900 - break; 901 - case ELFDATA2MSB: 902 - r = rbe; 903 - r2 = r2be; 904 - r8 = r8be; 905 - w = wbe; 906 - w8 = w8be; 907 - break; 908 - default: 909 - fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", 910 - ehdr->e32.e_ident[EI_DATA], fname); 911 - return -1; 912 - } 913 - 914 - if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) != 0 || 915 - (r2(&ehdr->e32.e_type) != ET_EXEC && r2(&ehdr->e32.e_type) != ET_DYN) || 916 - ehdr->e32.e_ident[EI_VERSION] != EV_CURRENT) { 917 - fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname); 918 - return -1; 919 - } 920 - 921 - switch (r2(&ehdr->e32.e_machine)) { 1226 + switch (elf_map_machine(ehdr)) { 922 1227 case EM_AARCH64: 923 1228 #ifdef MCOUNT_SORT_ENABLED 924 1229 sort_reloc = true; ··· 920 1281 break; 921 1282 default: 922 1283 fprintf(stderr, "unrecognized e_machine %d %s\n", 923 - r2(&ehdr->e32.e_machine), fname); 1284 + elf_parser.r2(&ehdr->e32.e_machine), fname); 924 1285 return -1; 925 1286 } 926 1287 927 - switch (ehdr->e32.e_ident[EI_CLASS]) { 928 - case ELFCLASS32: { 929 - struct elf_funcs efuncs = { 930 - .compare_extable = compare_extable_32, 931 - .ehdr_shoff = ehdr32_shoff, 932 - .ehdr_shentsize = ehdr32_shentsize, 933 - .ehdr_shstrndx = ehdr32_shstrndx, 934 - .ehdr_shnum = ehdr32_shnum, 935 - .shdr_addr = shdr32_addr, 936 - .shdr_offset = shdr32_offset, 937 - .shdr_link = shdr32_link, 938 - .shdr_size = shdr32_size, 939 - .shdr_name = shdr32_name, 940 - .shdr_type = shdr32_type, 941 - .shdr_entsize = shdr32_entsize, 942 - .sym_type = sym32_type, 943 - .sym_name = sym32_name, 944 - .sym_value = sym32_value, 945 - .sym_shndx = sym32_shndx, 946 - .rela_offset = rela32_offset, 947 - .rela_info = rela32_info, 948 - .rela_addend = rela32_addend, 949 - .rela_write_addend = rela32_write_addend, 950 - }; 951 - 952 - e = efuncs; 1288 + switch (elf_map_long_size(addr)) { 1289 + case 4: 1290 + compare_extable = compare_extable_32, 953 1291 long_size = 4; 954 1292 extable_ent_size = 8; 955 1293 956 - if (r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) || 957 - r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) { 1294 + if (elf_parser.r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) || 1295 + elf_parser.r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) { 958 1296 fprintf(stderr, 959 1297 "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); 960 1298 return -1; 961 1299 } 962 1300 963 - } 964 1301 break; 965 - case ELFCLASS64: { 966 - struct elf_funcs efuncs = { 967 - .compare_extable = compare_extable_64, 968 - .ehdr_shoff = ehdr64_shoff, 969 - .ehdr_shentsize = ehdr64_shentsize, 970 - .ehdr_shstrndx = ehdr64_shstrndx, 971 - .ehdr_shnum = ehdr64_shnum, 972 - .shdr_addr = shdr64_addr, 973 - .shdr_offset = shdr64_offset, 974 - .shdr_link = shdr64_link, 975 - .shdr_size = shdr64_size, 976 - .shdr_name = shdr64_name, 977 - .shdr_type = shdr64_type, 978 - .shdr_entsize = shdr64_entsize, 979 - .sym_type = sym64_type, 980 - .sym_name = sym64_name, 981 - .sym_value = sym64_value, 982 - .sym_shndx = sym64_shndx, 983 - .rela_offset = rela64_offset, 984 - .rela_info = rela64_info, 985 - .rela_addend = rela64_addend, 986 - .rela_write_addend = rela64_write_addend, 987 - }; 988 - 989 - e = efuncs; 1302 + case 8: 1303 + compare_extable = compare_extable_64, 990 1304 long_size = 8; 991 1305 extable_ent_size = 16; 992 1306 993 - if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) || 994 - r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) { 1307 + if (elf_parser.r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) || 1308 + elf_parser.r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) { 995 1309 fprintf(stderr, 996 1310 "unrecognized ET_EXEC/ET_DYN file: %s\n", 997 1311 fname); 998 1312 return -1; 999 1313 } 1000 1314 1001 - } 1002 1315 break; 1003 1316 default: 1004 1317 fprintf(stderr, "unrecognized ELF class %d %s\n", ··· 989 1398 990 1399 /* Process each file in turn, allowing deep failure. */ 991 1400 for (i = optind; i < argc; i++) { 992 - addr = mmap_file(argv[i], &size); 1401 + addr = elf_map(argv[i], &size, (1 << ET_EXEC) | (1 << ET_DYN)); 993 1402 if (!addr) { 994 1403 ++n_error; 995 1404 continue; ··· 998 1407 if (do_file(argv[i], addr)) 999 1408 ++n_error; 1000 1409 1001 - munmap(addr, size); 1410 + elf_unmap(addr, size); 1002 1411 } 1003 1412 1004 1413 return !!n_error;