1 /* libunwind - a platform-independent unwind library
2    Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P.
3 	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4 
5 This file is part of libunwind.
6 
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14 
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
25 
26 #include "offsets.h"
27 #include "unwind_i.h"
28 
29 HIDDEN dwarf_loc_t
x86_scratch_loc(struct cursor * c,unw_regnum_t reg)30 x86_scratch_loc (struct cursor *c, unw_regnum_t reg)
31 {
32   if (c->sigcontext_addr)
33     return x86_get_scratch_loc (c, reg);
34   else
35     return DWARF_REG_LOC (&c->dwarf, reg);
36 }
37 
38 HIDDEN int
tdep_access_reg(struct cursor * c,unw_regnum_t reg,unw_word_t * valp,int write)39 tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
40 		 int write)
41 {
42   dwarf_loc_t loc = DWARF_NULL_LOC;
43   unsigned int mask;
44   int arg_num;
45 
46   switch (reg)
47     {
48 
49     case UNW_X86_EIP:
50       if (write)
51 	c->dwarf.ip = *valp;		/* also update the EIP cache */
52       loc = c->dwarf.loc[EIP];
53       break;
54 
55     case UNW_X86_CFA:
56     case UNW_X86_ESP:
57       if (write)
58 	return -UNW_EREADONLYREG;
59       *valp = c->dwarf.cfa;
60       return 0;
61 
62     case UNW_X86_EAX:
63     case UNW_X86_EDX:
64       arg_num = reg - UNW_X86_EAX;
65       mask = (1 << arg_num);
66       if (write)
67 	{
68 	  c->dwarf.eh_args[arg_num] = *valp;
69 	  c->dwarf.eh_valid_mask |= mask;
70 	  return 0;
71 	}
72       else if ((c->dwarf.eh_valid_mask & mask) != 0)
73 	{
74 	  *valp = c->dwarf.eh_args[arg_num];
75 	  return 0;
76 	}
77       else
78 	loc = c->dwarf.loc[(reg == UNW_X86_EAX) ? EAX : EDX];
79       break;
80 
81     case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break;
82     case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break;
83 
84     case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break;
85     case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break;
86     case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break;
87     case UNW_X86_EFLAGS: loc = c->dwarf.loc[EFLAGS]; break;
88     case UNW_X86_TRAPNO: loc = c->dwarf.loc[TRAPNO]; break;
89 
90     case UNW_X86_FCW:
91     case UNW_X86_FSW:
92     case UNW_X86_FTW:
93     case UNW_X86_FOP:
94     case UNW_X86_FCS:
95     case UNW_X86_FIP:
96     case UNW_X86_FEA:
97     case UNW_X86_FDS:
98     case UNW_X86_MXCSR:
99     case UNW_X86_GS:
100     case UNW_X86_FS:
101     case UNW_X86_ES:
102     case UNW_X86_DS:
103     case UNW_X86_SS:
104     case UNW_X86_CS:
105     case UNW_X86_TSS:
106     case UNW_X86_LDT:
107       loc = x86_scratch_loc (c, reg);
108       break;
109 
110     default:
111       Debug (1, "bad register number %u\n", reg);
112       return -UNW_EBADREG;
113     }
114 
115   if (write)
116     return dwarf_put (&c->dwarf, loc, *valp);
117   else
118     return dwarf_get (&c->dwarf, loc, valp);
119 }
120 
121 HIDDEN int
tdep_access_fpreg(struct cursor * c,unw_regnum_t reg,unw_fpreg_t * valp,int write)122 tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
123 		   int write)
124 {
125   struct dwarf_loc loc = DWARF_NULL_LOC;
126 
127   switch (reg)
128     {
129     case UNW_X86_ST0:
130       loc = c->dwarf.loc[ST0];
131       break;
132 
133       /* stacked fp registers */
134     case UNW_X86_ST1:
135     case UNW_X86_ST2:
136     case UNW_X86_ST3:
137     case UNW_X86_ST4:
138     case UNW_X86_ST5:
139     case UNW_X86_ST6:
140     case UNW_X86_ST7:
141       /* SSE fp registers */
142     case UNW_X86_XMM0:
143     case UNW_X86_XMM1:
144     case UNW_X86_XMM2:
145     case UNW_X86_XMM3:
146     case UNW_X86_XMM4:
147     case UNW_X86_XMM5:
148     case UNW_X86_XMM6:
149     case UNW_X86_XMM7:
150     case UNW_X86_XMM0_lo:
151     case UNW_X86_XMM0_hi:
152     case UNW_X86_XMM1_lo:
153     case UNW_X86_XMM1_hi:
154     case UNW_X86_XMM2_lo:
155     case UNW_X86_XMM2_hi:
156     case UNW_X86_XMM3_lo:
157     case UNW_X86_XMM3_hi:
158     case UNW_X86_XMM4_lo:
159     case UNW_X86_XMM4_hi:
160     case UNW_X86_XMM5_lo:
161     case UNW_X86_XMM5_hi:
162     case UNW_X86_XMM6_lo:
163     case UNW_X86_XMM6_hi:
164     case UNW_X86_XMM7_lo:
165     case UNW_X86_XMM7_hi:
166       loc = x86_scratch_loc (c, reg);
167       break;
168 
169     default:
170       Debug (1, "bad register number %u\n", reg);
171       return -UNW_EBADREG;
172     }
173 
174   if (write)
175     return dwarf_putfp (&c->dwarf, loc, *valp);
176   else
177     return dwarf_getfp (&c->dwarf, loc, valp);
178 }
179