-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
libct/dmz: Reduce the binary size using nolibc #4024
Conversation
Oops, misclicked. I'll review this tomorrow. |
16b4e76
to
88f9c0d
Compare
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ | ||
/* | ||
* AARCH64 specific definitions for NOLIBC | ||
* Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it have license issue?
Not expert . Just thinking about how it lives with Apache 2.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It says it can be MIT, which should be compatible with Apache-2.
Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I think we can just keep MIT and remove the LGPL-2.1. Just remove the confusion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idem as the other comment. I think I prefer to keep it if we can keep it. Otherwise, updating to a newer version of nolibc in the future would be more painful (or we need to make a script that nolibc, removes this, maybe something else, etc.).
I think there is value in the simplicity of just a simple c&p, no patches added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot remove license headers. The code is dual-licensed but you need to keep the original copyright headers verbatim.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cyphar thanks for the comment!
e30851c
to
5578e95
Compare
libcontainer/dmz/nolibc/Makefile
Outdated
@@ -0,0 +1,91 @@ | |||
# SPDX-License-Identifier: GPL-2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is okay to include this file is GPLv2, but if someone can confirm it will be great.
Otherwise, we can remove it? We are not using this makefile anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be removed to avoid confusion (If we are going to merge this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I prefer to keep it if we can keep it. Otherwise, updating to a newer version of nolibc in the future would be more painful (or we need to make a script that takes that, removes this, maybe something else, etc.).
I think there is value in the simplicity of just a simple c&p.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is value in the simplicity of just a simple c&p.
The problem is that this is legally less simple.
It is not obvious (for non-maintainers) that the GPL-2.0 code is actually not linked with runc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, then! :)
01cbee2
to
3ff27ee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This nolibc
is really interesting :D!
I have a comment on the xstat.h
file:
#ifndef XSTAT_H | ||
#define XSTAT_H | ||
|
||
// Some old-kernels (like centos-7) don't have statx() defined in linux/stat.h. We can't include | ||
// sys/stat.h because it creates conflicts, so let's just define what we need here and be done with | ||
// this. | ||
// TODO (rata): I'll probably submit a patch to nolibc upstream so we can remove this hack in the | ||
// future. | ||
#include <linux/stat.h> /* for statx() */ | ||
|
||
#ifndef STATX_BASIC_STATS | ||
#include "linux/stat.h" | ||
#endif // STATX_BASIC_STATS | ||
|
||
#endif // XSTAT_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get your explanation regarding the problem.
But why do you have to include this file for dmz
?
I mean, dmz
only calls execve()
which directly calls the syscall.
Moreover, statx()
is defned in the nolibc
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because on centos-7, the <linux/stat.h>
header doesn't include the struct statx that nolibc uses in sys.h, where execve()
is defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got it! Thank you!
So, the upstream patch would be about using the nolibc
stat.h
in sys.h
rather than linux/stat.h
?
In any case, please send it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is the idea. But keeping nolibc unmodified here is way simpler that carrying out our patches to it. So, the xstat.h in runc seems way better than patching nolibc IMHO :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure!
Once your patch would be accepted upstream, you could update the code here but at the moment this is fine.
875a48e
to
8220ad2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove GPL-2.0 code
https://github.com/opencontainers/runc/pull/4024/files#r1337136436
8220ad2
to
f6a930a
Compare
@AkihiroSuda sure, changed it. Removed that and put a note on the README about it. PTAL |
@@ -2,5 +2,5 @@ | |||
include ../../cc_platform.mk | |||
|
|||
runc-dmz: _dmz.c | |||
$(CC) $(CFLAGS) -static -o $@ $^ | |||
$(CC) $(CFLAGS) -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib -lgcc -static -o $@ $^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add comments to explain these flags?
Why do we still need lgcc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a comment to explain that, it is what it is suggested in nolibc/nolibc.h: https://github.com/opencontainers/runc/pull/4024/files#diff-bc183fb7b7c25ee341d9ef03b3bcb444301270a7ef72291bc025d96f1d7046f1R66-R68
It works without -lgcc
, but in nolib.h they put it and the gcc manpage says that you need to add that if you use notstdlib to make sure the linking won't fail.
Linux repo has under `tools/include/nolibc` very simple include files that we can use to generate very small binaries that don't depend on libc. To make things even better, since Linux 6.6 it supports all the architectures we support in runc, which is just beautiful. The runc-dmz binary on x86_64 before this patch (on my debian host) was taking 636K, with this patch it takes only 8K. Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
f6a930a
to
90f5da6
Compare
@rata I think the source code of |
@lifubang I don't know a decent way to do that. Submodules seems painful, as we can't add a sub-folder (and adding the whole linux repo seems crazy), the configure script you mention seems complex too... I don't think we will need to update this often, if at all. Would it be okay to add the script if we happen to update this often? |
How about https://git-scm.com/docs/git-archive ?
|
Or https://www.git-scm.com/docs/git-sparse-checkout ? |
@lifubang hmmm, git-archive is to create an archive like tar/zip/gzip. Am I missing something? We don't want that here. IMHO trying to use submodules with sparse checkout is not worth it at this point. Not sure if it is possible (I'm not familiar with sparse checkout), but IMHO it doesn't seem worth the effort now. We can definitely change it if we do need to update this more than once per year. |
It seems very unlikely we will need to update this at all, let alone frequently -- given how minimal runc-dmz is and the fact that syscall numbers are fixed per-architecture. Once it works, it should just continue to work without any changes needed. The alternatives (submodules and subtree merges) have their own issues. If you use submodules, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
#elif defined(__aarch64__) | ||
#include "arch-aarch64.h" | ||
#elif defined(__mips__) && defined(_ABIO32) | ||
#include "arch-mips.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for not supporting MIPS64? (Is it still alive?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Runc currently doesn't support mips:
Lines 17 to 53 in 1a8b558
else ifeq ($(GOARCH),386) | |
# Always use the 64-bit compiler to build the 386 binary, which works for | |
# the more common cross-build method for x86 (namely, the equivalent of | |
# dpkg --add-architecture). | |
ifdef IS_SUSE | |
# There is no x86_64-suse-linux-gcc, so use the native one. | |
HOST := | |
CPU_TYPE := i586 | |
else | |
HOST := x86_64-$(PLATFORM)- | |
CPU_TYPE := i686 | |
endif | |
CFLAGS := -m32 -march=$(CPU_TYPE) $(CFLAGS) | |
else ifeq ($(GOARCH),amd64) | |
ifdef IS_SUSE | |
# There is no x86_64-suse-linux-gcc, so use the native one. | |
HOST := | |
else | |
HOST := x86_64-$(PLATFORM)- | |
endif | |
else ifeq ($(GOARCH),arm64) | |
HOST := aarch64-$(PLATFORM)- | |
else ifeq ($(GOARCH),arm) | |
# HOST already configured by release_build.sh in this case. | |
else ifeq ($(GOARCH),armel) | |
HOST := arm-$(PLATFORM)eabi- | |
else ifeq ($(GOARCH),armhf) | |
HOST := arm-$(PLATFORM)eabihf- | |
else ifeq ($(GOARCH),ppc64le) | |
HOST := powerpc64le-$(PLATFORM)- | |
else ifeq ($(GOARCH),riscv64) | |
HOST := riscv64-$(PLATFORM)- | |
else ifeq ($(GOARCH),s390x) | |
HOST := s390x-$(PLATFORM)- | |
else | |
$(error Unsupported GOARCH $(GOARCH)) | |
endif |
In a quick git blame on the linux kernel, I didn't find why
@cyphar cool! I guess you checked the arches (what I said in the PR description) and looks good? :) |
Yeah, it supports all of the architectures we do releases for. If we want to add MIPS64 releases in the future we can cross that bridge when we get to it (or someone complains). |
Thanks, SGTM |
Awesome contribution 🎉 🎉 🎉! |
Yes, exactly, I get a 4.8K runc-dmz in my machine. |
Linux repo has under
tools/include/nolibc
very simple include files that we can use to generate very small binaries that don't depend on libc.To make things even better, since Linux 6.6 it supports all the architectures we support in runc, which is just beautiful.
The runc-dmz binary on x86_64 before this patch (on my debian host) was taking 636K, with this patch it takes only 8K.
Please review this table of arches with special attention.
Here is a list of arches we currently produce a binary for (took the list from here https://github.com/opencontainers/runc/releases/tag/v1.1.9), I tried to map them to the equivalent arch in nolibc, to make sure we still support all arches. Please review this
If some arch is not supported, we should fallback to use stdlib for that arch. But I think all of them are supported.
What golang seems to support and nolibc doesn't is MIPS (mips, mipsle, mipsle64, mips64). So we might want to do the fallback anyways? :-(Yes, arch-mips.h is supported, but it seems not all those variants.It seems runc doesn't compile for mips, as shown herecc @cyphar @lifubang