From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) by sourceware.org (Postfix) with ESMTPS id CFA5E39494B4 for ; Mon, 19 Jul 2021 12:51:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org CFA5E39494B4 Received: by mail-pg1-x52d.google.com with SMTP id k20so18869115pgg.7 for ; Mon, 19 Jul 2021 05:51:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=MeU8ZX7lfjWshTSDcGUGLUh8PKNm/W8lTiHsmCh0g0M=; b=hX89k1nKUPK4QAhHIk8XVwPyuCF8RMaC/lv02b8NDRNMis+hPZ4BSm05Gnqj2mQanL QjALfJxs0YkVi7VG4RaU0N8vbz+orDbf4knI47jr3bw2J4cqa6dXzvZuDwPyiEmCLHkN 09Og8PdlJRF4GNF0tGRzOR1cS9Jn3MM9bQ4XbI2fugcHisT+j3DpSg662jNvyfdJdIn0 1zpRbyRLMB5T6TuOMIZGnW9ZkSLXq4FQsG47mJR9056n+M/9H6ArgNVh/0DTDqGn3etg brYIe6i8/fEB2YErBY+OwTo5nmWY+Cvvh2eE2aL1YViVE4v/bL1MLq6w/8kFd9ocP8Sd lHAw== X-Gm-Message-State: AOAM531If9X89DP1Sy+fhMURWuWxLkRruh1DoWAMr5FO+KshwRCV/IVn GnbphZT7J6Zkm/ppu/0VzBPd3ijIYmjd9w== X-Google-Smtp-Source: ABdhPJx+3wDtX9taJUztrtjCuiKb+siB4F5KFsHXIl4bbQt5LpWjz6kiH7dBpsrpEILC+waHa5ogKA== X-Received: by 2002:a63:ed12:: with SMTP id d18mr24524352pgi.12.1626699110773; Mon, 19 Jul 2021 05:51:50 -0700 (PDT) Received: from ?IPv6:2804:431:c7ca:1133:c8a4:b05d:5ba9:3665? ([2804:431:c7ca:1133:c8a4:b05d:5ba9:3665]) by smtp.gmail.com with ESMTPSA id o184sm22403660pga.18.2021.07.19.05.51.49 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 19 Jul 2021 05:51:50 -0700 (PDT) Subject: Re: Bulding syscall wrapper: how glibc determines if assembly or macro wrapper will generated? To: "Dmitrowski, Lukasz" , "libc-help@sourceware.org" References: From: Adhemerval Zanella Message-ID: Date: Mon, 19 Jul 2021 09:51:48 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.11.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-5.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-help@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-help mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Jul 2021 12:51:53 -0000 On 19/07/2021 06:26, Dmitrowski, Lukasz wrote: > Hello, > > I create a documentation describing how glibc builds syscall wrappers. I am currently limited to Linux x86_64 architecture only and base on https://sourceware.org/glibc/wiki/SyscallWrappers + source code analysis. > > I want to to know how glibc build system decides what type of syscall wrapper will be generated, assembly wrapper or macro wrapper. I have troubles trying to figure out how the glibc build system works on this level. > > 1. make-syscall.sh produces sysd-syscalls, that contains build formulas for assembly wrappers. > How sysd-syscalls is used by the build system after it is generated? By including the generated file: sysdeps/unix/Makefile 20 # Sysdep dirs unix/... can contain a file syscalls.list, 21 # which specifies objects to be compiled as simple Unix system calls. 22 23 -include $(common-objpfx)sysd-syscalls The '-' on the include is a directive for gnumake [1] to make it not fail if the file does not exists (since it will be regenerated). > > 2. I found out that if sysd-syscalls contains a build formula for assembly wrapper then this formula is always used when building glibc, but in some cases sysd-syscalls also shows that a *.c wrapper exists, even that it contains assembly wrapper formula. This is because make-syscall.sh searches multiple syscalls.list files and multiple related sysdirs for *.c wrappers, so sometimes *.c wrapper exists in such relation and sometimes not. Both are included into sysd-syscalls. The only C file that is used on the auto-generation scheme is the stub-syscalls.c one: sysdeps/unix/Makefile 35 sysdep_routines += stub-syscalls 36 $(objpfx)stub-syscalls.c: $(common-objpfx)sysd-syscalls \ 37 $(..)sysdeps/unix/Makefile It contains a set of symbols that are not implemented neither by glibc nor by kernel but should exist due ABI compatibility. For instance, on x86_64 it is bdflush@GLIBC_2.0, but it may vary depending of the ABI. The file is just an size optimization, since multiple symbols will be aliases to only one implementation, _no_syscall, that returns -1/ENOSYS. > > Example: > #### DIRECTORY = sysdeps/unix/sysv/linux/x86_64 > #### SYSDIRS = sysdeps/unix/sysv/linux/x86_64/64 > ... > #### CALL=socket NUMBER=41 ARGS=i:iii SOURCE=- > ifeq (,$(filter socket,$(unix-syscalls))) > unix-syscalls += socket > $(foreach p,$(sysd-rules-targets),$(foreach o,$(object-suffixes),$(objpfx)$(patsubst %,$p,socket)$o)): \ > $(..)sysdeps/unix/make-syscalls.sh > $(make-target-directory) > (echo '#define SYSCALL_NAME socket'; \ > echo '#define SYSCALL_NARGS 3'; \ > echo '#define SYSCALL_SYMBOL __socket'; \ > echo '#define SYSCALL_CANCELLABLE 0'; \ > echo '#define SYSCALL_NOERRNO 0'; \ > echo '#define SYSCALL_ERRVAL 0'; \ > echo '#include '; \ > echo 'weak_alias (__socket, socket)'; \ > echo 'hidden_weak (socket)'; \ > ) | $(compile-syscall) $(foreach p,$(patsubst %socket,%,$(basename $(@F))),$($(p)CPPFLAGS)) > endif > > ... > > #### DIRECTORY = sysdeps/unix > #### SYSDIRS = sysdeps/unix/sysv/linux/x86_64/64 sysdeps/unix/sysv/linux/x86_64 sysdeps/unix/sysv/linux/x86 sysdeps/x86/nptl sysdeps/unix/sysv/linux/wordsize-64 sysdeps/x86_64/nptl sysdeps/unix/sysv/linux sysdeps/nptl sysdeps/pthread sysdeps/gnu sysdeps/unix/inet sysdeps/unix/sysv sysdeps/unix/x86_64 > ... > #### CALL=socket NUMBER=41 ARGS=i:iii SOURCE=sysdeps/unix/sysv/linux/socket.c > > -- > Where is the exact point in the build system that decides if assembly wrapper (from template-syscall.S) or macro wrapper (from *.c file) will be generated? If I recall correctly, this is due the operator precedence on the o-iterator-doit on Makefules: 393 define o-iterator-doit 394 $(objpfx)%$o: %.S $(before-compile); $$(compile-command.S) 395 endef 396 object-suffixes-left := $(all-object-suffixes) 397 include $(o-iterator) 398 399 define o-iterator-doit 400 $(objpfx)%$o: %.c $(before-compile); $$(compile-command.c) 401 endef 402 object-suffixes-left := $(all-object-suffixes) 403 include $(o-iterator) 404 405 define o-iterator-doit 406 $(objpfx)%$o: %.cc $(before-compile); $$(compile-command.cc) 407 endef 408 object-suffixes-left := $(all-object-suffixes) 409 include $(o-iterator) The idea is an .S file will have precedence over the .c and .cc file on sysdeps folder usage. > > 3. If syscall wrapper is generated from *.c file, where can I find how the build formula is prepared by the build system? Currently there is no .c file besides stub-syscalls.c. All other implementation are done through the assembly auto-generation, done on the fly by the build. > > 4. How glibc determines a set of directories where make-syscall.sh looks for syscalls.list and *.c syscall wrappers? ($thisdir and $sysdirs variables in make-syscalls.sh) This is obtained from the sysdep_dirs dirs, created by configure: sysdeps/unix/Makefile 92 ifndef avoid-generated 93 $(common-objpfx)sysd-syscalls: $(..)sysdeps/unix/make-syscalls.sh \ 94 $(wildcard $(+sysdep_dirs:%=%/syscalls.list)) \ 95 $(wildcard $(+sysdep_dirs:%=%/arch-syscall.h)) \ 96 $(common-objpfx)libc-modules.stmp 97 for dir in $(+sysdep_dirs); do \ 98 test -f $$dir/syscalls.list && \ 99 { sysdirs='$(sysdirs)' \ 100 asm_CPP='$(COMPILE.S) -E -x assembler-with-cpp' \ 101 $(SHELL) $(dir $<)$(notdir $<) $$dir || exit 1; }; \ 102 test $$dir = $(..)sysdeps/unix && break; \ 103 done > $@T 104 mv -f $@T $@ 105 endif Makeconfig 58 # Complete path to sysdep dirs. 59 # `configure' writes a definition of `config-sysdirs' in `config.make'. 60 sysdirs := $(foreach D,$(config-sysdirs),$(firstword $(filter /%,$D) $(..)$D)) 61 62 +sysdep_dirs = $(sysdirs) 63 ifdef objdir 64 +sysdep_dirs := $(objdir) $(+sysdep_dirs) 65 endif For instance on x86_64: $ grep config-sysdirs config.make config-sysdirs = sysdeps/unix/sysv/linux/x86_64/64 sysdeps/unix/sysv/linux/x86_64 sysdeps/unix/sysv/linux/x86 sysdeps/x86/nptl sysdeps/unix/sysv/linux/wordsize-64 sysdeps/x86_64/nptl sysdeps/unix/sysv/linux sysdeps/np tl sysdeps/pthread sysdeps/gnu sysdeps/unix/inet sysdeps/unix/sysv sysdeps/unix/x86_64 sysdeps/unix sysdeps/posix sysdeps/x86_64/64 sysdeps/x86_64/fpu/multiarch sysdeps/x86_64/fpu sysdeps/x86/fpu sysdeps/x86_64/multiar ch sysdeps/x86_64 sysdeps/x86 sysdeps/ieee754/float128 sysdeps/ieee754/ldbl-96 sysdeps/ieee754/dbl-64 sysdeps/ieee754/flt-32 sysdeps/wordsize-64 sysdeps/ieee754 sysdeps/generic > > Will be greateful for help or reference to some docs. Thank you in advance! Unfortunately we don't have all of this proper documented. As a side note, I also have a project to get rid of the assembly routines and have all syscalls wrapper being done by C implementations instead. > [1] https://www.gnu.org/software/make/manual/html_node/Include.html