1ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux/* libunwind - a platform-independent unwind library
2ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   Copyright (C) 2008 CodeSourcery
3ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   Copyright (C) 2011-2013 Linaro Limited
4ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
5ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
6ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxThis file is part of libunwind.
7ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
8ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxPermission is hereby granted, free of charge, to any person obtaining
9ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxa copy of this software and associated documentation files (the
10ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux"Software"), to deal in the Software without restriction, including
11ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxwithout limitation the rights to use, copy, modify, merge, publish,
12ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxdistribute, sublicense, and/or sell copies of the Software, and to
13ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxpermit persons to whom the Software is furnished to do so, subject to
14ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxthe following conditions:
15ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
16ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxThe above copyright notice and this permission notice shall be
17ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxincluded in all copies or substantial portions of the Software.
18ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
19ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
26ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
27ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include "unwind_i.h"
28ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#include "offsets.h"
29ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
30ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#ifndef UNW_REMOTE_ONLY
31ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
32ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxHIDDEN inline int
33ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxaarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
34ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
35ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#ifdef __linux__
36ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  struct cursor *c = (struct cursor *) cursor;
37ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  unw_tdep_context_t *uc = c->dwarf.as_arg;
38ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
39ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (c->sigcontext_format == AARCH64_SCF_NONE)
40ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    {
41ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      /* Since there are no signals involved here we restore the non scratch
42ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	 registers only.  */
43ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      unsigned long regs[11];
44ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[0] = uc->uc_mcontext.regs[19];
45ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[1] = uc->uc_mcontext.regs[20];
46ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[2] = uc->uc_mcontext.regs[21];
47ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[3] = uc->uc_mcontext.regs[22];
48ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[4] = uc->uc_mcontext.regs[23];
49ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[5] = uc->uc_mcontext.regs[24];
50ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[6] = uc->uc_mcontext.regs[25];
51ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[7] = uc->uc_mcontext.regs[26];
52ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[8] = uc->uc_mcontext.regs[27];
53ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[9] = uc->uc_mcontext.regs[28];
54ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      regs[10] = uc->uc_mcontext.regs[30]; /* LR */
55ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      unsigned long sp = uc->uc_mcontext.sp;
56ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
57ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      struct regs_overlay {
58ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        char x[sizeof(regs)];
59ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      };
60ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
61ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      asm volatile (
62ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ldp x19, x20, [%0]\n"
63ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ldp x21, x22, [%0,16]\n"
64ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ldp x23, x24, [%0,32]\n"
65ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ldp x25, x26, [%0,48]\n"
66ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ldp x27, x28, [%0,64]\n"
67ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ldr x30, [%0,80]\n"
68ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "mov sp, %1\n"
69ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ret \n"
70ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        :
71ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        : "r" (regs),
72ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux          "r" (sp),
73ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux          "m" (*(struct regs_overlay *)regs)
74ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      );
75ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    }
76ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  else
77ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    {
78ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr;
79ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
80ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      if (c->dwarf.eh_valid_mask & 0x1) sc->regs[0] = c->dwarf.eh_args[0];
81ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      if (c->dwarf.eh_valid_mask & 0x2) sc->regs[1] = c->dwarf.eh_args[1];
82ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      if (c->dwarf.eh_valid_mask & 0x4) sc->regs[2] = c->dwarf.eh_args[2];
83ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      if (c->dwarf.eh_valid_mask & 0x8) sc->regs[3] = c->dwarf.eh_args[3];
84ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
85ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[4] = uc->uc_mcontext.regs[4];
86ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[5] = uc->uc_mcontext.regs[5];
87ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[6] = uc->uc_mcontext.regs[6];
88ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[7] = uc->uc_mcontext.regs[7];
89ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[8] = uc->uc_mcontext.regs[8];
90ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[9] = uc->uc_mcontext.regs[9];
91ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[10] = uc->uc_mcontext.regs[10];
92ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[11] = uc->uc_mcontext.regs[11];
93ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[12] = uc->uc_mcontext.regs[12];
94ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[13] = uc->uc_mcontext.regs[13];
95ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[14] = uc->uc_mcontext.regs[14];
96ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[15] = uc->uc_mcontext.regs[15];
97ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[16] = uc->uc_mcontext.regs[16];
98ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[17] = uc->uc_mcontext.regs[17];
99ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[18] = uc->uc_mcontext.regs[18];
100ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[19] = uc->uc_mcontext.regs[19];
101ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[20] = uc->uc_mcontext.regs[20];
102ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[21] = uc->uc_mcontext.regs[21];
103ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[22] = uc->uc_mcontext.regs[22];
104ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[23] = uc->uc_mcontext.regs[23];
105ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[24] = uc->uc_mcontext.regs[24];
106ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[25] = uc->uc_mcontext.regs[25];
107ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[26] = uc->uc_mcontext.regs[26];
108ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[27] = uc->uc_mcontext.regs[27];
109ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[28] = uc->uc_mcontext.regs[28];
110ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[29] = uc->uc_mcontext.regs[29];
111ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->regs[30] = uc->uc_mcontext.regs[30];
112ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->sp = uc->uc_mcontext.sp;
113ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->pc = uc->uc_mcontext.pc;
114ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      sc->pstate = uc->uc_mcontext.pstate;
115ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
116ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      asm volatile (
117ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "mov sp, %0\n"
118ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        "ret %1\n"
119ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux        : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
120ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      );
121ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux   }
122ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  unreachable();
123ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#else
124ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  printf ("%s: implement me\n", __FUNCTION__);
125ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#endif
126ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  return -UNW_EINVAL;
127ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
128ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
129ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux#endif /* !UNW_REMOTE_ONLY */
130ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
131ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxstatic inline void
132ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxestablish_machine_state (struct cursor *c)
133ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
134ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  unw_addr_space_t as = c->dwarf.as;
135ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  void *arg = c->dwarf.as_arg;
136ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  unw_fpreg_t fpval;
137ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  unw_word_t val;
138ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  int reg;
139ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
140ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  Debug (8, "copying out cursor state\n");
141ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
142ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  for (reg = 0; reg <= UNW_AARCH64_PSTATE; ++reg)
143ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    {
144ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      Debug (16, "copying %s %d\n", unw_regname (reg), reg);
145ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      if (unw_is_fpreg (reg))
146ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	{
147ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	  if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0)
148ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	    as->acc.access_fpreg (as, reg, &fpval, 1, arg);
149ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	}
150ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      else
151ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	{
152ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	  if (tdep_access_reg (c, reg, &val, 0) >= 0)
153ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	    as->acc.access_reg (as, reg, &val, 1, arg);
154ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	}
155ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    }
156ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
157ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
158ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan RouxPROTECTED int
159ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Rouxunw_resume (unw_cursor_t *cursor)
160ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux{
161ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  struct cursor *c = (struct cursor *) cursor;
162ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
163ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  Debug (1, "(cursor=%p)\n", c);
164ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
165ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  if (!c->dwarf.ip)
166ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    {
167ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      /* This can happen easily when the frame-chain gets truncated
168ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux	 due to bad or missing unwind-info.  */
169ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      Debug (1, "refusing to resume execution at address 0\n");
170ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux      return -UNW_EINVAL;
171ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux    }
172ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
173ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  establish_machine_state (c);
174ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux
175ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux  return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c,
176ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux				     c->dwarf.as_arg);
177ac6c0a6535975f1dc2da6e4e2766614baac2a14aYvan Roux}
178