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