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