aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/sortextable.h
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/sortextable.h')
-rw-r--r--scripts/sortextable.h79
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
77static int compare_extable(const void *a, const void *b) 80static 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
89static void 92static void
90do_func(Elf_Ehdr *const ehdr, char const *const fname) 93do_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}