aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/sortextable.c
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2012-04-24 14:23:14 -0400
committerH. Peter Anvin <hpa@zytor.com>2012-04-24 14:42:20 -0400
commitd59a16836d917548cf41eda3369936684d527f5f (patch)
treea332ee65290db2a53fb3cfca6e97de2a622c3df6 /scripts/sortextable.c
parent706276543b699d80f546e45f8b12574e7b18d952 (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/sortextable.c')
-rw-r--r--scripts/sortextable.c171
1 files changed, 111 insertions, 60 deletions
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
31static int fd_map; /* File descriptor for file being modified. */ 34static int fd_map; /* File descriptor for file being modified. */
32static int mmap_failed; /* Boolean flag. */ 35static int mmap_failed; /* Boolean flag. */
33static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ 36static 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. */ 100static uint64_t r8be(const uint64_t *x)
98
99static 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 104static uint32_t rbe(const uint32_t *x)
111static 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 108static uint16_t r2be(const uint16_t *x)
119static 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 112static uint64_t r8le(const uint64_t *x)
125static uint64_t w8nat(uint64_t const x)
126{ 113{
127 return x; 114 return get_unaligned_le64(x);
128} 115}
129 116static uint32_t rle(const uint32_t *x)
130static uint32_t w4nat(uint32_t const x) 117{
118 return get_unaligned_le32(x);
119}
120static uint16_t r2le(const uint16_t *x)
131{ 121{
132 return x; 122 return get_unaligned_le16(x);
133} 123}
134 124
135static uint32_t w2nat(uint16_t const x) 125static void w8be(uint64_t val, uint64_t *x)
126{
127 put_unaligned_be64(val, x);
128}
129static void wbe(uint32_t val, uint32_t *x)
130{
131 put_unaligned_be32(val, x);
132}
133static void w2be(uint16_t val, uint16_t *x)
134{
135 put_unaligned_be16(val, x);
136}
137static void w8le(uint64_t val, uint64_t *x)
138{
139 put_unaligned_le64(val, x);
140}
141static void wle(uint32_t val, uint32_t *x)
142{
143 put_unaligned_le32(val, x);
144}
145static void w2le(uint16_t val, uint16_t *x)
136{ 146{
137 return x; 147 put_unaligned_le16(val, x);
138} 148}
139 149
140static uint64_t (*w8)(uint64_t); 150static uint64_t (*r8)(const uint64_t *);
141static uint32_t (*w)(uint32_t); 151static uint32_t (*r)(const uint32_t *);
142static uint32_t (*w2)(uint16_t); 152static uint16_t (*r2)(const uint16_t *);
153static void (*w8)(uint64_t, uint64_t *);
154static void (*w)(uint32_t, uint32_t *);
155static void (*w2)(uint16_t, uint16_t *);
143 156
157typedef 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
164static 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
176static 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
151static void 202static void
152do_file(char const *const fname) 203do_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 */