summaryrefslogtreecommitdiff
path: root/usr.bin/kdump
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2021-12-23 18:50:34 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2021-12-23 18:50:34 +0000
commit5d8c8d969184612e68d66305dcfb6301593fd5a6 (patch)
tree2d2f27ca6a453314dc3f8f60804609bd242bf088 /usr.bin/kdump
parent400f5fa45fbb01e26f1de58370473241bef85589 (diff)
Roll the syscalls that have an off_t argument to remove the explicit padding.
Switch libc and ld.so to the generic stubs for these calls. WARNING: reboot to updated kernel before installing libc or ld.so! Time for a story... When gcc (back in 1.x days) first implemented long long, it didn't (always) pass 64bit arguments in 'aligned' registers/stack slots, with the result that argument offsets didn't match structure offsets. This affected the nine system calls that pass off_t arguments: ftruncate lseek mmap mquery pread preadv pwrite pwritev truncate To avoid having to do custom ASM wrappers for those, BSD put an explicit pad argument in so that the off_t argument would always start on a even slot and thus be naturally aligned. Thus those odd wrappers in lib/libc/sys/ that use __syscall() and pass an extra '0' argument. The ABIs for different CPUs eventually settled how things should be passed on each and gcc 2.x followed them. The only arch now where it helps is landisk, which needs to skip the last argument register if it would be the first half of a 64bit argument. So: add new syscalls without the pad argument and on landisk do that skipping directly in the syscall handler in the kernel. Keep compat support for the existing syscalls long enough for the transition. ok deraadt@
Diffstat (limited to 'usr.bin/kdump')
-rw-r--r--usr.bin/kdump/kdump.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index 52356862c40..c6e4f1786ad 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kdump.c,v 1.144 2021/07/12 15:09:19 beck Exp $ */
+/* $OpenBSD: kdump.c,v 1.145 2021/12/23 18:50:32 guenther Exp $ */
/*-
* Copyright (c) 1988, 1993
@@ -62,9 +62,10 @@
#include <netdb.h>
#include <poll.h>
#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <vis.h>
@@ -468,6 +469,10 @@ poctint(int arg)
#define Phexlonglong Phexlong
#define phexll NULL /* not actually used on LP64 */
+/* no padding before long long arguments, nor at end */
+#define PAD64 0
+#define END64 end_of_args
+
#else /* __LP64__ */
/* on ILP32, long long arguments are passed as two 32bit args */
@@ -491,6 +496,17 @@ phexll(long arg2)
return (0);
}
+/*
+ * Some ILP32 archs naturally align off_t arguments to 8byte boundaries
+ * Get the compiler to tell if this arch is one of them.
+ */
+struct padding_test {
+ int padtest_one;
+ off_t padtest_two;
+};
+#define PAD64 (offsetof(struct padding_test,padtest_two) == 8)
+#define END64 (PAD64 ? PASS_LONGLONG : end_of_args)
+
#endif /* __LP64__ */
static int (*long_formatters[])(long) = {
@@ -799,8 +815,12 @@ static const formatter scargs[][8] = {
[SYS_nfssvc] = { Phexint, Pptr },
[SYS_getfh] = { Ppath, Pptr },
[SYS_sysarch] = { Pdecint, Pptr },
- [SYS_pread] = { Pfd, Pptr, Pbigsize, PAD, Poff_t },
- [SYS_pwrite] = { Pfd, Pptr, Pbigsize, PAD, Poff_t },
+ [SYS_pread] = { Pfd, Pptr, Pbigsize, Poff_t, END64 },
+ [SYS_pwrite] = { Pfd, Pptr, Pbigsize, Poff_t, END64 },
+#ifdef SYS_pad_pread
+ [SYS_pad_pread] = { Pfd, Pptr, Pbigsize, PAD, Poff_t },
+ [SYS_pad_pwrite] = { Pfd, Pptr, Pbigsize, PAD, Poff_t },
+#endif
[SYS_setgid] = { Gidname },
[SYS_setegid] = { Gidname },
[SYS_seteuid] = { Uidname },
@@ -809,10 +829,16 @@ static const formatter scargs[][8] = {
[SYS_swapctl] = { Swapctlname, Pptr, Pdecint },
[SYS_getrlimit] = { Rlimitname, Pptr },
[SYS_setrlimit] = { Rlimitname, Pptr },
- [SYS_mmap] = { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, PAD, Poff_t },
- [SYS_lseek] = { Pfd, PAD, Poff_t, Whencename },
- [SYS_truncate] = { Ppath, PAD, Poff_t },
- [SYS_ftruncate] = { Pfd, PAD, Poff_t },
+ [SYS_mmap] = { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, Poff_t, END64 },
+ [SYS_lseek] = { Pfd, Poff_t, Whencename, END64 },
+ [SYS_truncate] = { Ppath, Poff_t, END64 },
+ [SYS_ftruncate] = { Pfd, Poff_t, END64 },
+#ifdef SYS_pad_mmap
+ [SYS_pad_mmap] = { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, PAD, Poff_t },
+ [SYS_pad_lseek] = { Pfd, PAD, Poff_t, Whencename },
+ [SYS_pad_truncate] = { Ppath, PAD, Poff_t },
+ [SYS_pad_ftruncate] = { Pfd, PAD, Poff_t },
+#endif
[SYS_sysctl] = { Pptr, Pcount, Pptr, Pptr, Pptr, Psize },
[SYS_mlock] = { Pptr, Pbigsize },
[SYS_munlock] = { Pptr, Pbigsize },
@@ -831,14 +857,21 @@ static const formatter scargs[][8] = {
[SYS_msync] = { Pptr, Pbigsize, Msyncflagsname },
[SYS_pipe] = { Pptr },
[SYS_fhopen] = { Pptr, Openflagsname },
- [SYS_preadv] = { Pfd, Pptr, Pcount, PAD, Poff_t },
- [SYS_pwritev] = { Pfd, Pptr, Pcount, PAD, Poff_t },
+ [SYS_preadv] = { Pfd, Pptr, Pcount, Poff_t, END64 },
+ [SYS_pwritev] = { Pfd, Pptr, Pcount, Poff_t, END64 },
+#ifdef SYS_pad_preadv
+ [SYS_pad_preadv] = { Pfd, Pptr, Pcount, PAD, Poff_t },
+ [SYS_pad_pwritev] = { Pfd, Pptr, Pcount, PAD, Poff_t },
+#endif
[SYS_mlockall] = { Mlockallname },
[SYS_getresuid] = { Pptr, Pptr, Pptr },
[SYS_setresuid] = { Uidname, Uidname, Uidname },
[SYS_getresgid] = { Pptr, Pptr, Pptr },
[SYS_setresgid] = { Gidname, Gidname, Gidname },
- [SYS_mquery] = { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, PAD, Poff_t },
+ [SYS_mquery] = { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, Poff_t, END64 },
+#ifdef SYS_pad_mquery
+ [SYS_pad_mquery] = { Pptr, Pbigsize, Mmapprotname, Mmapflagsname, Pfd, PAD, Poff_t },
+#endif
[SYS_closefrom] = { Pfd },
[SYS_sigaltstack] = { Pptr, Pptr },
[SYS_shmget] = { Pkey_t, Pbigsize, Semgetname },
@@ -922,8 +955,11 @@ ktrsyscall(struct ktr_syscall *ktr, size_t ktrlen)
} else if (ktr->ktr_code < nitems(scargs)) {
const formatter *fmts = scargs[ktr->ktr_code];
int fmt;
+ int arg = 0;
- while (narg && (fmt = *fmts) != 0) {
+ while (arg < narg && (fmt = *fmts) != 0) {
+ if (PAD64 && fmt == PASS_LONGLONG && (arg & 1))
+ goto skip;
if (sep)
putchar(sep);
sep = ',';
@@ -934,9 +970,11 @@ ktrsyscall(struct ktr_syscall *ktr, size_t ktrlen)
else if (long_formatters[-fmt](*ap))
sep = '\0';
fmts++;
+skip:
ap++;
- narg--;
+ arg++;
}
+ narg -= arg;
}
while (narg > 0) {
@@ -1106,6 +1144,9 @@ doerr:
if (fancy) {
switch (code) {
case SYS_lseek:
+#ifdef SYS_pad_lseek
+ case SYS_pad_lseek:
+#endif
(void)printf("%lld", retll);
if (retll < 0 || retll > 9)
(void)printf("/%#llx", retll);