From 05a9101485fd5a5c42c546cc720bc35fa4e3f06b Mon Sep 17 00:00:00 2001 From: "mostang.com!davidm" Date: Sat, 14 Feb 2004 07:53:31 +0000 Subject: [PATCH] (Logical change 1.168) --- tests/Gia64-test-nat.c | 182 ++++++++++++++++++++++++++++++++++++++ tests/Lia64-test-nat.c | 5 ++ tests/ia64-test-nat-asm.S | 81 +++++++++++++++++ 3 files changed, 268 insertions(+) diff --git a/tests/Gia64-test-nat.c b/tests/Gia64-test-nat.c index e69de29b..db8ed107 100644 --- a/tests/Gia64-test-nat.c +++ b/tests/Gia64-test-nat.c @@ -0,0 +1,182 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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 file tests corner-cases of unwinding across multiple stacks. + In particular, it verifies that the extreme case with a frame of 96 + stacked registers that are all backed up by separate stacks works + as expected. */ + +#include +#include + +#include + +#define NUM_RUNS 1 +//#define MAX_CHECKS 1024 +#define MAX_CHECKS 2 +#define MAX_VALUES_PER_FUNC 4 + +#define panic(args...) \ + do { fprintf (stderr, args); ++nerrors; } while (0) + +#define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0]))) + +typedef void save_func_t (void *funcs, unsigned long *vals); +typedef unw_word_t *check_func_t (unw_cursor_t *c, unsigned long *vals); + +extern save_func_t save_static_to_stacked; +static check_func_t check_static_to_stacked; + +static int verbose; +static int nerrors; + +static int num_checks; +static save_func_t *funcs[MAX_CHECKS + 1]; +static check_func_t *checks[MAX_CHECKS]; +static unw_word_t values[MAX_CHECKS*MAX_VALUES_PER_FUNC]; + +static struct + { + save_func_t *func; + check_func_t *check; + } +all_funcs[] = + { + { save_static_to_stacked, check_static_to_stacked } + }; + +static unw_word_t * +check_static_to_stacked (unw_cursor_t *c, unw_word_t *vals) +{ + unw_word_t r[4]; + unw_word_t nat[4]; + int i, ret; + + if (verbose) + printf ("%s()\n", __FUNCTION__); + + vals -= 4; + + for (i = 0; i < 4; ++i) + if ((ret = unw_get_reg (c, UNW_IA64_GR + 4 + i, &r[i])) < 0) + panic ("%s: failed to read register r%d, error=%d", + __FUNCTION__, 4 + i, ret); + + for (i = 0; i < 4; ++i) + if ((ret = unw_get_reg (c, UNW_IA64_NAT + 4 + i, &nat[i])) < 0) + panic ("%s: failed to read register nat%d, error=%d", + __FUNCTION__, 4 + i, ret); + + for (i = 0; i < 4; ++i) + { + if (verbose) + printf (" r%d = %c%016lx (expected %c%016lx)\n", + 4 + i, nat[i] ? '*' : ' ', r[i], + (vals[i] & 1) ? '*' : ' ', vals[i]); + + if (vals[i] & 1) + { + if (!nat[i]) + panic ("%s: r%d not a NaT!\n", __FUNCTION__, 4 + i); + } + else + { + if (nat[i]) + panic ("%s: r%d a NaT!\n", __FUNCTION__, 4 + i); + if (r[i] != vals[i]) + panic ("%s: r%d=%lx instead of %lx!\n", + __FUNCTION__, 4 + i, r[i], vals[i]); + } + } + return vals; +} + +static void +start_checks (void *funcs, unsigned long *vals) +{ + unw_context_t uc; + unw_cursor_t c; + int i, ret; + + unw_getcontext (&uc); + + if ((ret = unw_init_local (&c, &uc)) < 0) + panic ("%s: unw_init_local (ret=%d)", __FUNCTION__, ret); + + if ((ret = unw_step (&c)) < 0) + panic ("%s: unw_step (ret=%d)", __FUNCTION__, ret); + + for (i = 0; i < num_checks; ++i) + { + vals = (*checks[i]) (&c, vals); + + if ((ret = unw_step (&c)) < 0) + panic ("%s: unw_step (ret=%d)", __FUNCTION__, ret); + } +} + +static void +run_check (int test) +{ + int index, i; + + num_checks = (random () % MAX_CHECKS) + 1; + + for (i = 0; i < num_checks * MAX_VALUES_PER_FUNC; ++i) + values[i] = random (); + + for (i = 0; i < num_checks; ++i) + { + index = random () % NELEMS (all_funcs); + funcs[i] = all_funcs[index].func; + checks[i] = all_funcs[index].check; + } + + funcs[num_checks] = start_checks; + +printf("starting at funcs[0]=%p\n", funcs[0]); + (*funcs[0]) (funcs + 1, values); +} + +int +main (int argc, char **argv) +{ + int i; + + if (argc > 1) + verbose = 1; + + for (i = 0; i < NUM_RUNS; ++i) + run_check (i + 1); + + if (nerrors > 0) + { + fprintf (stderr, "FAILURE: detected %d errors\n", nerrors); + exit (-1); + } + if (verbose) + printf ("SUCCESS.\n"); + return 0; +} diff --git a/tests/Lia64-test-nat.c b/tests/Lia64-test-nat.c index e69de29b..6f86b566 100644 --- a/tests/Lia64-test-nat.c +++ b/tests/Lia64-test-nat.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gia64-test-nat.c" +#endif diff --git a/tests/ia64-test-nat-asm.S b/tests/ia64-test-nat-asm.S index e69de29b..1a87ff8f 100644 --- a/tests/ia64-test-nat-asm.S +++ b/tests/ia64-test-nat-asm.S @@ -0,0 +1,81 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +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. */ + + .text + + .global save_static_to_stacked + .proc save_static_to_stacked +save_static_to_stacked: + .prologue + .regstk 2, 7, 2, 0 + .save ar.pfs, loc0 + alloc loc0 = ar.pfs, 2, 7, 2, 0 + .save rp, loc1 + mov loc1 = rp + .spillreg r4, loc2 + mov loc2 = r4 + .spillreg r5, loc3 + mov loc3 = r5 + .spillreg r6, loc4 + mov loc4 = r6 + .spillreg r7, loc5 + mov loc5 = r7 + .body + ld8 r4 = [in1], 8;; + ld8 r5 = [in1], 8;; + ld8 r6 = [in1], 8;; + ld8 r7 = [in1], 8;; + tbit.nz p6, p0 = r4, 0 + tbit.nz p7, p0 = r5, 0 + tbit.nz p8, p0 = r6, 0 + tbit.nz p9, p0 = r7, 0;; +(p6) ld8.s r4 = [r0] +(p7) ld8.s r5 = [r0] +(p8) ld8.s r6 = [r0] +(p9) ld8.s r7 = [r0] + + ld8 r2 = [in0], 8 // read the next function pointer + ;; + ld8 r3 = [r2], 8 // read the function's entry-point + ;; + ld8 r2 = [r2] // read the function's gp + ;; + mov b6 = r3 + mov loc6 = gp + mov out0 = in0 + mov out1 = in1 + mov gp = r2 + br.call.sptk.many rp = b6;; + mov gp = loc6 + + mov r4 = loc2 + mov r5 = loc3 + mov r6 = loc4 + mov r7 = loc5 + + mov ar.pfs = loc0 + mov rp = loc1 + br.ret.sptk.many rp + .endp save_static_to_stacked