16daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang/* libunwind - a platform-independent unwind library
26daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang   Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
36daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
46daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
56daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangThis file is part of libunwind.
66daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
76daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangPermission is hereby granted, free of charge, to any person obtaining
86daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tanga copy of this software and associated documentation files (the
96daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang"Software"), to deal in the Software without restriction, including
106daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangwithout limitation the rights to use, copy, modify, merge, publish,
116daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangdistribute, sublicense, and/or sell copies of the Software, and to
126daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangpermit persons to whom the Software is furnished to do so, subject to
136daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangthe following conditions:
146daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
156daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangThe above copyright notice and this permission notice shall be
166daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangincluded in all copies or substantial portions of the Software.
176daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
186daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
196daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
206daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
216daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
226daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
236daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
246daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
256daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
266daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#include <stdlib.h>
276daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
286daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#include "unwind_i.h"
296daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
306daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#ifndef UNW_REMOTE_ONLY
316daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
326daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#if defined(__linux)
336daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
346daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang# include <sys/syscall.h>
356daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
366daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangstatic NORETURN inline long
376daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangmy_rt_sigreturn (void *new_sp, int in_syscall)
386daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang{
396daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  register unsigned long r25 __asm__ ("r25") = (in_syscall != 0);
406daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  register unsigned long r20 __asm__ ("r20") = SYS_rt_sigreturn;
416daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
426daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  __asm__ __volatile__ ("copy %0, %%sp\n"
436daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang			"be,l 0x100(%%sr2,%%r0),%%sr0,%%r31\n"
446daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang			"nop"
456daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang			:
466daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang			: "r"(new_sp), "r"(r20), "r"(r25)
476daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang			: "memory");
486daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  abort ();
496daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang}
506daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
516daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#endif /* __linux */
526daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
536daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangHIDDEN inline int
546daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tanghppa_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
556daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang{
566daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#if defined(__linux)
576daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  struct cursor *c = (struct cursor *) cursor;
586daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  ucontext_t *uc = c->dwarf.as_arg;
596daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
606daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  /* Ensure c->pi is up-to-date.  On PA-RISC, it's relatively common to be
616daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang     missing DWARF unwind info.  We don't want to fail in that case,
626daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang     because the frame-chain still would let us do a backtrace at
636daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang     least.  */
646daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  dwarf_make_proc_info (&c->dwarf);
656daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
666daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  if (unlikely (c->sigcontext_format != HPPA_SCF_NONE))
676daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    {
686daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
696daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
706daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc);
716daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      my_rt_sigreturn (sc, (sc->sc_flags & PARISC_SC_FLAG_IN_SYSCALL) != 0);
726daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    }
736daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  else
746daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    {
756daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip);
766daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      setcontext (uc);
776daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    }
786daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#else
796daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang# warning Implement me!
806daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#endif
816daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  return -UNW_EINVAL;
826daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang}
836daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
846daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang#endif /* !UNW_REMOTE_ONLY */
856daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
866daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang/* This routine is responsible for copying the register values in
876daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang   cursor C and establishing them as the current machine state. */
886daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
896daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangstatic inline int
906daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangestablish_machine_state (struct cursor *c)
916daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang{
926daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *,
936daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang		     int write, void *);
946daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *,
956daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang		       int write, void *);
966daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  unw_addr_space_t as = c->dwarf.as;
976daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  void *arg = c->dwarf.as_arg;
986daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  unw_fpreg_t fpval;
996daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  unw_word_t val;
1006daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  int reg;
1016daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1026daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  access_reg = as->acc.access_reg;
1036daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  access_fpreg = as->acc.access_fpreg;
1046daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1056daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  Debug (8, "copying out cursor state\n");
1066daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1076daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  for (reg = 0; reg <= UNW_REG_LAST; ++reg)
1086daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    {
1096daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      Debug (16, "copying %s %d\n", unw_regname (reg), reg);
1106daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      if (unw_is_fpreg (reg))
1116daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	{
1126daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	  if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
1136daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	    (*access_fpreg) (as, reg, &fpval, 1, arg);
1146daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	}
1156daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      else
1166daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	{
1176daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	  if (tdep_access_reg (c, reg, &val, 0) >= 0)
1186daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	    (*access_reg) (as, reg, &val, 1, arg);
1196daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang	}
1206daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    }
1216daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  return 0;
1226daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang}
1236daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1246daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-TangPROTECTED int
1256daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tangunw_resume (unw_cursor_t *cursor)
1266daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang{
1276daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  struct cursor *c = (struct cursor *) cursor;
1286daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  int ret;
1296daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1306daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  Debug (1, "(cursor=%p)\n", c);
1316daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1326daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  if (!c->dwarf.ip)
1336daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    {
1346daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      /* This can happen easily when the frame-chain gets truncated
1356daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang         due to bad or missing unwind-info.  */
1366daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      Debug (1, "refusing to resume execution at address 0\n");
1376daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang      return -UNW_EINVAL;
1386daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    }
1396daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1406daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  if ((ret = establish_machine_state (c)) < 0)
1416daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang    return ret;
1426daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang
1436daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang  return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
1446daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang				     c->dwarf.as_arg);
1456daeeac60ac046af9487dadd5a6b38fce0ea8219David Mosberger-Tang}
146