Commit 8a0f6d8c authored by Dmitry Chagin's avatar Dmitry Chagin
Browse files

kdump: Add preliminary support for decoding Linux syscalls

Reviewed by:		jhb
Differential revision:	https://reviews.freebsd.org/D35216
MFC after:		2 weeks
parent 8b8e2e8f
......@@ -17,4 +17,11 @@ LIBADD+= cap_pwd
CFLAGS+=-DWITH_CASPER
.endif
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \
${MACHINE_CPUARCH} == "i386"
SRCS+= linux.c
.endif
CFLAGS.linux.c+= -I${SRCTOP}/sys
.include <bsd.prog.mk>
......@@ -124,6 +124,8 @@ void ktrfaultend(struct ktr_faultend *);
void ktrkevent(struct kevent *);
void ktrstructarray(struct ktr_struct_array *, size_t);
void ktrbitset(char *, struct bitset *, size_t);
void ktrsyscall_freebsd(struct ktr_syscall *ktr, register_t **resip,
int *resnarg, char *resc, u_int sv_flags);
void usage(void);
#define TIMESTAMP_NONE 0x0
......@@ -766,19 +768,52 @@ print_signal(int signo)
void
ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags)
{
int narg = ktr->ktr_narg;
register_t *ip;
syscallname(ktr->ktr_code, sv_flags);
ip = &ktr->ktr_args[0];
if (narg) {
char c = '(';
if (fancy) {
switch (sv_flags & SV_ABI_MASK) {
case SV_ABI_FREEBSD:
ktrsyscall_freebsd(ktr, &ip, &narg, &c,
sv_flags);
break;
#ifdef SYSDECODE_HAVE_LINUX
case SV_ABI_LINUX:
#ifdef __amd64__
if (sv_flags & SV_ILP32)
ktrsyscall_linux32(ktr, &ip,
&narg, &c);
else
#endif
ktrsyscall_linux(ktr, &ip, &narg, &c);
break;
#endif /* SYSDECODE_HAVE_LINUX */
}
}
while (narg > 0)
print_number(ip, narg, c);
putchar(')');
}
putchar('\n');
}
void
ktrsyscall_freebsd(struct ktr_syscall *ktr, register_t **resip,
int *resnarg, char *resc, u_int sv_flags)
{
int narg = ktr->ktr_narg;
register_t *ip, *first;
intmax_t arg;
int quad_align, quad_slots;
syscallname(ktr->ktr_code, sv_flags);
ip = first = &ktr->ktr_args[0];
if (narg) {
char c = '(';
if (fancy &&
(sv_flags == 0 ||
(sv_flags & SV_ABI_MASK) == SV_ABI_FREEBSD)) {
char c = *resc;
quad_align = 0;
if (sv_flags & SV_ILP32) {
#ifdef __powerpc__
......@@ -1510,13 +1545,9 @@ ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags)
narg--;
break;
}
}
while (narg > 0) {
print_number(ip, narg, c);
}
putchar(')');
}
putchar('\n');
*resc = c;
*resip = ip;
*resnarg = narg;
}
void
......
......@@ -76,4 +76,13 @@ void print_mask_argul(bool (*decoder)(FILE *, u_long, u_long *),
bool print_mask_arg_part(bool (*decoder)(FILE *, int, int *),
int value, int *rem);
#ifdef SYSDECODE_HAVE_LINUX
void ktrsyscall_linux(struct ktr_syscall *ktr, register_t **resip,
int *resnarg, char *resc);
#ifdef __amd64__
void ktrsyscall_linux32(struct ktr_syscall *ktr, register_t **resip,
int *resnarg, char *resc);
#endif
#endif /* SYSDECODE_HAVE_LINUX */
#endif /* !__KDUMP_H__ */
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/uio.h>
#include <sys/ktrace.h>
#include <stddef.h>
#include <sysdecode.h>
#include "kdump.h"
#ifdef __amd64__
#include <amd64/linux/linux_syscall.h>
#include <amd64/linux32/linux32_syscall.h>
#elif __aarch64__
#include <arm64/linux/linux_syscall.h>
#elif __i386__
#include <i386/linux/linux_syscall.h>
#endif
static void
print_linux_signal(int signo)
{
const char *signame;
signame = sysdecode_linux_signal(signo);
if (signame != NULL)
printf("%s", signame);
else
printf("SIG %d", signo);
}
void
ktrsyscall_linux(struct ktr_syscall *ktr, register_t **resip,
int *resnarg, char *resc)
{
int narg = ktr->ktr_narg;
register_t *ip, *first;
int quad_align, quad_slots;
char c;
ip = first = &ktr->ktr_args[0];
c = *resc;
quad_align = 0;
quad_slots = 1;
switch (ktr->ktr_code) {
case LINUX_SYS_linux_clock_gettime:
case LINUX_SYS_linux_clock_settime:
case LINUX_SYS_linux_clock_getres:
case LINUX_SYS_linux_timer_create:
putchar('(');
sysdecode_linux_clockid(stdout, *ip);
c = ',';
ip++;
narg--;
break;
case LINUX_SYS_linux_kill:
case LINUX_SYS_linux_tkill:
case LINUX_SYS_linux_rt_sigqueueinfo:
print_number(ip, narg, c);
putchar(',');
print_linux_signal(*ip);
ip++;
narg--;
break;
case LINUX_SYS_linux_tgkill:
case LINUX_SYS_linux_rt_tgsigqueueinfo:
print_number(ip, narg, c);
print_number(ip, narg, c);
putchar(',');
print_linux_signal(*ip);
ip++;
narg--;
break;
case LINUX_SYS_linux_rt_sigaction:
putchar('(');
print_linux_signal(*ip);
ip++;
narg--;
c = ',';
break;
case LINUX_SYS_linux_ftruncate:
case LINUX_SYS_linux_truncate:
print_number(ip, narg, c);
print_number64(first, ip, narg, c);
break;
}
*resc = c;
*resip = ip;
*resnarg = narg;
}
#if defined(__amd64__)
void
ktrsyscall_linux32(struct ktr_syscall *ktr, register_t **resip,
int *resnarg, char *resc)
{
int narg = ktr->ktr_narg;
register_t *ip, *first;
int quad_align, quad_slots;
char c;
ip = first = &ktr->ktr_args[0];
c = *resc;
quad_align = 0;
quad_slots = 2;
switch (ktr->ktr_code) {
case LINUX32_SYS_linux_clock_gettime:
case LINUX32_SYS_linux_clock_settime:
case LINUX32_SYS_linux_clock_getres:
case LINUX32_SYS_linux_timer_create:
case LINUX32_SYS_linux_clock_gettime64:
case LINUX32_SYS_linux_clock_settime64:
case LINUX32_SYS_linux_clock_getres_time64:
putchar('(');
sysdecode_linux_clockid(stdout, *ip);
c = ',';
ip++;
narg--;
break;
case LINUX32_SYS_linux_kill:
case LINUX32_SYS_linux_tkill:
case LINUX32_SYS_linux_rt_sigqueueinfo:
print_number(ip, narg, c);
putchar(',');
print_linux_signal(*ip);
ip++;
narg--;
break;
case LINUX32_SYS_linux_tgkill:
case LINUX32_SYS_linux_rt_tgsigqueueinfo:
print_number(ip, narg, c);
print_number(ip, narg, c);
putchar(',');
print_linux_signal(*ip);
ip++;
narg--;
break;
case LINUX32_SYS_linux_signal:
case LINUX32_SYS_linux_sigaction:
case LINUX32_SYS_linux_rt_sigaction:
putchar('(');
print_linux_signal(*ip);
ip++;
narg--;
c = ',';
break;
case LINUX32_SYS_linux_ftruncate:
case LINUX32_SYS_linux_truncate:
print_number(ip, narg, c);
print_number64(first, ip, narg, c);
break;
}
*resc = c;
*resip = ip;
*resnarg = narg;
}
#endif /* __amd64__ */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment