mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-03-31 19:42:17 +02:00
(Logical change 1.29)
This commit is contained in:
parent
612e33825c
commit
b691bb1300
10 changed files with 386 additions and 0 deletions
|
@ -0,0 +1,52 @@
|
|||
static int
|
||||
find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
|
||||
void *arg, unw_dyn_info_list_t *list)
|
||||
{
|
||||
unw_dyn_info_t *di;
|
||||
|
||||
for (di = list->first; di; di = di->next)
|
||||
{
|
||||
if (ip >= di->start_ip && ip < di->end_ip)
|
||||
{
|
||||
pi->start_ip = di->start_ip;
|
||||
pi->end_ip = di->end_ip;
|
||||
pi->gp = di->gp;
|
||||
pi->format = di->format;
|
||||
switch (di->format)
|
||||
{
|
||||
case UNW_INFO_FORMAT_DYNAMIC:
|
||||
pi->proc_name = di->u.pi.name;
|
||||
pi->handler = di->u.pi.handler;
|
||||
pi->flags = di->u.pi.flags;
|
||||
pi->unwind_info = di;
|
||||
return 0;
|
||||
|
||||
case UNW_INFO_FORMAT_TABLE:
|
||||
#ifdef unw_search_unwind_table
|
||||
/* call platform-specific search routine: */
|
||||
return sysdep_search_unwind_table (as, ip, &di->u.ti, pi, arg);
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -UNW_ENOINFO;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_find_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_proc_info_t *pi, void *arg)
|
||||
{
|
||||
unw_dyn_info_list_t *list = NULL;
|
||||
|
||||
fprintf (stderr, "remote_find_proc_info: not implemented yet\n");
|
||||
/* use as.accessors to locate _U_dyn_info_list. */
|
||||
/* check _U_dyn_info_list.generation to see if cached info is stale */
|
||||
/* if cached info is stale, use as.accessors to read new info */
|
||||
/* internalize the data */
|
||||
/* re-check _U_dyn_info_list.generation to verify that read-in info
|
||||
is consistent */
|
||||
return find_proc_info (as, ip, pi, arg, list);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
/* This gets linked in only when UNW_REMOTE_ONLY is not defined. It
|
||||
must be a separate file to ensure registering dynamic info doesn't
|
||||
automatically drag in the lookup code and vice versa. */
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
unw_dyn_info_list_t _U_dyn_info_list
|
||||
__attribute__ ((section (".data.unwind_dynamic")));
|
|
@ -0,0 +1,52 @@
|
|||
#include <libunwind.h>
|
||||
|
||||
#ifndef HAVE_CMP8XCHG16
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* Make it easy to write thread-safe code which may or may not be
|
||||
linked against libpthread. The macros below can be used
|
||||
unconditionally and if -lpthread is around, they'll call the
|
||||
corresponding routines otherwise, they do nothing. */
|
||||
|
||||
#pragma weak pthread_rwlock_rdlock
|
||||
#pragma weak pthread_rwlock_wrlock
|
||||
#pragma weak pthread_rwlock_unlock
|
||||
|
||||
#define rw_rdlock(l) (pthread_rwlock_rdlock ? pthread_rwlock_rdlock (l) : 0)
|
||||
#define rw_wrlock(l) (pthread_rwlock_wrlock ? pthread_rwlock_wrlock (l) : 0)
|
||||
#define rw_unlock(l) (pthread_rwlock_unlock ? pthread_rwlock_unlock (l) : 0)
|
||||
|
||||
static pthread_rwlock_t registration_lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
#endif
|
||||
|
||||
extern unw_dyn_info_list_t _U_dyn_info_list;
|
||||
|
||||
int
|
||||
_U_dyn_register (unw_dyn_info_t *di)
|
||||
{
|
||||
#ifdef HAVE_CMP8XCHG16
|
||||
unw_dyn_info_t *old_list_head, *new_list_head;
|
||||
unsigned long old_gen, new_gen;
|
||||
|
||||
do
|
||||
{
|
||||
old_gen = _U_dyn_info_list.generation;
|
||||
old_list_head = _U_dyn_info_list.first;
|
||||
|
||||
new_gen = old_gen + 1;
|
||||
new_list_head = di;
|
||||
di->next = old_list_head;
|
||||
}
|
||||
while (cmp8xchg16 (&_U_dyn_info_list, new_gen, new_list_head) != old_gen);
|
||||
#else
|
||||
rw_wrlock (®istration_lock);
|
||||
{
|
||||
++_U_dyn_info_list.generation;
|
||||
di->next = _U_dyn_info_list.first;
|
||||
_U_dyn_info_list.first = di;
|
||||
}
|
||||
rw_unlock (®istration_lock);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef UNW_REMOTE_ONLY
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include "unw_find_dynamic_proc_info.c"
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef UNW_REMOTE_ONLY
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include "unw_get_accessors.c"
|
||||
#endif
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef UNW_REMOTE_ONLY
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include "unw_get_proc_info.c"
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "dyn-common.h"
|
||||
|
||||
int
|
||||
unw_find_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip,
|
||||
unw_proc_info_t *pi, void *arg)
|
||||
{
|
||||
extern unw_dyn_info_list_t _U_dyn_info_list;
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
return find_proc_info (as, ip, pi, arg, &_U_dyn_info_list);
|
||||
#else
|
||||
# ifdef UNW_REMOTE_ONLY
|
||||
return remote_find_proc_info (as, ip, pi, arg);
|
||||
# else
|
||||
if (as == unw_local_addr_space)
|
||||
return find_proc_info (as, ip, pi, arg, &_U_dyn_info_list);
|
||||
else
|
||||
return remote_find_proc_info (as, ip, pi, arg);
|
||||
# endif
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
unw_accessors_t *
|
||||
unw_get_accessors (unw_addr_space_t as)
|
||||
{
|
||||
return &as->acc;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2002 Hewlett-Packard Co
|
||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "unwind_i.h"
|
||||
|
||||
int
|
||||
unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi)
|
||||
{
|
||||
struct ia64_cursor *c = (struct ia64_cursor *) cursor;
|
||||
*pi = c->pi;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
#include <libunwind.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define panic(args...) \
|
||||
{ fprintf (stderr, args); exit (-1); }
|
||||
|
||||
typedef void (*template_t) (int, void (*)(),
|
||||
int (*)(const char *, ...), const char *,
|
||||
const char **);
|
||||
|
||||
static const char *strarr[] =
|
||||
{
|
||||
"i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", NULL
|
||||
};
|
||||
|
||||
#ifdef __ia64__
|
||||
struct fdesc
|
||||
{
|
||||
long code;
|
||||
long gp;
|
||||
};
|
||||
# define get_fdesc(fdesc,func) (fdesc = *(struct fdesc *) &(func))
|
||||
# define get_funcp(fdesc) ((template_t) &(fdesc))
|
||||
#else
|
||||
struct fdesc
|
||||
{
|
||||
long code;
|
||||
};
|
||||
# define get_fdesc(fdesc,func) (fdesc.code = (long) &(func))
|
||||
# define get_funcp(fdesc) ((template_t) (fdesc).code)
|
||||
#endif
|
||||
|
||||
static void
|
||||
flush_cache (void *addr, unsigned long len)
|
||||
{
|
||||
void *end = (char *) addr + len;
|
||||
|
||||
#ifdef __ia64__
|
||||
while (addr < end)
|
||||
{
|
||||
asm volatile ("fc %0" :: "r"(addr));
|
||||
addr = (char *) addr + 32;
|
||||
}
|
||||
asm volatile (";;sync.i;;srlz.i;;");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
template (int i, template_t self,
|
||||
int (*printer)(const char *, ...), const char *fmt, const char **arr)
|
||||
{
|
||||
(*printer) (fmt, arr[11 - i][0], arr[11 - i] + 1);
|
||||
if (i > 0)
|
||||
(*self) (i - 1, self, printer, fmt, arr);
|
||||
}
|
||||
|
||||
static void
|
||||
sighandler (int signal)
|
||||
{
|
||||
unw_cursor_t cursor;
|
||||
unw_word_t ip;
|
||||
unw_context_t uc;
|
||||
int count = 0;
|
||||
|
||||
printf ("caught signal %d\n", signal);
|
||||
|
||||
unw_getcontext (&uc);
|
||||
unw_init_local (&cursor, &uc);
|
||||
|
||||
while (!unw_is_signal_frame (&cursor))
|
||||
if (unw_step (&cursor) < 0)
|
||||
panic ("failed to find signal frame!\n");
|
||||
unw_step (&cursor);
|
||||
|
||||
do
|
||||
{
|
||||
unw_get_reg (&cursor, UNW_REG_IP, &ip);
|
||||
printf ("ip = %lx\n", (long) ip);
|
||||
++count;
|
||||
}
|
||||
while (unw_step (&cursor) > 0);
|
||||
|
||||
if (count != 13)
|
||||
panic ("FAILURE: expected 13, not %d frames below signal frame\n", count);
|
||||
|
||||
printf ("SUCCESS\n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
unw_dyn_region_info_t *region;
|
||||
unw_dyn_info_t di;
|
||||
struct fdesc fdesc;
|
||||
template_t funcp;
|
||||
void *mem;
|
||||
int ret;
|
||||
|
||||
mem = malloc (getpagesize ());
|
||||
|
||||
get_fdesc (fdesc, template);
|
||||
|
||||
printf ("old code @ %p, new code @ %p\n", (void *) fdesc.code, mem);
|
||||
|
||||
memcpy (mem, (void *) fdesc.code, 256);
|
||||
mprotect ((void *) ((long) mem & ~(getpagesize () - 1)),
|
||||
2*getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
flush_cache (mem, 256);
|
||||
|
||||
signal (SIGSEGV, sighandler);
|
||||
|
||||
/* register the new function: */
|
||||
region = alloca (_U_dyn_region_info_size (2));
|
||||
region->next = NULL;
|
||||
region->insn_count = 256;
|
||||
region->op_count = 2;
|
||||
_U_dyn_op_alias (®ion->op[0], 0, -1, fdesc.code);
|
||||
_U_dyn_op_stop (®ion->op[1]);
|
||||
|
||||
di.start_ip = (long) mem;
|
||||
di.end_ip = (long) mem + 256;
|
||||
di.gp = fdesc.gp;
|
||||
di.format = UNW_INFO_FORMAT_DYNAMIC;
|
||||
di.u.pi.name = "<copy of template()>";
|
||||
di.u.pi.handler = 0;
|
||||
di.u.pi.flags = 0;
|
||||
di.u.pi.regions = region;
|
||||
|
||||
ret = _U_dyn_register (&di);
|
||||
if (ret < 0)
|
||||
panic ("call to _U_dyn_register() failed: ret=%d\n", ret);
|
||||
|
||||
/* call new function: */
|
||||
fdesc.code = (long) mem;
|
||||
funcp = get_funcp (fdesc);
|
||||
|
||||
(*funcp) (10, funcp, printf, "iteration %c%s\n", strarr);
|
||||
return -1;
|
||||
}
|
Loading…
Add table
Reference in a new issue