1a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney/* 2a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * sortextable.c: Sort the kernel's exception table 3a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * 4d59a16836d917548cf41eda3369936684d527f5fDavid Daney * Copyright 2011 - 2012 Cavium, Inc. 5a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * 6a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Based on code taken from recortmcount.c which is: 7a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * 8a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. 9a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Licensed under the GNU General Public License, version 2 (GPLv2). 10a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * 11a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Restructured to fit Linux format, as well as other updates: 12a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. 13a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney */ 14a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 15a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney/* 16a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Strategy: alter the vmlinux file in-place. 17a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney */ 18a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 19a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <sys/types.h> 20a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <sys/mman.h> 21a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <sys/stat.h> 22a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <getopt.h> 23a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <elf.h> 24a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <fcntl.h> 25a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <setjmp.h> 26a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <stdio.h> 27a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <stdlib.h> 28a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <string.h> 29a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include <unistd.h> 30a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 31d59a16836d917548cf41eda3369936684d527f5fDavid Daney#include <tools/be_byteshift.h> 32d59a16836d917548cf41eda3369936684d527f5fDavid Daney#include <tools/le_byteshift.h> 33d59a16836d917548cf41eda3369936684d527f5fDavid Daney 34f06d19e460cdd326eff955ca614cb8064bd0a5f2Vineet Gupta#ifndef EM_ARCOMPACT 35f06d19e460cdd326eff955ca614cb8064bd0a5f2Vineet Gupta#define EM_ARCOMPACT 93 36f06d19e460cdd326eff955ca614cb8064bd0a5f2Vineet Gupta#endif 37f06d19e460cdd326eff955ca614cb8064bd0a5f2Vineet Gupta 3825df8198f4b257cf6db4d4f000c53accfa9c28f8Max Filippov#ifndef EM_XTENSA 3925df8198f4b257cf6db4d4f000c53accfa9c28f8Max Filippov#define EM_XTENSA 94 4025df8198f4b257cf6db4d4f000c53accfa9c28f8Max Filippov#endif 4125df8198f4b257cf6db4d4f000c53accfa9c28f8Max Filippov 42adace89562c7a9645b8dc84f6e1ac7ba8756094eWill Deacon#ifndef EM_AARCH64 43adace89562c7a9645b8dc84f6e1ac7ba8756094eWill Deacon#define EM_AARCH64 183 44adace89562c7a9645b8dc84f6e1ac7ba8756094eWill Deacon#endif 45adace89562c7a9645b8dc84f6e1ac7ba8756094eWill Deacon 46372c7209d6a05130b9d867f7ba350dec19e54030Michal Simek#ifndef EM_MICROBLAZE 47372c7209d6a05130b9d867f7ba350dec19e54030Michal Simek#define EM_MICROBLAZE 189 48372c7209d6a05130b9d867f7ba350dec19e54030Michal Simek#endif 49372c7209d6a05130b9d867f7ba350dec19e54030Michal Simek 50a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic int fd_map; /* File descriptor for file being modified. */ 51a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic int mmap_failed; /* Boolean flag. */ 52a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ 53a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic struct stat sb; /* Remember .st_size, etc. */ 54a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */ 55a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 56a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney/* setjmp() return values */ 57a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneyenum { 58a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney SJ_SETJMP = 0, /* hardwired first return */ 59a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney SJ_FAIL, 60a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney SJ_SUCCEED 61a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney}; 62a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 63a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney/* Per-file resource cleanup when multiple files. */ 64a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic void 65a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneycleanup(void) 66a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 67a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney if (!mmap_failed) 68a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney munmap(ehdr_curr, sb.st_size); 69a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney close(fd_map); 70a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 71a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 72a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic void __attribute__((noreturn)) 73a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneyfail_file(void) 74a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 75a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney cleanup(); 76a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney longjmp(jmpenv, SJ_FAIL); 77a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 78a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 79a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney/* 80a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Get the whole file as a programming convenience in order to avoid 81a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * malloc+lseek+read+free of many pieces. If successful, then mmap 82a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * avoids copying unused pieces; else just read the whole file. 83a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney * Open for both read and write. 84a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney */ 85a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic void *mmap_file(char const *fname) 86a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 87a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney void *addr; 88a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 89a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fd_map = open(fname, O_RDWR); 90a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney if (fd_map < 0 || fstat(fd_map, &sb) < 0) { 91a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney perror(fname); 92a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 93a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 94a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney if (!S_ISREG(sb.st_mode)) { 95a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "not a regular file: %s\n", fname); 96a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 97a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 98a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, 99a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fd_map, 0); 100a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney if (addr == MAP_FAILED) { 101a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney mmap_failed = 1; 102a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "Could not mmap file: %s\n", fname); 103a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 104a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 105a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney return addr; 106a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 107a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 108d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint64_t r8be(const uint64_t *x) 109a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 110d59a16836d917548cf41eda3369936684d527f5fDavid Daney return get_unaligned_be64(x); 111a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 112d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint32_t rbe(const uint32_t *x) 113a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 114d59a16836d917548cf41eda3369936684d527f5fDavid Daney return get_unaligned_be32(x); 115a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 116d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint16_t r2be(const uint16_t *x) 117a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 118d59a16836d917548cf41eda3369936684d527f5fDavid Daney return get_unaligned_be16(x); 119a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 120d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint64_t r8le(const uint64_t *x) 121a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 122d59a16836d917548cf41eda3369936684d527f5fDavid Daney return get_unaligned_le64(x); 123a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 124d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint32_t rle(const uint32_t *x) 125d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 126d59a16836d917548cf41eda3369936684d527f5fDavid Daney return get_unaligned_le32(x); 127d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 128d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint16_t r2le(const uint16_t *x) 129a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 130d59a16836d917548cf41eda3369936684d527f5fDavid Daney return get_unaligned_le16(x); 131a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 132a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 133d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void w8be(uint64_t val, uint64_t *x) 134d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 135d59a16836d917548cf41eda3369936684d527f5fDavid Daney put_unaligned_be64(val, x); 136d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 137d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void wbe(uint32_t val, uint32_t *x) 138d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 139d59a16836d917548cf41eda3369936684d527f5fDavid Daney put_unaligned_be32(val, x); 140d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 141d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void w2be(uint16_t val, uint16_t *x) 142d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 143d59a16836d917548cf41eda3369936684d527f5fDavid Daney put_unaligned_be16(val, x); 144d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 145d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void w8le(uint64_t val, uint64_t *x) 146d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 147d59a16836d917548cf41eda3369936684d527f5fDavid Daney put_unaligned_le64(val, x); 148d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 149d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void wle(uint32_t val, uint32_t *x) 150d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 151d59a16836d917548cf41eda3369936684d527f5fDavid Daney put_unaligned_le32(val, x); 152d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 153d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void w2le(uint16_t val, uint16_t *x) 154a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 155d59a16836d917548cf41eda3369936684d527f5fDavid Daney put_unaligned_le16(val, x); 156a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 157a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 158d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint64_t (*r8)(const uint64_t *); 159d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint32_t (*r)(const uint32_t *); 160d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic uint16_t (*r2)(const uint16_t *); 161d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void (*w8)(uint64_t, uint64_t *); 162d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void (*w)(uint32_t, uint32_t *); 163d59a16836d917548cf41eda3369936684d527f5fDavid Daneystatic void (*w2)(uint16_t, uint16_t *); 164a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 165d59a16836d917548cf41eda3369936684d527f5fDavid Daneytypedef void (*table_sort_t)(char *, int); 166a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 16759c36455d061e200f386e1817362f6afd6265b6aJamie Iles/* 16859c36455d061e200f386e1817362f6afd6265b6aJamie Iles * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of 16959c36455d061e200f386e1817362f6afd6265b6aJamie Iles * the way to -256..-1, to avoid conflicting with real section 17059c36455d061e200f386e1817362f6afd6265b6aJamie Iles * indices. 17159c36455d061e200f386e1817362f6afd6265b6aJamie Iles */ 17259c36455d061e200f386e1817362f6afd6265b6aJamie Iles#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1)) 17359c36455d061e200f386e1817362f6afd6265b6aJamie Iles 17459c36455d061e200f386e1817362f6afd6265b6aJamie Ilesstatic inline int is_shndx_special(unsigned int i) 17559c36455d061e200f386e1817362f6afd6265b6aJamie Iles{ 17659c36455d061e200f386e1817362f6afd6265b6aJamie Iles return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; 17759c36455d061e200f386e1817362f6afd6265b6aJamie Iles} 17859c36455d061e200f386e1817362f6afd6265b6aJamie Iles 17959c36455d061e200f386e1817362f6afd6265b6aJamie Iles/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ 18059c36455d061e200f386e1817362f6afd6265b6aJamie Ilesstatic inline unsigned int get_secindex(unsigned int shndx, 18159c36455d061e200f386e1817362f6afd6265b6aJamie Iles unsigned int sym_offs, 18259c36455d061e200f386e1817362f6afd6265b6aJamie Iles const Elf32_Word *symtab_shndx_start) 18359c36455d061e200f386e1817362f6afd6265b6aJamie Iles{ 18459c36455d061e200f386e1817362f6afd6265b6aJamie Iles if (is_shndx_special(shndx)) 18559c36455d061e200f386e1817362f6afd6265b6aJamie Iles return SPECIAL(shndx); 18659c36455d061e200f386e1817362f6afd6265b6aJamie Iles if (shndx != SHN_XINDEX) 18759c36455d061e200f386e1817362f6afd6265b6aJamie Iles return shndx; 18859c36455d061e200f386e1817362f6afd6265b6aJamie Iles return r(&symtab_shndx_start[sym_offs]); 18959c36455d061e200f386e1817362f6afd6265b6aJamie Iles} 19059c36455d061e200f386e1817362f6afd6265b6aJamie Iles 191a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney/* 32 bit and 64 bit are very similar */ 192a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include "sortextable.h" 193a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#define SORTEXTABLE_64 194a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney#include "sortextable.h" 195a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 196eb608fb366de123a97227437e5306f731f4a63c5Heiko Carstensstatic int compare_relative_table(const void *a, const void *b) 197d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 198d59a16836d917548cf41eda3369936684d527f5fDavid Daney int32_t av = (int32_t)r(a); 199d59a16836d917548cf41eda3369936684d527f5fDavid Daney int32_t bv = (int32_t)r(b); 200d59a16836d917548cf41eda3369936684d527f5fDavid Daney 201d59a16836d917548cf41eda3369936684d527f5fDavid Daney if (av < bv) 202d59a16836d917548cf41eda3369936684d527f5fDavid Daney return -1; 203d59a16836d917548cf41eda3369936684d527f5fDavid Daney if (av > bv) 204d59a16836d917548cf41eda3369936684d527f5fDavid Daney return 1; 205d59a16836d917548cf41eda3369936684d527f5fDavid Daney return 0; 206d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 207d59a16836d917548cf41eda3369936684d527f5fDavid Daney 208eb608fb366de123a97227437e5306f731f4a63c5Heiko Carstensstatic void sort_relative_table(char *extab_image, int image_size) 209d59a16836d917548cf41eda3369936684d527f5fDavid Daney{ 210d59a16836d917548cf41eda3369936684d527f5fDavid Daney int i; 211d59a16836d917548cf41eda3369936684d527f5fDavid Daney 212d59a16836d917548cf41eda3369936684d527f5fDavid Daney /* 213d59a16836d917548cf41eda3369936684d527f5fDavid Daney * Do the same thing the runtime sort does, first normalize to 214d59a16836d917548cf41eda3369936684d527f5fDavid Daney * being relative to the start of the section. 215d59a16836d917548cf41eda3369936684d527f5fDavid Daney */ 216d59a16836d917548cf41eda3369936684d527f5fDavid Daney i = 0; 217d59a16836d917548cf41eda3369936684d527f5fDavid Daney while (i < image_size) { 218d59a16836d917548cf41eda3369936684d527f5fDavid Daney uint32_t *loc = (uint32_t *)(extab_image + i); 219d59a16836d917548cf41eda3369936684d527f5fDavid Daney w(r(loc) + i, loc); 220d59a16836d917548cf41eda3369936684d527f5fDavid Daney i += 4; 221d59a16836d917548cf41eda3369936684d527f5fDavid Daney } 222d59a16836d917548cf41eda3369936684d527f5fDavid Daney 223eb608fb366de123a97227437e5306f731f4a63c5Heiko Carstens qsort(extab_image, image_size / 8, 8, compare_relative_table); 224d59a16836d917548cf41eda3369936684d527f5fDavid Daney 225d59a16836d917548cf41eda3369936684d527f5fDavid Daney /* Now denormalize. */ 226d59a16836d917548cf41eda3369936684d527f5fDavid Daney i = 0; 227d59a16836d917548cf41eda3369936684d527f5fDavid Daney while (i < image_size) { 228d59a16836d917548cf41eda3369936684d527f5fDavid Daney uint32_t *loc = (uint32_t *)(extab_image + i); 229d59a16836d917548cf41eda3369936684d527f5fDavid Daney w(r(loc) - i, loc); 230d59a16836d917548cf41eda3369936684d527f5fDavid Daney i += 4; 231d59a16836d917548cf41eda3369936684d527f5fDavid Daney } 232d59a16836d917548cf41eda3369936684d527f5fDavid Daney} 233a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 234a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneystatic void 235a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneydo_file(char const *const fname) 236a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 237d59a16836d917548cf41eda3369936684d527f5fDavid Daney table_sort_t custom_sort; 238d59a16836d917548cf41eda3369936684d527f5fDavid Daney Elf32_Ehdr *ehdr = mmap_file(fname); 239a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 240a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney ehdr_curr = ehdr; 241a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney switch (ehdr->e_ident[EI_DATA]) { 242a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney default: 243a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", 244a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney ehdr->e_ident[EI_DATA], fname); 245a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 246a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 247a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case ELFDATA2LSB: 248d59a16836d917548cf41eda3369936684d527f5fDavid Daney r = rle; 249d59a16836d917548cf41eda3369936684d527f5fDavid Daney r2 = r2le; 250d59a16836d917548cf41eda3369936684d527f5fDavid Daney r8 = r8le; 251d59a16836d917548cf41eda3369936684d527f5fDavid Daney w = wle; 252d59a16836d917548cf41eda3369936684d527f5fDavid Daney w2 = w2le; 253d59a16836d917548cf41eda3369936684d527f5fDavid Daney w8 = w8le; 254a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 255a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case ELFDATA2MSB: 256d59a16836d917548cf41eda3369936684d527f5fDavid Daney r = rbe; 257d59a16836d917548cf41eda3369936684d527f5fDavid Daney r2 = r2be; 258d59a16836d917548cf41eda3369936684d527f5fDavid Daney r8 = r8be; 259d59a16836d917548cf41eda3369936684d527f5fDavid Daney w = wbe; 260d59a16836d917548cf41eda3369936684d527f5fDavid Daney w2 = w2be; 261d59a16836d917548cf41eda3369936684d527f5fDavid Daney w8 = w8be; 262a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 263a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } /* end switch */ 264a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 265d59a16836d917548cf41eda3369936684d527f5fDavid Daney || r2(&ehdr->e_type) != ET_EXEC 266a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { 267a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname); 268a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 269a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 270a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 271d59a16836d917548cf41eda3369936684d527f5fDavid Daney custom_sort = NULL; 272d59a16836d917548cf41eda3369936684d527f5fDavid Daney switch (r2(&ehdr->e_machine)) { 273a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney default: 274a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "unrecognized e_machine %d %s\n", 275d59a16836d917548cf41eda3369936684d527f5fDavid Daney r2(&ehdr->e_machine), fname); 276a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 277a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 278a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case EM_386: 279a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case EM_X86_64: 2803193a98dc8777815803738fdae654c6ba0feee76Heiko Carstens case EM_S390: 281eb608fb366de123a97227437e5306f731f4a63c5Heiko Carstens custom_sort = sort_relative_table; 282eb608fb366de123a97227437e5306f731f4a63c5Heiko Carstens break; 283f06d19e460cdd326eff955ca614cb8064bd0a5f2Vineet Gupta case EM_ARCOMPACT: 284ee951c630c5ce5108f8014ce1c9d738b5bbfea60Stephen Boyd case EM_ARM: 285adace89562c7a9645b8dc84f6e1ac7ba8756094eWill Deacon case EM_AARCH64: 286372c7209d6a05130b9d867f7ba350dec19e54030Michal Simek case EM_MICROBLAZE: 287d59a16836d917548cf41eda3369936684d527f5fDavid Daney case EM_MIPS: 28825df8198f4b257cf6db4d4f000c53accfa9c28f8Max Filippov case EM_XTENSA: 289a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 290a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } /* end switch */ 291a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 292a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney switch (ehdr->e_ident[EI_CLASS]) { 293a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney default: 294a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "unrecognized ELF class %d %s\n", 295a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney ehdr->e_ident[EI_CLASS], fname); 296a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 297a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 298a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case ELFCLASS32: 299d59a16836d917548cf41eda3369936684d527f5fDavid Daney if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) 300d59a16836d917548cf41eda3369936684d527f5fDavid Daney || r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { 301a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, 302a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney "unrecognized ET_EXEC file: %s\n", fname); 303a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 304a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 305d59a16836d917548cf41eda3369936684d527f5fDavid Daney do32(ehdr, fname, custom_sort); 306a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 307a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case ELFCLASS64: { 308a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; 309d59a16836d917548cf41eda3369936684d527f5fDavid Daney if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) 310d59a16836d917548cf41eda3369936684d527f5fDavid Daney || r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { 311a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, 312a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney "unrecognized ET_EXEC file: %s\n", fname); 313a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fail_file(); 314a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 315d59a16836d917548cf41eda3369936684d527f5fDavid Daney do64(ghdr, fname, custom_sort); 316a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 317a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 318a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } /* end switch */ 319a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 320a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney cleanup(); 321a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 322a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 323a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneyint 324a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daneymain(int argc, char *argv[]) 325a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney{ 326a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney int n_error = 0; /* gcc-4.3.0 false positive complaint */ 327a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney int i; 328a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 329a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney if (argc < 2) { 330a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "usage: sortextable vmlinux...\n"); 331a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney return 0; 332a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 333a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 334a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney /* Process each file in turn, allowing deep failure. */ 335a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney for (i = 1; i < argc; i++) { 336a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney char *file = argv[i]; 337a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney int const sjval = setjmp(jmpenv); 338a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney 339a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney switch (sjval) { 340a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney default: 341a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fprintf(stderr, "internal error: %s\n", file); 342a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney exit(1); 343a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 344a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case SJ_SETJMP: /* normal sequence */ 345a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney /* Avoid problems if early cleanup() */ 346a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney fd_map = -1; 347a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney ehdr_curr = NULL; 348a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney mmap_failed = 1; 349a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney do_file(file); 350a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 351a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case SJ_FAIL: /* error in do_file or below */ 352a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney ++n_error; 353a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 354a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney case SJ_SUCCEED: /* premature success */ 355a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney /* do nothing */ 356a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney break; 357a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } /* end switch */ 358a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney } 359a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney return !!n_error; 360a79f248b9b309ebb5f34ca6a8fd1eb9e18db5720David Daney} 361