Skip to content
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

-fno-PIC targeting glibc should be legal #17430

Open
kubkon opened this issue Oct 7, 2023 · 4 comments
Open

-fno-PIC targeting glibc should be legal #17430

kubkon opened this issue Oct 7, 2023 · 4 comments
Assignees
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase. os-linux
Milestone

Comments

@kubkon
Copy link
Member

kubkon commented Oct 7, 2023

Zig Version

0.12.0-dev.832+d5c19ecd5

Steps to Reproduce and Observed Behavior

This is currently illegal:

$ echo "int main() { return 0; }" > main.c
$ zig cc -c -fno-PIC main.c -target x86_64-linux-gnu
error: unable to create compilation: TargetRequiresPIC

but is actually a valid compilation combo.

$ clang -c -fno-PIC main.c -target x86_64-linux-unknown-gnu

Expected Behavior

Compiles successfully.

@kubkon kubkon added bug Observed behavior contradicts documented or intended behavior os-linux zig cc Zig as a drop-in C compiler feature labels Oct 7, 2023
@kubkon kubkon added this to the 0.12.0 milestone Oct 7, 2023
@kubkon
Copy link
Member Author

kubkon commented Oct 9, 2023

OK, I've tried the proposed fix as follows:

diff --git a/src/Compilation.zig b/src/Compilation.zig
index 28b67ff7346..0afcd9f03f5 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1034,7 +1034,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
         const must_pic: bool = b: {
             if (target_util.requiresPIC(options.target, link_libc))
                 break :b true;
-            break :b link_mode == .Dynamic;
+            break :b link_mode == .Dynamic and options.output_mode == .Lib;
         };
         const pic = if (options.want_pic) |explicit| pic: {
             if (!explicit) {
@@ -5162,8 +5162,12 @@ pub fn addCCArgs(
                 },
             }
 
-            if (target_util.supports_fpic(target) and comp.bin_file.options.pic) {
-                try argv.append("-fPIC");
+            if (target_util.supports_fpic(target)) {
+                if (comp.bin_file.options.pic) {
+                    try argv.append("-fPIC");
+                } else {
+                    try argv.append("-fno-PIC");
+                }
             }
 
             if (comp.unwind_tables) {
diff --git a/src/target.zig b/src/target.zig
index c137166543d..125f48f81b6 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -192,10 +192,10 @@ pub fn requiresPIE(target: std.Target) bool {
 
 /// This function returns whether non-pic code is completely invalid on the given target.
 pub fn requiresPIC(target: std.Target, linking_libc: bool) bool {
+    _ = linking_libc;
     return target.isAndroid() or
         target.os.tag == .windows or target.os.tag == .uefi or
-        osRequiresLibC(target) or
-        (linking_libc and target.isGnuLibC());
+        osRequiresLibC(target);
 }
 
 /// This is not whether the target supports Position Independent Code, but whether the -fPIC

However, LLD fails to link test-std tests with a failed relocation error:

$ ./stage3/bin/zig test ../lib/std/std.zig  -target aarch64-linux-gnu --zig-lib-dir /home/kubkon/dev/zig/lib/ -lc
...
ld.lld: error: /home/kubkon/dev/zig/zig-cache/o/e765335f0502c09a9967f8a26326652a/test.o:(function math.mul__anon_6094: .text+0x3f00): improper alignment for relocation R_AARCH64_LDST64_ABS_LO12_NC: 0x2340BB4 is not aligned to 8 bytes

From my brief investigation this looks like a reference to __stack_chk_guard/__stack_chk_fail stating that the symbol is misaligned. The funny thing is this symbol is dynamically exported by libc.so and it is aligned alright. Anyhow, passing -fno-stack-protector and -fno-stack-check makes the issue go away.

Also, linking the binary with mold works fine and emits a functional binary:

$ mold -z stack-size=16777216 --gc-sections --eh-frame-hdr -znow -m aarch64linux -o test /home/kubkon/.cache/zig/o/12dd35ea87cd033035d74567d6572a28/Scrt1.o /home/kubkon/.cache/zig/o/57eaab073ec0faaaf3679b7767e6d438/crti.o -dynamic-linker /lib/ld-linux-aarch64.so.1 /home/kubkon/dev/zig/zig-cache/o/e765335f0502c09a9967f8a26326652a/test.o --as-needed /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/libm.so.6 /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/libpthread.so.0 /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/libc.so.6 /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/libdl.so.2 /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/librt.so.1 /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/libld.so.2 /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/libutil.so.1 /home/kubkon/.cache/zig/o/7a770135ee851ffefd975b614f376e2a/libresolv.so.2 /home/kubkon/.cache/zig/o/50bd6a549a142bd1999535df0d05b1f7/libc_nonshared.a /home/kubkon/.cache/zig/o/8f0c3369fc70e2e54e065f49c0565fda/libcompiler_rt.a /home/kubkon/.cache/zig/o/c3840fa00c1dd2a0af5ee276cfe081f4/crtn.o --allow-shlib-undefined
$ qemu-aarch64 -L /home/kubkon/dev/glibc/multi/install/glibcs/aarch64-linux-gnu test
...
2527 passed; 77 skipped; 0 failed.                                                                                                                                                   

I suspect there might be a bug in LLD somewhere, but instead of trying to narrow it down at this stage, I will defer it until our linker is capable of linking aarch64 and see what's up then.

@andrewrk andrewrk removed the zig cc Zig as a drop-in C compiler feature label Oct 9, 2023
@andrewrk andrewrk changed the title cc: -fno-PIC targeting glibc should be legal -fno-PIC targeting glibc should be legal Oct 9, 2023
@andrewrk andrewrk modified the milestones: 0.12.0, 1.0.0 Oct 11, 2023
@andrewrk andrewrk added enhancement Solving this issue will likely involve adding new logic or components to the codebase. and removed bug Observed behavior contradicts documented or intended behavior labels Oct 11, 2023
@Jarred-Sumner
Copy link
Contributor

Currently, about 3.72 MB of Bun's executable is .data.rel.ro on Linux x64. I think most of that would be removed if zig build-obj didn't prevent disabling PIC. Each time we return a runtime pointer from a comptime function, it appears to create a new symbol to relocate in the .data.rel.ro section on Linux.

Section Unit Symbol Filesize VMSize Percent of total file size
.rodata icudt75_dat [section .rodata] 30729184 30729184 31.71
.data.rel.ro [section .data.rel.ro] 3734616 3759256 3.88
.rodata [section .rodata] [section .rodata] 2994946 2994946 3.09
.rodata __anon_1124411 [section .rodata] 695727 695727 0.72
.rodata hencs [section .rodata] 524288 524288 0.54
.text JSC::FTL::(anonymous namespace)::LowerDFGToB3::lower() [section .text] 429088 429088 0.44
.rodata Bun::InternalModuleRegistryConstants::NodeCryptoCodeBytes [section .rodata] 428432 428432 0.44
.text Bun::ProcessBindingUV::jsGetErrorMap(JSC::JSGlobalObject*, JSC::CallFrame*) ProcessBindingTTYWrap.cpp 333728 333728 0.34
.rodata hdecs [section .rodata] 262144 262144 0.27
.rodata __anon_1127446 [section .rodata] 224938 224938 0.23
.rodata JSC::s_JSCCombinedCode [section .rodata] 215020 215020 0.22
.gnu.hash [section .gnu.hash] 190720 190720 0.2
.rodata __anon_1919867 [section .rodata] 164286 164286 0.17
.rodata Bun::InternalModuleRegistryConstants::NodeStreamCodeBytes [section .rodata] 158336 158336 0.16
.rodata ecp_nistz256_precomputed [section .rodata] 151552 151552 0.16
.text JSC::Yarr::createCharacterClass325() [section .text] 150464 150464 0.16

@alexrp
Copy link
Member

alexrp commented Oct 5, 2024

I tried making this change again and ran test-behavior:

test-behavior
└─ run test behavior-mips64-linux.4.19...6.10.3-gnuabi64.2.28-mips64-Debug-libc failure
qemu: uncaught target signal 10 (Bus error) - core dumped
error: the following command terminated with signal 7 (expected exited with code 0):
qemu-mips64 -L /opt/glibc/mips64-linux-gnuabi64 /home/alexrp/Source/zig/.zig-cache/o/15419225d1b4b615da9501b12d9a2344/test --seed=0x198ce05d --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-behavior
└─ run test behavior-mips64el-linux.4.19...6.10.3-gnuabi64.2.28-mips64-Debug-libc failure
qemu: uncaught target signal 10 (Bus error) - core dumped
error: the following command terminated with signal 7 (expected exited with code 0):
qemu-mips64el -L /opt/glibc/mips64el-linux-gnuabi64 /home/alexrp/Source/zig/.zig-cache/o/639bc2d91704d7f777acf4faff33380a/test --seed=0x198ce05d --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-behavior
└─ run test behavior-x86-linux.4.19...6.10.3-gnu.2.28-pentium4-Debug-libc failure
Arithmetic exception at address 0x2821a6
error: while executing test 'behavior.cast.test.@intFromFloat', the following command terminated with signal 11 (expected exited with code 0):
/home/alexrp/Source/zig/.zig-cache/o/5c98e94b27e524e8ccfff67b523bef97/test --seed=0x198ce05d --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-behavior
└─ run test behavior-arm-linux.4.19...6.10.3-gnueabihf.2.28-baseline-Debug-libc failure
Segmentation fault at address 0x8
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
error: while executing test 'behavior.usingnamespace.import_segregation.test.no clobbering happened', the following command terminated with signal 11 (expected exited with code 0):
qemu-arm -L /opt/glibc/arm-linux-gnueabihf /home/alexrp/Source/zig/.zig-cache/o/901cd9c1c937bc635e562270c3ed6f82/test --seed=0x198ce05d --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-behavior
└─ run test behavior-arm-linux.4.19...6.10.3-gnueabi.2.28-baseline-Debug-libc failure
Segmentation fault at address 0x8
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
error: while executing test 'behavior.usingnamespace.import_segregation.test.no clobbering happened', the following command terminated with signal 11 (expected exited with code 0):
qemu-arm -L /opt/glibc/arm-linux-gnueabi /home/alexrp/Source/zig/.zig-cache/o/02380e931e0244baf80cd3bc91b80682/test --seed=0x198ce05d --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-

(All other targets work.)

All of the crashes happen in std.posix.getenv() when accessing std.c.environ. 🤔

@alexrp
Copy link
Member

alexrp commented Oct 5, 2024

test-std has additional failures for riscv32 and riscv64:

test-std
└─ run test std-riscv64-linux.4.19...6.10.3-gnu.2.28-baseline_rv64-Debug-libc failure
Segmentation fault at address 0x0
error: while executing test 'dynamic_library.test.ElfDynLib', the following command terminated with signal 6 (expected exited with code 0):
qemu-riscv64 -L /opt/glibc/riscv64-linux-gnu /home/alexrp/Source/zig/.zig-cache/o/65fd1eda8449d4f97c118dc567f8a4fd/test --seed=0x8ceed8f9 --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-std
└─ run test std-mips64-linux.4.19...6.10.3-gnuabi64.2.28-mips64-Debug-libc failure
qemu: uncaught target signal 10 (Bus error) - core dumped
error: the following command terminated with signal 7 (expected exited with code 0):
qemu-mips64 -L /opt/glibc/mips64-linux-gnuabi64 /home/alexrp/Source/zig/.zig-cache/o/ef306dbdff797175d442b20b4bf0fea6/test --seed=0x8ceed8f9 --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-std
└─ run test std-arm-linux.4.19...6.10.3-gnueabi.2.28-baseline-Debug-libc failure
Segmentation fault at address 0x6d6f682f
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
error: while executing test 'dynamic_library.test.ElfDynLib', the following command terminated with signal 11 (expected exited with code 0):
qemu-arm -L /opt/glibc/arm-linux-gnueabi /home/alexrp/Source/zig/.zig-cache/o/086c35400c67058bbd4d9670ef8ba78d/test --seed=0x8ceed8f9 --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-std
└─ run test std-arm-linux.4.19...6.10.3-gnueabihf.2.28-baseline-Debug-libc failure
Segmentation fault at address 0x6d6f682f
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
error: while executing test 'dynamic_library.test.ElfDynLib', the following command terminated with signal 11 (expected exited with code 0):
qemu-arm -L /opt/glibc/arm-linux-gnueabihf /home/alexrp/Source/zig/.zig-cache/o/2ed917ab08d45eb131cf156d35ac9848/test --seed=0x8ceed8f9 --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-std
└─ run test std-riscv32-linux.4.19...6.10.3-gnu.2.33-baseline_rv32-Debug-libc failure
Segmentation fault at address 0x6d6f682f
error: while executing test 'dynamic_library.test.ElfDynLib', the following command terminated with signal 6 (expected exited with code 0):
qemu-riscv32 -L /opt/glibc/riscv32-linux-gnu /home/alexrp/Source/zig/.zig-cache/o/1bace442fe68e713b4a5358c3450b91a/test --seed=0x8ceed8f9 --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-std
└─ run test std-mips64el-linux.4.19...6.10.3-gnuabi64.2.28-mips64-Debug-libc failure
qemu: uncaught target signal 10 (Bus error) - core dumped
error: the following command terminated with signal 7 (expected exited with code 0):
qemu-mips64el -L /opt/glibc/mips64el-linux-gnuabi64 /home/alexrp/Source/zig/.zig-cache/o/4c701af80e1cc4ff3496e77316dd2782/test --seed=0x8ceed8f9 --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-
test-std
└─ run test std-x86-linux.4.19...6.10.3-gnu.2.28-pentium4-Debug-libc failure
Segmentation fault at address 0x6d6f682f
error: while executing test 'dynamic_library.test.ElfDynLib', the following command terminated with signal 11 (expected exited with code 0):
/home/alexrp/Source/zig/.zig-cache/o/a40134fd65d0c9ca797bcb3e6657bfc4/test --seed=0x8ceed8f9 --cache-dir=/home/alexrp/Source/zig/.zig-cache --listen=-

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Solving this issue will likely involve adding new logic or components to the codebase. os-linux
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants