0

I build the simplest program on current newest Fedora distribution (35):

$ cat test.c
int main(int argc, char **argv)
{
}

$ cc test.c

The resulting a.out can't be run on an older system, because the glibc on fedora 35 is 2.34:

$ readelf --dyn-sym a.out

Symbol table '.dynsym' contains 3 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.34 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

For example, on Ubuntu 20 I get this error:

$ ./a.out
./a.out: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./a.out)

How can I build an program on newer Linux that can run on older Linux?

I couldn't find any simple solution. There's a complicated one but nothing simple.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
yuanjianpeng
  • 335
  • 1
  • 9
  • 1
    Usually, the easiest way is to build in a Docker (or other) container containing your target platform, so that you link against the older library. Or link statically - but that has trade-offs of its own. – Toby Speight Aug 18 '23 at 08:39
  • Is there any link option to use old version function on glibc or totally disable symbol version – yuanjianpeng Aug 18 '23 at 08:55
  • Unless you have old headers installed the compiler doesn't know what symbols the old glibc provides, or what their signatures are. – Charles Duffy Aug 19 '23 at 03:40
  • By the way, note that there **are** plenty of practical options -- be it installing those old headers, or running a completely static build (with the libc functions the executable needs built into the executable itself instead of loaded from a library). So anything equivalent to "you can't" is not an accurate answer. – Charles Duffy Aug 19 '23 at 03:43
  • @CharlesDuffy Note that _headers_ have very little to do with symbol versioning -- you also need old library _binaries_ (`ctr0.o`, `libc.so.6`, etc.) to link against. – Employed Russian Aug 19 '23 at 03:46
  • Dynamic linking happens at runtime. If you don't have symbol versions, for C, the headers are enough for dynamic content. (Your .o files _aren't_ dynamic content, granted, but that's why I'm narrowing my definitions; as long as the statically linked .o or .a files don't make version-specific assumptions about the dynamically linked content it's moot). – Charles Duffy Aug 19 '23 at 03:48
  • Anyhow -- in C, the headers determine the calling signature, and the ABI locks a signature down to a stack layout used to pass arguments during a call. So the headers have _everything_ to do with it; if you know the headers and the ABI spec the dynamic linker can put together the other details later. – Charles Duffy Aug 19 '23 at 03:51
  • @CharlesDuffy Your understanding of this issue appears to be incomplete. If your `.o` doesn't specify a version and you link that `.o` into `foo.so` without any version info present, your `foo.so` will be "versionless". Which (of the several available) version do you think will be selected _at runtime_? Answer: the _wrong_ one. – Employed Russian Aug 19 '23 at 04:07
  • As I understand the premise and goal, the intent is to build a binary to be deployed to a system with only an old version, so behavior on systems with multiple choices of libc is moot. Which is to say, yes, I know what symbol versions are for. That doesn't mean they're always relevant or necessary. – Charles Duffy Aug 19 '23 at 12:07
  • (Hi; I used to be half the team doing userland porting and packaging for an embedded distro back around 2000 or so. That's a world where one very much cares only about making the contents of an image mutually compatible with everything else in that same image; one thing we wrote tools for was to strip any symbols the customer's installed binaries never linked to out of the local shared libraries). – Charles Duffy Aug 19 '23 at 12:12

1 Answers1

0

How can I build an program on newer Linux that can run on older Linux?

See this answer (down at the bottom) for possible solutions.

Is there any link option to use old version function on glibc or totally disable symbol version

The symbol versioning is there for a reason -- the symbols are not ABI-compatible. If there was a link option to disable symbol versioning, your executable built with it would then run on the older system, and crash with an error that would be very hard for you to understand.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362