corsix / polyfill-glibc

Patch Linux executables for compatibility with older glibc
Other
143 stars 1 forks source link

Polyfill for `__cxa_thread_atexit_impl@GLIBC_2.18` and `quick_exit@GLIBC_2.24` Missing for Target Glibc 2.17 #1

Closed brynne8 closed 1 month ago

brynne8 commented 1 month ago

Hello,

I am attempting to polyfill a binary named bun with the target glibc version set to 2.17 using the polyfill-glibc tool. However, I encountered an error indicating that the tool lacks the necessary knowledge to handle two specific symbols:

  1. __cxa_thread_atexit_impl@GLIBC_2.18
  2. quick_exit@GLIBC_2.24

The error message is as follows:

$ ./polyfill-glibc --target-glibc=2.17 ./bun
Cannot change target version of ./bun to 2.17 (x86_64) due to missing knowledge about how to handle:
  __cxa_thread_atexit_impl@GLIBC_2.18
  quick_exit@GLIBC_2.24

It appears that the current implementation of polyfill-glibc does not support these symbols for the target glibc version I specified. Could you please advise on whether there is a workaround for this issue or if there are plans to add support for these symbols in future updates?

corsix commented 1 month ago

Thanks for trying out polyfill-glibc and opening an issue.

I think quick_exit should be handled by calling quick_exit@GLIBC_2.24 if it is present, and calling quick_exit@GLIBC_2.10 otherwise. This will mean that quick_exit calls destructors for thread_local variables if the ambient glibc is version 2.18 though 2.23 (inclusive), and doesn't otherwise. A more aggressive strategy could remove this divergence, and never call destructors for thread_local variables, but the ways I can think of achieving this are all somewhat distasteful.

I think __cxa_thread_atexit_impl should be handled by calling __cxa_thread_atexit_impl@GLIBC_2.18 if it is present, and constructing something out of pthread_key_create / pthread_setspecific / pthread_getspecific / __cxa_atexit otherwise. I think it'll also want the equivalent of --add-flags df_1_nodelete to avoid some sharp corners.

I'm travelling at the moment, but hopefully I'll be able to put something together for this over the next few days.

corsix commented 1 month ago

I've pushed da442be; please let me know whether it works for you.

brynne8 commented 1 month ago

I polyfilled bun without any warning or errors, but when I try to run the polyfilled binary on CentOS 7 (glibc 2.17)

[root@nlp ~]# ./bun
./bun: symbol lookup error: ./bun: undefined symbol: __cxa_thread_atexit_impl
corsix commented 1 month ago

I've pushed a few more commits, which at least for me, allows me to take a recent bun, polyfill it, and run it on CentOS 7. Please try 1a527cbf7b to see whether the same is true for you.

brynne8 commented 1 month ago

It seems to work. But the binary cannot run a simple test.js.

============================================================
Bun v1.1.8 (89d25807) Linux x64
Args: "./bun", "run", "test.js"
Features: jsc
Elapsed: 7ms | User: 1ms | Sys: 6ms
RSS: 1.07GB | Peak: 37.36MB | Commit: 1.07GB | Faults: 0

panic(main thread): Segmentation fault at address 0x0
oh no: Bun has crashed. This indicates a bug in Bun, not your code.

To send a redacted crash report to Bun's team,
please file a GitHub issue using the link below:

 https://bun.report/1.1.8/lr189d2580AC2/5ijE+kyNwy204D2rwr7Cm8lplD+ghl6C0xk9+D2zzo5C2/np5C4r6g0CA2AA

It's maybe not your problem. But original Bun of course could run a simple JS file.

corsix commented 1 month ago

Looks like there was at least one more issue my side; with 4cfa944c28 I can now run the following (arbitrarily chosen) test.js:

const proc = Bun.spawn(["cat"], {
  stdin: await fetch(
    "https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js",
  ),
});

const text = await new Response(proc.stdout).text();
console.log(text);

If your test.js still fails, please feel free to share whatever information you can.

brynne8 commented 1 month ago

Wow it works! Thank you.

corsix commented 1 month ago

Super, glad to hear it. Do let me know if you run into any subsequent problems.