diff options
Diffstat (limited to 'scripts/sortextable.h')
-rw-r--r-- | scripts/sortextable.h | 79 |
1 files changed, 51 insertions, 28 deletions
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 | } |