18d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala/* libunwind - a platform-independent unwind library
28d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala   Copyright (C) 2008 CodeSourcery
38d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala   Copyright 2011 Linaro Limited
48d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala   Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
58d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
68d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaThis file is part of libunwind.
78d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
88d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaPermission is hereby granted, free of charge, to any person obtaining
98d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalaa copy of this software and associated documentation files (the
108d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala"Software"), to deal in the Software without restriction, including
118d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalawithout limitation the rights to use, copy, modify, merge, publish,
128d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantaladistribute, sublicense, and/or sell copies of the Software, and to
138d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalapermit persons to whom the Software is furnished to do so, subject to
148d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalathe following conditions:
158d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
168d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaThe above copyright notice and this permission notice shall be
178d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalaincluded in all copies or substantial portions of the Software.
188d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
198d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
208d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
218d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
228d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
238d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
248d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
258d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
268d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
278d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala#include "unwind_i.h"
288d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala#include "offsets.h"
298d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
308d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala#ifndef UNW_REMOTE_ONLY
318d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
328d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaHIDDEN inline int
338d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalash_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
348d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala{
358d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala#ifdef __linux__
368d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  struct cursor *c = (struct cursor *) cursor;
378d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  unw_tdep_context_t *uc = c->dwarf.as_arg;
388d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
398d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  if (c->sigcontext_format == SH_SCF_NONE)
408d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala    {
418d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      /* Since there are no signals involved here we restore the non scratch
428d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	 registers only.  */
438d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      unsigned long regs[8];
448d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[0] = uc->uc_mcontext.gregs[8];
458d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[1] = uc->uc_mcontext.gregs[9];
468d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[2] = uc->uc_mcontext.gregs[10];
478d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[3] = uc->uc_mcontext.gregs[11];
488d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[4] = uc->uc_mcontext.gregs[12];
498d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[5] = uc->uc_mcontext.gregs[13];
508d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[6] = uc->uc_mcontext.gregs[14];
518d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      regs[7] = uc->uc_mcontext.gregs[15];
528d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      unsigned long pc = uc->uc_mcontext.pr;
538d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
548d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      struct regs_overlay {
558d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	char x[sizeof(regs)];
568d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      };
578d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
588d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      asm volatile (
598d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0+, r8\n"
608d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0+, r9\n"
618d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0+, r10\n"
628d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0+, r11\n"
638d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0+, r12\n"
648d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0+, r13\n"
658d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0+, r14\n"
668d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov.l @%0,  r15\n"
678d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"lds %1, pr\n"
688d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"rts\n"
698d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"nop\n"
708d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	:
718d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	: "r" (regs),
728d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	  "r" (pc),
738d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	  "m" (*(struct regs_overlay *)regs)
748d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      );
758d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala    }
768d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  else
778d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala    {
788d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      /* In case a signal frame is involved, we're using its trampoline which
798d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	 calls sigreturn.  */
808d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
818d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[0] = uc->uc_mcontext.gregs[0];
828d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[1] = uc->uc_mcontext.gregs[1];
838d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[2] = uc->uc_mcontext.gregs[2];
848d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[3] = uc->uc_mcontext.gregs[3];
858d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[4] = uc->uc_mcontext.gregs[4];
868d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[5] = uc->uc_mcontext.gregs[5];
878d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[6] = uc->uc_mcontext.gregs[6];
888d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[7] = uc->uc_mcontext.gregs[7];
898d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[8] = uc->uc_mcontext.gregs[8];
908d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[9] = uc->uc_mcontext.gregs[9];
918d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[10] = uc->uc_mcontext.gregs[10];
928d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[11] = uc->uc_mcontext.gregs[11];
938d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[12] = uc->uc_mcontext.gregs[12];
948d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[13] = uc->uc_mcontext.gregs[13];
958d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[14] = uc->uc_mcontext.gregs[14];
968d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_regs[15] = uc->uc_mcontext.gregs[15];
978d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_pc = uc->uc_mcontext.pc;
988d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      sc->sc_pr = uc->uc_mcontext.pr;
998d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1008d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      /* Set the SP and the PC in order to continue execution at the modified
1018d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	 trampoline which restores the signal mask and the registers.  */
1028d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      asm __volatile__ (
1038d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"mov %0, r15\n"
1048d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"lds %1, pr\n"
1058d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"rts\n"
1068d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	"nop\n"
1078d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	:
1088d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	: "r" (c->sigcontext_sp),
1098d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	  "r" (c->sigcontext_pc)
1108d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      );
1118d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala   }
11210b064ffe902d5af31bb49bd8e4f03c545f8d462Ladislav Michl  unreachable();
1138d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala#endif
1148d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  return -UNW_EINVAL;
1158d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala}
1168d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1178d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala#endif /* !UNW_REMOTE_ONLY */
1188d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1198d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalastatic inline void
1208d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalaestablish_machine_state (struct cursor *c)
1218d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala{
1228d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  unw_addr_space_t as = c->dwarf.as;
1238d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  void *arg = c->dwarf.as_arg;
1248d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  unw_fpreg_t fpval;
1258d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  unw_word_t val;
1268d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  int reg;
1278d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1288d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  Debug (8, "copying out cursor state\n");
1298d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1308d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  for (reg = 0; reg <= UNW_REG_LAST; ++reg)
1318d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala    {
1328d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      Debug (16, "copying %s %d\n", unw_regname (reg), reg);
1338d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      if (unw_is_fpreg (reg))
1348d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	{
1358d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	  if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
1368d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	    as->acc.access_fpreg (as, reg, &fpval, 1, arg);
1378d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	}
1388d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      else
1398d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	{
1408d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	  if (tdep_access_reg (c, reg, &val, 0) >= 0)
1418d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	    as->acc.access_reg (as, reg, &val, 1, arg);
1428d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	}
1438d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala    }
1448d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala}
1458d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1468d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi RantalaPROTECTED int
1478d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantalaunw_resume (unw_cursor_t *cursor)
1488d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala{
1498d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  struct cursor *c = (struct cursor *) cursor;
1508d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1518d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  Debug (1, "(cursor=%p)\n", c);
1528d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1538d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  if (!c->dwarf.ip)
1548d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala    {
1558d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      /* This can happen easily when the frame-chain gets truncated
1568d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala	 due to bad or missing unwind-info.  */
1578d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      Debug (1, "refusing to resume execution at address 0\n");
1588d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala      return -UNW_EINVAL;
1598d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala    }
1608d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1618d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  establish_machine_state (c);
1628d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala
1638d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala  return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
1648d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala				     c->dwarf.as_arg);
1658d5b1aeeffb80515197fd7aeee0b3fbfac904ecdTommi Rantala}
166