ARC: dw2 unwind: Ignore CIE version !=1 gracefully instead of bailing

ARC dwarf unwinder only supports CIE version == 1
The boot time dwarf sanitizer (part of binary lookup table constructor)
would simply bail if it saw CIE version == 3, rendering unwinder with a
NULL lookup table.

It seems libgcc linked with kernel does have such entries.

With fallback linear search removed, and a NULL binary lookup table,
unwinder fails to generate any stack trace.

So allow graceful ignoring of unsupported CIE entries.

This problem was initially seen in Alexey's setup (and not mine) as he
was using buildroot built toolchain (libgcc) which doesn't get built with
CFLAGS_FOR_TARGET="-gdwarf-2 which is my default

Fixes STAR 9000985048: "kernel unwinder broken with stock tools"

Fixes: 2e22502c08 ARC: dw2 unwind: Remove falllback linear search thru FDE entries
Reported-by Alexey Brodkin <abrodkin@synopsys.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
Vineet Gupta 2015-12-16 17:17:00 +05:30
parent bc79c9a721
commit 323f41f9e7

View File

@ -293,13 +293,13 @@ static void init_unwind_hdr(struct unwind_table *table,
const u32 *cie = cie_for_fde(fde, table);
signed ptrType;
if (cie == &not_fde)
if (cie == &not_fde) /* only process FDE here */
continue;
if (cie == NULL || cie == &bad_cie)
return;
continue; /* say FDE->CIE.version != 1 */
ptrType = fde_pointer_type(cie);
if (ptrType < 0)
return;
continue;
ptr = (const u8 *)(fde + 2);
if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
@ -343,6 +343,10 @@ static void init_unwind_hdr(struct unwind_table *table,
if (fde[1] == 0xffffffff)
continue; /* this is a CIE */
if (*(u8 *)(cie + 2) != 1)
continue; /* FDE->CIE.version not supported */
ptr = (const u8 *)(fde + 2);
header->table[n].start = read_pointer(&ptr,
(const u8 *)(fde + 1) +
@ -519,7 +523,8 @@ static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
|| (*cie & (sizeof(*cie) - 1))
|| (cie[1] != 0xffffffff))
|| (cie[1] != 0xffffffff)
|| ( *(u8 *)(cie + 2) != 1)) /* version 1 supported */
return NULL; /* this is not a (valid) CIE */
return cie;
}