summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Syromyatnikov <evgsyr@gmail.com>2018-10-23 17:57:22 +0200
committerEugene Syromyatnikov <evgsyr@gmail.com>2022-08-29 20:24:41 +0200
commit65819010e6652196f9b6b0b48aa6176cc4d5f026 (patch)
treeb8a7966257302703a375093b3cdefe48bcb8d036
parent10eba44cada1ce0193ab7d191795779736672ca7 (diff)
downloadstrace-esyr/ptp.tar.gz
ptp: update decoderesyr/ptp
CHECK_*_SIZE checks are added as minimum safe-guards against implicit decoding breakages, since the types infrastructure, that would allow proper checking, has been removed in v5.11~8. * xlat/ptp_pin_funcs.in: New file. * ptp.c: Include "xlat/ptp_pin_funcs.h". (print_ptp_clock_time): Add rtc argument that signifies that the clock data is RTC-like, so it is worthy of pretty-printing; print reserved field if it is non-zero; print time in the ISO 8601 format only if rtc argument is set and the xlat decoding format is not raw. (print_ptp_clock_time_am): Pass true in the rtc argument to print_ptp_clock_time. (print_ptp_clock_time3_am): New function. (PRINT_RSV): New macro. (ptp_ioctl): Re-order switch cases to reflect the ioctl macros declaration order. (ptp_ioctl) <case PTP_CLOCK_GETCAPS, case PTP_CLOCK_GETCAPS2>: Add size checks; print n_pins, cross_timestamping, adjust_phase, and non-zero rsv fields. (ptp_ioctl) <case PTP_EXTTS_REQUEST, case PTP_EXTTS_REQUEST2>: Add size checks; print index field as unsigned; print non-zero rsv field for PTP_EXTTS_REQUEST2. (ptp_ioctl) <case PTP_PEROUT_REQUEST, case PTP_PEROUT_REQUEST2>: Add size checks; print either phase (non-RTC) or start (RTC) field depending on the presence of PTP_PEROUT_PHASE among flags; print period as non-RTC value; print index as unsigned; print "PTP_PEROUT_???" instead of "PTP_???" as flags fallback value; print either on field or non-zero rsv field (only for PTP_PEROUT_REQUEST2) depending on presence of PTP_PEROUT_DUTY_CYCLE among flags. (ptp_ioctl) <case PTP_ENABLE_PPS, case PTP_ENABLE_PPS>: Print arg as unsigned. (ptp_ioctl) <case PTP_SYS_OFFSET, case PTP_SYS_OFFSET2>: Add size checks; print non-zero rsv field on entering; do not interpret the structure as unavailable in case of syscall error; use MIN macro for n_samples calculation instead of open-coding it. (ptp_ioctl) <case PTP_PIN_GETFUNC, case PTP_PIN_GETFUNC2, case PTP_PIN_SETFUNC, case PTP_PIN_SETFUNC2, case PTP_SYS_OFFSET_PRECISE, case PTP_SYS_OFFSET_PRECISE2, case PTP_SYS_OFFSET_EXTENDED, case PTP_SYS_OFFSET_EXTENDED2>: Implement decoding. * tests/.gitignore: Add ioctl_ptp-Xabbrev, ioctl_ptp-Xraw, ioctl_ptp-Xverbose, ioctl_ptp-success, ioctl_ptp-success-Xabbrev, ioctl_ptp-success-Xraw, and ioctl_ptp-success-Xverbose. * tests/Makefile.am (check_PROGRAMS): Add ioctl_ptp-success, ioctl_ptp-success-Xabbrev, ioctl_ptp-success-Xraw, and ioctl_ptp-success-Xverbose. * tests/gen_tests.in (ioctl_ptp-Xabbrev, ioctl_ptp-Xraw, ioctl_ptp-Xverbose, ioctl_ptp-success, ioctl_ptp-success-Xabbrev, ioctl_ptp-success-Xraw, ioctl_ptp-success-Xverbose): New tests. * tests/ioctl_ptp-Xabbrev.c: New file. * tests/ioctl_ptp-Xraw.c: Likewise. * tests/ioctl_ptp-Xverbose.c: Likewise. * tests/ioctl_ptp-success-Xabbrev.c: Likewise. * tests/ioctl_ptp-success-Xraw.c: Likewise. * tests/ioctl_ptp-success-Xverbose.c: Likewise. * tests/ioctl_ptp-success.c: Likewise. * tests/ioctl_ptp.c: Update expected output, add checks. * tests/pure_executables.list: Add ioctl_ptp-Xabbrev, ioctl_ptp-Xraw, and ioctl_ptp-Xverbose. * NEWS: Mention it.
-rw-r--r--NEWS1
-rw-r--r--src/ptp.c247
-rw-r--r--src/xlat/ptp_pin_funcs.in6
-rw-r--r--tests/.gitignore7
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/gen_tests.in9
-rw-r--r--tests/ioctl_ptp-Xabbrev.c2
-rw-r--r--tests/ioctl_ptp-Xraw.c2
-rw-r--r--tests/ioctl_ptp-Xverbose.c2
-rw-r--r--tests/ioctl_ptp-success-Xabbrev.c2
-rw-r--r--tests/ioctl_ptp-success-Xraw.c2
-rw-r--r--tests/ioctl_ptp-success-Xverbose.c2
-rw-r--r--tests/ioctl_ptp-success.c2
-rw-r--r--tests/ioctl_ptp.c683
-rwxr-xr-xtests/pure_executables.list3
15 files changed, 854 insertions, 120 deletions
diff --git a/NEWS b/NEWS
index bd1c40560..b2c3df68a 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Noteworthy changes in release ?.?? (????-??-??)
===============================================
* Improvements
+ * Enhanced decoding of PTP_* ioctl commands.
* Bug fixes
diff --git a/src/ptp.c b/src/ptp.c
index 43b1b666e..65fbc5245 100644
--- a/src/ptp.c
+++ b/src/ptp.c
@@ -14,26 +14,59 @@
# include "xlat/ptp_extts_flags.h"
# include "xlat/ptp_perout_flags.h"
+# include "xlat/ptp_pin_funcs.h"
static void
-print_ptp_clock_time(const struct ptp_clock_time *const p)
+print_ptp_clock_time(const struct ptp_clock_time *const p, bool rtc)
{
tprint_struct_begin();
PRINT_FIELD_D(*p, sec);
tprint_struct_next();
PRINT_FIELD_U(*p, nsec);
+ if (p->reserved) {
+ tprint_struct_next();
+ PRINT_FIELD_X(*p, reserved);
+ }
tprint_struct_end();
- tprints_comment(sprinttime_nsec(p->sec, p->nsec));
+
+ if (rtc && xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW)
+ tprints_comment(sprinttime_nsec(p->sec, p->nsec));
}
static bool
print_ptp_clock_time_am(struct tcb *tcp, void *elem_buf, size_t elem_size,
void *data)
{
- print_ptp_clock_time(elem_buf);
+ print_ptp_clock_time(elem_buf, true);
return true;
}
+static bool
+print_ptp_clock_time3_am(struct tcb *tcp, void *elem_buf, size_t elem_size,
+ void *data)
+{
+ const struct ptp_clock_time *const p = elem_buf;
+
+ tprint_array_begin();
+ print_ptp_clock_time(p, true);
+ tprint_array_next();
+ print_ptp_clock_time(p + 1, true);
+ tprint_array_next();
+ print_ptp_clock_time(p + 2, true);
+ tprint_array_end();
+
+ return true;
+}
+
+#define PRINT_RSV(where_, field_) \
+ do { \
+ if (!IS_ARRAY_ZERO(where_.field_)) { \
+ tprint_struct_next(); \
+ PRINT_FIELD_ARRAY(where_, field_, tcp, \
+ print_xint_array_member); \
+ } \
+ } while (0)
+
int
ptp_ioctl(struct tcb *const tcp, const unsigned int code,
const kernel_ulong_t arg)
@@ -42,18 +75,59 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code,
return RVAL_DECODED;
switch (code) {
+ case PTP_CLOCK_GETCAPS:
+ case PTP_CLOCK_GETCAPS2: {
+ struct ptp_clock_caps caps;
+ CHECK_TYPE_SIZE(caps.rsv, sizeof(unsigned int) * 12);
+ CHECK_IOCTL_SIZE(PTP_CLOCK_GETCAPS, 80);
+ CHECK_IOCTL_SIZE(PTP_CLOCK_GETCAPS2, 80);
+
+ if (entering(tcp)) {
+ tprint_arg_next();
+ return 0;
+ }
+
+ if (umove_or_printaddr(tcp, arg, &caps))
+ break;
+
+ tprint_struct_begin();
+ PRINT_FIELD_D(caps, max_adj);
+ tprint_struct_next();
+ PRINT_FIELD_D(caps, n_alarm);
+ tprint_struct_next();
+ PRINT_FIELD_D(caps, n_ext_ts);
+ tprint_struct_next();
+ PRINT_FIELD_D(caps, n_per_out);
+ tprint_struct_next();
+ PRINT_FIELD_D(caps, pps);
+ tprint_struct_next();
+ PRINT_FIELD_D(caps, n_pins);
+ tprint_struct_next();
+ PRINT_FIELD_D(caps, cross_timestamping);
+ tprint_struct_next();
+ PRINT_FIELD_D(caps, adjust_phase);
+ PRINT_RSV(caps, rsv);
+ tprint_struct_end();
+ break;
+ }
+
case PTP_EXTTS_REQUEST:
case PTP_EXTTS_REQUEST2: {
struct ptp_extts_request extts;
+ CHECK_TYPE_SIZE(extts.rsv, sizeof(unsigned int) * 2);
+ CHECK_IOCTL_SIZE(PTP_EXTTS_REQUEST, 16);
+ CHECK_IOCTL_SIZE(PTP_EXTTS_REQUEST2, 16);
tprint_arg_next();
if (umove_or_printaddr(tcp, arg, &extts))
break;
tprint_struct_begin();
- PRINT_FIELD_D(extts, index);
+ PRINT_FIELD_U(extts, index);
tprint_struct_next();
PRINT_FIELD_FLAGS(extts, flags, ptp_extts_flags, "PTP_???");
+ if (code == PTP_EXTTS_REQUEST2)
+ PRINT_RSV(extts, rsv);
tprint_struct_end();
break;
}
@@ -61,20 +135,37 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code,
case PTP_PEROUT_REQUEST:
case PTP_PEROUT_REQUEST2: {
struct ptp_perout_request perout;
+ CHECK_TYPE_SIZE(perout.rsv, sizeof(unsigned int) * 4);
+ CHECK_IOCTL_SIZE(PTP_PEROUT_REQUEST, 56);
+ CHECK_IOCTL_SIZE(PTP_PEROUT_REQUEST2, 56);
tprint_arg_next();
if (umove_or_printaddr(tcp, arg, &perout))
break;
tprint_struct_begin();
- PRINT_FIELD_OBJ_PTR(perout, start, print_ptp_clock_time);
+ if (perout.flags & PTP_PEROUT_PHASE) {
+ PRINT_FIELD_OBJ_PTR(perout, phase, print_ptp_clock_time,
+ false);
+ } else {
+ PRINT_FIELD_OBJ_PTR(perout, start, print_ptp_clock_time,
+ true);
+ }
tprint_struct_next();
- PRINT_FIELD_OBJ_PTR(perout, period, print_ptp_clock_time);
+ PRINT_FIELD_OBJ_PTR(perout, period, print_ptp_clock_time,
+ false);
tprint_struct_next();
- PRINT_FIELD_D(perout, index);
+ PRINT_FIELD_U(perout, index);
tprint_struct_next();
PRINT_FIELD_FLAGS(perout, flags, ptp_perout_flags,
- "PTP_???");
+ "PTP_PEROUT_???");
+ if (perout.flags & PTP_PEROUT_DUTY_CYCLE) {
+ tprint_struct_next();
+ PRINT_FIELD_OBJ_PTR(perout, on, print_ptp_clock_time,
+ false);
+ } else if (code == PTP_PEROUT_REQUEST2) {
+ PRINT_RSV(perout, rsv);
+ }
tprint_struct_end();
break;
}
@@ -82,12 +173,15 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code,
case PTP_ENABLE_PPS:
case PTP_ENABLE_PPS2:
tprint_arg_next();
- PRINT_VAL_D(arg);
+ PRINT_VAL_X(arg);
break;
case PTP_SYS_OFFSET:
case PTP_SYS_OFFSET2: {
struct ptp_sys_offset sysoff;
+ CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 3);
+ CHECK_IOCTL_SIZE(PTP_SYS_OFFSET, 832);
+ CHECK_IOCTL_SIZE(PTP_SYS_OFFSET2, 832);
if (entering(tcp)) {
tprint_arg_next();
@@ -96,42 +190,145 @@ ptp_ioctl(struct tcb *const tcp, const unsigned int code,
tprint_struct_begin();
PRINT_FIELD_U(sysoff, n_samples);
+ PRINT_RSV(sysoff, rsv);
return 0;
} else {
- if (tfetch_mem(tcp, arg, sizeof(sysoff), &sysoff)) {
+ if (syserror(tcp)) {
+ /* ... */
+ } else if (!umove(tcp, arg, &sysoff)) {
unsigned int n_samples =
- sysoff.n_samples > PTP_MAX_SAMPLES
- ? PTP_MAX_SAMPLES : sysoff.n_samples;
+ MIN(sysoff.n_samples, PTP_MAX_SAMPLES);
tprint_struct_next();
PRINT_FIELD_ARRAY_UPTO(sysoff, ts,
2 * n_samples + 1, tcp,
print_ptp_clock_time_am);
+ } else {
+ tprint_struct_next();
+ tprint_unavailable();
}
tprint_struct_end();
break;
}
}
- case PTP_CLOCK_GETCAPS:
- case PTP_CLOCK_GETCAPS2: {
- struct ptp_clock_caps caps;
- if (entering(tcp))
+ case PTP_PIN_GETFUNC:
+ case PTP_PIN_GETFUNC2:
+ case PTP_PIN_SETFUNC:
+ case PTP_PIN_SETFUNC2: {
+ struct ptp_pin_desc pinfunc;
+ CHECK_TYPE_SIZE(pinfunc.rsv, sizeof(unsigned int) * 5);
+ CHECK_IOCTL_SIZE(PTP_PIN_GETFUNC, 96);
+ CHECK_IOCTL_SIZE(PTP_PIN_GETFUNC2, 96);
+ CHECK_IOCTL_SIZE(PTP_PIN_SETFUNC, 96);
+ CHECK_IOCTL_SIZE(PTP_PIN_SETFUNC2, 96);
+
+ if (entering(tcp)) {
+ tprint_arg_next();
+
+ if (umove_or_printaddr(tcp, arg, &pinfunc))
+ break;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(pinfunc, index);
+
+ switch (code) {
+ case PTP_PIN_GETFUNC2:
+ PRINT_RSV(pinfunc, rsv);
+ ATTRIBUTE_FALLTHROUGH;
+ case PTP_PIN_GETFUNC:
+ return 0;
+ }
+ } else /* getter syscall exit */ {
+ if (syserror(tcp)) {
+ tprint_struct_end();
+ break;
+ }
+
+ if (umove(tcp, arg, &pinfunc) < 0) {
+ tprint_arg_next();
+ tprint_unavailable();
+ tprint_struct_end();
+ break;
+ }
+ }
+
+ /* setter syscall enter or getter syscall exit */
+ switch (code) {
+ case PTP_PIN_GETFUNC:
+ case PTP_PIN_GETFUNC2:
+ tprint_struct_next();
+ PRINT_FIELD_CSTRING(pinfunc, name);
+ }
+ tprint_struct_next();
+ PRINT_FIELD_XVAL(pinfunc, func, ptp_pin_funcs, "PTP_PF_???");
+ tprint_struct_next();
+ PRINT_FIELD_U(pinfunc, chan);
+ if (code == PTP_PIN_SETFUNC2) {
+ PRINT_RSV(pinfunc, rsv);
+ }
+ tprint_struct_end();
+ break;
+ }
+
+ case PTP_SYS_OFFSET_PRECISE:
+ case PTP_SYS_OFFSET_PRECISE2: {
+ struct ptp_sys_offset_precise sysoff;
+ CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 4);
+ CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_PRECISE, 64);
+ CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_PRECISE2, 64);
+
+ if (entering(tcp)) {
+ tprint_arg_next();
return 0;
+ }
- tprint_arg_next();
- if (umove_or_printaddr(tcp, arg, &caps))
+ if (umove_or_printaddr(tcp, arg, &sysoff))
break;
tprint_struct_begin();
- PRINT_FIELD_D(caps, max_adj);
- tprint_struct_next();
- PRINT_FIELD_D(caps, n_alarm);
+ PRINT_FIELD_OBJ_PTR(sysoff, device, print_ptp_clock_time, true);
tprint_struct_next();
- PRINT_FIELD_D(caps, n_ext_ts);
- tprint_struct_next();
- PRINT_FIELD_D(caps, n_per_out);
+ PRINT_FIELD_OBJ_PTR(sysoff, sys_realtime, print_ptp_clock_time,
+ true);
tprint_struct_next();
- PRINT_FIELD_D(caps, pps);
+ PRINT_FIELD_OBJ_PTR(sysoff, sys_monoraw, print_ptp_clock_time,
+ false);
+ PRINT_RSV(sysoff, rsv);
+ tprint_struct_end();
+ break;
+ }
+
+ case PTP_SYS_OFFSET_EXTENDED:
+ case PTP_SYS_OFFSET_EXTENDED2: {
+ struct ptp_sys_offset_extended sysoff;
+ CHECK_TYPE_SIZE(sysoff.rsv, sizeof(unsigned int) * 3);
+ CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_EXTENDED, 1216);
+ CHECK_IOCTL_SIZE(PTP_SYS_OFFSET_EXTENDED2, 1216);
+
+ if (entering(tcp)) {
+ tprint_arg_next();
+ if (umove_or_printaddr(tcp, arg, &sysoff))
+ break;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(sysoff, n_samples);
+ PRINT_RSV(sysoff, rsv);
+ return 0;
+ }
+
+ if (syserror(tcp)) {
+ /* ... */
+ } else if (!umove(tcp, arg, &sysoff)) {
+ unsigned int n_samples =
+ MIN(sysoff.n_samples, PTP_MAX_SAMPLES);
+ tprint_struct_next();
+ PRINT_FIELD_ARRAY_UPTO(sysoff, ts,
+ n_samples, tcp,
+ print_ptp_clock_time3_am);
+ } else {
+ tprint_struct_next();
+ tprint_unavailable();
+ }
tprint_struct_end();
break;
}
diff --git a/src/xlat/ptp_pin_funcs.in b/src/xlat/ptp_pin_funcs.in
new file mode 100644
index 000000000..7226b9279
--- /dev/null
+++ b/src/xlat/ptp_pin_funcs.in
@@ -0,0 +1,6 @@
+#enum
+#value_indexed
+PTP_PF_NONE 0
+PTP_PF_EXTTS 1
+PTP_PF_PEROUT 2
+PTP_PF_PHYSYNC 3
diff --git a/tests/.gitignore b/tests/.gitignore
index 62c0844be..a8d2ffa94 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -349,6 +349,13 @@ ioctl_nsfs
ioctl_perf
ioctl_perf-success
ioctl_ptp
+ioctl_ptp-Xabbrev
+ioctl_ptp-Xraw
+ioctl_ptp-Xverbose
+ioctl_ptp-success
+ioctl_ptp-success-Xabbrev
+ioctl_ptp-success-Xraw
+ioctl_ptp-success-Xverbose
ioctl_random
ioctl_rtc
ioctl_rtc-success
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 452fcfa76..9ef7d751a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -216,6 +216,10 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
ioctl_mtd-success \
ioctl_nsfs \
ioctl_perf-success \
+ ioctl_ptp-success \
+ ioctl_ptp-success-Xabbrev \
+ ioctl_ptp-success-Xraw \
+ ioctl_ptp-success-Xverbose \
ioctl_rtc-success \
ioctl_rtc-v \
ioctl_seccomp \
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 5a7074dd8..5c059e0ac 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -366,7 +366,14 @@ ioctl_nbd +ioctl.test -y
ioctl_nsfs +ioctl.test -esignal=none
ioctl_perf +ioctl.test
ioctl_perf-success +ioctl-success.sh -a35
-ioctl_ptp +ioctl.test
+ioctl_ptp +ioctl.test -a29
+ioctl_ptp-Xabbrev +ioctl.test -a29 -Xabbrev
+ioctl_ptp-Xraw +ioctl.test -a20 -s51 -Xraw
+ioctl_ptp-Xverbose +ioctl.test -a46 -s51 -Xverbose
+ioctl_ptp-success +ioctl-success.sh -a29
+ioctl_ptp-success-Xabbrev +ioctl-success.sh -a29 -Xabbrev
+ioctl_ptp-success-Xraw +ioctl-success.sh -a20 -s51 -Xraw
+ioctl_ptp-success-Xverbose +ioctl-success.sh -a46 -s51 -Xverbose
ioctl_random +ioctl.test
ioctl_rtc +ioctl.test
ioctl_rtc-success +ioctl-success.sh -a22
diff --git a/tests/ioctl_ptp-Xabbrev.c b/tests/ioctl_ptp-Xabbrev.c
new file mode 100644
index 000000000..6b1a92ef1
--- /dev/null
+++ b/tests/ioctl_ptp-Xabbrev.c
@@ -0,0 +1,2 @@
+#define XLAT_ABBREV 1
+#include "ioctl_ptp.c"
diff --git a/tests/ioctl_ptp-Xraw.c b/tests/ioctl_ptp-Xraw.c
new file mode 100644
index 000000000..471dfe590
--- /dev/null
+++ b/tests/ioctl_ptp-Xraw.c
@@ -0,0 +1,2 @@
+#define XLAT_RAW 1
+#include "ioctl_ptp.c"
diff --git a/tests/ioctl_ptp-Xverbose.c b/tests/ioctl_ptp-Xverbose.c
new file mode 100644
index 000000000..3182564dc
--- /dev/null
+++ b/tests/ioctl_ptp-Xverbose.c
@@ -0,0 +1,2 @@
+#define XLAT_VERBOSE 1
+#include "ioctl_ptp.c"
diff --git a/tests/ioctl_ptp-success-Xabbrev.c b/tests/ioctl_ptp-success-Xabbrev.c
new file mode 100644
index 000000000..4ad4140f3
--- /dev/null
+++ b/tests/ioctl_ptp-success-Xabbrev.c
@@ -0,0 +1,2 @@
+#define XLAT_ABBREV 1
+#include "ioctl_ptp-success.c"
diff --git a/tests/ioctl_ptp-success-Xraw.c b/tests/ioctl_ptp-success-Xraw.c
new file mode 100644
index 000000000..4091833d8
--- /dev/null
+++ b/tests/ioctl_ptp-success-Xraw.c
@@ -0,0 +1,2 @@
+#define XLAT_RAW 1
+#include "ioctl_ptp-success.c"
diff --git a/tests/ioctl_ptp-success-Xverbose.c b/tests/ioctl_ptp-success-Xverbose.c
new file mode 100644
index 000000000..0fde98ea1
--- /dev/null
+++ b/tests/ioctl_ptp-success-Xverbose.c
@@ -0,0 +1,2 @@
+#define XLAT_VERBOSE 1
+#include "ioctl_ptp-success.c"
diff --git a/tests/ioctl_ptp-success.c b/tests/ioctl_ptp-success.c
new file mode 100644
index 000000000..6f2161be0
--- /dev/null
+++ b/tests/ioctl_ptp-success.c
@@ -0,0 +1,2 @@
+#define INJECT_RETVAL 42
+#include "ioctl_ptp.c"
diff --git a/tests/ioctl_ptp.c b/tests/ioctl_ptp.c
index 349b6e364..f5afef663 100644
--- a/tests/ioctl_ptp.c
+++ b/tests/ioctl_ptp.c
@@ -9,11 +9,13 @@
*/
#include "tests.h"
+#include "scno.h"
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ptp_clock.h>
@@ -21,119 +23,612 @@
#include "xlat.h"
#include "xlat/ptp_extts_flags.h"
#include "xlat/ptp_perout_flags.h"
+#include "xlat/ptp_pin_funcs.h"
+
+
+#ifdef INJECT_RETVAL
+# define INJ_STR " (INJECTED)"
+#else
+# define INJ_STR ""
+#endif
+
+#define ARRAY_END(a_) ((a_) + ARRAY_SIZE(a_))
+#define ARR_ITEM(arr_, idx_) ((arr_)[(idx_) % ARRAY_SIZE(arr_)])
+
+#if STRACE_SIZEOF_KERNEL_LONG_T == SIZEOF_KERNEL_LONG_T
+# define SAFE_TIME_T(t_) t_
+#else
+# define SAFE_TIME_T(t_) ((time_t) (t_))
+#endif
+
+static const char *errstr;
+
+static long
+sys_ioctl(kernel_long_t fd, kernel_ulong_t cmd, kernel_ulong_t arg)
+{
+#ifdef INJECT_RETVAL
+ static char buf[256];
+#endif
+ const long rc = syscall(__NR_ioctl, fd, cmd, arg);
+#ifdef INJECT_RETVAL
+ snprintf(buf, sizeof(buf), "%s (INJECTED)", sprintrc(rc));
+ errstr = buf;
+#else
+ errstr = sprintrc(rc);
+#endif
+ return rc;
+}
static void
-test_no_device(void)
+print_lltime(const long long sec, const unsigned long long nsec)
{
- const char *errstr;
+#if !XLAT_RAW
+ if ((time_t) sec != sec)
+ return;
- TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_clock_caps, caps);
- fill_memory(caps, sizeof(*caps));
+ print_time_t_nsec(sec, nsec, 1);
+#endif
+}
- TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset, sysoff);
- fill_memory(sysoff, sizeof(*sysoff));
+static void
+check_bad_ptr(const uint32_t ioc_val, const char *const ioc_str,
+ const void *const p, const size_t sz)
+{
+ sys_ioctl(-1, ioc_val, (uintptr_t) NULL);
+ printf("ioctl(-1, " XLAT_FMT ", NULL) = %s\n",
+ XLAT_SEL(ioc_val, ioc_str), errstr);
- TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_extts_request, extts);
- fill_memory(extts, sizeof(*extts));
+ sys_ioctl(-1, ioc_val, (uintptr_t) p + sz);
+ printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n",
+ XLAT_SEL(ioc_val, ioc_str), p + sz, errstr);
+ sys_ioctl(-1, ioc_val, (uintptr_t) p + 1);
+ printf("ioctl(-1, " XLAT_FMT ", %p) = %s\n",
+ XLAT_SEL(ioc_val, ioc_str), p + 1, errstr);
+}
+
+static void
+test_no_device(void)
+{
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_clock_caps, caps);
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset, sysoff);
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset_extended, soext);
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_sys_offset_precise, soprec);
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_extts_request, extts);
TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_perout_request, perout);
- fill_memory(perout, sizeof(*perout));
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct ptp_pin_desc, pindesc);
+ long rc;
+
+ /* unrecognized */
+ static const uint8_t unk_nums[] = { 0, 19, 20, 255 };
+
+ for (const uint8_t *p = unk_nums; p < ARRAY_END(unk_nums); p++) {
+ for (uint16_t sz = 0; sz < 1280; sz += 8) {
+ static const struct strval32 dirs[] = {
+ { ARG_STR(_IOC_NONE) },
+ { ARG_STR(_IOC_READ) },
+ { ARG_STR(_IOC_WRITE) },
+ { ARG_STR(_IOC_READ|_IOC_WRITE) },
+ };
+ for (const struct strval32 *d = dirs;
+ d < ARRAY_END(dirs); d++) {
+ uint32_t ioc =
+ _IOC(d->val, PTP_CLK_MAGIC, *p, sz);
+ sys_ioctl(-1, ioc, 0);
+ printf("ioctl(-1, "
+ XLAT_KNOWN_FMT("%#x",
+ "_IOC(%s, %#x, %#x, %#x)")
+ ", 0) = %s\n",
+ NABBR(ioc,)
+ NRAW(d->str, PTP_CLK_MAGIC, *p, sz,)
+ errstr);
+
+ /* soprec is the biggest var, at 1216 bytes */
+ sys_ioctl(-1, ioc, (uintptr_t) soext);
+ printf("ioctl(-1, "
+ XLAT_KNOWN_FMT("%#x",
+ "_IOC(%s, %#x, %#x, %#x)")
+ ", %p) = %s\n",
+ NABBR(ioc,)
+ NRAW(d->str, PTP_CLK_MAGIC, *p, sz,)
+ soext, errstr);
+ }
+ }
+ }
+
+ /* PTP_CLOCK_GETCAPS{,2} */
+ static const struct strval32 ioc_caps[] = {
+ { ARG_STR(PTP_CLOCK_GETCAPS) },
+ { ARG_STR(PTP_CLOCK_GETCAPS2) },
+ };
+ for (const struct strval32 *c = ioc_caps; c < ARRAY_END(ioc_caps); c++)
+ {
+ check_bad_ptr(c->val, c->str, caps, sizeof(*caps));
+
+ memset(caps, 0, sizeof(*caps));
+ rc = sys_ioctl(-1, c->val, (uintptr_t) caps);
+ printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str));
+ if (rc >= 0) {
+ printf("{max_adj=0, n_alarm=0, n_ext_ts=0, n_per_out=0"
+ ", pps=0, n_pins=0, cross_timestamping=0"
+ ", adjust_phase=0}");
+ } else {
+ printf("%p", caps);
+ }
+ printf(") = %s\n", errstr);
+
+ fill_memory32(caps, sizeof(*caps));
+ rc = sys_ioctl(-1, c->val, (uintptr_t) caps);
+ printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str));
+ if (rc >= 0) {
+ printf("{max_adj=-2136948512, n_alarm=-2136948511"
+ ", n_ext_ts=-2136948510, n_per_out=-2136948509"
+ ", pps=-2136948508, n_pins=-2136948507"
+ ", cross_timestamping=-2136948506"
+ ", adjust_phase=-2136948505"
+ ", rsv=[0x80a0c0e8, 0x80a0c0e9, 0x80a0c0ea"
+ ", 0x80a0c0eb, 0x80a0c0ec, 0x80a0c0ed"
+ ", 0x80a0c0ee, 0x80a0c0ef, 0x80a0c0f0"
+ ", 0x80a0c0f1, 0x80a0c0f2, 0x80a0c0f3]}");
+ } else {
+ printf("%p", caps);
+ }
+ printf(") = %s\n", errstr);
+ }
+
+ /* PTP_EXTTS_REQUEST{,2} */
+ static const struct strval32 ioc_extts[] = {
+ { ARG_STR(PTP_EXTTS_REQUEST) },
+ { ARG_STR(PTP_EXTTS_REQUEST2) },
+ };
+ static const struct strval32 extts_flags[] = {
+ { ARG_XLAT_KNOWN(0x1, "PTP_ENABLE_FEATURE") },
+ { ARG_XLAT_KNOWN(0xdeadbabe, "PTP_RISING_EDGE|PTP_FALLING_EDGE"
+ "|PTP_STRICT_FLAGS|0xdeadbab0") },
+ { ARG_XLAT_UNKNOWN(0xbadbeef0, "PTP_???") },
+ { ARG_STR(0) },
+ };
+ for (const struct strval32 *c = ioc_extts; c < ARRAY_END(ioc_extts);
+ c++) {
+ check_bad_ptr(c->val, c->str, extts, sizeof(*extts));
- /* PTP_CLOCK_GETCAPS */
- errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS, NULL));
- printf("ioctl(-1, PTP_CLOCK_GETCAPS, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS, caps));
- printf("ioctl(-1, PTP_CLOCK_GETCAPS, %p) = %s\n", caps, errstr);
+ memset(extts, 0, sizeof(*extts));
+ sys_ioctl(-1, c->val, (uintptr_t) extts);
+ printf("ioctl(-1, " XLAT_FMT ", {index=0, flags=0}) = %s\n",
+ XLAT_SEL(c->val, c->str), errstr);
- /* PTP_SYS_OFFSET */
- errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET, NULL));
- printf("ioctl(-1, PTP_SYS_OFFSET, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET, sysoff));
- printf("ioctl(-1, PTP_SYS_OFFSET, {n_samples=%u}) = %s\n",
- sysoff->n_samples, errstr);
+ extts->index = 3141592653;
+ for (size_t i = 0; i < ARRAY_SIZE(extts_flags); i++) {
+ extts->flags = extts_flags[i].val;
+ extts->rsv[0] = i & 1 ? 0xdeadc0de : 0;
+ extts->rsv[1] = i & 2 ? 0xcafebeef : 0;
+
+ sys_ioctl(-1, c->val, (uintptr_t) extts);
+ printf("ioctl(-1, " XLAT_FMT ", {index=3141592653"
+ ", flags=%s",
+ XLAT_SEL(c->val, c->str), extts_flags[i].str);
+ if (c->val == PTP_EXTTS_REQUEST2 && (i & 3)) {
+ printf(", rsv=[%#x, %#x]",
+ i & 1 ? 0xdeadc0de : 0,
+ i & 2 ? 0xcafebeef : 0);
+ }
+ printf("}) = %s\n", errstr);
+
+ }
+ }
+
+ /* PTP_PEROUT_REQUEST{,2} */
+ static const struct strval32 ioc_perout[] = {
+ { ARG_STR(PTP_PEROUT_REQUEST) },
+ { ARG_STR(PTP_PEROUT_REQUEST2) },
+ };
+ static const struct perout_flags {
+ uint32_t is_phase :1,
+ is_duty_cycle :1;
+ uint32_t flags;
+ const char *str;
+ } perout_flags[] = {
+ { false, false, ARG_STR(0) },
+ { false, false, ARG_XLAT_KNOWN(0x1, "PTP_PEROUT_ONE_SHOT") },
+ { false, true, ARG_XLAT_KNOWN(0x3, "PTP_PEROUT_ONE_SHOT"
+ "|PTP_PEROUT_DUTY_CYCLE") },
+ { true, false,
+ ARG_XLAT_KNOWN(0xc0dedbad, "PTP_PEROUT_ONE_SHOT"
+ "|PTP_PEROUT_PHASE|0xc0dedba8") },
+ { true, true,
+ ARG_XLAT_KNOWN(0xdeadbeef,
+ "PTP_PEROUT_ONE_SHOT|PTP_PEROUT_DUTY_CYCLE"
+ "|PTP_PEROUT_PHASE|0xdeadbee8") },
+ { false, false, ARG_XLAT_UNKNOWN(0xdeadbea8, "PTP_PEROUT_???") }
+ };
+ for (const struct strval32 *c = ioc_perout; c < ARRAY_END(ioc_perout);
+ c++) {
+ check_bad_ptr(c->val, c->str, perout, sizeof(*perout));
+
+ memset(perout, 0, sizeof(*perout));
+ sys_ioctl(-1, c->val, (uintptr_t) perout);
+ printf("ioctl(-1, " XLAT_FMT ", {start={sec=0, nsec=0}"
+ ", period={sec=0, nsec=0}, index=0, flags=0}) = %s\n",
+ XLAT_SEL(c->val, c->str), errstr);
+
+ for (size_t i = 0; i < ARRAY_SIZE(perout_flags); i++) {
+ perout->start.sec = SAFE_TIME_T(0x123456789ULL);
+ perout->start.nsec = i & 1 ? 1234567890 : 123456789;
+ perout->start.reserved = i & 2 ? 2718281828 : 0;
+ perout->period.sec = 0xabcdef;
+ perout->period.nsec = i & 1 ? 123456789 : 0;
+ perout->period.reserved = i & 2 ? 0 : 2345678901;
+ perout->index = 3141592653U;
+ perout->flags= perout_flags[i].flags;
+ perout->on.sec = i & 3 ? 0xabcdef0123456789ULL : 0;
+ perout->on.nsec = i & 2 ? 123456789 : 0;
+ perout->on.reserved = i & 4 ? 2345678901U : 0;
+
+ sys_ioctl(-1, c->val, (uintptr_t) perout);
+ printf("ioctl(-1, " XLAT_FMT ", {%s={sec=%lld"
+ ", nsec=%u%s}",
+ XLAT_SEL(c->val, c->str),
+ perout_flags[i].is_phase ? "phase" : "start",
+ perout->start.sec,
+ i & 1 ? 1234567890 : 123456789,
+ i & 2 ? ", reserved=0xa205b064" : "");
+ if (!perout_flags[i].is_phase) {
+ print_lltime(perout->start.sec,
+ perout->start.nsec);
+ }
+ printf(", period={sec=11259375, nsec=%u%s}"
+ ", index=3141592653, flags=%s",
+ i & 1 ? 123456789 : 0,
+ i & 2 ? "" : ", reserved=0x8bd03835",
+ perout_flags[i].str);
+ if (perout_flags[i].is_duty_cycle) {
+ printf(", on={sec=%lld, nsec=%u%s}",
+ i & 3 ? 0xabcdef0123456789ULL : 0,
+ i & 2 ? 123456789 : 0,
+ i & 4 ? ", reserved=0x8bd03835" : "");
+ } else if (i && c->val == PTP_PEROUT_REQUEST2) {
+ printf(", rsv=[%#x, %#x, %#x, %#x]",
+ i & 3 ? BE_LE(0xabcdef01, 0x23456789) : 0,
+ i & 3 ? BE_LE(0x23456789, 0xabcdef01) : 0,
+ i & 2 ? 123456789 : 0,
+ i & 4 ? 2345678901U : 0);
+ }
+ printf("}) = %s\n", errstr);
+ }
+ }
/* PTP_ENABLE_PPS */
- errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS, 0));
- printf("ioctl(-1, PTP_ENABLE_PPS, 0) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS, 1));
- printf("ioctl(-1, PTP_ENABLE_PPS, 1) = %s\n", errstr);
-
- /* PTP_EXTTS_REQUEST */
- errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST, NULL));
- printf("ioctl(-1, PTP_EXTTS_REQUEST, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST, extts));
- printf("ioctl(-1, PTP_EXTTS_REQUEST, {index=%d, flags=", extts->index);
- printflags(ptp_extts_flags, extts->flags, "PTP_???");
- printf("}) = %s\n", errstr);
-
- /* PTP_PEROUT_REQUEST */
- errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST, NULL));
- printf("ioctl(-1, PTP_PEROUT_REQUEST, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST, perout));
- printf("ioctl(-1, PTP_PEROUT_REQUEST"
- ", {start={sec=%" PRId64 ", nsec=%" PRIu32 "}",
- (int64_t) perout->start.sec, perout->start.nsec);
- print_time_t_nsec(perout->start.sec, perout->start.nsec, 1);
- printf(", period={sec=%" PRId64 ", nsec=%" PRIu32 "}",
- (int64_t)perout->period.sec, perout->period.nsec);
- print_time_t_nsec(perout->period.sec, perout->period.nsec, 1);
- printf(", index=%d, flags=", perout->index);
- printflags(ptp_perout_flags, perout->flags, "PTP_???");
- printf("}) = %s\n", errstr);
-
- /* PTP_CLOCK_GETCAPS2 */
- errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS2, NULL));
- printf("ioctl(-1, PTP_CLOCK_GETCAPS2, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_CLOCK_GETCAPS2, caps));
- printf("ioctl(-1, PTP_CLOCK_GETCAPS2, %p) = %s\n", caps, errstr);
-
- /* PTP_SYS_OFFSET2 */
- errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET2, NULL));
- printf("ioctl(-1, PTP_SYS_OFFSET2, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_SYS_OFFSET2, sysoff));
- printf("ioctl(-1, PTP_SYS_OFFSET2, {n_samples=%u}) = %s\n",
- sysoff->n_samples, errstr);
+ sys_ioctl(-1, PTP_ENABLE_PPS, 0);
+ printf("ioctl(-1, %s, 0) = %s\n",
+ XLAT_STR(PTP_ENABLE_PPS), errstr);
+ sys_ioctl(-1, PTP_ENABLE_PPS, -1);
+ printf("ioctl(-1, %s, %#lx) = %s\n",
+ XLAT_STR(PTP_ENABLE_PPS), (long int) -1, errstr);
/* PTP_ENABLE_PPS2 */
- errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS2, 0));
- printf("ioctl(-1, PTP_ENABLE_PPS2, 0) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_ENABLE_PPS2, 1));
- printf("ioctl(-1, PTP_ENABLE_PPS2, 1) = %s\n", errstr);
-
- /* PTP_EXTTS_REQUEST2 */
- errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST2, NULL));
- printf("ioctl(-1, PTP_EXTTS_REQUEST2, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_EXTTS_REQUEST2, extts));
- printf("ioctl(-1, PTP_EXTTS_REQUEST2, {index=%d, flags=", extts->index);
- printflags(ptp_extts_flags, extts->flags, "PTP_???");
- printf("}) = %s\n", errstr);
-
- /* PTP_PEROUT_REQUEST2 */
- errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST2, NULL));
- printf("ioctl(-1, PTP_PEROUT_REQUEST2, NULL) = %s\n", errstr);
- errstr = sprintrc(ioctl(-1, PTP_PEROUT_REQUEST2, perout));
- printf("ioctl(-1, PTP_PEROUT_REQUEST2, {start={sec=%" PRId64
- ", nsec=%" PRIu32 "}, period={sec=%" PRId64 ", nsec=%" PRIu32 "}"
- ", index=%d, flags=",
- (int64_t) perout->start.sec, perout->start.nsec,
- (int64_t)perout->period.sec, perout->period.nsec, perout->index);
- printflags(ptp_perout_flags, perout->flags, "PTP_???");
- printf("}) = %s\n", errstr);
+ sys_ioctl(-1, PTP_ENABLE_PPS2, 0);
+ printf("ioctl(-1, %s, 0) = %s\n",
+ XLAT_STR(PTP_ENABLE_PPS2), errstr);
+ sys_ioctl(-1, PTP_ENABLE_PPS2, -123456789);
+ printf("ioctl(-1, %s, %#lx) = %s\n",
+ XLAT_STR(PTP_ENABLE_PPS2), (long int) -123456789, errstr);
- /* unrecognized */
- ioctl(-1, _IOC(_IOC_READ, PTP_CLK_MAGIC, 0xff, 0xfe), 0);
- printf("ioctl(-1, _IOC(_IOC_READ, %#x, 0xff, 0xfe), 0) = %s\n",
- PTP_CLK_MAGIC, errstr);
-
- const unsigned long arg = (unsigned long) 0xfacefeeddeadbeefULL;
- ioctl(-1, _IOC(_IOC_WRITE, PTP_CLK_MAGIC, 0xfd, 0xfc), arg);
- printf("ioctl(-1, _IOC(_IOC_WRITE, %#x, 0xfd, 0xfc), %#lx)"
- " = %s\n", PTP_CLK_MAGIC, arg, errstr);
+ /* PTP_SYS_OFFSET{,2} */
+ static const struct strval32 ioc_sysoff[] = {
+ { ARG_STR(PTP_SYS_OFFSET) },
+ { ARG_STR(PTP_SYS_OFFSET2) },
+ };
+ for (const struct strval32 *c = ioc_sysoff; c < ARRAY_END(ioc_sysoff);
+ c++) {
+ check_bad_ptr(c->val, c->str, sysoff, sizeof(*sysoff));
+
+ memset(sysoff, 0, sizeof(*sysoff));
+ rc = sys_ioctl(-1, c->val, (uintptr_t) sysoff);
+ printf("ioctl(-1, " XLAT_FMT ", {n_samples=0%s}) = %s\n",
+ XLAT_SEL(c->val, c->str),
+ rc >= 0 ? ", ts=[{sec=0, nsec=0}]" : "", errstr);
+
+ for (size_t i = 0; i < 4; i++) {
+ sysoff->n_samples = i > 2 ? 0xdeadface : i * 12 + 1;
+ sysoff->rsv[0] = i & 1 ? 0xbadfaced : 0;
+ sysoff->rsv[2] = i & 2 ? 0xcafeface : 0;
+ for (size_t j = 0; j < 2 * PTP_MAX_SAMPLES + 1; j++) {
+ sysoff->ts[j].sec = SAFE_TIME_T(2345678901U + j);
+ sysoff->ts[j].nsec = 999999999 - i * 12 + j;
+ sysoff->ts[j].reserved = j & 1 ? 0xdeadface : 0;
+ }
+
+ rc = sys_ioctl(-1, c->val, (uintptr_t) sysoff);
+ printf("ioctl(-1, " XLAT_FMT ", {n_samples=%zu%s%s%s%s",
+ XLAT_SEL(c->val, c->str),
+ i > 2 ? 0xdeadface : i * 12 + 1,
+ i & 3 ? ", rsv=[" : "",
+ i & 3 ? i & 1 ? "0xbadfaced" : "0" : "",
+ i & 3 ? ", 0, " : "",
+ i & 3 ? i & 2 ? "0xcafeface]" : "0]" : "");
+ if (rc >= 0) {
+ for (size_t j = 0;
+ j < MIN(i * 24 + 3,
+ XLAT_RAW || XLAT_VERBOSE ? 51
+ : 32);
+ j++) {
+ printf("%s{sec=%lld, nsec=%u%s}",
+ j ? ", " : ", ts=[",
+ sysoff->ts[j].sec,
+ sysoff->ts[j].nsec,
+ j & 1 ? ", reserved=0xdeadface"
+ : "");
+ print_lltime(sysoff->ts[j].sec,
+ sysoff->ts[j].nsec);
+ }
+ printf("%s]",
+ XLAT_RAW || XLAT_VERBOSE || i < 2
+ ? "" : ", ...");
+ }
+ printf("}) = %s\n", errstr);
+ }
+ }
+
+ /* PTP_PIN_[GS]ETFUNC{,2} */
+ static const struct ioc_pin {
+ uint32_t is_get :1,
+ is_v2 :1;
+ uint32_t val;
+ const char *str;
+ } ioc_pin[] = {
+ { true, false, ARG_STR(PTP_PIN_GETFUNC) },
+ { true, true, ARG_STR(PTP_PIN_GETFUNC2) },
+ { false, false, ARG_STR(PTP_PIN_SETFUNC) },
+ { false, true, ARG_STR(PTP_PIN_SETFUNC2) },
+ };
+ static const struct strval32 pin_funcs[] = {
+ { ENUM_KNOWN(0x1, PTP_PF_EXTTS) },
+ { ENUM_KNOWN(0x3, PTP_PF_PHYSYNC) },
+ { ARG_XLAT_UNKNOWN(0x4, "PTP_PF_???") },
+ { ARG_XLAT_UNKNOWN(0xdeadcafe, "PTP_PF_???") },
+ };
+ for (const struct ioc_pin *c = ioc_pin; c < ARRAY_END(ioc_pin); c++) {
+ check_bad_ptr(c->val, c->str, pindesc, sizeof(*pindesc));
+
+ memset(pindesc, 0, sizeof(*pindesc));
+ rc = sys_ioctl(-1, c->val, (uintptr_t) pindesc);
+ printf("ioctl(-1, " XLAT_FMT ", {index=0",
+ XLAT_SEL(c->val, c->str));
+ if (rc >= 0 || !c->is_get) {
+ printf("%s, func=" XLAT_FMT ", chan=0",
+ c->is_get ? ", name=\"\"" : "",
+ XLAT_ARGS(PTP_PF_NONE));
+ }
+ printf("}) = %s\n", errstr);
+
+ for (size_t i = 0; i < ARRAY_SIZE(pin_funcs); i++) {
+ memcpy(pindesc->name,
+ i & 1 ? "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"
+ "OH HAI THAR\176\177\377\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ : "abcdefghijklmnopqrstuvwxyz0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
+ sizeof(pindesc->name));
+ pindesc->index = 0xcafebabeU;
+ pindesc->func = pin_funcs[i].val;
+ pindesc->chan = 0xfeedbeefU;
+ pindesc->rsv[0] = i & 1 ? 0xbadc0ded : 0;
+ pindesc->rsv[4] = i & 2 ? 0 : 0xdadfaced;
+
+ rc = sys_ioctl(-1, c->val, (uintptr_t) pindesc);
+ printf("ioctl(-1, " XLAT_FMT ", {index=3405691582",
+ XLAT_SEL(c->val, c->str));
+ if (c->is_get && c->is_v2 && (i & 3) != 2) {
+ printf(", rsv=[%#x, 0, 0, 0, %#x]",
+ i & 1 ? 0xbadc0ded : 0,
+ i & 2 ? 0 : 0xdadfaced);
+ }
+ if (rc >= 0 || !c->is_get) {
+ if (c->is_get) {
+ printf(", name=\"%s",
+ i & 1 ? "\\1\\2\\3\\4\\5\\6\\7"
+ "\\10\\t\\n\\v\\f\\r\\16"
+ "\\17OH HAI THAR~\\177"
+ "\\377\""
+ : "abcdefghijklmnopqrstuvw"
+ "xyz0123456789ABCDEFGHIJ"
+ "KLMNOPQRSTUVWXYZ0\""
+ "...");
+ }
+ printf(", func=%s, chan=4276993775",
+ pin_funcs[i].str);
+ if (!c->is_get && c->is_v2
+ && ((i & 1) || !(i & 2))) {
+ printf(", rsv=[%#x, 0, 0, 0, %#x]",
+ i & 1 ? 0xbadc0ded : 0,
+ i & 2 ? 0 : 0xdadfaced);
+ }
+ }
+ printf("}) = %s\n", errstr);
+ }
+ }
+
+ /* PTP_SYS_OFFSET_PRECISE{,2} */
+ static const struct strval32 ioc_soprec[] = {
+ { ARG_STR(PTP_SYS_OFFSET_PRECISE) },
+ { ARG_STR(PTP_SYS_OFFSET_PRECISE2) },
+ };
+ static const struct ptp_clock_time ts_vecs[] = {
+ { 0, 123456789 },
+ { 0x23456789, 0, 0xdeadface },
+ { SAFE_TIME_T(0x123456789ab), 1234567890 },
+ { SAFE_TIME_T(0x123456789abcd), 987654321, 0x1 },
+ };
+ for (const struct strval32 *c = ioc_soprec; c < ARRAY_END(ioc_soprec);
+ c++) {
+ check_bad_ptr(c->val, c->str, soprec, sizeof(*soprec));
+
+ memset(soprec, 0, sizeof(*soprec));
+ rc = sys_ioctl(-1, c->val, (uintptr_t) soprec);
+ printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c->val, c->str));
+ if (rc >= 0) {
+ printf("{device={sec=0, nsec=0}"
+ ", sys_realtime={sec=0, nsec=0}"
+ ", sys_monoraw={sec=0, nsec=0}}");
+ } else {
+ printf("%p", soprec);
+ }
+ printf(") = %s\n", errstr);
+
+ for (size_t i = 0; i < ARRAY_SIZE(ts_vecs); i++) {
+ soprec->device = ts_vecs[i];
+ soprec->sys_realtime = ARR_ITEM(ts_vecs, i + 1);
+ soprec->sys_monoraw = ARR_ITEM(ts_vecs, i + 2);
+ soprec->rsv[0] = i & 1 ? 0 : 0xbadfaced;
+ soprec->rsv[3] = i & 2 ? 0 : 0xdeadbeef;
+
+ rc = sys_ioctl(-1, c->val, (uintptr_t) soprec);
+ printf("ioctl(-1, " XLAT_FMT ", ",
+ XLAT_SEL(c->val, c->str));
+ if (rc >= 0) {
+ printf("{device={sec=%lld, nsec=%u",
+ ts_vecs[i].sec, ts_vecs[i].nsec);
+ if (i & 1) {
+ printf(", reserved=%#x",
+ ts_vecs[i].reserved);
+ }
+ printf("}");
+ print_lltime(ts_vecs[i].sec, ts_vecs[i].nsec);
+ printf(", sys_realtime={sec=%lld, nsec=%u",
+ ARR_ITEM(ts_vecs, i + 1).sec,
+ ARR_ITEM(ts_vecs, i + 1).nsec);
+ if (!(i & 1)) {
+ printf(", reserved=%#x",
+ ARR_ITEM(ts_vecs, i + 1).reserved
+ );
+ }
+ printf("}");
+ print_lltime(ARR_ITEM(ts_vecs, i + 1).sec,
+ ARR_ITEM(ts_vecs, i + 1).nsec);
+ printf(", sys_monoraw={sec=%lld, nsec=%u",
+ ARR_ITEM(ts_vecs, i + 2).sec,
+ ARR_ITEM(ts_vecs, i + 2).nsec);
+ if (i & 1) {
+ printf(", reserved=%#x",
+ ARR_ITEM(ts_vecs, i + 2).reserved
+ );
+ }
+ printf("}");
+ if ((i & 3) != 3) {
+ printf(", rsv=[%#x, 0, 0, %#x]",
+ i & 1 ? 0 : 0xbadfaced,
+ i & 2 ? 0 : 0xdeadbeef);
+ }
+ printf("}");
+ } else {
+ printf("%p", soprec);
+ }
+ printf(") = %s\n", errstr);
+ }
+ }
+
+ /* PTP_SYS_OFFSET_EXTENDED{,2} */
+ static const struct strval32 ioc_soext[] = {
+ { ARG_STR(PTP_SYS_OFFSET_EXTENDED) },
+ { ARG_STR(PTP_SYS_OFFSET_EXTENDED2) },
+ };
+ for (const struct strval32 *c = ioc_soext; c < ARRAY_END(ioc_soext);
+ c++) {
+ check_bad_ptr(c->val, c->str, soext, sizeof(*soext));
+
+ memset(soext, 0, sizeof(*soext));
+ rc = sys_ioctl(-1, c->val, (uintptr_t) soext);
+ printf("ioctl(-1, " XLAT_FMT ", {n_samples=0%s}) = %s\n",
+ XLAT_SEL(c->val, c->str),
+ rc >= 0 ? ", ts=[]" : "", errstr);
+
+ for (size_t i = 0; i < 4; i++) {
+ soext->n_samples = i > 2 ? 0xdeadface : i * 12 + 1;
+ soext->rsv[0] = i & 1 ? 0xbadfaced : 0;
+ soext->rsv[2] = i & 2 ? 0xcafeface : 0;
+ for (size_t j = 0; j < PTP_MAX_SAMPLES; j++) {
+ soext->ts[j][0].sec =
+ SAFE_TIME_T(2345678901U + j);
+ soext->ts[j][0].nsec = 999999999 - i * 12 + j;
+ soext->ts[j][0].reserved = j & 1 ? 0xbee : 0;
+
+ soext->ts[j][1].sec =
+ SAFE_TIME_T(-123456780123L + j);
+ soext->ts[j][1].nsec = -(i * 12) + j;
+ soext->ts[j][1].reserved = j & 2 ? 0xface : 0;
+
+ soext->ts[j][2].sec =
+ SAFE_TIME_T(j * (1 << 30));
+ soext->ts[j][2].nsec = j * (1 << 29);
+ soext->ts[j][2].reserved = j & 4 ? 0xbabe : 0;
+ }
+
+ rc = sys_ioctl(-1, c->val, (uintptr_t) soext);
+ printf("ioctl(-1, " XLAT_FMT ", {n_samples=%zu",
+ XLAT_SEL(c->val, c->str),
+ i > 2 ? 0xdeadface : i * 12 + 1);
+ if (i & 3) {
+ printf(", rsv=[%#x, 0, %#x]",
+ i & 1 ? 0xbadfaced : 0,
+ i & 2 ? 0xcafeface : 0);
+ }
+ if (rc >= 0) {
+ for (size_t j = 0; j < MIN(i * 12 + 1, 25); j++)
+ {
+ printf("%s", j ? "], " : ", ts=[");
+ for (size_t k = 0; k < 3; k++) {
+ printf("%s{sec=%lld, nsec=%u",
+ k ? ", " : "[",
+ soext->ts[j][k].sec,
+ soext->ts[j][k].nsec);
+ if (soext->ts[j][k].reserved)
+ printf(", reserved=%#x",
+ soext->ts[j][k]
+ .reserved);
+ printf("}");
+ print_lltime(
+ soext->ts[j][k].sec,
+ soext->ts[j][k].nsec);
+ }
+ }
+ printf("]]");
+ }
+ printf("}) = %s\n", errstr);
+ }
+ }
}
int
-main(void)
+main(int argc, char *argv[])
{
+#ifdef INJECT_RETVAL
+ unsigned long num_skip;
+ bool locked = false;
+
+ if (argc < 2)
+ error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]);
+
+ num_skip = strtoul(argv[1], NULL, 0);
+ for (unsigned int i = 0; i < num_skip; i++) {
+ long rc = sys_ioctl(-1, PTP_CLOCK_GETCAPS, 0);
+ printf("ioctl(-1, %s, NULL) = %s%s\n",
+ XLAT_STR(PTP_CLOCK_GETCAPS), sprintrc(rc),
+ rc == 42 ? " (INJECTED)" : "");
+
+ if (rc != 42)
+ continue;
+
+ locked = true;
+ break;
+ }
+
+ if (!locked) {
+ error_msg_and_fail("Have not locked on ioctl(-1"
+ ", PTP_CLOCK_GETCAPS, NULL) returning 42");
+ }
+#endif /* INJECT_RETVAL */
+
test_no_device();
puts("+++ exited with 0 +++");
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index e794602dc..451c476f0 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -230,6 +230,9 @@ ioctl_mtd
ioctl_nbd
ioctl_perf
ioctl_ptp
+ioctl_ptp-Xabbrev
+ioctl_ptp-Xraw
+ioctl_ptp-Xverbose
ioctl_random
ioctl_rtc
ioctl_scsi