1/*
2Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
3Permission is hereby granted, free of charge, to any person
4obtaining a copy of this software and associated documentation
5files (the "Software"), to deal in the Software without
6restriction, including without limitation the rights to use,
7copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the
9Software is furnished to do so, subject to the following
10conditions:
11
12The above copyright notice and this permission notice shall be
13included in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23*/
24
25#include "uwx_env.h"
26#include "uwx_utable.h"
27#include "uwx_uinfo.h"
28#include "uwx_scoreboard.h"
29#include "uwx_trace.h"
30
31#ifdef UWX_TRACE_ENABLE
32
33void uwx_trace_init(struct uwx_env *env)
34{
35    char *tstr;
36
37    tstr = getenv("UWX_TRACE");
38    if (tstr != NULL) {
39	while (*tstr != '\0') {
40	    switch (*tstr) {
41		case 'i': env->trace |= UWX_TRACE_UINFO; break;
42		case 't': env->trace |= UWX_TRACE_UTABLE; break;
43		case 'b': env->trace |= UWX_TRACE_SB; break;
44		case 'r': env->trace |= UWX_TRACE_RSTATE; break;
45		case 's': env->trace |= UWX_TRACE_STEP; break;
46		case 'c': env->trace |= UWX_TRACE_CONTEXT; break;
47		case 'C': env->trace |= UWX_TRACE_COPYIN; break;
48		case 'L': env->trace |= UWX_TRACE_LOOKUPIP; break;
49		case '?':
50#ifdef _KERNEL
51		    fprintf(stderr, "UWX_TRACE flag `%c' unknown.\n", *tstr);
52#else
53		    fprintf(stderr, "UWX_TRACE flags:\n");
54		    fprintf(stderr, "  i: unwind info\n");
55		    fprintf(stderr, "  t: unwind table searching\n");
56		    fprintf(stderr, "  b: scoreboard management\n");
57		    fprintf(stderr, "  r: register state vector\n");
58		    fprintf(stderr, "  s: step\n");
59		    fprintf(stderr, "  c: context\n");
60		    fprintf(stderr, "  C: copyin callback\n");
61		    fprintf(stderr, "  L: lookup ip callback\n");
62		    exit(1);
63#endif
64	    }
65	    tstr++;
66	}
67    }
68}
69
70char *uwx_sb_rnames[] = {
71    "RP", "PSP", "PFS",
72    "PREDS", "UNAT", "PRIUNAT", "RNAT", "LC", "FPSR",
73    "GR4", "GR5", "GR6", "GR7",
74    "BR1", "BR2", "BR3", "BR4", "BR5",
75    "FR2", "FR3", "FR4", "FR5",
76    "FR16", "FR17", "FR18", "FR19",
77    "FR20", "FR21", "FR22", "FR23",
78    "FR24", "FR25", "FR26", "FR27",
79    "FR28", "FR29", "FR30", "FR31",
80};
81
82void uwx_dump_rstate(int regid, uint64_t rstate)
83{
84    int reg;
85
86    if (rstate == UWX_DISP_NONE)
87	return;
88    fprintf(stderr, "    %-7s", uwx_sb_rnames[regid]);
89    switch (UWX_GET_DISP_CODE(rstate)) {
90	case UWX_DISP_NONE:
91	    fprintf(stderr, "    unchanged\n");
92	    break;
93	case UWX_DISP_SPPLUS(0):
94	    fprintf(stderr, "    SP + %d\n", (int)rstate & ~0x07);
95	    break;
96	case UWX_DISP_SPREL(0):
97	    fprintf(stderr, "    [SP + %d]\n", (int)rstate & ~0x07);
98	    break;
99	case UWX_DISP_PSPREL(0):
100	    fprintf(stderr, "    [PSP + 16 - %d]\n", (int)rstate & ~0x07);
101	    break;
102	case UWX_DISP_REG(0):
103	    reg = UWX_GET_DISP_REGID(rstate);
104	    if (reg == UWX_REG_AR_PFS)
105		fprintf(stderr, "    AR.PFS\n");
106	    else if (reg == UWX_REG_AR_UNAT)
107		fprintf(stderr, "    AR.UNAT\n");
108	    else if (reg >= UWX_REG_GR(0) && reg < UWX_REG_GR(128))
109		fprintf(stderr, "    GR%d\n", reg - UWX_REG_GR(0));
110	    else if (reg >= UWX_REG_FR(0) && reg < UWX_REG_FR(128))
111		fprintf(stderr, "    FR%d\n", reg - UWX_REG_FR(0));
112	    else if (reg >= UWX_REG_BR(0) && reg < UWX_REG_BR(8))
113		fprintf(stderr, "    BR%d\n", reg - UWX_REG_BR(0));
114	    else
115		fprintf(stderr, "    <reg %d>\n", reg);
116	    break;
117	default:
118	    fprintf(stderr, "    <%08lx>\n", (long)rstate);
119	    break;
120    }
121}
122
123void uwx_dump_scoreboard(
124    struct uwx_scoreboard *scoreboard,
125    int nsbreg,
126    struct uwx_rhdr *rhdr,
127    int cur_slot,
128    int ip_slot)
129{
130    int i;
131
132    if (rhdr->is_prologue)
133	fprintf(stderr, "  Prologue region (start = %d, length = %d)\n",
134		    (int)cur_slot, (int)rhdr->rlen);
135    else
136	fprintf(stderr, "  Body region (start = %d, length = %d, ecount = %d)\n",
137		    cur_slot, (int)rhdr->rlen, rhdr->ecount);
138    if (ip_slot < rhdr->rlen)
139	fprintf(stderr, "    IP is in this region (offset = %d)\n", ip_slot);
140    for (i = 0; i < nsbreg; i++)
141	uwx_dump_rstate(i, scoreboard->rstate[i]);
142}
143
144void uwx_dump_uinfo_block(
145	struct uwx_utable_entry *uentry,
146	unsigned int ulen)
147{
148    int i;
149    uint32_t *uinfo = (uint32_t *)(intptr_t)uentry->unwind_info;
150
151    ulen += DWORDSZ;		/* Include unwind info header */
152    if (uentry->unwind_flags & UNWIND_TBL_32BIT) /* and personality routine */
153	ulen += WORDSZ;
154    else
155	ulen += DWORDSZ;
156    while (ulen >= WORDSZ) {
157	fprintf(stderr, "  %08lx: ", (unsigned long)uinfo);
158	for (i = 0; i < 4 * WORDSZ && ulen >= WORDSZ; i += WORDSZ) {
159	    fprintf(stderr, " %04x", *uinfo++);
160	    ulen -= WORDSZ;
161	}
162	fprintf(stderr, "\n");
163    }
164}
165
166#endif /* UWX_TRACE_ENABLE */
167