Line data Source code
1 : // Copyright (c) 2014, Google Inc.
2 : // All rights reserved.
3 : //
4 : // Redistribution and use in source and binary forms, with or without
5 : // modification, are permitted provided that the following conditions are
6 : // met:
7 : //
8 : // * Redistributions of source code must retain the above copyright
9 : // notice, this list of conditions and the following disclaimer.
10 : // * Redistributions in binary form must reproduce the above
11 : // copyright notice, this list of conditions and the following disclaimer
12 : // in the documentation and/or other materials provided with the
13 : // distribution.
14 : // * Neither the name of Google Inc. nor the names of its
15 : // contributors may be used to endorse or promote products derived from
16 : // this software without specific prior written permission.
17 : //
18 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 :
30 : #include "linux/dump_writer_common/ucontext_reader.h"
31 :
32 : #include "common/linux/linux_libc_support.h"
33 : #include "google_breakpad/common/minidump_format.h"
34 :
35 : namespace google_breakpad {
36 :
37 : // Minidump defines register structures which are different from the raw
38 : // structures which we get from the kernel. These are platform specific
39 : // functions to juggle the ucontext and user structures into minidump format.
40 :
41 : #if defined(__i386__)
42 :
43 : uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
44 : return uc->uc_mcontext.gregs[REG_ESP];
45 : }
46 :
47 : uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
48 : return uc->uc_mcontext.gregs[REG_EIP];
49 : }
50 :
51 : void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc,
52 : const struct _libc_fpstate* fp) {
53 : const greg_t* regs = uc->uc_mcontext.gregs;
54 :
55 : out->context_flags = MD_CONTEXT_X86_FULL |
56 : MD_CONTEXT_X86_FLOATING_POINT;
57 :
58 : out->gs = regs[REG_GS];
59 : out->fs = regs[REG_FS];
60 : out->es = regs[REG_ES];
61 : out->ds = regs[REG_DS];
62 :
63 : out->edi = regs[REG_EDI];
64 : out->esi = regs[REG_ESI];
65 : out->ebx = regs[REG_EBX];
66 : out->edx = regs[REG_EDX];
67 : out->ecx = regs[REG_ECX];
68 : out->eax = regs[REG_EAX];
69 :
70 : out->ebp = regs[REG_EBP];
71 : out->eip = regs[REG_EIP];
72 : out->cs = regs[REG_CS];
73 : out->eflags = regs[REG_EFL];
74 : out->esp = regs[REG_UESP];
75 : out->ss = regs[REG_SS];
76 :
77 : out->float_save.control_word = fp->cw;
78 : out->float_save.status_word = fp->sw;
79 : out->float_save.tag_word = fp->tag;
80 : out->float_save.error_offset = fp->ipoff;
81 : out->float_save.error_selector = fp->cssel;
82 : out->float_save.data_offset = fp->dataoff;
83 : out->float_save.data_selector = fp->datasel;
84 :
85 : // 8 registers * 10 bytes per register.
86 : my_memcpy(out->float_save.register_area, fp->_st, 10 * 8);
87 : }
88 :
89 : #elif defined(__x86_64)
90 :
91 0 : uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
92 0 : return uc->uc_mcontext.gregs[REG_RSP];
93 : }
94 :
95 0 : uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
96 0 : return uc->uc_mcontext.gregs[REG_RIP];
97 : }
98 :
99 0 : void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc,
100 : const struct _libc_fpstate* fpregs) {
101 0 : const greg_t* regs = uc->uc_mcontext.gregs;
102 :
103 0 : out->context_flags = MD_CONTEXT_AMD64_FULL;
104 :
105 0 : out->cs = regs[REG_CSGSFS] & 0xffff;
106 :
107 0 : out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff;
108 0 : out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff;
109 :
110 0 : out->eflags = regs[REG_EFL];
111 :
112 0 : out->rax = regs[REG_RAX];
113 0 : out->rcx = regs[REG_RCX];
114 0 : out->rdx = regs[REG_RDX];
115 0 : out->rbx = regs[REG_RBX];
116 :
117 0 : out->rsp = regs[REG_RSP];
118 0 : out->rbp = regs[REG_RBP];
119 0 : out->rsi = regs[REG_RSI];
120 0 : out->rdi = regs[REG_RDI];
121 0 : out->r8 = regs[REG_R8];
122 0 : out->r9 = regs[REG_R9];
123 0 : out->r10 = regs[REG_R10];
124 0 : out->r11 = regs[REG_R11];
125 0 : out->r12 = regs[REG_R12];
126 0 : out->r13 = regs[REG_R13];
127 0 : out->r14 = regs[REG_R14];
128 0 : out->r15 = regs[REG_R15];
129 :
130 0 : out->rip = regs[REG_RIP];
131 :
132 0 : out->flt_save.control_word = fpregs->cwd;
133 0 : out->flt_save.status_word = fpregs->swd;
134 0 : out->flt_save.tag_word = fpregs->ftw;
135 0 : out->flt_save.error_opcode = fpregs->fop;
136 0 : out->flt_save.error_offset = fpregs->rip;
137 0 : out->flt_save.data_offset = fpregs->rdp;
138 0 : out->flt_save.error_selector = 0; // We don't have this.
139 0 : out->flt_save.data_selector = 0; // We don't have this.
140 0 : out->flt_save.mx_csr = fpregs->mxcsr;
141 0 : out->flt_save.mx_csr_mask = fpregs->mxcr_mask;
142 0 : my_memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16);
143 0 : my_memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16);
144 0 : }
145 :
146 : #elif defined(__ARM_EABI__)
147 :
148 : uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
149 : return uc->uc_mcontext.arm_sp;
150 : }
151 :
152 : uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
153 : return uc->uc_mcontext.arm_pc;
154 : }
155 :
156 : void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) {
157 : out->context_flags = MD_CONTEXT_ARM_FULL;
158 :
159 : out->iregs[0] = uc->uc_mcontext.arm_r0;
160 : out->iregs[1] = uc->uc_mcontext.arm_r1;
161 : out->iregs[2] = uc->uc_mcontext.arm_r2;
162 : out->iregs[3] = uc->uc_mcontext.arm_r3;
163 : out->iregs[4] = uc->uc_mcontext.arm_r4;
164 : out->iregs[5] = uc->uc_mcontext.arm_r5;
165 : out->iregs[6] = uc->uc_mcontext.arm_r6;
166 : out->iregs[7] = uc->uc_mcontext.arm_r7;
167 : out->iregs[8] = uc->uc_mcontext.arm_r8;
168 : out->iregs[9] = uc->uc_mcontext.arm_r9;
169 : out->iregs[10] = uc->uc_mcontext.arm_r10;
170 :
171 : out->iregs[11] = uc->uc_mcontext.arm_fp;
172 : out->iregs[12] = uc->uc_mcontext.arm_ip;
173 : out->iregs[13] = uc->uc_mcontext.arm_sp;
174 : out->iregs[14] = uc->uc_mcontext.arm_lr;
175 : out->iregs[15] = uc->uc_mcontext.arm_pc;
176 :
177 : out->cpsr = uc->uc_mcontext.arm_cpsr;
178 :
179 : // TODO: fix this after fixing ExceptionHandler
180 : out->float_save.fpscr = 0;
181 : my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
182 : my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
183 : }
184 :
185 : #elif defined(__aarch64__)
186 :
187 : uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
188 : return uc->uc_mcontext.sp;
189 : }
190 :
191 : uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
192 : return uc->uc_mcontext.pc;
193 : }
194 :
195 : void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc,
196 : const struct fpsimd_context* fpregs) {
197 : out->context_flags = MD_CONTEXT_ARM64_FULL;
198 :
199 : out->cpsr = static_cast<uint32_t>(uc->uc_mcontext.pstate);
200 : for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
201 : out->iregs[i] = uc->uc_mcontext.regs[i];
202 : out->iregs[MD_CONTEXT_ARM64_REG_SP] = uc->uc_mcontext.sp;
203 : out->iregs[MD_CONTEXT_ARM64_REG_PC] = uc->uc_mcontext.pc;
204 :
205 : out->float_save.fpsr = fpregs->fpsr;
206 : out->float_save.fpcr = fpregs->fpcr;
207 : my_memcpy(&out->float_save.regs, &fpregs->vregs,
208 : MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
209 : }
210 :
211 : #elif defined(__mips__)
212 :
213 : uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
214 : return uc->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
215 : }
216 :
217 : uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
218 : return uc->uc_mcontext.pc;
219 : }
220 :
221 : void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) {
222 : #if _MIPS_SIM == _ABI64
223 : out->context_flags = MD_CONTEXT_MIPS64_FULL;
224 : #elif _MIPS_SIM == _ABIO32
225 : out->context_flags = MD_CONTEXT_MIPS_FULL;
226 : #else
227 : #error "This mips ABI is currently not supported (n32)"
228 : #endif
229 :
230 : for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
231 : out->iregs[i] = uc->uc_mcontext.gregs[i];
232 :
233 : out->mdhi = uc->uc_mcontext.mdhi;
234 : out->mdlo = uc->uc_mcontext.mdlo;
235 :
236 : out->hi[0] = uc->uc_mcontext.hi1;
237 : out->hi[1] = uc->uc_mcontext.hi2;
238 : out->hi[2] = uc->uc_mcontext.hi3;
239 : out->lo[0] = uc->uc_mcontext.lo1;
240 : out->lo[1] = uc->uc_mcontext.lo2;
241 : out->lo[2] = uc->uc_mcontext.lo3;
242 : out->dsp_control = uc->uc_mcontext.dsp;
243 :
244 : out->epc = uc->uc_mcontext.pc;
245 : out->badvaddr = 0; // Not reported in signal context.
246 : out->status = 0; // Not reported in signal context.
247 : out->cause = 0; // Not reported in signal context.
248 :
249 : for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
250 : out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
251 :
252 : out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
253 : #if _MIPS_SIM == _ABIO32
254 : out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
255 : #endif
256 : }
257 : #endif
258 :
259 : } // namespace google_breakpad
|