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