(root)/
strace-6.5/
tests/
ioctl_counter.c
       1  /*
       2   * Check decoding of COUNTER_* commands of ioctl syscall.
       3   *
       4   * Copyright (c) 2022 Eugene Syromyatnikov <evgsyr@gmail.com>.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include "scno.h"
      12  
      13  #include <errno.h>
      14  #include <inttypes.h>
      15  #include <stdio.h>
      16  #include <stdlib.h>
      17  #include <string.h>
      18  #include <unistd.h>
      19  
      20  #include <linux/ioctl.h>
      21  #include <linux/counter.h>
      22  
      23  
      24  /* A hack for handling different types of _IOC() on various platforms */
      25  #if XLAT_RAW
      26  # define XLAT_ARGS_U(a_) (unsigned int) (a_)
      27  #elif XLAT_VERBOSE
      28  # define XLAT_ARGS_U(a_) (unsigned int) (a_), #a_
      29  #else
      30  # define XLAT_ARGS_U(a_) #a_
      31  #endif
      32  
      33  static const char *errstr;
      34  
      35  static long
      36  sys_ioctl(kernel_long_t fd, kernel_ulong_t cmd, kernel_ulong_t arg)
      37  {
      38  	const long rc = syscall(__NR_ioctl, fd, cmd, arg);
      39  	errstr = sprintrc(rc);
      40  	return rc;
      41  }
      42  
      43  int
      44  main(void)
      45  {
      46  	static const struct {
      47  		uint32_t val;
      48  		const char *str;
      49  	} dirs[] = {
      50  		{ ARG_STR(_IOC_NONE) },
      51  		{ ARG_STR(_IOC_READ) },
      52  		{ ARG_STR(_IOC_WRITE) },
      53  		{ ARG_STR(_IOC_READ|_IOC_WRITE) },
      54  	};
      55  	static const kernel_ulong_t magic =
      56  		(kernel_ulong_t) 0xdeadbeefbadc0dedULL;
      57  
      58  	/* Unknown counter ioctl */
      59  	for (size_t i = 0; i < ARRAY_SIZE(dirs); i++) {
      60  		for (unsigned int j = 0; j < 32; j += 1) {
      61  			sys_ioctl(-1, _IOC(dirs[i].val, '>', 3, j), magic);
      62  			printf("ioctl(-1, "
      63  			       XLAT_KNOWN(%#x, "_IOC(%s, 0x3e, 0x3, %#x)")
      64  			       ", %#lx) = %s\n",
      65  #if XLAT_RAW || XLAT_VERBOSE
      66  			       (unsigned int) _IOC(dirs[i].val, '>', 3, j),
      67  #endif
      68  #if !XLAT_RAW
      69  			       dirs[i].str, j,
      70  #endif
      71  			       (unsigned long) magic, errstr);
      72  		}
      73  	}
      74  
      75  	/* COUNTER_ADD_WATCH_IOCTL */
      76  	static const struct {
      77  		struct counter_watch val;;
      78  		const char *str;
      79  	} watches[] = {
      80  		{ { { 0 } },
      81  		  "{component={type=" XLAT_KNOWN(0, "COUNTER_COMPONENT_NONE")
      82  		  ", scope=" XLAT_KNOWN(0, "COUNTER_SCOPE_DEVICE")
      83  		  ", parent=0, id=0}"
      84  		  ", event=" XLAT_KNOWN(0, "COUNTER_EVENT_OVERFLOW")
      85  		  ", channel=0}" },
      86  		{ { { COUNTER_COMPONENT_EXTENSION, COUNTER_SCOPE_COUNT,
      87  		      23, 42 }, COUNTER_EVENT_CAPTURE, 69 },
      88  		  "{component="
      89  		  "{type=" XLAT_KNOWN(0x5, "COUNTER_COMPONENT_EXTENSION")
      90  		  ", scope=" XLAT_KNOWN(0x2, "COUNTER_SCOPE_COUNT")
      91  		  ", parent=23, id=42}"
      92  		  ", event=" XLAT_KNOWN(0x6, "COUNTER_EVENT_CAPTURE")
      93  		  ", channel=69}" },
      94  		{ { { COUNTER_COMPONENT_EXTENSION + 1, COUNTER_SCOPE_COUNT + 1,
      95  		      142, 160 }, COUNTER_EVENT_CAPTURE + 1, 173 },
      96  		  "{component={type=" XLAT_UNKNOWN(0x6, "COUNTER_COMPONENT_???")
      97  		  ", scope=" XLAT_UNKNOWN(0x3, "COUNTER_SCOPE_???")
      98  		  ", parent=142, id=160}"
      99  		  ", event=" XLAT_UNKNOWN(0x7, "COUNTER_EVENT_???")
     100  		  ", channel=173}" },
     101  	};
     102  	TAIL_ALLOC_OBJECT_CONST_PTR(struct counter_watch, watch);
     103  
     104  	sys_ioctl(-1, COUNTER_ADD_WATCH_IOCTL, 0);
     105  	printf("ioctl(-1, " XLAT_FMT ", NULL) = %s\n",
     106  	       XLAT_ARGS_U(COUNTER_ADD_WATCH_IOCTL), errstr);
     107  
     108  	sys_ioctl(-1, COUNTER_ADD_WATCH_IOCTL, (uintptr_t) watch + 1);
     109  	printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n",
     110  	       XLAT_ARGS_U(COUNTER_ADD_WATCH_IOCTL),
     111  	       (char *) watch + 1, errstr);
     112  
     113  	for (size_t i = 0; i < ARRAY_SIZE(watches); i++) {
     114  		memcpy(watch, &watches[i].val, sizeof(watches[i].val));
     115  		sys_ioctl(-1, COUNTER_ADD_WATCH_IOCTL, (uintptr_t) watch);
     116  		printf("ioctl(-1, " XLAT_FMT ", %s) = %s\n",
     117  		       XLAT_ARGS_U(COUNTER_ADD_WATCH_IOCTL),
     118  		       watches[i].str, errstr);
     119  	}
     120  
     121  	/* COUNTER_ENABLE_EVENTS_IOCTL */
     122  	sys_ioctl(-1, COUNTER_ENABLE_EVENTS_IOCTL, magic);
     123  	printf("ioctl(-1, " XLAT_FMT ") = %s\n",
     124  	       XLAT_ARGS_U(COUNTER_ENABLE_EVENTS_IOCTL), errstr);
     125  
     126  	/* COUNTER_DISABLE_EVENTS_IOCTL */
     127  	sys_ioctl(-1, COUNTER_DISABLE_EVENTS_IOCTL, magic);
     128  	printf("ioctl(-1, " XLAT_FMT ") = %s\n",
     129  	       XLAT_ARGS_U(COUNTER_DISABLE_EVENTS_IOCTL), errstr);
     130  
     131  	puts("+++ exited with 0 +++");
     132  	return 0;
     133  }