1 /* $OpenBSD: fxproc0.c,v 1.1.1.1 2018/08/21 18:35:18 bluhm Exp $ */ 2 /* 3 * Copyright (c) 2018 Alexander Bluhm <bluhm@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/proc.h> 20 #include <sys/user.h> 21 #include <machine/fpu.h> 22 #include <machine/pcb.h> 23 24 #include <err.h> 25 #include <fcntl.h> 26 #include <kvm.h> 27 #include <limits.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 32 void __dead usage(void); 33 void fenv_proc(kvm_t *, unsigned long); 34 35 void __dead 36 usage(void) 37 { 38 fprintf(stderr, "usage: %s [-M core] [-N system]\n", getprogname()); 39 exit(1); 40 } 41 42 int 43 main(int argc, char *argv[]) 44 { 45 char errbuf[_POSIX2_LINE_MAX]; 46 char *memf, *nlistf; 47 kvm_t *kd; 48 int ch; 49 struct nlist nl[] = { { .n_name = "_proc0" }, { .n_name = NULL } }; 50 51 memf = nlistf = NULL; 52 while ((ch = getopt(argc, argv, "M:N:")) != -1) { 53 switch(ch) { 54 case 'M': 55 memf = optarg; 56 break; 57 case 'N': 58 nlistf = optarg; 59 break; 60 default: 61 usage(); 62 } 63 } 64 argc -= optind; 65 argv += optind; 66 if (argc) 67 usage(); 68 69 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 70 if (kd == NULL) 71 errx(1, "kvm_openfiles: %s", errbuf); 72 if (kvm_nlist(kd, nl) == -1) 73 errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 74 if (nl[0].n_type == 0) 75 errx(1, "name '%s' has type %d", nl[0].n_name, nl[0].n_type); 76 fenv_proc(kd, nl[0].n_value); 77 78 if (kvm_close(kd) == -1) 79 errx(1, "kvm_close: %s", kvm_geterr(kd)); 80 return 0; 81 } 82 83 void 84 fenv_proc(kvm_t *kd, unsigned long p) 85 { 86 struct proc proc; 87 struct user user; 88 struct fxsave64 *fxs = &user.u_pcb.pcb_savefpu.fp_fxsave; 89 size_t i; 90 91 if (kvm_read(kd, p, &proc, sizeof(proc)) == -1) 92 errx(1, "kvm_read proc: %s", kvm_geterr(kd)); 93 if (kvm_read(kd, (u_long)proc.p_addr, &user, sizeof(user)) == -1) 94 errx(1, "kvm_read user: %s", kvm_geterr(kd)); 95 96 if (fxs != &fxs->fx_fcw) 97 errx(1, "fxsave start %p, fx_fcw start %p", 98 &fxs, &fxs->fx_fcw); 99 printf("fcw\t%04x\n", fxs->fx_fcw); 100 printf("fsw\t%04x\n", fxs->fx_fsw); 101 printf("ftw\t%02x\n", fxs->fx_ftw); 102 printf("unused1\t%02x\n", fxs->fx_unused1); 103 printf("fop\t%04x\n", fxs->fx_fop); 104 printf("rip\t%016llx\n", fxs->fx_rip); 105 printf("rdp\t%016llx\n", fxs->fx_rdp); 106 printf("mxcsr\t%08x\n", fxs->fx_mxcsr); 107 printf("mxcsr_mask\t%08x\n", fxs->fx_mxcsr_mask); 108 if (&fxs->fx_mxcsr_mask + 1 != fxs->fx_st) 109 errx(1, "fx_mxcsr_mask end %p, fx_st start %p", 110 &fxs->fx_mxcsr_mask + 1, fxs->fx_st); 111 for (i = 0; i < nitems(fxs->fx_st); i++) 112 printf("st[%zu]\t%016llx:%016llx\n", i, 113 fxs->fx_st[i][1], fxs->fx_st[i][0]); 114 if (&fxs->fx_st[i] != fxs->fx_xmm) 115 errx(1, "fx_st end %p, fx_xmm start %p", 116 &fxs->fx_st[i], fxs->fx_xmm); 117 for (i = 0; i < nitems(fxs->fx_xmm); i++) 118 printf("xmm[%zu]\t%016llx:%016llx\n", i, 119 fxs->fx_xmm[i][1], fxs->fx_xmm[i][0]); 120 if (&fxs->fx_xmm[i] != fxs->fx_unused3) 121 errx(1, "fx_xmm end %p, fx_unused3 start %p", 122 &fxs->fx_xmm[i], fxs->fx_unused3); 123 for (i = 0; i < nitems(fxs->fx_unused3); i++) 124 printf("unused3[%zu]\t%02x\n", i, fxs->fx_unused3[i]); 125 if (&fxs->fx_unused3[i] != fxs + 1) 126 errx(1, "fx_unused3 end %p, fxsave end %p", 127 &fxs->fx_unused3[i], fxs + 1); 128 } 129