6

Is there a way to resolve the number of an observed syscall:

SYS_345(0xe, 0xbff94188, 0x2, 0x4000, 0xb6526000) = 2

to its symbolic name in the running kernel without looking it up, in the sources?

EDIT The use case being an outdated strace binary on a foreign box whose kernel sources may be tedious to retrieve.

2
  • Note, another command that has built-in lists of syscalls per architecture is ausyscall from the audit package. Eg ausyscall i386 345 gives sendmmsg.
    – meuh
    Commented May 23, 2018 at 12:48
  • @meuh Thanks, that’s something new to me. However: “Unknown syscall 345 using i386 lookup table” :-[ Maybe post an answer regardless, it might solve the issue for other users.
    – phg
    Commented May 23, 2018 at 15:43

1 Answer 1

7
+100

As far as I know, there is no guaranteed way of determining the mapping from system call numbers to system call names from a running kernel. Finding the call corresponding to a system call number always involves digging through the source code...

Developers of software which needs to perform this sort of mapping tend to maintain their own lists of system calls; this is the approach used by strace. It does mean any given version of such programs is liable to be outdated compared to any given kernel, although in practice system calls are added slowly enough for this not to be much of an issue.

Even looking values up in the kernel source is complicated, because the mappings are stored in different ways depending on the architecture. Even on architectures where the mapping is “simple”, such as x86 with its system call tables, finding the call for a given number can involve multiple lookups in various places.

One quick, reliable way to find the mappings for a system, as long as it has GCC and the system headers, is to use the latter. For example,

awk 'BEGIN { print "#include <sys/syscall.h>" } /p_syscall_meta/ { syscall = substr($NF, 19); printf "syscalls[SYS_%s] = \"%s\";\n", syscall, syscall }' /proc/kallsyms |
sort -u | gcc -E -P - | less

extracts the list of Linux system calls from /proc/kallsyms, builds a snippet of C code (or rather, C pre-processor code) and feeds it through the pre-processor, producing something like

syscalls[288] = "accept4";
syscalls[43] = "accept";
syscalls[21] = "access";
syscalls[163] = "acct";
syscalls[248] = "add_key";

etc. You can use GCC flags to tweak the architecture to match the kernel if necessary (e.g. -m32 to see i386 system call numbers, or -mx32 for x86-32 numbers).

In your case, 345 is the number for the sendmmsg system call on i386, and doesn’t correspond to anything on x86-64 or x86-32. It was introduced in 2011, around the 2.6.39 timeframe, so any system using the long-standing 2.6.32 as a base for its kernel and related programs wouldn’t know about it (so you might see this with a strace of similar vintage, and a newer kernel).

2
  • I like the approach to this answer. Turns out, the man-pages package on the system at hand is just as outdated as strace … Now I have two problems. Not your fault, of course. I wonder if there’s a way of parsing the kernel image with /proc/kallsyms to reconstruct the symbol mapping …
    – phg
    Commented May 23, 2018 at 11:30
  • Good point, see the updated version which uses kallsyms. Commented May 23, 2018 at 11:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .