brintos

brintos / linux-shallow public Read only

0
0
Text · 15.3 KiB · 04788e5 Raw
810 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * Ptrace interface test helper functions4 *5 * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.6 */7 8#define __SANE_USERSPACE_TYPES__9 10#include <inttypes.h>11#include <unistd.h>12#include <stdlib.h>13#include <string.h>14#include <malloc.h>15#include <errno.h>16#include <time.h>17#include <sys/ptrace.h>18#include <sys/ioctl.h>19#include <sys/uio.h>20#include <sys/types.h>21#include <sys/wait.h>22#include <sys/signal.h>23#include <sys/ipc.h>24#include <sys/shm.h>25#include <sys/user.h>26#include <sys/syscall.h>27#include <linux/elf.h>28#include <linux/types.h>29#include <linux/auxvec.h>30#include "reg.h"31#include "utils.h"32 33#define TEST_PASS 034#define TEST_FAIL 135 36struct fpr_regs {37	__u64 fpr[32];38	__u64 fpscr;39};40 41struct tm_spr_regs {42	unsigned long tm_tfhar;43	unsigned long tm_texasr;44	unsigned long tm_tfiar;45};46 47#ifndef NT_PPC_TAR48#define NT_PPC_TAR	0x10349#define NT_PPC_PPR	0x10450#define NT_PPC_DSCR	0x10551#define NT_PPC_EBB	0x10652#define NT_PPC_PMU	0x10753#define NT_PPC_TM_CGPR	0x10854#define NT_PPC_TM_CFPR	0x10955#define NT_PPC_TM_CVMX	0x10a56#define NT_PPC_TM_CVSX	0x10b57#define NT_PPC_TM_SPR	0x10c58#define NT_PPC_TM_CTAR	0x10d59#define NT_PPC_TM_CPPR	0x10e60#define NT_PPC_TM_CDSCR	0x10f61#endif62 63/* Basic ptrace operations */64int start_trace(pid_t child)65{66	int ret;67 68	ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);69	if (ret) {70		perror("ptrace(PTRACE_ATTACH) failed");71		return TEST_FAIL;72	}73	ret = waitpid(child, NULL, 0);74	if (ret != child) {75		perror("waitpid() failed");76		return TEST_FAIL;77	}78	return TEST_PASS;79}80 81int stop_trace(pid_t child)82{83	int ret;84 85	ret = ptrace(PTRACE_DETACH, child, NULL, NULL);86	if (ret) {87		perror("ptrace(PTRACE_DETACH) failed");88		return TEST_FAIL;89	}90	return TEST_PASS;91}92 93int cont_trace(pid_t child)94{95	int ret;96 97	ret = ptrace(PTRACE_CONT, child, NULL, NULL);98	if (ret) {99		perror("ptrace(PTRACE_CONT) failed");100		return TEST_FAIL;101	}102	return TEST_PASS;103}104 105int ptrace_read_regs(pid_t child, unsigned long type, unsigned long regs[],106		     int n)107{108	struct iovec iov;109	long ret;110 111	FAIL_IF(start_trace(child));112 113	iov.iov_base = regs;114	iov.iov_len = n * sizeof(unsigned long);115 116	ret = ptrace(PTRACE_GETREGSET, child, type, &iov);117	if (ret)118		return ret;119 120	FAIL_IF(stop_trace(child));121 122	return TEST_PASS;123}124 125long ptrace_write_regs(pid_t child, unsigned long type, unsigned long regs[],126		       int n)127{128	struct iovec iov;129	long ret;130 131	FAIL_IF(start_trace(child));132 133	iov.iov_base = regs;134	iov.iov_len = n * sizeof(unsigned long);135 136	ret = ptrace(PTRACE_SETREGSET, child, type, &iov);137 138	FAIL_IF(stop_trace(child));139 140	return ret;141}142 143/* TAR, PPR, DSCR */144int show_tar_registers(pid_t child, unsigned long *out)145{146	struct iovec iov;147	unsigned long *reg;148	int ret;149 150	reg = malloc(sizeof(unsigned long));151	if (!reg) {152		perror("malloc() failed");153		return TEST_FAIL;154	}155	iov.iov_base = (u64 *) reg;156	iov.iov_len = sizeof(unsigned long);157 158	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov);159	if (ret) {160		perror("ptrace(PTRACE_GETREGSET) failed");161		goto fail;162	}163	if (out)164		out[0] = *reg;165 166	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov);167	if (ret) {168		perror("ptrace(PTRACE_GETREGSET) failed");169		goto fail;170	}171	if (out)172		out[1] = *reg;173 174	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov);175	if (ret) {176		perror("ptrace(PTRACE_GETREGSET) failed");177		goto fail;178	}179	if (out)180		out[2] = *reg;181 182	free(reg);183	return TEST_PASS;184fail:185	free(reg);186	return TEST_FAIL;187}188 189int write_tar_registers(pid_t child, unsigned long tar,190		unsigned long ppr, unsigned long dscr)191{192	struct iovec iov;193	unsigned long *reg;194	int ret;195 196	reg = malloc(sizeof(unsigned long));197	if (!reg) {198		perror("malloc() failed");199		return TEST_FAIL;200	}201 202	iov.iov_base = (u64 *) reg;203	iov.iov_len = sizeof(unsigned long);204 205	*reg = tar;206	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov);207	if (ret) {208		perror("ptrace(PTRACE_SETREGSET) failed");209		goto fail;210	}211 212	*reg = ppr;213	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov);214	if (ret) {215		perror("ptrace(PTRACE_SETREGSET) failed");216		goto fail;217	}218 219	*reg = dscr;220	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov);221	if (ret) {222		perror("ptrace(PTRACE_SETREGSET) failed");223		goto fail;224	}225 226	free(reg);227	return TEST_PASS;228fail:229	free(reg);230	return TEST_FAIL;231}232 233int show_tm_checkpointed_state(pid_t child, unsigned long *out)234{235	struct iovec iov;236	unsigned long *reg;237	int ret;238 239	reg = malloc(sizeof(unsigned long));240	if (!reg) {241		perror("malloc() failed");242		return TEST_FAIL;243	}244 245	iov.iov_base = (u64 *) reg;246	iov.iov_len = sizeof(unsigned long);247 248	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov);249	if (ret) {250		perror("ptrace(PTRACE_GETREGSET) failed");251		goto fail;252	}253	if (out)254		out[0] = *reg;255 256	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov);257	if (ret) {258		perror("ptrace(PTRACE_GETREGSET) failed");259		goto fail;260	}261	if (out)262		out[1] = *reg;263 264	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov);265	if (ret) {266		perror("ptrace(PTRACE_GETREGSET) failed");267		goto fail;268	}269	if (out)270		out[2] = *reg;271 272	free(reg);273	return TEST_PASS;274 275fail:276	free(reg);277	return TEST_FAIL;278}279 280int write_ckpt_tar_registers(pid_t child, unsigned long tar,281		unsigned long ppr, unsigned long dscr)282{283	struct iovec iov;284	unsigned long *reg;285	int ret;286 287	reg = malloc(sizeof(unsigned long));288	if (!reg) {289		perror("malloc() failed");290		return TEST_FAIL;291	}292 293	iov.iov_base = (u64 *) reg;294	iov.iov_len = sizeof(unsigned long);295 296	*reg = tar;297	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov);298	if (ret) {299		perror("ptrace(PTRACE_GETREGSET) failed");300		goto fail;301	}302 303	*reg = ppr;304	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov);305	if (ret) {306		perror("ptrace(PTRACE_GETREGSET) failed");307		goto fail;308	}309 310	*reg = dscr;311	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov);312	if (ret) {313		perror("ptrace(PTRACE_GETREGSET) failed");314		goto fail;315	}316 317	free(reg);318	return TEST_PASS;319fail:320	free(reg);321	return TEST_FAIL;322}323 324/* FPR */325int show_fpr(pid_t child, __u64 *fpr)326{327	struct fpr_regs *regs;328	int ret, i;329 330	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));331	ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);332	if (ret) {333		perror("ptrace(PTRACE_GETREGSET) failed");334		return TEST_FAIL;335	}336 337	if (fpr) {338		for (i = 0; i < 32; i++)339			fpr[i] = regs->fpr[i];340	}341	return TEST_PASS;342}343 344int write_fpr(pid_t child, __u64 val)345{346	struct fpr_regs *regs;347	int ret, i;348 349	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));350	ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);351	if (ret) {352		perror("ptrace(PTRACE_GETREGSET) failed");353		return TEST_FAIL;354	}355 356	for (i = 0; i < 32; i++)357		regs->fpr[i] = val;358 359	ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs);360	if (ret) {361		perror("ptrace(PTRACE_GETREGSET) failed");362		return TEST_FAIL;363	}364	return TEST_PASS;365}366 367int show_ckpt_fpr(pid_t child, __u64 *fpr)368{369	struct fpr_regs *regs;370	struct iovec iov;371	int ret, i;372 373	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));374	iov.iov_base = regs;375	iov.iov_len = sizeof(struct fpr_regs);376 377	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);378	if (ret) {379		perror("ptrace(PTRACE_GETREGSET) failed");380		return TEST_FAIL;381	}382 383	if (fpr) {384		for (i = 0; i < 32; i++)385			fpr[i] = regs->fpr[i];386	}387 388	return TEST_PASS;389}390 391int write_ckpt_fpr(pid_t child, unsigned long val)392{393	struct fpr_regs *regs;394	struct iovec iov;395	int ret, i;396 397	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));398	iov.iov_base = regs;399	iov.iov_len = sizeof(struct fpr_regs);400 401	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);402	if (ret) {403		perror("ptrace(PTRACE_GETREGSET) failed");404		return TEST_FAIL;405	}406 407	for (i = 0; i < 32; i++)408		regs->fpr[i] = val;409 410	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov);411	if (ret) {412		perror("ptrace(PTRACE_GETREGSET) failed");413		return TEST_FAIL;414	}415	return TEST_PASS;416}417 418/* GPR */419int show_gpr(pid_t child, unsigned long *gpr)420{421	struct pt_regs *regs;422	int ret, i;423 424	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));425	if (!regs) {426		perror("malloc() failed");427		return TEST_FAIL;428	}429 430	ret = ptrace(PTRACE_GETREGS, child, NULL, regs);431	if (ret) {432		perror("ptrace(PTRACE_GETREGSET) failed");433		return TEST_FAIL;434	}435 436	if (gpr) {437		for (i = 14; i < 32; i++)438			gpr[i-14] = regs->gpr[i];439	}440 441	return TEST_PASS;442}443 444long sys_ptrace(enum __ptrace_request request, pid_t pid, unsigned long addr, unsigned long data)445{446	return syscall(__NR_ptrace, request, pid, (void *)addr, data);447}448 449// 33 because of FPSCR450#define PT_NUM_FPRS	(33 * (sizeof(__u64) / sizeof(unsigned long)))451 452__u64 *peek_fprs(pid_t child)453{454	unsigned long *fprs, *p, addr;455	long ret;456	int i;457 458	fprs = malloc(sizeof(unsigned long) * PT_NUM_FPRS);459	if (!fprs) {460		perror("malloc() failed");461		return NULL;462	}463 464	for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) {465		addr = sizeof(unsigned long) * (PT_FPR0 + i);466		ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)p);467		if (ret) {468			perror("ptrace(PTRACE_PEEKUSR) failed");469			return NULL;470		}471	}472 473	addr = sizeof(unsigned long) * (PT_FPR0 + i);474	ret = sys_ptrace(PTRACE_PEEKUSER, child, addr, (unsigned long)&addr);475	if (!ret) {476		printf("ptrace(PTRACE_PEEKUSR) succeeded unexpectedly!\n");477		return NULL;478	}479 480	return (__u64 *)fprs;481}482 483int poke_fprs(pid_t child, unsigned long *fprs)484{485	unsigned long *p, addr;486	long ret;487	int i;488 489	for (i = 0, p = fprs; i < PT_NUM_FPRS; i++, p++) {490		addr = sizeof(unsigned long) * (PT_FPR0 + i);491		ret = sys_ptrace(PTRACE_POKEUSER, child, addr, *p);492		if (ret) {493			perror("ptrace(PTRACE_POKEUSR) failed");494			return -1;495		}496	}497 498	addr = sizeof(unsigned long) * (PT_FPR0 + i);499	ret = sys_ptrace(PTRACE_POKEUSER, child, addr, addr);500	if (!ret) {501		printf("ptrace(PTRACE_POKEUSR) succeeded unexpectedly!\n");502		return -1;503	}504 505	return 0;506}507 508int write_gpr(pid_t child, unsigned long val)509{510	struct pt_regs *regs;511	int i, ret;512 513	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));514	if (!regs) {515		perror("malloc() failed");516		return TEST_FAIL;517	}518 519	ret = ptrace(PTRACE_GETREGS, child, NULL, regs);520	if (ret) {521		perror("ptrace(PTRACE_GETREGSET) failed");522		return TEST_FAIL;523	}524 525	for (i = 14; i < 32; i++)526		regs->gpr[i] = val;527 528	ret = ptrace(PTRACE_SETREGS, child, NULL, regs);529	if (ret) {530		perror("ptrace(PTRACE_GETREGSET) failed");531		return TEST_FAIL;532	}533	return TEST_PASS;534}535 536int show_ckpt_gpr(pid_t child, unsigned long *gpr)537{538	struct pt_regs *regs;539	struct iovec iov;540	int ret, i;541 542	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));543	if (!regs) {544		perror("malloc() failed");545		return TEST_FAIL;546	}547 548	iov.iov_base = (u64 *) regs;549	iov.iov_len = sizeof(struct pt_regs);550 551	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);552	if (ret) {553		perror("ptrace(PTRACE_GETREGSET) failed");554		return TEST_FAIL;555	}556 557	if (gpr) {558		for (i = 14; i < 32; i++)559			gpr[i-14] = regs->gpr[i];560	}561 562	return TEST_PASS;563}564 565int write_ckpt_gpr(pid_t child, unsigned long val)566{567	struct pt_regs *regs;568	struct iovec iov;569	int ret, i;570 571	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));572	if (!regs) {573		perror("malloc() failed\n");574		return TEST_FAIL;575	}576	iov.iov_base = (u64 *) regs;577	iov.iov_len = sizeof(struct pt_regs);578 579	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);580	if (ret) {581		perror("ptrace(PTRACE_GETREGSET) failed");582		return TEST_FAIL;583	}584 585	for (i = 14; i < 32; i++)586		regs->gpr[i] = val;587 588	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov);589	if (ret) {590		perror("ptrace(PTRACE_GETREGSET) failed");591		return TEST_FAIL;592	}593	return TEST_PASS;594}595 596/* VMX */597int show_vmx(pid_t child, unsigned long vmx[][2])598{599	int ret;600 601	ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);602	if (ret) {603		perror("ptrace(PTRACE_GETVRREGS) failed");604		return TEST_FAIL;605	}606	return TEST_PASS;607}608 609int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])610{611	unsigned long regs[34][2];612	struct iovec iov;613	int ret;614 615	iov.iov_base = (u64 *) regs;616	iov.iov_len = sizeof(regs);617	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);618	if (ret) {619		perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");620		return TEST_FAIL;621	}622	memcpy(vmx, regs, sizeof(regs));623	return TEST_PASS;624}625 626 627int write_vmx(pid_t child, unsigned long vmx[][2])628{629	int ret;630 631	ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);632	if (ret) {633		perror("ptrace(PTRACE_SETVRREGS) failed");634		return TEST_FAIL;635	}636	return TEST_PASS;637}638 639int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])640{641	unsigned long regs[34][2];642	struct iovec iov;643	int ret;644 645	memcpy(regs, vmx, sizeof(regs));646	iov.iov_base = (u64 *) regs;647	iov.iov_len = sizeof(regs);648	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);649	if (ret) {650		perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");651		return TEST_FAIL;652	}653	return TEST_PASS;654}655 656/* VSX */657int show_vsx(pid_t child, unsigned long *vsx)658{659	int ret;660 661	ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);662	if (ret) {663		perror("ptrace(PTRACE_GETVSRREGS) failed");664		return TEST_FAIL;665	}666	return TEST_PASS;667}668 669int show_vsx_ckpt(pid_t child, unsigned long *vsx)670{671	unsigned long regs[32];672	struct iovec iov;673	int ret;674 675	iov.iov_base = (u64 *) regs;676	iov.iov_len = sizeof(regs);677	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);678	if (ret) {679		perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");680		return TEST_FAIL;681	}682	memcpy(vsx, regs, sizeof(regs));683	return TEST_PASS;684}685 686int write_vsx(pid_t child, unsigned long *vsx)687{688	int ret;689 690	ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);691	if (ret) {692		perror("ptrace(PTRACE_SETVSRREGS) failed");693		return TEST_FAIL;694	}695	return TEST_PASS;696}697 698int write_vsx_ckpt(pid_t child, unsigned long *vsx)699{700	unsigned long regs[32];701	struct iovec iov;702	int ret;703 704	memcpy(regs, vsx, sizeof(regs));705	iov.iov_base = (u64 *) regs;706	iov.iov_len = sizeof(regs);707	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);708	if (ret) {709		perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");710		return TEST_FAIL;711	}712	return TEST_PASS;713}714 715/* TM SPR */716int show_tm_spr(pid_t child, struct tm_spr_regs *out)717{718	struct tm_spr_regs *regs;719	struct iovec iov;720	int ret;721 722	regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));723	if (!regs) {724		perror("malloc() failed");725		return TEST_FAIL;726	}727 728	iov.iov_base = (u64 *) regs;729	iov.iov_len = sizeof(struct tm_spr_regs);730 731	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);732	if (ret) {733		perror("ptrace(PTRACE_GETREGSET) failed");734		return TEST_FAIL;735	}736 737	if (out)738		memcpy(out, regs, sizeof(struct tm_spr_regs));739 740	return TEST_PASS;741}742 743 744 745/* Analyse TEXASR after TM failure */746inline unsigned long get_tfiar(void)747{748	return mfspr(SPRN_TFIAR);749}750 751void analyse_texasr(unsigned long texasr)752{753	printf("TEXASR: %16lx\t", texasr);754 755	if (texasr & TEXASR_FP)756		printf("TEXASR_FP  ");757 758	if (texasr & TEXASR_DA)759		printf("TEXASR_DA  ");760 761	if (texasr & TEXASR_NO)762		printf("TEXASR_NO  ");763 764	if (texasr & TEXASR_FO)765		printf("TEXASR_FO  ");766 767	if (texasr & TEXASR_SIC)768		printf("TEXASR_SIC  ");769 770	if (texasr & TEXASR_NTC)771		printf("TEXASR_NTC  ");772 773	if (texasr & TEXASR_TC)774		printf("TEXASR_TC  ");775 776	if (texasr & TEXASR_TIC)777		printf("TEXASR_TIC  ");778 779	if (texasr & TEXASR_IC)780		printf("TEXASR_IC  ");781 782	if (texasr & TEXASR_IFC)783		printf("TEXASR_IFC  ");784 785	if (texasr & TEXASR_ABT)786		printf("TEXASR_ABT  ");787 788	if (texasr & TEXASR_SPD)789		printf("TEXASR_SPD  ");790 791	if (texasr & TEXASR_HV)792		printf("TEXASR_HV  ");793 794	if (texasr & TEXASR_PR)795		printf("TEXASR_PR  ");796 797	if (texasr & TEXASR_FS)798		printf("TEXASR_FS  ");799 800	if (texasr & TEXASR_TE)801		printf("TEXASR_TE  ");802 803	if (texasr & TEXASR_ROT)804		printf("TEXASR_ROT  ");805 806	printf("TFIAR :%lx\n", get_tfiar());807}808 809void store_gpr(unsigned long *addr);810