Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARC: dw2 unwind: Reinstante unwinding out of modules

The fix which removed linear searching of dwarf (because binary lookup
data always exists) missed out on the fact that modules don't get the
binary lookup tables info. This caused unwinding out of modules to stop
working.

So add binary lookup header setup (equivalent of eh_frame_hdr setup) to
modules as well.

While at it, confine the header setup to within unwinder code,
reducing one API exposed out of unwinder code.

Fixes: 2e22502c080f ARC: dw2 unwind: Remove falllback linear search thru FDE entries
Cc: <stable@vger.kernel.org>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>

+26 -19
-4
arch/arc/include/asm/unwind.h
··· 112 112 113 113 extern int arc_unwind(struct unwind_frame_info *frame); 114 114 extern void arc_unwind_init(void); 115 - extern void arc_unwind_setup(void); 116 115 extern void *unwind_add_table(struct module *module, const void *table_start, 117 116 unsigned long table_size); 118 117 extern void unwind_remove_table(void *handle, int init_only); ··· 151 152 { 152 153 } 153 154 154 - static inline void arc_unwind_setup(void) 155 - { 156 - } 157 155 #define unwind_add_table(a, b, c) 158 156 #define unwind_remove_table(a, b) 159 157
-1
arch/arc/kernel/setup.c
··· 429 429 #endif 430 430 431 431 arc_unwind_init(); 432 - arc_unwind_setup(); 433 432 } 434 433 435 434 static int __init customize_machine(void)
+26 -14
arch/arc/kernel/unwind.c
··· 170 170 171 171 static unsigned long read_pointer(const u8 **pLoc, 172 172 const void *end, signed ptrType); 173 + static void init_unwind_hdr(struct unwind_table *table, 174 + void *(*alloc) (unsigned long)); 175 + 176 + /* 177 + * wrappers for header alloc (vs. calling one vs. other at call site) 178 + * to elide section mismatches warnings 179 + */ 180 + static void *__init unw_hdr_alloc_early(unsigned long sz) 181 + { 182 + return __alloc_bootmem_nopanic(sz, sizeof(unsigned int), 183 + MAX_DMA_ADDRESS); 184 + } 185 + 186 + static void *unw_hdr_alloc(unsigned long sz) 187 + { 188 + return kmalloc(sz, GFP_KERNEL); 189 + } 173 190 174 191 static void init_unwind_table(struct unwind_table *table, const char *name, 175 192 const void *core_start, unsigned long core_size, ··· 226 209 __start_unwind, __end_unwind - __start_unwind, 227 210 NULL, 0); 228 211 /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/ 212 + 213 + init_unwind_hdr(&root_table, unw_hdr_alloc_early); 229 214 } 230 215 231 216 static const u32 bad_cie, not_fde; ··· 260 241 e2->fde = v; 261 242 } 262 243 263 - static void __init setup_unwind_table(struct unwind_table *table, 264 - void *(*alloc) (unsigned long)) 244 + static void init_unwind_hdr(struct unwind_table *table, 245 + void *(*alloc) (unsigned long)) 265 246 { 266 247 const u8 *ptr; 267 248 unsigned long tableSize = table->size, hdrSize; ··· 319 300 320 301 hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int) 321 302 + 2 * n * sizeof(unsigned long); 303 + 322 304 header = alloc(hdrSize); 323 305 if (!header) 324 306 return; 307 + 325 308 header->version = 1; 326 309 header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native; 327 310 header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4; ··· 363 342 table->header = (const void *)header; 364 343 } 365 344 366 - static void *__init balloc(unsigned long sz) 367 - { 368 - return __alloc_bootmem_nopanic(sz, 369 - sizeof(unsigned int), 370 - __pa(MAX_DMA_ADDRESS)); 371 - } 372 - 373 - void __init arc_unwind_setup(void) 374 - { 375 - setup_unwind_table(&root_table, balloc); 376 - } 377 - 378 345 #ifdef CONFIG_MODULES 379 346 380 347 static struct unwind_table *last_table; ··· 385 376 module->module_init, module->init_size, 386 377 table_start, table_size, 387 378 NULL, 0); 379 + 380 + init_unwind_hdr(table, unw_hdr_alloc); 388 381 389 382 #ifdef UNWIND_DEBUG 390 383 unw_debug("Table added for [%s] %lx %lx\n", ··· 450 439 info.init_only = init_only; 451 440 452 441 unlink_table(&info); /* XXX: SMP */ 442 + kfree(table->header); 453 443 kfree(table); 454 444 } 455 445