mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-02-04 13:32:55 +01:00
(script_new): Clear abi_marker to 0.
(emit_nat_info): For registers saved in a general-register, use IA64_INSN_SET_REG instead of IA64_INSN_SET. Set insn.dst to register number, instead of unw.preg_index[i]. (compile_reg): Set val directly to register number, instead of unw.preg_index[i]. Use IA64_INSN_INC_PSP instead of IA64_INSN_ADD to pop a fixed stack frame. (build_script): Handle signal-frames by directly copying abi_marker, rather than emitting an IA64_INSN_SET instruction. (run_script): Copy abi_marker into cursor. Rather than updating a word, update a save-location. Only exceptions are IA64_INSN_INC_PSP and IA64_INSN_LOAD_PSP. (Logical change 1.84)
This commit is contained in:
parent
693c4fa30c
commit
8bf1568dbf
1 changed files with 40 additions and 43 deletions
|
@ -184,6 +184,7 @@ script_new (struct ia64_script_cache *cache, unw_word_t ip)
|
||||||
script->ip = ip;
|
script->ip = ip;
|
||||||
script->hint = 0;
|
script->hint = 0;
|
||||||
script->count = 0;
|
script->count = 0;
|
||||||
|
script->abi_marker = 0;
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,15 +220,15 @@ emit_nat_info (struct ia64_state_record *sr, int i, struct ia64_script *script)
|
||||||
switch (r->where)
|
switch (r->where)
|
||||||
{
|
{
|
||||||
case IA64_WHERE_GR:
|
case IA64_WHERE_GR:
|
||||||
val = IA64_LOC (r->val, 0);
|
opc = IA64_INSN_SET_REG;
|
||||||
|
val = r->val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_WHERE_FR:
|
case IA64_WHERE_FR:
|
||||||
val = 0; /* value doesn't matter... */
|
break; /* value doesn't matter... */
|
||||||
break;
|
|
||||||
|
|
||||||
case IA64_WHERE_BR:
|
case IA64_WHERE_BR:
|
||||||
val = IA64_LOC (0, 0); /* no NaT bit */
|
/* val==0 results in IA64_LOC_NULL, i.e., no NaT bit */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_WHERE_PSPREL:
|
case IA64_WHERE_PSPREL:
|
||||||
|
@ -241,7 +242,7 @@ emit_nat_info (struct ia64_state_record *sr, int i, struct ia64_script *script)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
insn.opc = opc;
|
insn.opc = opc;
|
||||||
insn.dst = unw.preg_index[i];
|
insn.dst = i;
|
||||||
insn.val = val;
|
insn.val = val;
|
||||||
script_emit (script, insn);
|
script_emit (script, insn);
|
||||||
}
|
}
|
||||||
|
@ -273,7 +274,7 @@ compile_reg (struct ia64_state_record *sr, int i, struct ia64_script *script)
|
||||||
}
|
}
|
||||||
else if (rval >= 4 && rval <= 7)
|
else if (rval >= 4 && rval <= 7)
|
||||||
/* register got spilled to a preserved register */
|
/* register got spilled to a preserved register */
|
||||||
val = unw.preg_index[IA64_REG_R4 + (rval - 4)];
|
val = IA64_REG_R4 + (rval - 4);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* register got spilled to a scratch register */
|
/* register got spilled to a scratch register */
|
||||||
|
@ -284,9 +285,9 @@ compile_reg (struct ia64_state_record *sr, int i, struct ia64_script *script)
|
||||||
|
|
||||||
case IA64_WHERE_FR:
|
case IA64_WHERE_FR:
|
||||||
if (rval <= 5)
|
if (rval <= 5)
|
||||||
val = unw.preg_index[IA64_REG_F2 + (rval - 1)];
|
val = IA64_REG_F2 + (rval - 1);
|
||||||
else if (rval >= 16 && rval <= 31)
|
else if (rval >= 16 && rval <= 31)
|
||||||
val = unw.preg_index[IA64_REG_F16 + (rval - 16)];
|
val = IA64_REG_F16 + (rval - 16);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
opc = IA64_INSN_MOVE_SCRATCH;
|
opc = IA64_INSN_MOVE_SCRATCH;
|
||||||
|
@ -296,7 +297,7 @@ compile_reg (struct ia64_state_record *sr, int i, struct ia64_script *script)
|
||||||
|
|
||||||
case IA64_WHERE_BR:
|
case IA64_WHERE_BR:
|
||||||
if (rval >= 1 && rval <= 5)
|
if (rval >= 1 && rval <= 5)
|
||||||
val = unw.preg_index[IA64_REG_B1 + (rval - 1)];
|
val = IA64_REG_B1 + (rval - 1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
opc = IA64_INSN_MOVE_SCRATCH;
|
opc = IA64_INSN_MOVE_SCRATCH;
|
||||||
|
@ -322,7 +323,7 @@ compile_reg (struct ia64_state_record *sr, int i, struct ia64_script *script)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
insn.opc = opc;
|
insn.opc = opc;
|
||||||
insn.dst = unw.preg_index[i];
|
insn.dst = i;
|
||||||
insn.val = val;
|
insn.val = val;
|
||||||
script_emit (script, insn);
|
script_emit (script, insn);
|
||||||
if (is_preserved_gr)
|
if (is_preserved_gr)
|
||||||
|
@ -330,11 +331,10 @@ compile_reg (struct ia64_state_record *sr, int i, struct ia64_script *script)
|
||||||
|
|
||||||
if (i == IA64_REG_PSP)
|
if (i == IA64_REG_PSP)
|
||||||
{
|
{
|
||||||
/* info->psp must contain the _value_ of the previous sp, not
|
/* c->psp must contain the _value_ of the previous sp, not it's
|
||||||
it's save location. We get this by dereferencing the value
|
save-location. We get this by dereferencing the value we
|
||||||
we just stored in info->psp: */
|
just stored in loc[IA64_REG_PSP]: */
|
||||||
insn.opc = IA64_INSN_LOAD;
|
insn.opc = IA64_INSN_LOAD_PSP;
|
||||||
insn.dst = insn.val = unw.preg_index[IA64_REG_PSP];
|
|
||||||
script_emit (script, insn);
|
script_emit (script, insn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,8 +360,7 @@ build_script (struct cursor *c, struct ia64_script *script)
|
||||||
&& sr.curr.reg[IA64_REG_PSP].val != 0)
|
&& sr.curr.reg[IA64_REG_PSP].val != 0)
|
||||||
{
|
{
|
||||||
/* new psp is psp plus frame size */
|
/* new psp is psp plus frame size */
|
||||||
insn.opc = IA64_INSN_ADD;
|
insn.opc = IA64_INSN_INC_PSP;
|
||||||
insn.dst = struct_offset (struct cursor, psp) / 8;
|
|
||||||
insn.val = sr.curr.reg[IA64_REG_PSP].val; /* frame size */
|
insn.val = sr.curr.reg[IA64_REG_PSP].val; /* frame size */
|
||||||
script_emit (script, insn);
|
script_emit (script, insn);
|
||||||
}
|
}
|
||||||
|
@ -387,14 +386,7 @@ build_script (struct cursor *c, struct ia64_script *script)
|
||||||
for (i = IA64_REG_PSP; i < IA64_NUM_PREGS; ++i)
|
for (i = IA64_REG_PSP; i < IA64_NUM_PREGS; ++i)
|
||||||
compile_reg (&sr, i, script);
|
compile_reg (&sr, i, script);
|
||||||
|
|
||||||
if (sr.is_signal_frame)
|
script->abi_marker = sr.abi_marker;
|
||||||
{
|
|
||||||
insn.opc = IA64_INSN_SET;
|
|
||||||
insn.dst = struct_offset (struct cursor, is_signal_frame) / 8;
|
|
||||||
insn.val = 1;
|
|
||||||
script_emit (script, insn);
|
|
||||||
}
|
|
||||||
|
|
||||||
script_finalize (script, c, &sr);
|
script_finalize (script, c, &sr);
|
||||||
|
|
||||||
ia64_free_state_record (&sr);
|
ia64_free_state_record (&sr);
|
||||||
|
@ -409,14 +401,16 @@ static inline int
|
||||||
run_script (struct ia64_script *script, struct cursor *c)
|
run_script (struct ia64_script *script, struct cursor *c)
|
||||||
{
|
{
|
||||||
struct ia64_script_insn *ip, *limit, next_insn;
|
struct ia64_script_insn *ip, *limit, next_insn;
|
||||||
unw_word_t val, unat_addr, *s = (unw_word_t *) c;
|
unw_word_t val, unat_addr;
|
||||||
unsigned long opc, dst;
|
unsigned long opc, dst;
|
||||||
|
ia64_loc_t loc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
c->pi = script->pi;
|
c->pi = script->pi;
|
||||||
ip = script->insn;
|
ip = script->insn;
|
||||||
limit = script->insn + script->count;
|
limit = script->insn + script->count;
|
||||||
next_insn = *ip;
|
next_insn = *ip;
|
||||||
|
c->abi_marker = script->abi_marker;
|
||||||
|
|
||||||
while (ip++ < limit)
|
while (ip++ < limit)
|
||||||
{
|
{
|
||||||
|
@ -428,49 +422,52 @@ run_script (struct ia64_script *script, struct cursor *c)
|
||||||
switch (opc)
|
switch (opc)
|
||||||
{
|
{
|
||||||
case IA64_INSN_SET:
|
case IA64_INSN_SET:
|
||||||
s[dst] = val;
|
loc = IA64_LOC_ADDR (val, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_ADD:
|
case IA64_INSN_SET_REG:
|
||||||
s[dst] += val;
|
loc = IA64_LOC_REG (val, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_ADD_PSP:
|
case IA64_INSN_ADD_PSP:
|
||||||
s[dst] = c->psp + val;
|
loc = IA64_LOC_ADDR (c->psp + val, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_ADD_SP:
|
case IA64_INSN_ADD_SP:
|
||||||
s[dst] = c->sp + val;
|
loc = IA64_LOC_ADDR (c->sp + val, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_MOVE:
|
case IA64_INSN_MOVE:
|
||||||
s[dst] = s[val];
|
loc = c->loc[val];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_MOVE_SCRATCH:
|
case IA64_INSN_MOVE_SCRATCH:
|
||||||
s[dst] = ia64_scratch_loc (c, val);
|
loc = ia64_scratch_loc (c, val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_MOVE_STACKED:
|
case IA64_INSN_MOVE_STACKED:
|
||||||
val = rotate_gr (c, val);
|
val = rotate_gr (c, val);
|
||||||
ret = ia64_get_stacked (c, val, &s[dst], NULL);
|
if ((ret = ia64_get_stacked (c, val, &loc, NULL)) < 0)
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_SETNAT_MEMSTK:
|
case IA64_INSN_SETNAT_MEMSTK:
|
||||||
ret = ia64_get (c, c->pri_unat_loc, &unat_addr);
|
if ((ret = ia64_get (c, c->loc[IA64_REG_PRI_UNAT_MEM],
|
||||||
if (ret < 0)
|
&unat_addr)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
s[dst] = IA64_LOC (unat_addr >> 3, IA64_LOC_TYPE_MEMSTK_NAT);
|
loc = IA64_LOC_ADDR (unat_addr, IA64_LOC_TYPE_MEMSTK_NAT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IA64_INSN_LOAD:
|
case IA64_INSN_INC_PSP:
|
||||||
ret = ia64_get (c, s[val], &s[dst]);
|
c->psp += val;
|
||||||
if (ret < 0)
|
continue;
|
||||||
|
|
||||||
|
case IA64_INSN_LOAD_PSP:
|
||||||
|
if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
c->loc[dst] = loc;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue