summaryrefslogtreecommitdiff
path: root/tests/ia64-test-dyn1.c
diff options
context:
space:
mode:
authormostang.com!davidm <mostang.com!davidm>2003-02-27 09:58:57 +0000
committermostang.com!davidm <mostang.com!davidm>2003-02-27 09:58:57 +0000
commit45776310947e41852765c6c2399f9e090e12dc99 (patch)
treeeabcbbd4aa444ba53331bdb12b3fc39828c12b43 /tests/ia64-test-dyn1.c
parent404230b56acf69b1c3db2e686dfc19e2f6bbca47 (diff)
downloadlibunwind-45776310947e41852765c6c2399f9e090e12dc99.tar.gz
Don't be verbose by default.
(main): Send SIGUSR1 before dynamic testing starts, SIGUSR2 afterwards (makes it easy for test-ptrace to catch when verification should begin). Add test case for func_vframe(). (Logical change 1.56)
Diffstat (limited to 'tests/ia64-test-dyn1.c')
-rw-r--r--tests/ia64-test-dyn1.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/tests/ia64-test-dyn1.c b/tests/ia64-test-dyn1.c
index e69de29b..f006bbc8 100644
--- a/tests/ia64-test-dyn1.c
+++ b/tests/ia64-test-dyn1.c
@@ -0,0 +1,221 @@
+#include <libunwind.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/mman.h>
+
+int verbose;
+
+#ifdef __ia64__
+# define GET_ENTRY(fdesc) (((uintptr_t *) (fdesc))[0])
+# define GET_GP(fdesc) (((uintptr_t *) (fdesc))[0])
+# define EXTRA 16
+#else
+# define GET_ENTRY(fdesc) ((uintptr_t ) (fdesc))
+# define GET_GP(fdesc) (0)
+# define EXTRA 0
+#endif
+
+static void
+flush_cache (void *addr, size_t len)
+{
+#ifdef __ia64__
+ void *end = (char *) addr + len;
+
+ while (addr < end)
+ {
+ asm volatile ("fc %0" :: "r"(addr));
+ addr = (char *) addr + 32;
+ }
+ asm volatile (";;sync.i;;srlz.i;;");
+#endif
+}
+
+int
+make_executable (void *addr, size_t len)
+{
+ if (mprotect ((void *) (((long) addr) & -getpagesize ()), len,
+ PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
+ {
+ perror ("mprotect");
+ return -1;
+ }
+ flush_cache (addr, len);
+ return 0;
+}
+
+void *
+create_func (unw_dyn_info_t *di, const char *name, long (*func) (),
+ void *end, unw_dyn_region_info_t *region)
+{
+ void *mem, *memend, *addr, *fptr;
+ unw_word_t gp = 0;
+ size_t len;
+
+ len = (uintptr_t) end - GET_ENTRY (func) + EXTRA;
+ mem = malloc (len);
+ if (verbose)
+ printf ("%s: cloning %s at %p (%Zu bytes)\n",
+ __FUNCTION__, name, mem, len);
+ memend = (char *) mem + len;
+
+#ifdef __ia64__
+ addr = (void *) GET_ENTRY (func);
+
+ /* build function descriptor: */
+ ((long *) mem)[0] = (long) mem + 16; /* entry point */
+ ((long *) mem)[1] = GET_GP (func); /* global-pointer */
+ fptr = mem;
+ mem = (void *) ((long) mem + 16);
+#else
+ fptr = mem;
+#endif
+
+ len = (char *) memend - (char *) mem;
+ memcpy (mem, addr, len);
+
+ if (make_executable (mem, len) < 0)
+ return NULL;
+
+ if (di)
+ {
+ memset (di, 0, sizeof (*di));
+ di->start_ip = (unw_word_t) mem;
+ di->end_ip = (unw_word_t) memend;
+ di->gp = gp;
+ di->format = UNW_INFO_FORMAT_DYNAMIC;
+ di->u.pi.name_ptr = (unw_word_t) name;
+ di->u.pi.regions = region;
+ }
+ return fptr;
+}
+
+int
+main (int argc, char **argv)
+{
+ extern long func_add1 (long);
+ extern char func_add1_end[];
+ extern long func_add3 (long, long (*[])());
+ extern char func_add3_end[];
+ extern long func_vframe (long);
+ extern char func_vframe_end[];
+ unw_dyn_region_info_t *r_pro, *r_epi, *r, *rtmp;
+ unw_dyn_info_t di0, di1, di2, di3;
+ long (*add1) (long);
+ long (*add3_0) (long);
+ long (*add3_1) (long, void *[]);
+ long (*vframe) (long);
+ void *flist[2];
+ long ret;
+
+ signal (SIGUSR1, SIG_IGN);
+ signal (SIGUSR2, SIG_IGN);
+
+ if (argc != 1)
+ verbose = 1;
+
+ add1 = create_func (&di0, "func_add1", func_add1, func_add1_end, NULL);
+
+ /* Describe the epilogue of func_add3: */
+ r_epi = alloca (_U_dyn_region_info_size (5));
+ r_epi->next = NULL;
+ r_epi->insn_count = -9;
+ r_epi->op_count = 2;
+ _U_dyn_op_pop_frames (&r_epi->op[0],
+ _U_QP_TRUE, /* when=*/ 5, /* num_frames=*/ 1);
+ _U_dyn_op_stop (&r_epi->op[1]);
+
+ /* Describe the prologue of func_add3: */
+ r_pro = alloca (_U_dyn_region_info_size (4));
+ r_pro->next = r_epi;
+ r_pro->insn_count = 8;
+ r_pro->op_count = 4;
+ _U_dyn_op_save_reg (&r_pro->op[0], _U_QP_TRUE, /* when=*/ 0,
+ /* reg=*/ UNW_IA64_AR_PFS, /* dst=*/ UNW_IA64_GR + 34);
+ _U_dyn_op_add (&r_pro->op[1], _U_QP_TRUE, /* when=*/ 2,
+ /* reg= */ UNW_IA64_SP, /* val=*/ -16);
+ _U_dyn_op_save_reg (&r_pro->op[2], _U_QP_TRUE, /* when=*/ 4,
+ /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 3);
+ _U_dyn_op_spill_sp_rel (&r_pro->op[3], _U_QP_TRUE, /* when=*/ 7,
+ /* reg=*/ UNW_IA64_RP, /* off=*/ 16);
+
+ /* Create regions for func_vframe: */
+ r = alloca (_U_dyn_region_info_size (16));
+ r->next = NULL;
+ r->insn_count = 4;
+ r->op_count = 0;
+ _U_dyn_op_label_state (&r->op[r->op_count++], /* label=*/ 100402);
+ _U_dyn_op_pop_frames (&r->op[r->op_count++], _U_QP_TRUE, /* when=*/ 3,
+ /* num_frames=*/ 1);
+ _U_dyn_op_stop (&r->op[r->op_count++]);
+
+ rtmp = r;
+ r = alloca (_U_dyn_region_info_size (16));
+ r->next = rtmp;
+ r->insn_count = 16;
+ r->op_count = 0;
+ _U_dyn_op_save_reg (&r->op[r->op_count++], _U_QP_TRUE, /* when=*/ 8,
+ /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 3);
+ _U_dyn_op_pop_frames (&r->op[r->op_count++], _U_QP_TRUE, /* when=*/ 10,
+ /* num_frames=*/ 1);
+ _U_dyn_op_stop (&r->op[r->op_count++]);
+
+ rtmp = r;
+ r = alloca (_U_dyn_region_info_size (16));
+ r->next = rtmp;
+ r->insn_count = 5;
+ r->op_count = 0;
+ _U_dyn_op_save_reg (&r->op[r->op_count++], _U_QP_TRUE, /* when=*/ 1,
+ /* reg=*/ UNW_IA64_RP, /* dst=*/ UNW_IA64_GR + 33);
+ _U_dyn_op_save_reg (&r->op[r->op_count++], _U_QP_TRUE, /* when=*/ 2,
+ /* reg=*/ UNW_IA64_SP, /* dst=*/ UNW_IA64_GR + 34);
+ _U_dyn_op_spill_fp_rel (&r->op[r->op_count++], _U_QP_TRUE, /* when=*/ 4,
+ /* reg=*/ UNW_IA64_AR_PFS, /* off=*/ 16);
+ _U_dyn_op_label_state (&r->op[r->op_count++], /* label=*/ 100402);
+ _U_dyn_op_stop (&r->op[r->op_count++]);
+
+ /* Create two functions which can share the region-list: */
+ add3_0 = create_func (&di1, "func_add3/0", func_add3, func_add3_end, r_pro);
+ add3_1 = create_func (&di2, "func_add3/1", func_add3, func_add3_end, r_pro);
+ vframe = create_func (&di3, "func_vframe", func_vframe, func_vframe_end, r);
+
+ _U_dyn_register (&di1);
+ _U_dyn_register (&di2);
+ _U_dyn_register (&di3);
+ _U_dyn_register (&di0);
+
+ flist[0] = add3_0;
+ flist[1] = add1;
+
+ kill (getpid (), SIGUSR1); /* do something ptmon can latch onto */
+ ret = (*add3_1) (13, flist);
+ if (ret != 18)
+ {
+ fprintf (stderr, "FAILURE: (*add3_1)(13) returned %ld\n", ret);
+ exit (-1);
+ }
+
+ ret = (*vframe) (48);
+ if (ret != 4)
+ {
+ fprintf (stderr, "FAILURE: (*vframe)(16) returned %ld\n", ret);
+ exit (-1);
+ }
+ ret = (*vframe) (64);
+ if (ret != 10)
+ {
+ fprintf (stderr, "FAILURE: (*vframe)(32) returned %ld\n", ret);
+ exit (-1);
+ }
+ kill (getpid (), SIGUSR2); /* do something ptmon can latch onto */
+
+ _U_dyn_cancel (&di0);
+ _U_dyn_cancel (&di1);
+ _U_dyn_cancel (&di3);
+ _U_dyn_cancel (&di2);
+
+ return 0;
+}