#include "libunwind_i.h"
-#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
-#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
-#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
+#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
+#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
+#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
-#define ARM_EXIDX_CANT_UNWIND 0x00000001
-#define ARM_EXIDX_COMPACT 0x80000000
+#define ARM_EXIDX_CANT_UNWIND 0x00000001
+#define ARM_EXIDX_COMPACT 0x80000000
-#define ARM_EXTBL_OP_FINISH 0xb0
+#define ARM_EXTBL_OP_FINISH 0xb0
enum arm_exbuf_cmd_flags {
ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
static inline int
prel31_to_addr (unw_addr_space_t as, void *arg, unw_word_t prel31,
- unw_word_t *val)
+ unw_word_t *val)
{
unw_word_t offset;
case ARM_EXIDX_CMD_FINISH:
/* Set LR to PC if not set already. */
if (DWARF_IS_NULL_LOC (c->loc[UNW_ARM_R15]))
- c->loc[UNW_ARM_R15] = c->loc[UNW_ARM_R14];
+ c->loc[UNW_ARM_R15] = c->loc[UNW_ARM_R14];
/* Set IP. */
dwarf_get (c, c->loc[UNW_ARM_R15], &c->ip);
break;
break;
case ARM_EXIDX_CMD_REG_POP:
for (i = 0; i < 16; i++)
- if (edata->data & (1 << i))
- {
- Debug (2, "pop {r%d}\n", i);
- c->loc[UNW_ARM_R0 + i] = DWARF_LOC (c->cfa, 0);
- c->cfa += 4;
- }
+ if (edata->data & (1 << i))
+ {
+ Debug (2, "pop {r%d}\n", i);
+ c->loc[UNW_ARM_R0 + i] = DWARF_LOC (c->cfa, 0);
+ c->cfa += 4;
+ }
/* Set cfa in case the SP got popped. */
if (edata->data & (1 << 13))
- dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa);
+ dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa);
break;
case ARM_EXIDX_CMD_REG_TO_SP:
assert (edata->data < 16);
case ARM_EXIDX_CMD_VFP_POP:
/* Skip VFP registers, but be sure to adjust stack */
for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
- i++)
- c->cfa += 8;
+ i++)
+ c->cfa += 8;
if (!(edata->data & ARM_EXIDX_VFP_DOUBLE))
- c->cfa += 4;
+ c->cfa += 4;
break;
case ARM_EXIDX_CMD_WREG_POP:
for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data);
- i++)
- c->cfa += 8;
+ i++)
+ c->cfa += 8;
break;
case ARM_EXIDX_CMD_WCGR_POP:
for (i = 0; i < 4; i++)
- if (edata->data & (1 << i))
- c->cfa += 4;
+ if (edata->data & (1 << i))
+ c->cfa += 4;
break;
case ARM_EXIDX_CMD_REFUSED:
case ARM_EXIDX_CMD_RESERVED:
{
uint8_t op = READ_OP ();
if ((op & 0xc0) == 0x00)
- {
- edata.cmd = ARM_EXIDX_CMD_DATA_POP;
- edata.data = (((int)op & 0x3f) << 2) + 4;
- }
+ {
+ edata.cmd = ARM_EXIDX_CMD_DATA_POP;
+ edata.data = (((int)op & 0x3f) << 2) + 4;
+ }
else if ((op & 0xc0) == 0x40)
- {
- edata.cmd = ARM_EXIDX_CMD_DATA_PUSH;
- edata.data = (((int)op & 0x3f) << 2) + 4;
- }
+ {
+ edata.cmd = ARM_EXIDX_CMD_DATA_PUSH;
+ edata.data = (((int)op & 0x3f) << 2) + 4;
+ }
else if ((op & 0xf0) == 0x80)
- {
- uint8_t op2 = READ_OP ();
- if (op == 0x80 && op2 == 0x00)
- edata.cmd = ARM_EXIDX_CMD_REFUSED;
- else
- {
- edata.cmd = ARM_EXIDX_CMD_REG_POP;
- edata.data = ((op & 0xf) << 8) | op2;
- edata.data = edata.data << 4;
- }
- }
+ {
+ uint8_t op2 = READ_OP ();
+ if (op == 0x80 && op2 == 0x00)
+ edata.cmd = ARM_EXIDX_CMD_REFUSED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_REG_POP;
+ edata.data = ((op & 0xf) << 8) | op2;
+ edata.data = edata.data << 4;
+ }
+ }
else if ((op & 0xf0) == 0x90)
- {
- if (op == 0x9d || op == 0x9f)
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
- else
- {
- edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
- edata.data = op & 0x0f;
- }
- }
+ {
+ if (op == 0x9d || op == 0x9f)
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
+ edata.data = op & 0x0f;
+ }
+ }
else if ((op & 0xf0) == 0xa0)
- {
- unsigned end = (op & 0x07);
- edata.data = (1 << (end + 1)) - 1;
- edata.data = edata.data << 4;
- if (op & 0x08)
- edata.data |= 1 << 14;
- edata.cmd = ARM_EXIDX_CMD_REG_POP;
- }
+ {
+ unsigned end = (op & 0x07);
+ edata.data = (1 << (end + 1)) - 1;
+ edata.data = edata.data << 4;
+ if (op & 0x08)
+ edata.data |= 1 << 14;
+ edata.cmd = ARM_EXIDX_CMD_REG_POP;
+ }
else if (op == ARM_EXTBL_OP_FINISH)
- {
- edata.cmd = ARM_EXIDX_CMD_FINISH;
- buf = end;
- }
+ {
+ edata.cmd = ARM_EXIDX_CMD_FINISH;
+ buf = end;
+ }
else if (op == 0xb1)
- {
- uint8_t op2 = READ_OP ();
- if (op2 == 0 || (op2 & 0xf0))
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
- else
- {
- edata.cmd = ARM_EXIDX_CMD_REG_POP;
- edata.data = op2 & 0x0f;
- }
- }
+ {
+ uint8_t op2 = READ_OP ();
+ if (op2 == 0 || (op2 & 0xf0))
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_REG_POP;
+ edata.data = op2 & 0x0f;
+ }
+ }
else if (op == 0xb2)
- {
- uint32_t offset = 0;
- uint8_t byte, shift = 0;
- do
- {
- byte = READ_OP ();
- offset |= (byte & 0x7f) << shift;
- shift += 7;
- }
- while (byte & 0x80);
- edata.data = offset * 4 + 0x204;
- edata.cmd = ARM_EXIDX_CMD_DATA_POP;
- }
+ {
+ uint32_t offset = 0;
+ uint8_t byte, shift = 0;
+ do
+ {
+ byte = READ_OP ();
+ offset |= (byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+ edata.data = offset * 4 + 0x204;
+ edata.cmd = ARM_EXIDX_CMD_DATA_POP;
+ }
else if (op == 0xb3 || op == 0xc8 || op == 0xc9)
- {
- edata.cmd = ARM_EXIDX_CMD_VFP_POP;
- edata.data = READ_OP ();
- if (op == 0xc8)
- edata.data |= ARM_EXIDX_VFP_SHIFT_16;
- if (op != 0xb3)
- edata.data |= ARM_EXIDX_VFP_DOUBLE;
- }
+ {
+ edata.cmd = ARM_EXIDX_CMD_VFP_POP;
+ edata.data = READ_OP ();
+ if (op == 0xc8)
+ edata.data |= ARM_EXIDX_VFP_SHIFT_16;
+ if (op != 0xb3)
+ edata.data |= ARM_EXIDX_VFP_DOUBLE;
+ }
else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0)
- {
- edata.cmd = ARM_EXIDX_CMD_VFP_POP;
- edata.data = 0x80 | (op & 0x07);
- if ((op & 0xf8) == 0xd0)
- edata.data |= ARM_EXIDX_VFP_DOUBLE;
- }
+ {
+ edata.cmd = ARM_EXIDX_CMD_VFP_POP;
+ edata.data = 0x80 | (op & 0x07);
+ if ((op & 0xf8) == 0xd0)
+ edata.data |= ARM_EXIDX_VFP_DOUBLE;
+ }
else if (op >= 0xc0 && op <= 0xc5)
- {
- edata.cmd = ARM_EXIDX_CMD_WREG_POP;
- edata.data = 0xa0 | (op & 0x07);
- }
+ {
+ edata.cmd = ARM_EXIDX_CMD_WREG_POP;
+ edata.data = 0xa0 | (op & 0x07);
+ }
else if (op == 0xc6)
- {
- edata.cmd = ARM_EXIDX_CMD_WREG_POP;
- edata.data = READ_OP ();
- }
+ {
+ edata.cmd = ARM_EXIDX_CMD_WREG_POP;
+ edata.data = READ_OP ();
+ }
else if (op == 0xc7)
- {
- uint8_t op2 = READ_OP ();
- if (op2 == 0 || (op2 & 0xf0))
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
- else
- {
- edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
- edata.data = op2 & 0x0f;
- }
- }
+ {
+ uint8_t op2 = READ_OP ();
+ if (op2 == 0 || (op2 & 0xf0))
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
+ else
+ {
+ edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
+ edata.data = op2 & 0x0f;
+ }
+ }
else
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
+ edata.cmd = ARM_EXIDX_CMD_RESERVED;
ret = arm_exidx_apply_cmd (&edata, c);
if (ret < 0)
- return ret;
+ return ret;
}
return 0;
}
* if set to 0x1: the function cannot be unwound (EXIDX_CANTUNWIND)
* if bit 31 is one: this is a table entry itself (ARM_EXIDX_COMPACT)
* if bit 31 is zero: this is a prel31 offset of the start of the
- table entry for this function */
+ table entry for this function */
if (prel31_to_addr(c->as, c->as_arg, entry, &addr) < 0)
return -UNW_EINVAL;
else if (data & ARM_EXIDX_COMPACT)
{
Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr,
- (data >> 24) & 0x7f, data);
+ (data >> 24) & 0x7f, data);
buf[nbuf++] = data >> 16;
buf[nbuf++] = data >> 8;
buf[nbuf++] = data;
return -UNW_EINVAL;
if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, c->as_arg) < 0)
- return -UNW_EINVAL;
+ return -UNW_EINVAL;
if (data & ARM_EXIDX_COMPACT)
- {
- int pers = (data >> 24) & 0x0f;
- Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, pers, data);
- if (pers == 1 || pers == 2)
- {
- n_table_words = (data >> 16) & 0xff;
- extbl_data += 4;
- }
- else
- buf[nbuf++] = data >> 16;
- buf[nbuf++] = data >> 8;
- buf[nbuf++] = data;
- }
+ {
+ int pers = (data >> 24) & 0x0f;
+ Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, pers, data);
+ if (pers == 1 || pers == 2)
+ {
+ n_table_words = (data >> 16) & 0xff;
+ extbl_data += 4;
+ }
+ else
+ buf[nbuf++] = data >> 16;
+ buf[nbuf++] = data >> 8;
+ buf[nbuf++] = data;
+ }
else
- {
- unw_word_t pers;
- if (prel31_to_addr (c->as, c->as_arg, extbl_data, &pers) < 0)
- return -UNW_EINVAL;
- Debug (2, "%p Personality routine: %8p\n", (void *)addr,
- (void *)pers);
- if ((*c->as->acc.access_mem)(c->as, extbl_data + 4, &data, 0,
- c->as_arg) < 0)
- return -UNW_EINVAL;
- n_table_words = data >> 24;
- buf[nbuf++] = data >> 16;
- buf[nbuf++] = data >> 8;
- buf[nbuf++] = data;
- extbl_data += 8;
- }
+ {
+ unw_word_t pers;
+ if (prel31_to_addr (c->as, c->as_arg, extbl_data, &pers) < 0)
+ return -UNW_EINVAL;
+ Debug (2, "%p Personality routine: %8p\n", (void *)addr,
+ (void *)pers);
+ if ((*c->as->acc.access_mem)(c->as, extbl_data + 4, &data, 0,
+ c->as_arg) < 0)
+ return -UNW_EINVAL;
+ n_table_words = data >> 24;
+ buf[nbuf++] = data >> 16;
+ buf[nbuf++] = data >> 8;
+ buf[nbuf++] = data;
+ extbl_data += 8;
+ }
assert (n_table_words <= 5);
unsigned j;
for (j = 0; j < n_table_words; j++)
- {
- if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0,
- c->as_arg) < 0)
- return -UNW_EINVAL;
- extbl_data += 4;
- buf[nbuf++] = data >> 24;
- buf[nbuf++] = data >> 16;
- buf[nbuf++] = data >> 8;
- buf[nbuf++] = data >> 0;
- }
+ {
+ if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0,
+ c->as_arg) < 0)
+ return -UNW_EINVAL;
+ extbl_data += 4;
+ buf[nbuf++] = data >> 24;
+ buf[nbuf++] = data >> 16;
+ buf[nbuf++] = data >> 8;
+ buf[nbuf++] = data >> 0;
+ }
}
if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH)
PROTECTED int
tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
- unw_dyn_info_t *di, unw_proc_info_t *pi,
- int need_unwind_info, void *arg)
+ unw_dyn_info_t *di, unw_proc_info_t *pi,
+ int need_unwind_info, void *arg)
{
if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)
&& di->format == UNW_INFO_FORMAT_ARM_EXIDX)
{
/* The .ARM.exidx section contains a sorted list of key-value pairs -
- the unwind entries. The 'key' is a prel31 offset to the start of a
- function. We binary search this section in order to find the
- appropriate unwind entry. */
+ the unwind entries. The 'key' is a prel31 offset to the start of a
+ function. We binary search this section in order to find the
+ appropriate unwind entry. */
unw_word_t first = di->u.rti.table_data;
unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8;
unw_word_t entry, val;
if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val)
- return -UNW_ENOINFO;
+ return -UNW_ENOINFO;
if (prel31_to_addr (as, arg, last, &val) < 0)
- return -UNW_EINVAL;
+ return -UNW_EINVAL;
if (ip >= val)
- {
- entry = last;
+ {
+ entry = last;
- if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
- return -UNW_EINVAL;
+ if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0)
+ return -UNW_EINVAL;
- pi->end_ip = di->end_ip -1;
- }
+ pi->end_ip = di->end_ip -1;
+ }
else
- {
- while (first < last - 8)
- {
- entry = first + (((last - first) / 8 + 1) >> 1) * 8;
+ {
+ while (first < last - 8)
+ {
+ entry = first + (((last - first) / 8 + 1) >> 1) * 8;
- if (prel31_to_addr (as, arg, entry, &val) < 0)
- return -UNW_EINVAL;
+ if (prel31_to_addr (as, arg, entry, &val) < 0)
+ return -UNW_EINVAL;
- if (ip < val)
- last = entry;
- else
- first = entry;
- }
+ if (ip < val)
+ last = entry;
+ else
+ first = entry;
+ }
- entry = first;
+ entry = first;
- if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
- return -UNW_EINVAL;
+ if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0)
+ return -UNW_EINVAL;
- if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
- return -UNW_EINVAL;
+ if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0)
+ return -UNW_EINVAL;
- pi->end_ip--;
- }
+ pi->end_ip--;
+ }
if (need_unwind_info)
- {
- pi->unwind_info_size = 8;
- pi->unwind_info = (void *) entry;
- pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
- }
+ {
+ pi->unwind_info_size = 8;
+ pi->unwind_info = (void *) entry;
+ pi->format = UNW_INFO_FORMAT_ARM_EXIDX;
+ }
return 0;
}
else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)
- && di->format != UNW_INFO_FORMAT_ARM_EXIDX)
+ && di->format != UNW_INFO_FORMAT_ARM_EXIDX)
return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg);
return -UNW_ENOINFO;
for (n = info->dlpi_phnum; --n >= 0; phdr++)
{
switch (phdr->p_type)
- {
- case PT_LOAD:
- if (cb_data->ip >= phdr->p_vaddr + info->dlpi_addr &&
- cb_data->ip < phdr->p_vaddr + info->dlpi_addr + phdr->p_memsz)
- p_text = phdr;
- break;
-
- case PT_ARM_EXIDX:
- p_arm_exidx = phdr;
- break;
-
- default:
- break;
- }
+ {
+ case PT_LOAD:
+ if (cb_data->ip >= phdr->p_vaddr + info->dlpi_addr &&
+ cb_data->ip < phdr->p_vaddr + info->dlpi_addr + phdr->p_memsz)
+ p_text = phdr;
+ break;
+
+ case PT_ARM_EXIDX:
+ p_arm_exidx = phdr;
+ break;
+
+ default:
+ break;
+ }
}
if (p_text && p_arm_exidx)
HIDDEN int
arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
- unw_proc_info_t *pi, int need_unwind_info, void *arg)
+ unw_proc_info_t *pi, int need_unwind_info, void *arg)
{
int ret = -1;
intrmask_t saved_mask;
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (cb_data.single_fde)
- /* already got the result in *pi */
- return 0;
+ /* already got the result in *pi */
+ return 0;
if (cb_data.di_debug.format != -1)
- ret = tdep_search_unwind_table (as, ip, &cb_data.di_debug, pi,
- need_unwind_info, arg);
+ ret = tdep_search_unwind_table (as, ip, &cb_data.di_debug, pi,
+ need_unwind_info, arg);
else
- ret = -UNW_ENOINFO;
+ ret = -UNW_ENOINFO;
}
if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
if (cb_data.di.format != -1)
- ret = tdep_search_unwind_table (as, ip, &cb_data.di, pi,
- need_unwind_info, arg);
+ ret = tdep_search_unwind_table (as, ip, &cb_data.di, pi,
+ need_unwind_info, arg);
else
- ret = -UNW_ENOINFO;
+ ret = -UNW_ENOINFO;
}
if (ret < 0)