Recent

Author Topic: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found  (Read 43847 times)

stephanie

  • New Member
  • *
  • Posts: 27
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #30 on: October 04, 2022, 02:03:45 pm »
Hello,
thanks for your answers, they helped me a lot to understand better.
At this point virtualization with VirtualBox or using debootstrap is the best solution.
I was already using this solution, although sometimes vice versa, in the sense that I often test new versions of Lazarus on a virtual machine first before moving on to work on the updated version.
For example now I have a Debian Buster with Lazarus 2.0.4 on the host machine and a XUbuntu 22.04 with Lazarus 2.2.4 on the guest.
I just would have preferred to be able to test the executable generated on the guest on the host, but I understand that it is not possible and then I will test on the guest, no problem.
One last question: being Linux Open Source, couldn't you add some older version library packages, with an option to compile with them?
With Windows presumably it cannot be possible for licensing reasons, but with Linux it should perhaps be possible.
However now it is much clearer to me, thank you very much for your answers.
Best regards,
Stephanie

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #31 on: October 04, 2022, 02:42:18 pm »
...
One last question: being Linux Open Source, couldn't you add some older version library packages, with an option to compile with them?

Not sure to understand but, apart for libc.so, you may use LoadLibrary(/path/of/library) (= dlopen()) instead of linking the library at compilation (using "external").
https://wiki.freepascal.org/Lazarus/FPC_Libraries#Loadlibrary_-_dynamically_loading_a_dynamic_library

And have the choice to load the library form where an when you want.

For example, this fpgui project dynamically loads X11 and TThreads dependencies:
https://github.com/fredvs/uidesigner_ext

 
« Last Edit: October 04, 2022, 02:54:38 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #32 on: October 05, 2022, 01:25:52 am »
Another thing worth keeping in mind is that this is, hopefully, a one-off problem.
Over time, all the systems running <v2.34 will be updated and will work in a post 2.34 world.  I have tested the latest Ubuntu, it uses 2.35 and binaries made there work fine on a 2.34 system. Promising ...

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #33 on: October 05, 2022, 09:02:13 am »
One last question: being Linux Open Source, couldn't you add some older version library packages, with an option to compile with them?

In theory, yes, but due to Linux favouring Open Source software: simply recompile the applications in question. Much less maintainance burden for the distribution developers.

Another thing worth keeping in mind is that this is, hopefully, a one-off problem.
Over time, all the systems running <v2.34 will be updated and will work in a post 2.34 world.  I have tested the latest Ubuntu, it uses 2.35 and binaries made there work fine on a 2.34 system. Promising ...

It's not a one-off problem, because it will surface every time the developers of the C library introduce a versioned symbol that's used by a program. In the case of 2.35 vs 2.34 they simply didn't introduce such a symbol or your program doesn't access the symbol in question.

maxerist

  • New Member
  • *
  • Posts: 20
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #34 on: November 19, 2022, 09:20:47 am »
This is probably the longest thread about the topic, I'll add also my two cents. Please, correct me for everything I did wrong.

There's a program readelf and anyone can list any versioned glibc symbols in executables, so, o, a files with the following command
 
Quote
readelf -Ws {file} | grep GLIBC

you will see the lines ending with something like ".... pthread_mutex_destroy@GLIBC_2.2.5 (2)"
GLIBC_2.2.5 из the version (set) (abi) that was chosen by the linker, the number in parenthesis is the version of this symbol. So @GLIBC_2.8 (2) will mean that the later abi list was chosen (2.8) but actual version of the symbol is the same

The compiler (fpc in our case) don't use such versioned symbols, it's the linker who sees pthread_mutex_destroy and having glibc on this system with particular latest abi, chooses the @ ending.
We in pascal have already a feature to limit this. So if you declare the imported function like
 
Code: Pascal  [Select][+][-]
  1. pthread_mutex_destroy... external clib name 'pthread_mutex_destroy@GLIBC_2.2.5'

the linker will be content to follow. Only the abi set like here (2.2.5) should exist in the glibc version in the system.

Also note that if experimenting with linking particular versions there are some states when the symbol with invalid name might exist in compiled units, but linker doesn't care (for example with the declaration is implementation-only and not used inside the implementation section)

In classic c as long as I remember there's no syntax to use a different imported name for a function, but at least for gcc recently one can use symver macro. I successfully tested this preparing a special sqlite versions for static linking.

Code: C  [Select][+][-]
  1.   __asm__(".symver pthread_mutexattr_init,pthread_mutexattr_init@GLIBC_2.2.5");
  2.  

This is great (as long as correct set of functions are chosen) so for the units the end developer has in control, the changes can be made to compile on newer system for executable to work on older ones.

But there are also fpc and lazarus that might use glibc directly or indirectly. Create a simple lazarus form project and readelf it. You will get probably dozens of versioned glibc functions.

Also one of such cases if one creates absolutely new "simple program" having nothing in it and compiling into 200k executable. You readelf it, you won't find any glibc dependencies. But add dynlibs to uses section and you will get dlopen and several other dl... functions with version information (probably 2.34 for recent linux versions, since this glibc version is notable in that they merged different so modules to reside in the single libc so they have to do version increase for plenty of related functions). But the glibc binding is unexpected, the dl unit having dlopen declaration uses "dl" lib. Here we have an indirect consequence, it's probably the smart linker of recent versions who knows (or resolved with symbol chaining) that here it maps dl* function to newly reappeared ones in glibc. I also tried to make a vanilla case with a very simple program with a single simple dlopen import declaration pointing to dl (libdl) lib but the linker still took versioned glibc function for the imported symbol

So fpc (and probably lazarus also) formally distance themselves from the c runtime in most of basic cases (probably threads is another exception) but has no full control about it. But in case with acknowledge that investigation of basic glibc usage in fpc/lazaraus is possible then the capping might look like this

Code: Pascal  [Select][+][-]
  1.  
  2. {$ifdef ...}
  3.    glibc_ver_cap = '@GLIBC_2.2.5'
  4. {$else}
  5.    glibc_ver_cap =  ...
  6. ....
  7.     glibc_ver_cap =  '';
  8. {$endif}
  9.  
  10. pthread_mutex_destroy... external clib name 'pthread_mutex_destroy' + glibc_ver_cap;
  11.  
  12.  


But the road is probably difficult. I suspect for example for dl* functions that prior to some version before 2.34 there were no dl* symbols in glibc and everyone linked against libdl. So in some cases the name manipulating might involve not only the name of the imported symbol but also the name of the lib.

Probably compiling on a "minimum" system is still the golden rule for us. The minor issue here is that dealing with this I had to install rpm-based set on a CentOS 7 based system and ended up repacking fpc installer with the instructions found here in forum and elsewhere at the web. Probably the suggestion here is for future fpc installer not to use [ rpmlib(payloadiszstd) ] compression for easier installig in earlier linux versions.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #35 on: November 19, 2022, 10:35:33 am »
@maxerist Thanks for that, I think you're the first person pointing out- certainly in this thread- the importance of the @ qualifier in an external declaration.

I usually wrap program-controlled dynamic linkage in a class, and when I have time I'll review that in light of what you're saying about different versions of libdl etc.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #36 on: November 19, 2022, 11:26:52 pm »
Also one of such cases if one creates absolutely new "simple program" having nothing in it and compiling into 200k executable. You readelf it, you won't find any glibc dependencies.

The RTL links against the C library only when the used units require it. And the core units don't. That's why for threading support you need to add cthreads.

But add dynlibs to uses section and you will get dlopen and several other dl... functions with version information (probably 2.34 for recent linux versions, since this glibc version is notable in that they merged different so modules to reside in the single libc so they have to do version increase for plenty of related functions). But the glibc binding is unexpected, the dl unit having dlopen declaration uses "dl" lib. Here we have an indirect consequence, it's probably the smart linker of recent versions who knows (or resolved with symbol chaining) that here it maps dl* function to newly reappeared ones in glibc.

That is because the dl unit which is used by the DynLibs unit explicitly links against the C library:

Code: Pascal  [Select][+][-]
  1. {$if defined(linux)}
  2.     { if libc is not linked explicitly, FPC might chose the wrong startup code, as
  3.       libdl depends on libc on linux, this does not hurt }
  4.     {$linklib c}
  5. {$endif}

So fpc (and probably lazarus also) formally distance themselves from the c runtime in most of basic cases (probably threads is another exception) but has no full control about it.

For Lazarus not linking against the C library is not really possible, because it requires the use of C libraries be it GTK, Qt or - if one would do a custom drawn widgetset - against the X11 or Wayland libraries.

But in case with acknowledge that investigation of basic glibc usage in fpc/lazaraus is possible then the capping might look like this

We are not interested in introducing any kind of capping regarding the C library into the RTL. If you want your program to support a certain C library version then compile on a distribution with that version.

maxerist

  • New Member
  • *
  • Posts: 20
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #37 on: November 20, 2022, 06:39:39 pm »
@MarkMLl, thanks for mentioning dynamic loading, if one has control of a unit with external declarations to glibc he or she can choose dynamic loading instead of static declarations and this can help with avoiding the problem with versioned symbols

@PascalDragon, thanks for clarifications and explaining the state of things at the moment. You added to my conviction that trying to implement full glibc version control is not feasible.

Also some additional observations. When we compile on a system with glibc version N, the question arises what is the minimum glibc version M when the program will start on a system with it and not complain about not founding some versioned symbol. The answer it depends... All info below is for Linux x86_64

It looks like For glibc 2.34 N = M = 2.34 in 99.999% cases. This is because the glibc team did a big thing finally merging (libdl libpthread libc libutil libanl) into one library and making some additional changes so finally many dl*, pthread* functions increased in version and even  __libc_start_main did. The latter is important because this is a symbol fpc magically control by itself and the end program developer has no control of it (PascalDragon will correct me is I'm wrong).

But for earlier version M < N for many cases. For example, I compiled a blank form Lazarus project on a system with 2.28 and it looked like all symbols were from 2.2.5. Another approach for guessing was when I collected all default symbols from 2.28 libs (libdl libpthread libc ...) with readelf ... | grep @@... and grouped the result list by count. The majority of public symbols (probably 90%) were from version 2.2.5, the next in charts were 2.3, 2.4, 2.3.4. So it depends on the functions used in the program.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #38 on: November 20, 2022, 06:53:33 pm »
@MarkMLl, thanks for mentioning dynamic loading, if one has control of a unit with external declarations to glibc he or she can choose dynamic loading instead of static declarations and this can help with avoiding the problem with versioned symbols

Except that it /is/ relevant for access to libdl etc. itself.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

maxerist

  • New Member
  • *
  • Posts: 20
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #39 on: November 24, 2022, 03:13:17 pm »
Just would like to share a proof of concept approach for building the fpc/lazarus executable on another system with limited requirements (fpc/lazarus not required)

This will work becuase of the following observations:
  • officially fpc links on linux with gnu linker (ld)
  • any symbol in object files generated by fpc (or gcc) doesn't require any version from the glibc functions unless specifically crafted (@ versioning from previous posts). It is the linker and the system it works on that insist on versioning.
But I should mention that this method involved some cheating unless fpc has or will have some option allowing working without one. Also the details about my experience will require adjustments with other project/configurations

Part 1. fpc/lazarus on any machine you prefer to develop with

During the compilation process fpc launches the linker (/usr/bin/ld ) to link all the required object files (o, a) into the executable. We will just learn how the compiles does this and reproduce it on another machine. The actual line involved can be seen if you check [ Verbosity-Show executable info (Win32 only) (-vx)  ] and after that either  "Copy all/Original messages to clipboard" to find it amongst them or  "Filter non-urgent message-None" and copy individual line
It should look something like
Quote
  "Debug: Executing "/usr/bin/ld" with command line "-b elf64-x86-64 -m elf_x86_64  --dynamic-linker=/lib64/ld-linux-x86-64.so.2     -L. -o {pathToTargetExeFile} -T {pathToScript} -e _start"

Here {pathToTargetExeFile} is to be modified or left as it is and {pathToScript} is important part that involves cheating.

All the paths to necessary files is in the script. All linked object files, search directories and so on. Normally this file (its name is something like link4372.res) is created by the compiler and deleted after linking.

But you can let it live with two alternative options:
  • if your program is big enough or/and your real/virtual machine slow enough, you can just go in your file manager of choice and just copy it while the ld is linking.
  • you can force the linker (and also fpc compiling chain) to interrupt with an error (by for example introducing an external, required, but absent symbol). Because of this "bug" (or feature for this technique) the script file survives. It looks like it resides where your project is.

The script contains several sections, but we're  interested in INPUT( and GROUP( ones with absolute pathes. Fpc does a great job introducing here all the correct absolute pathes to all required object (o) or library (a) pathes. In my case I even felt free to delete all the directories from the SEARCH_DIR section. The only exceptions were crti.o and crtn.o files whose pathes were wrong, I just fixed them.

So the steps involved in linking on another machines are:
  • collecting all the files mentioned in INPUT, GROUP sections and copying them into another place on another machine
  • correcting the corresponding paths in the script
  • running /usr/bin/ld on another machine with correct path to the new modifed script.

Part 2. The OS/machine.

In my case I made the experiment with a fresh Debian 64 install. Currently (23.11.2022) it contains glibc 2.31 so compilable for glibc 2.31 and lower versions. For my project due to a singe symbol this was 2.28 (All other symbols were from 2.2.5).
There were requirements for successful linking
  •   sudo apt install build-essential  (for gnu build chain, containing ld)
  •   sudo apt install libgtk2.0-dev  (gtk2 development, Lazarus itself requires it when installing)

That's almost all, also just stripped the executable since it contained the debug symbols.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #40 on: November 24, 2022, 05:35:59 pm »
I'd throw in (after a few minutes playing) that on Linux Lazarus Options -> Compiler Options -> Custom Options -> All Options ... gives you a checkbox for -sh (or you can just add that to the "Custom Options" list). Selecting that results in a build finishing with a ppas.sh script and a .res for the linker's -T option.

That has some useful implications for an issue I raised a couple of weeks ago where it wasn't possible to build FPC 3.2 using 3.0 on Linux x86_64, which the developers brushed under the carpet.

Another thing worth getting into the doctrine is that ld (GNU ld, particularly on Linux) resolves all symlinks, so moving a binary between systems with substantially different varianct of core libraries can be an issue.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

maxerist

  • New Member
  • *
  • Posts: 20
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #41 on: November 25, 2022, 09:43:30 am »
I'd throw in (after a few minutes playing) that on Linux Lazarus Options -> Compiler Options -> Custom Options -> All Options ... gives you a checkbox for -sh ....
Great to know, thanks.  I wish I knew, my post would be much shorter :)

I can confirm that for sh/st options the res file is exactly the same as the one that is created and deleted without it. Also the shell script generated by fpc works when executed on another machine (providing other necessary steps were made). It links and aslo extracts debug symbols (if necessary) and strips. The only difference I noticed between sh and st (shell for target linking) options is that latter uses the tool executable names without full paths, probably assuming that the tools locations might be different.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #42 on: November 25, 2022, 09:56:28 am »
I can confirm that for sh/st options the res file is exactly the same as the one that is created and deleted without it.

I've not checked yet but expect differences in the .res file between 3.0.4 and 3.2.0, relating to the -T warning that appeared during a 3.0 compilation. That can have various side-effects, depending on target.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #43 on: November 27, 2022, 09:56:02 pm »
I can confirm that for sh/st options the res file is exactly the same as the one that is created and deleted without it. Also the shell script generated by fpc works when executed on another machine (providing other necessary steps were made). It links and aslo extracts debug symbols (if necessary) and strips. The only difference I noticed between sh and st (shell for target linking) options is that latter uses the tool executable names without full paths, probably assuming that the tools locations might be different.

-sh -> Script for linking on host
-st -> Script for linking on target

That's why there are differences.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found
« Reply #44 on: November 27, 2022, 11:06:00 pm »
-sh -> Script for linking on host
-st -> Script for linking on target

That's why there are differences.

Sorry, I should have spotted that and saved you some work.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018