This is a quick guide for finding out the definition of library function, syscall wrapper and definition. Wrote for my colleague who ask me the definition of sched_yield in glibc. I will also mention how to find out the definition of readdir(library function).

Check manpage to know it is a syscall or library function

According to man 1 man, 2 is syscall, so sched_yield is only a syscall(There are lots of name share between library function and syscall).

    2   System calls (functions provided by the kernel)
    3   Library calls (functions within program libraries)
> man sched_yield
Man: find all matching manual pages (set MAN_POSIXLY_CORRECT to avoid this)
 * sched_yield (2)
   sched_yield (3p)
Man: What manual page do you want?

Manpage will also show the section number in the beginning of it. E.g. “GETDENTS(2)” means it is a syscall. We could see “Glibc does not provide a wrapper for these system calls” which is not shown in the manpage of sched_yield. It means that getdents is a syscall which is not wrapped by glibc. sched_yield is a syscall which is wrapped by glibc.

> man getdents
GETDENTS(2)                                                                                Linux Programmer's Manual                                                                               GETDENTS(2)

       Glibc does not provide a wrapper for these system calls; call them using syscall(2).  You will need to define the linux_dirent or linux_dirent64 structure yourself.  However, you probably want to use
       readdir(3) instead.

       These calls supersede readdir(2).

Find the definition of syscall in glibc

There are different ways to know where glibc implements a syscall. E.g. we could grep the source code, find the syscall named source code or find the dependency file in the build directory of glibc.

It is easy to know definition from the dependency file in build directory when there is the coresponding compiler:

> find . -name sched_yield.o.d

Usually, the second line of dependency show the definition. In sched_yield.o, we see headers instead of c source code. It means that sched_yield is wrapped by the assembly language.

> head -n 2 posix/sched_yield.o
$(common-objpfx)posix/sched_yield.o: \
  ../include/stdc-predef.h ../include/libc-symbols.h \

We could confirm it in sysd-syscalls in build directory. All the syscalls found in this file(exclude comments) is wrapped by assembly language and controlled by several macros:

#### CALL=sched_yield NUMBER=(124) ARGS=i: SOURCE=-
ifeq (,$(filter sched_yield,$(unix-syscalls)))
unix-syscalls += sched_yield
$(foreach p,$(sysd-rules-targets),$(foreach o,$(object-suffixes),$(objpfx)$(patsubst %,$p,sched_yield)$o)): \
        (echo '#define SYSCALL_NAME sched_yield'; \
         echo '#define SYSCALL_NARGS 0'; \
         echo '#define SYSCALL_SYMBOL __sched_yield'; \
         echo '#include <syscall-template.S>'; \
         echo 'weak_alias (__sched_yield, sched_yield)'; \
         echo 'libc_hidden_weak (sched_yield)'; \
        ) | $(compile-syscall) $(foreach p,$(patsubst %sched_yield,%,$(basename $(@F))),$($(p)CPPFLAGS))

The above macro show that the name, number of args and symbol of sched_yield syscall. There are also another two useful macros:

Find the definition in kernel

Most of the architecture make use of the include/uapi/asm-generic/unistd.h with their own options in unistd.h of “arch/arch_name/include”. We could saw the file name of a syscall in this file. For example, the following result show that sched_yield() is defined in “kernel/sched/core.c”.

> grep "\(\/\*.*\*\/\)\|\(sched_yield\)" include/uapi/asm-generic/unistd.h | grep sched_yield -B 1
/* kernel/sched/core.c */
#define __NR_sched_yield 124
__SYSCALL(__NR_sched_yield, sys_sched_yield)

Searching “SYS.*sched_yield” in “kernel/sched/core.c” will find the location of definition.

Find the definition of library function in glibc

As we mentioned, getdents() is not wrapped by glibc. readdir() is the recommandation library function to use it. We could find the definition of readdir() is “sysdeps/posix/readdir.c” with above method:

> head -n 2 `find . -name readdir.o.d`
$(common-objpfx)dirent/readdir.o: \
 ../sysdeps/posix/readdir.c ../include/stdc-predef.h \

When we search in source code, we could know the name of function by searching alias like this:

> grep alias sysdeps/posix/readdir.c | grep -w readdir
weak_alias (__readdir, readdir)

And we could find that __readdir() call getdents()/getdents64() through __getdents() in above file.

Q & A

Q: Why we do not search the syscall named file in glibc source code directly?