diff options
Diffstat (limited to 'scripts/sortextable.c')
| -rw-r--r-- | scripts/sortextable.c | 171 | 
1 files changed, 111 insertions, 60 deletions
diff --git a/scripts/sortextable.c b/scripts/sortextable.c index f51f1d43da6..1ca9ceb95eb 100644 --- a/scripts/sortextable.c +++ b/scripts/sortextable.c @@ -1,7 +1,7 @@  /*   * sortextable.c: Sort the kernel's exception table   * - * Copyright 2011 Cavium, Inc. + * Copyright 2011 - 2012 Cavium, Inc.   *   * Based on code taken from recortmcount.c which is:   * @@ -28,6 +28,9 @@  #include <string.h>  #include <unistd.h> +#include <tools/be_byteshift.h> +#include <tools/le_byteshift.h> +  static int fd_map;	/* File descriptor for file being modified. */  static int mmap_failed; /* Boolean flag. */  static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */ @@ -94,109 +97,157 @@ static void *mmap_file(char const *fname)  	return addr;  } -/* w8rev, w8nat, ...: Handle endianness. */ - -static uint64_t w8rev(uint64_t const x) +static uint64_t r8be(const uint64_t *x)  { -	return   ((0xff & (x >> (0 * 8))) << (7 * 8)) -	       | ((0xff & (x >> (1 * 8))) << (6 * 8)) -	       | ((0xff & (x >> (2 * 8))) << (5 * 8)) -	       | ((0xff & (x >> (3 * 8))) << (4 * 8)) -	       | ((0xff & (x >> (4 * 8))) << (3 * 8)) -	       | ((0xff & (x >> (5 * 8))) << (2 * 8)) -	       | ((0xff & (x >> (6 * 8))) << (1 * 8)) -	       | ((0xff & (x >> (7 * 8))) << (0 * 8)); +	return get_unaligned_be64(x);  } - -static uint32_t w4rev(uint32_t const x) +static uint32_t rbe(const uint32_t *x)  { -	return   ((0xff & (x >> (0 * 8))) << (3 * 8)) -	       | ((0xff & (x >> (1 * 8))) << (2 * 8)) -	       | ((0xff & (x >> (2 * 8))) << (1 * 8)) -	       | ((0xff & (x >> (3 * 8))) << (0 * 8)); +	return get_unaligned_be32(x);  } - -static uint32_t w2rev(uint16_t const x) +static uint16_t r2be(const uint16_t *x)  { -	return   ((0xff & (x >> (0 * 8))) << (1 * 8)) -	       | ((0xff & (x >> (1 * 8))) << (0 * 8)); +	return get_unaligned_be16(x);  } - -static uint64_t w8nat(uint64_t const x) +static uint64_t r8le(const uint64_t *x)  { -	return x; +	return get_unaligned_le64(x);  } - -static uint32_t w4nat(uint32_t const x) +static uint32_t rle(const uint32_t *x) +{ +	return get_unaligned_le32(x); +} +static uint16_t r2le(const uint16_t *x)  { -	return x; +	return get_unaligned_le16(x);  } -static uint32_t w2nat(uint16_t const x) +static void w8be(uint64_t val, uint64_t *x) +{ +	put_unaligned_be64(val, x); +} +static void wbe(uint32_t val, uint32_t *x) +{ +	put_unaligned_be32(val, x); +} +static void w2be(uint16_t val, uint16_t *x) +{ +	put_unaligned_be16(val, x); +} +static void w8le(uint64_t val, uint64_t *x) +{ +	put_unaligned_le64(val, x); +} +static void wle(uint32_t val, uint32_t *x) +{ +	put_unaligned_le32(val, x); +} +static void w2le(uint16_t val, uint16_t *x)  { -	return x; +	put_unaligned_le16(val, x);  } -static uint64_t (*w8)(uint64_t); -static uint32_t (*w)(uint32_t); -static uint32_t (*w2)(uint16_t); +static uint64_t (*r8)(const uint64_t *); +static uint32_t (*r)(const uint32_t *); +static uint16_t (*r2)(const uint16_t *); +static void (*w8)(uint64_t, uint64_t *); +static void (*w)(uint32_t, uint32_t *); +static void (*w2)(uint16_t, uint16_t *); +typedef void (*table_sort_t)(char *, int);  /* 32 bit and 64 bit are very similar */  #include "sortextable.h"  #define SORTEXTABLE_64  #include "sortextable.h" +static int compare_x86_table(const void *a, const void *b) +{ +	int32_t av = (int32_t)r(a); +	int32_t bv = (int32_t)r(b); + +	if (av < bv) +		return -1; +	if (av > bv) +		return 1; +	return 0; +} + +static void sort_x86_table(char *extab_image, int image_size) +{ +	int i; + +	/* +	 * Do the same thing the runtime sort does, first normalize to +	 * being relative to the start of the section. +	 */ +	i = 0; +	while (i < image_size) { +		uint32_t *loc = (uint32_t *)(extab_image + i); +		w(r(loc) + i, loc); +		i += 4; +	} + +	qsort(extab_image, image_size / 8, 8, compare_x86_table); + +	/* Now denormalize. */ +	i = 0; +	while (i < image_size) { +		uint32_t *loc = (uint32_t *)(extab_image + i); +		w(r(loc) - i, loc); +		i += 4; +	} +}  static void  do_file(char const *const fname)  { -	Elf32_Ehdr *const ehdr = mmap_file(fname); +	table_sort_t custom_sort; +	Elf32_Ehdr *ehdr = mmap_file(fname);  	ehdr_curr = ehdr; -	w = w4nat; -	w2 = w2nat; -	w8 = w8nat;  	switch (ehdr->e_ident[EI_DATA]) { -		static unsigned int const endian = 1;  	default:  		fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",  			ehdr->e_ident[EI_DATA], fname);  		fail_file();  		break;  	case ELFDATA2LSB: -		if (*(unsigned char const *)&endian != 1) { -			/* main() is big endian, file.o is little endian. */ -			w = w4rev; -			w2 = w2rev; -			w8 = w8rev; -		} +		r = rle; +		r2 = r2le; +		r8 = r8le; +		w = wle; +		w2 = w2le; +		w8 = w8le;  		break;  	case ELFDATA2MSB: -		if (*(unsigned char const *)&endian != 0) { -			/* main() is little endian, file.o is big endian. */ -			w = w4rev; -			w2 = w2rev; -			w8 = w8rev; -		} +		r = rbe; +		r2 = r2be; +		r8 = r8be; +		w = wbe; +		w2 = w2be; +		w8 = w8be;  		break;  	}  /* end switch */  	if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 -	||  w2(ehdr->e_type) != ET_EXEC +	||  r2(&ehdr->e_type) != ET_EXEC  	||  ehdr->e_ident[EI_VERSION] != EV_CURRENT) {  		fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname);  		fail_file();  	} -	switch (w2(ehdr->e_machine)) { +	custom_sort = NULL; +	switch (r2(&ehdr->e_machine)) {  	default:  		fprintf(stderr, "unrecognized e_machine %d %s\n", -			w2(ehdr->e_machine), fname); +			r2(&ehdr->e_machine), fname);  		fail_file();  		break;  	case EM_386: -	case EM_MIPS:  	case EM_X86_64: +		custom_sort = sort_x86_table; +		break; +	case EM_MIPS:  		break;  	}  /* end switch */ @@ -207,23 +258,23 @@ do_file(char const *const fname)  		fail_file();  		break;  	case ELFCLASS32: -		if (w2(ehdr->e_ehsize) != sizeof(Elf32_Ehdr) -		||  w2(ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { +		if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) +		||  r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) {  			fprintf(stderr,  				"unrecognized ET_EXEC file: %s\n", fname);  			fail_file();  		} -		do32(ehdr, fname); +		do32(ehdr, fname, custom_sort);  		break;  	case ELFCLASS64: {  		Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; -		if (w2(ghdr->e_ehsize) != sizeof(Elf64_Ehdr) -		||  w2(ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { +		if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) +		||  r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) {  			fprintf(stderr,  				"unrecognized ET_EXEC file: %s\n", fname);  			fail_file();  		} -		do64(ghdr, fname); +		do64(ghdr, fname, custom_sort);  		break;  	}  	}  /* end switch */  |