|
@@ -170,6 +170,23 @@ static struct unwind_table *find_table(unsigned long pc)
|
|
|
|
|
|
static unsigned long read_pointer(const u8 **pLoc,
|
|
|
const void *end, signed ptrType);
|
|
|
+static void init_unwind_hdr(struct unwind_table *table,
|
|
|
+ void *(*alloc) (unsigned long));
|
|
|
+
|
|
|
+/*
|
|
|
+ * wrappers for header alloc (vs. calling one vs. other at call site)
|
|
|
+ * to elide section mismatches warnings
|
|
|
+ */
|
|
|
+static void *__init unw_hdr_alloc_early(unsigned long sz)
|
|
|
+{
|
|
|
+ return __alloc_bootmem_nopanic(sz, sizeof(unsigned int),
|
|
|
+ MAX_DMA_ADDRESS);
|
|
|
+}
|
|
|
+
|
|
|
+static void *unw_hdr_alloc(unsigned long sz)
|
|
|
+{
|
|
|
+ return kmalloc(sz, GFP_KERNEL);
|
|
|
+}
|
|
|
|
|
|
static void init_unwind_table(struct unwind_table *table, const char *name,
|
|
|
const void *core_start, unsigned long core_size,
|
|
@@ -209,6 +226,8 @@ void __init arc_unwind_init(void)
|
|
|
__start_unwind, __end_unwind - __start_unwind,
|
|
|
NULL, 0);
|
|
|
/*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
|
|
|
+
|
|
|
+ init_unwind_hdr(&root_table, unw_hdr_alloc_early);
|
|
|
}
|
|
|
|
|
|
static const u32 bad_cie, not_fde;
|
|
@@ -241,8 +260,8 @@ static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
|
|
|
e2->fde = v;
|
|
|
}
|
|
|
|
|
|
-static void __init setup_unwind_table(struct unwind_table *table,
|
|
|
- void *(*alloc) (unsigned long))
|
|
|
+static void init_unwind_hdr(struct unwind_table *table,
|
|
|
+ void *(*alloc) (unsigned long))
|
|
|
{
|
|
|
const u8 *ptr;
|
|
|
unsigned long tableSize = table->size, hdrSize;
|
|
@@ -277,10 +296,10 @@ static void __init setup_unwind_table(struct unwind_table *table,
|
|
|
if (cie == ¬_fde)
|
|
|
continue;
|
|
|
if (cie == NULL || cie == &bad_cie)
|
|
|
- return;
|
|
|
+ goto ret_err;
|
|
|
ptrType = fde_pointer_type(cie);
|
|
|
if (ptrType < 0)
|
|
|
- return;
|
|
|
+ goto ret_err;
|
|
|
|
|
|
ptr = (const u8 *)(fde + 2);
|
|
|
if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
|
|
@@ -296,13 +315,15 @@ static void __init setup_unwind_table(struct unwind_table *table,
|
|
|
}
|
|
|
|
|
|
if (tableSize || !n)
|
|
|
- return;
|
|
|
+ goto ret_err;
|
|
|
|
|
|
hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
|
|
|
+ 2 * n * sizeof(unsigned long);
|
|
|
+
|
|
|
header = alloc(hdrSize);
|
|
|
if (!header)
|
|
|
- return;
|
|
|
+ goto ret_err;
|
|
|
+
|
|
|
header->version = 1;
|
|
|
header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
|
|
|
header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
|
|
@@ -340,18 +361,10 @@ static void __init setup_unwind_table(struct unwind_table *table,
|
|
|
table->hdrsz = hdrSize;
|
|
|
smp_wmb();
|
|
|
table->header = (const void *)header;
|
|
|
-}
|
|
|
-
|
|
|
-static void *__init balloc(unsigned long sz)
|
|
|
-{
|
|
|
- return __alloc_bootmem_nopanic(sz,
|
|
|
- sizeof(unsigned int),
|
|
|
- __pa(MAX_DMA_ADDRESS));
|
|
|
-}
|
|
|
+ return;
|
|
|
|
|
|
-void __init arc_unwind_setup(void)
|
|
|
-{
|
|
|
- setup_unwind_table(&root_table, balloc);
|
|
|
+ret_err:
|
|
|
+ panic("Attention !!! Dwarf FDE parsing errors\n");;
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_MODULES
|
|
@@ -377,6 +390,8 @@ void *unwind_add_table(struct module *module, const void *table_start,
|
|
|
table_start, table_size,
|
|
|
NULL, 0);
|
|
|
|
|
|
+ init_unwind_hdr(table, unw_hdr_alloc);
|
|
|
+
|
|
|
#ifdef UNWIND_DEBUG
|
|
|
unw_debug("Table added for [%s] %lx %lx\n",
|
|
|
module->name, table->core.pc, table->core.range);
|
|
@@ -439,6 +454,7 @@ void unwind_remove_table(void *handle, int init_only)
|
|
|
info.init_only = init_only;
|
|
|
|
|
|
unlink_table(&info); /* XXX: SMP */
|
|
|
+ kfree(table->header);
|
|
|
kfree(table);
|
|
|
}
|
|
|
|
|
@@ -588,9 +604,6 @@ static signed fde_pointer_type(const u32 *cie)
|
|
|
const u8 *ptr = (const u8 *)(cie + 2);
|
|
|
unsigned version = *ptr;
|
|
|
|
|
|
- if (version != 1)
|
|
|
- return -1; /* unsupported */
|
|
|
-
|
|
|
if (*++ptr) {
|
|
|
const char *aug;
|
|
|
const u8 *end = (const u8 *)(cie + 1) + *cie;
|
|
@@ -1002,9 +1015,7 @@ int arc_unwind(struct unwind_frame_info *frame)
|
|
|
ptr = (const u8 *)(cie + 2);
|
|
|
end = (const u8 *)(cie + 1) + *cie;
|
|
|
frame->call_frame = 1;
|
|
|
- if ((state.version = *ptr) != 1)
|
|
|
- cie = NULL; /* unsupported version */
|
|
|
- else if (*++ptr) {
|
|
|
+ if (*++ptr) {
|
|
|
/* check if augmentation size is first (thus present) */
|
|
|
if (*ptr == 'z') {
|
|
|
while (++ptr < end && *ptr) {
|