Ginit.c revision 3eb5704c20acb444c4c15c754b8cecc41835dc55
13eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm/* libunwind - a platform-independent unwind library
23eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm   Copyright (C) 2002, 2004 Hewlett-Packard Co
33eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
43eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
53eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmThis file is part of libunwind.
63eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
73eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining
83eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidma copy of this software and associated documentation files (the
93eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm"Software"), to deal in the Software without restriction, including
103eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish,
113eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to
123eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to
133eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmthe following conditions:
143eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
153eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmThe above copyright notice and this permission notice shall be
163eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmincluded in all copies or substantial portions of the Software.
173eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
183eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
193eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
203eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
213eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
223eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
233eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
243eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
253eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
263eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#include <stdlib.h>
273eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#include <string.h>
283eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
293eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#include "unwind_i.h"
303eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
313eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#ifdef UNW_REMOTE_ONLY
323eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
333eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm/* unw_local_addr_space is a NULL pointer in this case.  */
343eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmPROTECTED unw_addr_space_t unw_local_addr_space;
353eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
363eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#else /* !UNW_REMOTE_ONLY */
373eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
383eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmstatic struct unw_addr_space local_addr_space;
393eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
403eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmPROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
413eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
423eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmstatic inline void *
433eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmuc_addr (ucontext_t *uc, int reg)
443eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
453eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  void *addr;
463eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
473eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  switch (reg)
483eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    {
493eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_EAX: addr = &uc->uc_mcontext.gregs[REG_EAX]; break;
503eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_EBX: addr = &uc->uc_mcontext.gregs[REG_EBX]; break;
513eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_ECX: addr = &uc->uc_mcontext.gregs[REG_ECX]; break;
523eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_EDX: addr = &uc->uc_mcontext.gregs[REG_EDX]; break;
533eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_ESI: addr = &uc->uc_mcontext.gregs[REG_ESI]; break;
543eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_EDI: addr = &uc->uc_mcontext.gregs[REG_EDI]; break;
553eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_EBP: addr = &uc->uc_mcontext.gregs[REG_EBP]; break;
563eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_EIP: addr = &uc->uc_mcontext.gregs[REG_EIP]; break;
573eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    case UNW_X86_ESP: addr = &uc->uc_mcontext.gregs[REG_ESP]; break;
583eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
593eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    default:
603eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      addr = NULL;
613eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    }
623eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return addr;
633eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
643eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
653eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm# ifdef UNW_LOCAL_ONLY
663eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
673eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmvoid *
683eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm_Ux86_uc_addr (ucontext_t *uc, int reg)
693eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
703eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return uc_addr (uc, reg);
713eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
723eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
733eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm# endif /* UNW_LOCAL_ONLY */
743eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
753eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmHIDDEN unw_dyn_info_list_t _U_dyn_info_list;
763eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
773eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm/* XXX fix me: there is currently no way to locate the dyn-info list
783eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm       by a remote unwinder.  On ia64, this is done via a special
793eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm       unwind-table entry.  Perhaps something similar can be done with
803eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm       DWARF2 unwind info.  */
813eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
823eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmstatic void
833eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmput_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
843eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
853eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  /* it's a no-op */
863eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
873eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
883eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmstatic int
893eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmget_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
903eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm			void *arg)
913eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
923eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list;
933eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return 0;
943eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
953eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
963eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmstatic int
973eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmaccess_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
983eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm	    void *arg)
993eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
1003eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  if (write)
1013eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    {
1023eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      Debug (16, "mem[%x] <- %x\n", addr, *val);
1033eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      *(unw_word_t *) addr = *val;
1043eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    }
1053eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  else
1063eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    {
1073eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      *val = *(unw_word_t *) addr;
1083eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      Debug (16, "mem[%x] -> %x\n", addr, *val);
1093eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    }
1103eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return 0;
1113eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
1123eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1133eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmstatic int
1143eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmaccess_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
1153eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm	    void *arg)
1163eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
1173eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  unw_word_t *addr;
1183eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  ucontext_t *uc = arg;
1193eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1203eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#if 0
1213eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  if (reg >= UNW_IA64_FR && reg < UNW_IA64_FR + 128)
1223eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    goto badreg;
1233eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#endif
1243eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1253eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  addr = uc_addr (uc, reg);
1263eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  if (!addr)
1273eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    goto badreg;
1283eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1293eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  if (write)
1303eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    {
1313eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      *(unw_word_t *) addr = *val;
1323eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      Debug (16, "%s <- %x\n", unw_regname (reg), *val);
1333eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    }
1343eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  else
1353eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    {
1363eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      *val = *(unw_word_t *) addr;
1373eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      Debug (16, "%s -> %x\n", unw_regname (reg), *val);
1383eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    }
1393eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return 0;
1403eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1413eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm badreg:
1423eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  Debug (1, "bad register number %u\n", reg);
1433eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return -UNW_EBADREG;
1443eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
1453eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1463eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmstatic int
1473eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmaccess_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
1483eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm	      int write, void *arg)
1493eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
1503eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#if 1
1513eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  printf ("access_fpreg: screams to get implemented, doesn't it?\n");
1523eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return 0;
1533eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#else
1543eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  ucontext_t *uc = arg;
1553eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  unw_fpreg_t *addr;
1563eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1573eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  if (reg < UNW_IA64_FR || reg >= UNW_IA64_FR + 128)
1583eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    goto badreg;
1593eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1603eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  addr = uc_addr (uc, reg);
1613eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  if (!addr)
1623eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    goto badreg;
1633eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1643eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  if (write)
1653eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    {
1663eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      Debug (16, "%s <- %016lx.%016lx\n",
1673eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm	     unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
1683eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      *(unw_fpreg_t *) addr = *val;
1693eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    }
1703eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  else
1713eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    {
1723eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      *val = *(unw_fpreg_t *) addr;
1733eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm      Debug (16, "%s -> %016lx.%016lx\n",
1743eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm	     unw_regname (reg), val->raw.bits[1], val->raw.bits[0]);
1753eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm    }
1763eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return 0;
1773eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1783eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm badreg:
1793eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  Debug (1, "bad register number %u\n", reg);
1803eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  /* attempt to access a non-preserved register */
1813eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  return -UNW_EBADREG;
1823eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#endif
1833eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
1843eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1853eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmHIDDEN void
1863eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidmx86_local_addr_space_init (void)
1873eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm{
1883eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  memset (&local_addr_space, 0, sizeof (local_addr_space));
1893eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.caching_policy = UNW_CACHE_GLOBAL;
1903eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.acc.find_proc_info = UNW_ARCH_OBJ (find_proc_info);
1913eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.acc.put_unwind_info = put_unwind_info;
1923eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr;
1933eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.acc.access_mem = access_mem;
1943eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.acc.access_reg = access_reg;
1953eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.acc.access_fpreg = access_fpreg;
1963eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm  local_addr_space.acc.resume = x86_local_resume;
1973eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm}
1983eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm
1993eb5704c20acb444c4c15c754b8cecc41835dc55homeip.net!davidm#endif /* !UNW_REMOTE_ONLY */
200