diff options
| author | David Daney <david.daney@cavium.com> | 2012-04-24 14:23:14 -0400 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2012-04-24 14:42:20 -0400 |
| commit | d59a16836d917548cf41eda3369936684d527f5f (patch) | |
| tree | a332ee65290db2a53fb3cfca6e97de2a622c3df6 /scripts | |
| parent | 706276543b699d80f546e45f8b12574e7b18d952 (diff) | |
scripts/sortextable: Handle relative entries, and other cleanups
x86 is now using relative rather than absolute addresses in its
exception table, so we add a sorter for these. If there are
relocations on the __ex_table section, they are redundant and probably
incorrect after the sort, so they are zeroed out leaving them valid
and consistent.
Also use the unaligned safe accessors from tools/{be,le}_byteshift.h
Signed-off-by: David Daney <david.daney@cavium.com>
Link: http://lkml.kernel.org/r/1335291795-26693-2-git-send-email-ddaney.cavm@gmail.com
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/Makefile | 2 | ||||
| -rw-r--r-- | scripts/sortextable.c | 171 | ||||
| -rw-r--r-- | scripts/sortextable.h | 79 |
3 files changed, 164 insertions, 88 deletions
diff --git a/scripts/Makefile b/scripts/Makefile index 43e19b9fc641..9eace52c64df 100644 --- a/scripts/Makefile +++ b/scripts/Makefile | |||
| @@ -15,6 +15,8 @@ hostprogs-$(CONFIG_IKCONFIG) += bin2c | |||
| 15 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount | 15 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount |
| 16 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable | 16 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable |
| 17 | 17 | ||
| 18 | HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include | ||
| 19 | |||
| 18 | always := $(hostprogs-y) $(hostprogs-m) | 20 | always := $(hostprogs-y) $(hostprogs-m) |
| 19 | 21 | ||
| 20 | # The following hostprogs-y programs are only build on demand | 22 | # The following hostprogs-y programs are only build on demand |
diff --git a/scripts/sortextable.c b/scripts/sortextable.c index f51f1d43da63..1ca9ceb95eb6 100644 --- a/scripts/sortextable.c +++ b/scripts/sortextable.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * sortextable.c: Sort the kernel's exception table | 2 | * sortextable.c: Sort the kernel's exception table |
| 3 | * | 3 | * |
| 4 | * Copyright 2011 Cavium, Inc. | 4 | * Copyright 2011 - 2012 Cavium, Inc. |
| 5 | * | 5 | * |
| 6 | * Based on code taken from recortmcount.c which is: | 6 | * Based on code taken from recortmcount.c which is: |
| 7 | * | 7 | * |
| @@ -28,6 +28,9 @@ | |||
| 28 | #include <string.h> | 28 | #include <string.h> |
| 29 | #include <unistd.h> | 29 | #include <unistd.h> |
| 30 | 30 | ||
| 31 | #include <tools/be_byteshift.h> | ||
| 32 | #include <tools/le_byteshift.h> | ||
| 33 | |||
| 31 | static int fd_map; /* File descriptor for file being modified. */ | 34 | static int fd_map; /* File descriptor for file being modified. */ |
| 32 | static int mmap_failed; /* Boolean flag. */ | 35 | static int mmap_failed; /* Boolean flag. */ |
| 33 | static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ | 36 | static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ |
| @@ -94,109 +97,157 @@ static void *mmap_file(char const *fname) | |||
| 94 | return addr; | 97 | return addr; |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 97 | /* w8rev, w8nat, ...: Handle endianness. */ | 100 | static uint64_t r8be(const uint64_t *x) |
| 98 | |||
| 99 | static uint64_t w8rev(uint64_t const x) | ||
| 100 | { | 101 | { |
| 101 | return ((0xff & (x >> (0 * 8))) << (7 * 8)) | 102 | return get_unaligned_be64(x); |
| 102 | | ((0xff & (x >> (1 * 8))) << (6 * 8)) | ||
| 103 | | ((0xff & (x >> (2 * 8))) << (5 * 8)) | ||
| 104 | | ((0xff & (x >> (3 * 8))) << (4 * 8)) | ||
| 105 | | ((0xff & (x >> (4 * 8))) << (3 * 8)) | ||
| 106 | | ((0xff & (x >> (5 * 8))) << (2 * 8)) | ||
| 107 | | ((0xff & (x >> (6 * 8))) << (1 * 8)) | ||
| 108 | | ((0xff & (x >> (7 * 8))) << (0 * 8)); | ||
| 109 | } | 103 | } |
| 110 | 104 | static uint32_t rbe(const uint32_t *x) | |
| 111 | static uint32_t w4rev(uint32_t const x) | ||
| 112 | { | 105 | { |
| 113 | return ((0xff & (x >> (0 * 8))) << (3 * 8)) | 106 | return get_unaligned_be32(x); |
| 114 | | ((0xff & (x >> (1 * 8))) << (2 * 8)) | ||
| 115 | | ((0xff & (x >> (2 * 8))) << (1 * 8)) | ||
| 116 | | ((0xff & (x >> (3 * 8))) << (0 * 8)); | ||
| 117 | } | 107 | } |
| 118 | 108 | static uint16_t r2be(const uint16_t *x) | |
| 119 | static uint32_t w2rev(uint16_t const x) | ||
| 120 | { | 109 | { |
| 121 | return ((0xff & (x >> (0 * 8))) << (1 * 8)) | 110 | return get_unaligned_be16(x); |
| 122 | | ((0xff & (x >> (1 * 8))) << (0 * 8)); | ||
| 123 | } | 111 | } |
| 124 | 112 | static uint64_t r8le(const uint64_t *x) | |
| 125 | static uint64_t w8nat(uint64_t const x) | ||
| 126 | { | 113 | { |
| 127 | return x; | 114 | return get_unaligned_le64(x); |
| 128 | } | 115 | } |
| 129 | 116 | static uint32_t rle(const uint32_t *x) | |
| 130 | static uint32_t w4nat(uint32_t const x) | 117 | { |
| 118 | return get_unaligned_le32(x); | ||
| 119 | } | ||
| 120 | static uint16_t r2le(const uint16_t *x) | ||
| 131 | { | 121 | { |
| 132 | return x; | 122 | return get_unaligned_le16(x); |
| 133 | } | 123 | } |
| 134 | 124 | ||
| 135 | static uint32_t w2nat(uint16_t const x) | 125 | static void w8be(uint64_t val, uint64_t *x) |
| 126 | { | ||
| 127 | put_unaligned_be64(val, x); | ||
| 128 | } | ||
| 129 | static void wbe(uint32_t val, uint32_t *x) | ||
| 130 | { | ||
| 131 | put_unaligned_be32(val, x); | ||
| 132 | } | ||
| 133 | static void w2be(uint16_t val, uint16_t *x) | ||
| 134 | { | ||
| 135 | put_unaligned_be16(val, x); | ||
| 136 | } | ||
| 137 | static void w8le(uint64_t val, uint64_t *x) | ||
| 138 | { | ||
| 139 | put_unaligned_le64(val, x); | ||
| 140 | } | ||
| 141 | static void wle(uint32_t val, uint32_t *x) | ||
| 142 | { | ||
| 143 | put_unaligned_le32(val, x); | ||
| 144 | } | ||
| 145 | static void w2le(uint16_t val, uint16_t *x) | ||
| 136 | { | 146 | { |
| 137 | return x; | 147 | put_unaligned_le16(val, x); |
| 138 | } | 148 | } |
| 139 | 149 | ||
| 140 | static uint64_t (*w8)(uint64_t); | 150 | static uint64_t (*r8)(const uint64_t *); |
| 141 | static uint32_t (*w)(uint32_t); | 151 | static uint32_t (*r)(const uint32_t *); |
| 142 | static uint32_t (*w2)(uint16_t); | 152 | static uint16_t (*r2)(const uint16_t *); |
| 153 | static void (*w8)(uint64_t, uint64_t *); | ||
| 154 | static void (*w)(uint32_t, uint32_t *); | ||
| 155 | static void (*w2)(uint16_t, uint16_t *); | ||
| 143 | 156 | ||
| 157 | typedef void (*table_sort_t)(char *, int); | ||
| 144 | 158 | ||
| 145 | /* 32 bit and 64 bit are very similar */ | 159 | /* 32 bit and 64 bit are very similar */ |
| 146 | #include "sortextable.h" | 160 | #include "sortextable.h" |
| 147 | #define SORTEXTABLE_64 | 161 | #define SORTEXTABLE_64 |
| 148 | #include "sortextable.h" | 162 | #include "sortextable.h" |
| 149 | 163 | ||
| 164 | static int compare_x86_table(const void *a, const void *b) | ||
| 165 | { | ||
| 166 | int32_t av = (int32_t)r(a); | ||
| 167 | int32_t bv = (int32_t)r(b); | ||
| 168 | |||
| 169 | if (av < bv) | ||
| 170 | return -1; | ||
| 171 | if (av > bv) | ||
| 172 | return 1; | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void sort_x86_table(char *extab_image, int image_size) | ||
| 177 | { | ||
| 178 | int i; | ||
| 179 | |||
| 180 | /* | ||
| 181 | * Do the same thing the runtime sort does, first normalize to | ||
| 182 | * being relative to the start of the section. | ||
| 183 | */ | ||
| 184 | i = 0; | ||
| 185 | while (i < image_size) { | ||
| 186 | uint32_t *loc = (uint32_t *)(extab_image + i); | ||
| 187 | w(r(loc) + i, loc); | ||
| 188 | i += 4; | ||
| 189 | } | ||
| 190 | |||
| 191 | qsort(extab_image, image_size / 8, 8, compare_x86_table); | ||
| 192 | |||
| 193 | /* Now denormalize. */ | ||
| 194 | i = 0; | ||
| 195 | while (i < image_size) { | ||
| 196 | uint32_t *loc = (uint32_t *)(extab_image + i); | ||
| 197 | w(r(loc) - i, loc); | ||
| 198 | i += 4; | ||
| 199 | } | ||
| 200 | } | ||
| 150 | 201 | ||
| 151 | static void | 202 | static void |
| 152 | do_file(char const *const fname) | 203 | do_file(char const *const fname) |
| 153 | { | 204 | { |
| 154 | Elf32_Ehdr *const ehdr = mmap_file(fname); | 205 | table_sort_t custom_sort; |
| 206 | Elf32_Ehdr *ehdr = mmap_file(fname); | ||
| 155 | 207 | ||
| 156 | ehdr_curr = ehdr; | 208 | ehdr_curr = ehdr; |
| 157 | w = w4nat; | ||
| 158 | w2 = w2nat; | ||
| 159 | w8 = w8nat; | ||
| 160 | switch (ehdr->e_ident[EI_DATA]) { | 209 | switch (ehdr->e_ident[EI_DATA]) { |
| 161 | static unsigned int const endian = 1; | ||
| 162 | default: | 210 | default: |
| 163 | fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", | 211 | fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", |
| 164 | ehdr->e_ident[EI_DATA], fname); | 212 | ehdr->e_ident[EI_DATA], fname); |
| 165 | fail_file(); | 213 | fail_file(); |
| 166 | break; | 214 | break; |
| 167 | case ELFDATA2LSB: | 215 | case ELFDATA2LSB: |
| 168 | if (*(unsigned char const *)&endian != 1) { | 216 | r = rle; |
| 169 | /* main() is big endian, file.o is little endian. */ | 217 | r2 = r2le; |
| 170 | w = w4rev; | 218 | r8 = r8le; |
| 171 | w2 = w2rev; | 219 | w = wle; |
| 172 | w8 = w8rev; | 220 | w2 = w2le; |
| 173 | } | 221 | w8 = w8le; |
| 174 | break; | 222 | break; |
| 175 | case ELFDATA2MSB: | 223 | case ELFDATA2MSB: |
| 176 | if (*(unsigned char const *)&endian != 0) { | 224 | r = rbe; |
| 177 | /* main() is little endian, file.o is big endian. */ | 225 | r2 = r2be; |
| 178 | w = w4rev; | 226 | r8 = r8be; |
| 179 | w2 = w2rev; | 227 | w = wbe; |
| 180 | w8 = w8rev; | 228 | w2 = w2be; |
| 181 | } | 229 | w8 = w8be; |
| 182 | break; | 230 | break; |
| 183 | } /* end switch */ | 231 | } /* end switch */ |
| 184 | if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 | 232 | if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 |
| 185 | || w2(ehdr->e_type) != ET_EXEC | 233 | || r2(&ehdr->e_type) != ET_EXEC |
| 186 | || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { | 234 | || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { |
| 187 | fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname); | 235 | fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname); |
| 188 | fail_file(); | 236 | fail_file(); |
| 189 | } | 237 | } |
| 190 | 238 | ||
| 191 | switch (w2(ehdr->e_machine)) { | 239 | custom_sort = NULL; |
| 240 | switch (r2(&ehdr->e_machine)) { | ||
| 192 | default: | 241 | default: |
| 193 | fprintf(stderr, "unrecognized e_machine %d %s\n", | 242 | fprintf(stderr, "unrecognized e_machine %d %s\n", |
| 194 | w2(ehdr->e_machine), fname); | 243 | r2(&ehdr->e_machine), fname); |
| 195 | fail_file(); | 244 | fail_file(); |
| 196 | break; | 245 | break; |
| 197 | case EM_386: | 246 | case EM_386: |
| 198 | case EM_MIPS: | ||
| 199 | case EM_X86_64: | 247 | case EM_X86_64: |
| 248 | custom_sort = sort_x86_table; | ||
| 249 | break; | ||
| 250 | case EM_MIPS: | ||
| 200 | break; | 251 | break; |
| 201 | } /* end switch */ | 252 | } /* end switch */ |
| 202 | 253 | ||
| @@ -207,23 +258,23 @@ do_file(char const *const fname) | |||
| 207 | fail_file(); | 258 | fail_file(); |
| 208 | break; | 259 | break; |
| 209 | case ELFCLASS32: | 260 | case ELFCLASS32: |
| 210 | if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr) | 261 | if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) |
| 211 | || w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { | 262 | || r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { |
| 212 | fprintf(stderr, | 263 | fprintf(stderr, |
| 213 | "unrecognized ET_EXEC file: %s\n", fname); | 264 | "unrecognized ET_EXEC file: %s\n", fname); |
| 214 | fail_file(); | 265 | fail_file(); |
| 215 | } | 266 | } |
| 216 | do32(ehdr, fname); | 267 | do32(ehdr, fname, custom_sort); |
| 217 | break; | 268 | break; |
| 218 | case ELFCLASS64: { | 269 | case ELFCLASS64: { |
| 219 | Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; | 270 | Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; |
| 220 | if (w2(ghdr->e_ehsize) != sizeof(Elf64_Ehdr) | 271 | if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) |
| 221 | || w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { | 272 | || r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { |
| 222 | fprintf(stderr, | 273 | fprintf(stderr, |
| 223 | "unrecognized ET_EXEC file: %s\n", fname); | 274 | "unrecognized ET_EXEC file: %s\n", fname); |
| 224 | fail_file(); | 275 | fail_file(); |
| 225 | } | 276 | } |
| 226 | do64(ghdr, fname); | 277 | do64(ghdr, fname, custom_sort); |
| 227 | break; | 278 | break; |
| 228 | } | 279 | } |
| 229 | } /* end switch */ | 280 | } /* end switch */ |
diff --git a/scripts/sortextable.h b/scripts/sortextable.h index bb6aaf166002..e4fd45b7e456 100644 --- a/scripts/sortextable.h +++ b/scripts/sortextable.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * sortextable.h | 2 | * sortextable.h |
| 3 | * | 3 | * |
| 4 | * Copyright 2011 Cavium, Inc. | 4 | * Copyright 2011 - 2012 Cavium, Inc. |
| 5 | * | 5 | * |
| 6 | * Some of this code was taken out of recordmcount.h written by: | 6 | * Some of this code was taken out of recordmcount.h written by: |
| 7 | * | 7 | * |
| @@ -30,6 +30,7 @@ | |||
| 30 | #undef fn_ELF_R_SYM | 30 | #undef fn_ELF_R_SYM |
| 31 | #undef fn_ELF_R_INFO | 31 | #undef fn_ELF_R_INFO |
| 32 | #undef uint_t | 32 | #undef uint_t |
| 33 | #undef _r | ||
| 33 | #undef _w | 34 | #undef _w |
| 34 | 35 | ||
| 35 | #ifdef SORTEXTABLE_64 | 36 | #ifdef SORTEXTABLE_64 |
| @@ -51,6 +52,7 @@ | |||
| 51 | # define fn_ELF_R_SYM fn_ELF64_R_SYM | 52 | # define fn_ELF_R_SYM fn_ELF64_R_SYM |
| 52 | # define fn_ELF_R_INFO fn_ELF64_R_INFO | 53 | # define fn_ELF_R_INFO fn_ELF64_R_INFO |
| 53 | # define uint_t uint64_t | 54 | # define uint_t uint64_t |
| 55 | # define _r r8 | ||
| 54 | # define _w w8 | 56 | # define _w w8 |
| 55 | #else | 57 | #else |
| 56 | # define extable_ent_size 8 | 58 | # define extable_ent_size 8 |
| @@ -71,23 +73,24 @@ | |||
| 71 | # define fn_ELF_R_SYM fn_ELF32_R_SYM | 73 | # define fn_ELF_R_SYM fn_ELF32_R_SYM |
| 72 | # define fn_ELF_R_INFO fn_ELF32_R_INFO | 74 | # define fn_ELF_R_INFO fn_ELF32_R_INFO |
| 73 | # define uint_t uint32_t | 75 | # define uint_t uint32_t |
| 76 | # define _r r | ||
| 74 | # define _w w | 77 | # define _w w |
| 75 | #endif | 78 | #endif |
| 76 | 79 | ||
| 77 | static int compare_extable(const void *a, const void *b) | 80 | static int compare_extable(const void *a, const void *b) |
| 78 | { | 81 | { |
| 79 | const uint_t *aa = a; | 82 | Elf_Addr av = _r(a); |
| 80 | const uint_t *bb = b; | 83 | Elf_Addr bv = _r(b); |
| 81 | 84 | ||
| 82 | if (_w(*aa) < _w(*bb)) | 85 | if (av < bv) |
| 83 | return -1; | 86 | return -1; |
| 84 | if (_w(*aa) > _w(*bb)) | 87 | if (av > bv) |
| 85 | return 1; | 88 | return 1; |
| 86 | return 0; | 89 | return 0; |
| 87 | } | 90 | } |
| 88 | 91 | ||
| 89 | static void | 92 | static void |
| 90 | do_func(Elf_Ehdr *const ehdr, char const *const fname) | 93 | do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort) |
| 91 | { | 94 | { |
| 92 | Elf_Shdr *shdr; | 95 | Elf_Shdr *shdr; |
| 93 | Elf_Shdr *shstrtab_sec; | 96 | Elf_Shdr *shstrtab_sec; |
| @@ -97,19 +100,31 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname) | |||
| 97 | Elf_Sym *sym; | 100 | Elf_Sym *sym; |
| 98 | Elf_Sym *sort_needed_sym; | 101 | Elf_Sym *sort_needed_sym; |
| 99 | Elf_Shdr *sort_needed_sec; | 102 | Elf_Shdr *sort_needed_sec; |
| 103 | Elf_Rel *relocs = NULL; | ||
| 104 | int relocs_size; | ||
| 100 | uint32_t *sort_done_location; | 105 | uint32_t *sort_done_location; |
| 101 | const char *secstrtab; | 106 | const char *secstrtab; |
| 102 | const char *strtab; | 107 | const char *strtab; |
| 108 | char *extab_image; | ||
| 109 | int extab_index = 0; | ||
| 103 | int i; | 110 | int i; |
| 104 | int idx; | 111 | int idx; |
| 105 | 112 | ||
| 106 | shdr = (Elf_Shdr *)((void *)ehdr + _w(ehdr->e_shoff)); | 113 | shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff)); |
| 107 | shstrtab_sec = shdr + w2(ehdr->e_shstrndx); | 114 | shstrtab_sec = shdr + r2(&ehdr->e_shstrndx); |
| 108 | secstrtab = (const char *)ehdr + _w(shstrtab_sec->sh_offset); | 115 | secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset); |
| 109 | for (i = 0; i < w2(ehdr->e_shnum); i++) { | 116 | for (i = 0; i < r2(&ehdr->e_shnum); i++) { |
| 110 | idx = w(shdr[i].sh_name); | 117 | idx = r(&shdr[i].sh_name); |
| 111 | if (strcmp(secstrtab + idx, "__ex_table") == 0) | 118 | if (strcmp(secstrtab + idx, "__ex_table") == 0) { |
| 112 | extab_sec = shdr + i; | 119 | extab_sec = shdr + i; |
| 120 | extab_index = i; | ||
| 121 | } | ||
| 122 | if ((r(&shdr[i].sh_type) == SHT_REL || | ||
| 123 | r(&shdr[i].sh_type) == SHT_RELA) && | ||
| 124 | r(&shdr[i].sh_info) == extab_index) { | ||
| 125 | relocs = (void *)ehdr + _r(&shdr[i].sh_offset); | ||
| 126 | relocs_size = _r(&shdr[i].sh_size); | ||
| 127 | } | ||
| 113 | if (strcmp(secstrtab + idx, ".symtab") == 0) | 128 | if (strcmp(secstrtab + idx, ".symtab") == 0) |
| 114 | symtab_sec = shdr + i; | 129 | symtab_sec = shdr + i; |
| 115 | if (strcmp(secstrtab + idx, ".strtab") == 0) | 130 | if (strcmp(secstrtab + idx, ".strtab") == 0) |
| @@ -127,21 +142,29 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname) | |||
| 127 | fprintf(stderr, "no __ex_table in file: %s\n", fname); | 142 | fprintf(stderr, "no __ex_table in file: %s\n", fname); |
| 128 | fail_file(); | 143 | fail_file(); |
| 129 | } | 144 | } |
| 130 | strtab = (const char *)ehdr + _w(strtab_sec->sh_offset); | 145 | strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset); |
| 131 | 146 | ||
| 132 | /* Sort the table in place */ | 147 | extab_image = (void *)ehdr + _r(&extab_sec->sh_offset); |
| 133 | qsort((void *)ehdr + _w(extab_sec->sh_offset), | 148 | |
| 134 | (_w(extab_sec->sh_size) / extable_ent_size), | 149 | if (custom_sort) { |
| 135 | extable_ent_size, compare_extable); | 150 | custom_sort(extab_image, _r(&extab_sec->sh_size)); |
| 151 | } else { | ||
| 152 | int num_entries = _r(&extab_sec->sh_size) / extable_ent_size; | ||
| 153 | qsort(extab_image, num_entries, | ||
| 154 | extable_ent_size, compare_extable); | ||
| 155 | } | ||
| 156 | /* If there were relocations, we no longer need them. */ | ||
| 157 | if (relocs) | ||
| 158 | memset(relocs, 0, relocs_size); | ||
| 136 | 159 | ||
| 137 | /* find main_extable_sort_needed */ | 160 | /* find main_extable_sort_needed */ |
| 138 | sort_needed_sym = NULL; | 161 | sort_needed_sym = NULL; |
| 139 | for (i = 0; i < _w(symtab_sec->sh_size) / sizeof(Elf_Sym); i++) { | 162 | for (i = 0; i < _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); i++) { |
| 140 | sym = (void *)ehdr + _w(symtab_sec->sh_offset); | 163 | sym = (void *)ehdr + _r(&symtab_sec->sh_offset); |
| 141 | sym += i; | 164 | sym += i; |
| 142 | if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) | 165 | if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) |
| 143 | continue; | 166 | continue; |
| 144 | idx = w(sym->st_name); | 167 | idx = r(&sym->st_name); |
| 145 | if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) { | 168 | if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) { |
| 146 | sort_needed_sym = sym; | 169 | sort_needed_sym = sym; |
| 147 | break; | 170 | break; |
| @@ -153,16 +176,16 @@ do_func(Elf_Ehdr *const ehdr, char const *const fname) | |||
| 153 | fname); | 176 | fname); |
| 154 | fail_file(); | 177 | fail_file(); |
| 155 | } | 178 | } |
| 156 | sort_needed_sec = &shdr[w2(sort_needed_sym->st_shndx)]; | 179 | sort_needed_sec = &shdr[r2(&sort_needed_sym->st_shndx)]; |
| 157 | sort_done_location = (void *)ehdr + | 180 | sort_done_location = (void *)ehdr + |
| 158 | _w(sort_needed_sec->sh_offset) + | 181 | _r(&sort_needed_sec->sh_offset) + |
| 159 | _w(sort_needed_sym->st_value) - | 182 | _r(&sort_needed_sym->st_value) - |
| 160 | _w(sort_needed_sec->sh_addr); | 183 | _r(&sort_needed_sec->sh_addr); |
| 161 | 184 | ||
| 185 | #if 1 | ||
| 162 | printf("sort done marker at %lx\n", | 186 | printf("sort done marker at %lx\n", |
| 163 | (unsigned long) (_w(sort_needed_sec->sh_offset) + | 187 | (unsigned long)((char *)sort_done_location - (char *)ehdr)); |
| 164 | _w(sort_needed_sym->st_value) - | 188 | #endif |
| 165 | _w(sort_needed_sec->sh_addr))); | ||
| 166 | /* We sorted it, clear the flag. */ | 189 | /* We sorted it, clear the flag. */ |
| 167 | *sort_done_location = 0; | 190 | w(0, sort_done_location); |
| 168 | } | 191 | } |
