From owner-svn-src-all@freebsd.org Wed Mar 15 23:08:12 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 70124D0E270; Wed, 15 Mar 2017 23:08:12 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2DF9310CB; Wed, 15 Mar 2017 23:08:12 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v2FN8BJa097483; Wed, 15 Mar 2017 23:08:11 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v2FN8B7r097482; Wed, 15 Mar 2017 23:08:11 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201703152308.v2FN8B7r097482@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Wed, 15 Mar 2017 23:08:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315336 - head/usr.bin/truss X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Mar 2017 23:08:12 -0000 Author: jhb Date: Wed Mar 15 23:08:11 2017 New Revision: 315336 URL: https://svnweb.freebsd.org/changeset/base/315336 Log: Automate the handling of QUAD_ALIGN and QUAD_SLOTS. Previously, the offset in a system call description specified the array index of the start of a system call argument. For most system call arguments this was the same as the index of the argument in the function signature. 64-bit arguments (off_t and id_t values) passed on 32-bit platforms use two slots in the array however. This was handled by adding (QUAD_SLOTS - 1) to the slot indicies of any subsequent arguments after a 64-bit argument (though written as ("{ Quad, 1 }, { Int, 1 + QUAD_SLOTS }" rather than "{ Quad, 1 }, { Int, 2 + QUAD_SLOTS - 1 }"). If a system call contained multiple 64-bit arguments (such as posix_fadvise()), then additional arguments would need to use 'QUAD_SLOTS * 2' but remember to subtract 2 from the initial number, etc. In addition, 32-bit powerpc requires 64-bit arguments to be 64-bit aligned, so if the effective index in the array of a 64-bit argument is odd, it needs QUAD_ALIGN added to the current and any subsequent slots. However, if the effective index in the array of a 64-bit argument was even, QUAD_ALIGN was omitted. This approach was messy and error prone. This commit replaces it with automated pre-processing of the system call table to do fixups for 64-bit argument offsets. The offset in a system call description now indicates the index of an argument in the associated function call's signature. A fixup function is run against each decoded system call description during startup on 32-bit platforms. The fixup function maintains an 'offset' value which holds an offset to be added to each remaining system call argument's index. Initially offset is 0. When a 64-bit system call argument is encountered, the offset is first aligned to a 64-bit boundary (only on powerpc) and then incremented to account for the second argument slot used by the argument. This modified 'offset' is then applied to any remaining arguments. This approach does require a few things that were not previously required: 1) Each system call description must now list arguments in ascending order (existing ones all do) without using duplicate slots in the register array. A new assert() should catch any future descriptions which violate this rule. 2) A system call description is still permitted to omit arguments (though none currently do), but if the call accepts 64-bit arguments those cannot be omitted or incorrect results will be displated on 32-bit systems. Tested on: amd64 and i386 Modified: head/usr.bin/truss/syscalls.c Modified: head/usr.bin/truss/syscalls.c ============================================================================== --- head/usr.bin/truss/syscalls.c Wed Mar 15 22:39:15 2017 (r315335) +++ head/usr.bin/truss/syscalls.c Wed Mar 15 23:08:11 2017 (r315336) @@ -71,20 +71,6 @@ __FBSDID("$FreeBSD$"); #include "extern.h" #include "syscall.h" -/* 64-bit alignment on 32-bit platforms. */ -#if !defined(__LP64__) && defined(__powerpc__) -#define QUAD_ALIGN 1 -#else -#define QUAD_ALIGN 0 -#endif - -/* Number of slots needed for a 64-bit argument. */ -#ifdef __LP64__ -#define QUAD_SLOTS 1 -#else -#define QUAD_SLOTS 2 -#endif - /* * This should probably be in its own file, sorted alphabetically. */ @@ -154,7 +140,7 @@ static struct syscall decoded_syscalls[] { .name = "fstatfs", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { StatFs | OUT, 1 } } }, { .name = "ftruncate", .ret_type = 1, .nargs = 2, - .args = { { Int | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } }, + .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } }, { .name = "futimens", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timespec2 | IN, 1 } } }, { .name = "futimes", .ret_type = 1, .nargs = 2, @@ -210,8 +196,7 @@ static struct syscall decoded_syscalls[] .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 }, { Atflags, 4 } } }, { .name = "lseek", .ret_type = 2, .nargs = 3, - .args = { { Int, 0 }, { QuadHex, 1 + QUAD_ALIGN }, - { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } }, + .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } }, { .name = "lstat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, { .name = "lutimes", .ret_type = 1, .nargs = 2, @@ -230,7 +215,7 @@ static struct syscall decoded_syscalls[] .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } }, { .name = "mmap", .ret_type = 1, .nargs = 6, .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, - { Int, 4 }, { QuadHex, 5 + QUAD_ALIGN } } }, + { Int, 4 }, { QuadHex, 5 } } }, { .name = "modfind", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "mount", .ret_type = 1, .nargs = 4, @@ -257,9 +242,7 @@ static struct syscall decoded_syscalls[] { .name = "posix_openpt", .ret_type = 1, .nargs = 1, .args = { { Open, 0 } } }, { .name = "procctl", .ret_type = 1, .nargs = 4, - .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN }, - { Procctl, 1 + QUAD_ALIGN + QUAD_SLOTS }, - { Ptr, 2 + QUAD_ALIGN + QUAD_SLOTS } } }, + .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } }, { .name = "read", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } }, { .name = "readlink", .ret_type = 1, .nargs = 3, @@ -326,7 +309,7 @@ static struct syscall decoded_syscalls[] { .name = "thr_self", .ret_type = 1, .nargs = 1, .args = { { Ptr, 0 } } }, { .name = "truncate", .ret_type = 1, .nargs = 2, - .args = { { Name | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } }, + .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } }, #if 0 /* Does not exist */ { .name = "umount", .ret_type = 1, .nargs = 2, @@ -349,11 +332,8 @@ static struct syscall decoded_syscalls[] .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 }, { Rusage | OUT, 3 } } }, { .name = "wait6", .ret_type = 1, .nargs = 6, - .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN }, - { ExitStatus | OUT, 1 + QUAD_ALIGN + QUAD_SLOTS }, - { Waitoptions, 2 + QUAD_ALIGN + QUAD_SLOTS }, - { Rusage | OUT, 3 + QUAD_ALIGN + QUAD_SLOTS }, - { Ptr, 4 + QUAD_ALIGN + QUAD_SLOTS } } }, + .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 }, + { Waitoptions, 3 }, { Rusage | OUT, 4 }, { Ptr, 5 } } }, { .name = "write", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } }, @@ -811,14 +791,65 @@ print_mask_arg(bool (*decoder)(FILE *, i fprintf(fp, "|0x%x", rem); } +#ifndef __LP64__ +/* + * Add argument padding to subsequent system calls afater a Quad + * syscall arguments as needed. This used to be done by hand in the + * decoded_syscalls table which was ugly and error prone. It is + * simpler to do the fixup of offsets at initalization time than when + * decoding arguments. + */ +static void +quad_fixup(struct syscall *sc) +{ + int offset, prev; + u_int i; + + offset = 0; + prev = -1; + for (i = 0; i < sc->nargs; i++) { + /* This arg type is a dummy that doesn't use offset. */ + if ((sc->args[i].type & ARG_MASK) == PipeFds) + continue; + + assert(prev < sc->args[i].offset); + prev = sc->args[i].offset; + sc->args[i].offset += offset; + switch (sc->args[i].type & ARG_MASK) { + case Quad: + case QuadHex: +#ifdef __powerpc__ + /* + * 64-bit arguments on 32-bit powerpc must be + * 64-bit aligned. If the current offset is + * not aligned, the calling convention inserts + * a 32-bit pad argument that should be skipped. + */ + if (sc->args[i].offset % 2 == 1) { + sc->args[i].offset++; + offset++; + } +#endif + offset++; + default: + break; + } + } +} +#endif + void init_syscalls(void) { struct syscall *sc; STAILQ_INIT(&syscalls); - for (sc = decoded_syscalls; sc->name != NULL; sc++) + for (sc = decoded_syscalls; sc->name != NULL; sc++) { +#ifndef __LP64__ + quad_fixup(sc); +#endif STAILQ_INSERT_HEAD(&syscalls, sc, entries); + } } static struct syscall *