in kernel/unwind.c [604:658]
static signed fde_pointer_type(const u32 *cie)
{
const u8 *ptr = (const u8 *)(cie + 2);
unsigned int version = *ptr;
if (*++ptr) {
const char *aug;
const u8 *end = (const u8 *)(cie + 1) + *cie;
uleb128_t len;
/* check if augmentation size is first (and thus present) */
if (*ptr != 'z')
return -1;
/* check if augmentation string is nul-terminated */
aug = (const void *)ptr;
ptr = memchr(aug, 0, end - ptr);
if (ptr == NULL)
return -1;
++ptr; /* skip terminator */
get_uleb128(&ptr, end); /* skip code alignment */
get_sleb128(&ptr, end); /* skip data alignment */
/* skip return address column */
version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
len = get_uleb128(&ptr, end); /* augmentation length */
if (ptr + len < ptr || ptr + len > end)
return -1;
end = ptr + len;
while (*++aug) {
if (ptr >= end)
return -1;
switch (*aug) {
case 'L':
++ptr;
break;
case 'P':{
signed ptrType = *ptr++;
if (!read_pointer(&ptr, end, ptrType)
|| ptr > end)
return -1;
}
break;
case 'R':
return *ptr;
default:
return -1;
}
}
}
return DW_EH_PE_native | DW_EH_PE_abs;
}