public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* question of compatibility between different GLIBC symbol versions
@ 2023-07-17 23:13 robert rozee
  2023-07-17 23:34 ` Andrew Pinski
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: robert rozee @ 2023-07-17 23:13 UTC (permalink / raw)
  To: libc-alpha

Hi,
    I'm after a little guidance around GLIBC/libc versioned symbols, in particular using older symbol versions (2.2.5) and using 'artificially' unversioned symbols.

A little background: I am a user of FPC/Lazarus, and use Lazarus to create GUI applications to run on Linux desktop systems. When a GUI application is compiled the resulting ELF binary ends up linked to a couple of dozen versioned libc symbols, of particular interest to me are the six symbols: __libc_start_main, dlopen, dlclose, dladdr, dlsym, and dlerror. These six symbols are normally versioned as GLIBC_2.34 if the compile is carried out on a recent Linux distro, and versioned as GLIBC_2.2.5 if compiled on an older distro. This presents a problem - a binary created on a recent distro will not run on an older distro due to the symbol versioning. The generally accepted workaround for this within the FPC/Lazarus community is to always keep an 'old' Linux VM handy for compiling on, however over time this is becoming a progressively more difficult solution.


I've managed to achieve a simple workaround that allows the removing of versioning from symbols, as well as bringing in libdl.so.2 as a 'NEEDED' library. This yields a binary that runs on recent and older Linux distros. I've also verified that for each of the above six symbols, both recent (2.34) and older (2.2.5) versions point to the same entry point within libc.so.6.


I'm left with two questions...

(1) Is it OK to use unversioned libc symbols through 'manipulation' of the compile-time linking process? This will result in the binary picking up the latest version of each symbol at run-time. I am not aware of unversioned symbols normally being introduced into an application's Dynamic Symbol Table when a versioned one of the same name exists, and it seems that libc.so.6 has contained NO unversioned symbols for at least 20 years. So it is perhaps fair to say that at best unversioned libc symbols are not a 'normal thing'.

(2) Is it OK to instead hard-code (within the FPC RTL and Lazarus LCL) all libc symbols to their earliest (in most cases GLIBC_2.2.5) versions? Then the only 'manipulation' required is injecting libdl.so.2 as a 'NEEDED' library. But will symbols versioned GLIBC_2.2.5 at some future time be depreciated from GLIBC? And/or will libdl.so.2 at some future time be removed, thereby breaking any binary that has it as 'NEEDED'?


Would much appreciate any help anyone can offer,


cheers,
rob   :-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-17 23:13 question of compatibility between different GLIBC symbol versions robert rozee
@ 2023-07-17 23:34 ` Andrew Pinski
  2023-07-17 23:36 ` DJ Delorie
  2023-07-18  8:00 ` Florian Weimer
  2 siblings, 0 replies; 13+ messages in thread
From: Andrew Pinski @ 2023-07-17 23:34 UTC (permalink / raw)
  To: robert rozee; +Cc: libc-alpha

On Mon, Jul 17, 2023 at 4:14 PM robert rozee via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> Hi,
>     I'm after a little guidance around GLIBC/libc versioned symbols, in particular using older symbol versions (2.2.5) and using 'artificially' unversioned symbols.
>
> A little background: I am a user of FPC/Lazarus, and use Lazarus to create GUI applications to run on Linux desktop systems. When a GUI application is compiled the resulting ELF binary ends up linked to a couple of dozen versioned libc symbols, of particular interest to me are the six symbols: __libc_start_main, dlopen, dlclose, dladdr, dlsym, and dlerror. These six symbols are normally versioned as GLIBC_2.34 if the compile is carried out on a recent Linux distro, and versioned as GLIBC_2.2.5 if compiled on an older distro. This presents a problem - a binary created on a recent distro will not run on an older distro due to the symbol versioning. The generally accepted workaround for this within the FPC/Lazarus community is to always keep an 'old' Linux VM handy for compiling on, however over time this is becoming a progressively more difficult solution.

A Linux container rather than a VM might be easier to use and would
make it independent of VM kernel.
You could also use a sysroot and do a "cross compile" that sysroot.
This is how people handle this issue really.
And is extendable and does not require VMs or even other bigger issues
with forward compatibility; only backwards compatibility.

Thanks,
Andrew

>
>
> I've managed to achieve a simple workaround that allows the removing of versioning from symbols, as well as bringing in libdl.so.2 as a 'NEEDED' library. This yields a binary that runs on recent and older Linux distros. I've also verified that for each of the above six symbols, both recent (2.34) and older (2.2.5) versions point to the same entry point within libc.so.6.
>
>
> I'm left with two questions...
>
> (1) Is it OK to use unversioned libc symbols through 'manipulation' of the compile-time linking process? This will result in the binary picking up the latest version of each symbol at run-time. I am not aware of unversioned symbols normally being introduced into an application's Dynamic Symbol Table when a versioned one of the same name exists, and it seems that libc.so.6 has contained NO unversioned symbols for at least 20 years. So it is perhaps fair to say that at best unversioned libc symbols are not a 'normal thing'.
>
> (2) Is it OK to instead hard-code (within the FPC RTL and Lazarus LCL) all libc symbols to their earliest (in most cases GLIBC_2.2.5) versions? Then the only 'manipulation' required is injecting libdl.so.2 as a 'NEEDED' library. But will symbols versioned GLIBC_2.2.5 at some future time be depreciated from GLIBC? And/or will libdl.so.2 at some future time be removed, thereby breaking any binary that has it as 'NEEDED'?
>
>
> Would much appreciate any help anyone can offer,
>
>
> cheers,
> rob   :-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-17 23:13 question of compatibility between different GLIBC symbol versions robert rozee
  2023-07-17 23:34 ` Andrew Pinski
@ 2023-07-17 23:36 ` DJ Delorie
  2023-07-18  8:00 ` Florian Weimer
  2 siblings, 0 replies; 13+ messages in thread
From: DJ Delorie @ 2023-07-17 23:36 UTC (permalink / raw)
  To: robert rozee; +Cc: libc-alpha


TL;DR Always build on the oldest OS you plan on supporting.

robert rozee via Libc-alpha <libc-alpha@sourceware.org> writes:
> (1) Is it OK to use unversioned libc symbols through 'manipulation' of
> the compile-time linking process?

If you do this, your application will only run (if it runs at all) on
the libc version you compile against, because you have disabled the
compatibility features completely.

> (2) Is it OK to instead hard-code (within the FPC RTL and Lazarus LCL)
> all libc symbols to their earliest (in most cases GLIBC_2.2.5)
> versions?

No.  The reason those functions have different versions is because
*they're different*.  That includes "passing different arguments".  The
version you link against is the one that matches the headers that
describe it.

I wrote an article about this a few years ago:

https://developers.redhat.com/blog/2019/08/01/how-the-gnu-c-library-handles-backward-compatibility

One alternative to maintaining an old OS is to maintain an old
*buildroot* instead, which contains the headers and libraries from that
old OS.  How to build against a buildroot is outside the scope of this
list, but mostly it's about setting the compiler and linker flags
accordingly.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-17 23:13 question of compatibility between different GLIBC symbol versions robert rozee
  2023-07-17 23:34 ` Andrew Pinski
  2023-07-17 23:36 ` DJ Delorie
@ 2023-07-18  8:00 ` Florian Weimer
  2023-07-18  8:14   ` Andreas Schwab
                     ` (2 more replies)
  2 siblings, 3 replies; 13+ messages in thread
From: Florian Weimer @ 2023-07-18  8:00 UTC (permalink / raw)
  To: robert rozee via Libc-alpha; +Cc: robert rozee

* robert rozee via Libc-alpha:

> A little background: I am a user of FPC/Lazarus, and use Lazarus to
> create GUI applications to run on Linux desktop systems. When a GUI
> application is compiled the resulting ELF binary ends up linked to a
> couple of dozen versioned libc symbols, of particular interest to me
> are the six symbols: __libc_start_main, dlopen, dlclose, dladdr,
> dlsym, and dlerror. These six symbols are normally versioned as
> GLIBC_2.34 if the compile is carried out on a recent Linux distro, and
> versioned as GLIBC_2.2.5 if compiled on an older distro. This presents
> a problem - a binary created on a recent distro will not run on an
> older distro due to the symbol versioning. The generally accepted
> workaround for this within the FPC/Lazarus community is to always keep
> an 'old' Linux VM handy for compiling on, however over time this is
> becoming a progressively more difficult solution.

Starting with glibc 2.34, the statically linked startup code that calls
__libc_start_main is incompatible with earlier glibc versions.  So you'd
have to bundle your own version of that.

Removing symbol versioning as a whole is probably not a good idea.  It
will likely continue to work for a while in the sense that newly linked
binaries will run correctly even if they combine FPC code with code
written in other languages.  (I expect that linked applications will
keep working indefinitely as far as glibc is concerned.)  Still it's
probably better to use the .symver assembler directive to specify the
symbol versions you want explicitly.  (If you have your own assembler,
you might have to implement it there first.)

> (1) Is it OK to use unversioned libc symbols through 'manipulation' of
> the compile-time linking process? This will result in the binary
> picking up the latest version of each symbol at run-time.

At run time, it really should be the earliest implemented (base)
version, otherwise we have a bug.

At static link time, the link editor picks the default symbol version,
which is usually the most recent symbol version.

> I am not aware of unversioned symbols normally being introduced into
> an application's Dynamic Symbol Table when a versioned one of the same
> name exists, and it seems that libc.so.6 has contained NO unversioned
> symbols for at least 20 years. So it is perhaps fair to say that at
> best unversioned libc symbols are not a 'normal thing'.

It's usually the result of buggy underlinking, not something done
deliberately.  There seem to be other bugs as well.  For example,
on my system /usr/lib64/firefox/libipcclientcerts.so, has unversioned
references to mprotect and sysconf:

   52: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF mprotect
   53: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF sysconf

Even though it contains other versioned glibc symbols.  It's also odd
that these symbols come after the defined symbols in the table; with
GNU_HASH, they should come before.  This is probably a toolchain bug
somewhere.

> (2) Is it OK to instead hard-code (within the FPC RTL and Lazarus LCL)
> all libc symbols to their earliest (in most cases GLIBC_2.2.5)
> versions? Then the only 'manipulation' required is injecting
> libdl.so.2 as a 'NEEDED' library. But will symbols versioned
> GLIBC_2.2.5 at some future time be depreciated from GLIBC?

No, these symbols will be provided indefinitely, as long as we
maintained the current x86-64 ABI.

> And/or will libdl.so.2 at some future time be removed, thereby
> breaking any binary that has it as 'NEEDED'?

The file may vanish from disk, but libdl.so.2 DT_NEEDED references will
continue to work for as long as we maintain ABI compatibility.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-18  8:00 ` Florian Weimer
@ 2023-07-18  8:14   ` Andreas Schwab
  2023-07-18 12:24     ` Florian Weimer
  2023-07-20  5:44   ` robert rozee
  2023-07-20 11:47   ` robert rozee
  2 siblings, 1 reply; 13+ messages in thread
From: Andreas Schwab @ 2023-07-18  8:14 UTC (permalink / raw)
  To: Florian Weimer via Libc-alpha; +Cc: Florian Weimer, robert rozee

On Jul 18 2023, Florian Weimer via Libc-alpha wrote:

> It's usually the result of buggy underlinking, not something done
> deliberately.  There seem to be other bugs as well.  For example,
> on my system /usr/lib64/firefox/libipcclientcerts.so, has unversioned
> references to mprotect and sysconf:
>
>    52: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF mprotect
>    53: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF sysconf
>
> Even though it contains other versioned glibc symbols.  It's also odd
> that these symbols come after the defined symbols in the table; with
> GNU_HASH, they should come before.  This is probably a toolchain bug
> somewhere.

They use a version script, so it may just be a bug in how that is
generated.  (I don't see either of those references in the version of
firefox I have.)

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-18  8:14   ` Andreas Schwab
@ 2023-07-18 12:24     ` Florian Weimer
  0 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2023-07-18 12:24 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Florian Weimer via Libc-alpha, robert rozee

* Andreas Schwab:

> On Jul 18 2023, Florian Weimer via Libc-alpha wrote:
>
>> It's usually the result of buggy underlinking, not something done
>> deliberately.  There seem to be other bugs as well.  For example,
>> on my system /usr/lib64/firefox/libipcclientcerts.so, has unversioned
>> references to mprotect and sysconf:
>>
>>    52: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF mprotect
>>    53: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF sysconf
>>
>> Even though it contains other versioned glibc symbols.  It's also odd
>> that these symbols come after the defined symbols in the table; with
>> GNU_HASH, they should come before.  This is probably a toolchain bug
>> somewhere.
>
> They use a version script, so it may just be a bug in how that is
> generated.  (I don't see either of those references in the version of
> firefox I have.)

It's injected by build/unix/elfhack.  We still use that in some of our
builds, although it happens that today I looked at a libxul.so object
that got corrupted by it (it seems).

Thanks,
Florian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-18  8:00 ` Florian Weimer
  2023-07-18  8:14   ` Andreas Schwab
@ 2023-07-20  5:44   ` robert rozee
  2023-07-20  7:22     ` Florian Weimer
  2023-07-20 11:47   ` robert rozee
  2 siblings, 1 reply; 13+ messages in thread
From: robert rozee @ 2023-07-20  5:44 UTC (permalink / raw)
  To: libc-alpha

> Sent: Tuesday, July 18, 2023 at 8:00 PM
> From: "Florian Weimer" <fweimer@redhat.com>
> > A little background: I am a user of FPC/Lazarus, and use Lazarus to
> > create GUI applications to run on Linux desktop systems. When a GUI
> > application is compiled the resulting ELF binary ends up linked to a
> > couple of dozen versioned libc symbols, of particular interest to me
> > are the six symbols: __libc_start_main, dlopen, dlclose, dladdr,
> > dlsym, and dlerror. These six symbols are normally versioned as
> > GLIBC_2.34 if the compile is carried out on a recent Linux distro, and
> > versioned as GLIBC_2.2.5 if compiled on an older distro. This presents
> > a problem - a binary created on a recent distro will not run on an
> > older distro due to the symbol versioning. The generally accepted
> > workaround for this within the FPC/Lazarus community is to always keep
> > an 'old' Linux VM handy for compiling on, however over time this is
> > becoming a progressively more difficult solution.

> Starting with glibc 2.34, the statically linked startup code that calls
> __libc_start_main is incompatible with earlier glibc versions. So you'd
> have to bundle your own version of that.

with FPC the startup code that calls __libc_start_main is (as far as i can
determine) hard-coded and has not been changed since 2005. FPC/Lazarus has
no knowledge of C header files. there is NO practical means of changing
this. is this going to be a problem in future?

i take it the incompatibility you mention is to do with the parameters init
and fini, where pre-2.34 these both MUST point to valid code, whereas for
2.34 and later init SHOULD be set to NULL? will there be some future
requirement that init MUST be set to NULL?


> Removing symbol versioning as a whole is probably not a good idea [...]
> probably better to use the .symver assembler directive to specify the
> symbol versions you want explicitly. (If you have your own assembler,
> you might have to implement it there first.)

FPC/Lazarus can handle versioned symbols OK, but the developers choose to
NOT specify versions as they believe that it is far better to always use the
most recent version of a symbol available at compile-time. this leaves 2.34
and later symbols linked to old hard-coded prototypes (circa 2005).


> > (1) Is it OK to use unversioned libc symbols through 'manipulation' of
> > the compile-time linking process? This will result in the binary
> > picking up the latest version of each symbol at run-time.

> At run time, it really should be the earliest implemented (base)
> version, otherwise we have a bug.

> At static link time, the link editor picks the default symbol version,
> which is usually the most recent symbol version.

with FPC/Lazarus the Dynamic Symbol Table of the ELF header currently always
ends up (without outside intervention) containing the  most recent symbol
versions. my solution is to create a 'fake' libdl.so file that defines
a set of unversioned symbols. the linker picks up these symbols in
preference to the ones contained in libdl.so.2 or libc.so.6.


> > I am not aware of unversioned symbols normally being introduced into
> > an application's Dynamic Symbol Table when a versioned one of the same
> > name exists [...]
> It's usually the result of buggy underlinking, not something done
> deliberately [...]

unfortunately, while  my 'fake' libdl.so file works 100% for injecting
unversioned symbols, but can NOT successfully inject a GLIBC_2.2.5
versioned __libc_start_main. i'm not quite sure why.


> > (2) Is it OK to instead hard-code (within the FPC RTL and Lazarus LCL)
> > all libc symbols to their earliest (in most cases GLIBC_2.2.5)
> > versions? Then the only 'manipulation' required is injecting
> > libdl.so.2 as a 'NEEDED' library. But will symbols versioned
> > GLIBC_2.2.5 at some future time be depreciated from GLIBC?

> [...] these symbols will be provided indefinitely, as long as we
> maintained the current x86-64 ABI.

excellent! this removes one of the the main objection raised over
hard-coding to use GLIBC_2.2.5 symbols.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-20  5:44   ` robert rozee
@ 2023-07-20  7:22     ` Florian Weimer
  2023-07-20  8:32       ` robert rozee
  0 siblings, 1 reply; 13+ messages in thread
From: Florian Weimer @ 2023-07-20  7:22 UTC (permalink / raw)
  To: robert rozee via Libc-alpha; +Cc: robert rozee

* robert rozee via Libc-alpha:

>> Sent: Tuesday, July 18, 2023 at 8:00 PM
>> From: "Florian Weimer" <fweimer@redhat.com>
>> > A little background: I am a user of FPC/Lazarus, and use Lazarus to
>> > create GUI applications to run on Linux desktop systems. When a GUI
>> > application is compiled the resulting ELF binary ends up linked to a
>> > couple of dozen versioned libc symbols, of particular interest to me
>> > are the six symbols: __libc_start_main, dlopen, dlclose, dladdr,
>> > dlsym, and dlerror. These six symbols are normally versioned as
>> > GLIBC_2.34 if the compile is carried out on a recent Linux distro, and
>> > versioned as GLIBC_2.2.5 if compiled on an older distro. This presents
>> > a problem - a binary created on a recent distro will not run on an
>> > older distro due to the symbol versioning. The generally accepted
>> > workaround for this within the FPC/Lazarus community is to always keep
>> > an 'old' Linux VM handy for compiling on, however over time this is
>> > becoming a progressively more difficult solution.
>
>> Starting with glibc 2.34, the statically linked startup code that calls
>> __libc_start_main is incompatible with earlier glibc versions. So you'd
>> have to bundle your own version of that.
>
> with FPC the startup code that calls __libc_start_main is (as far as i can
> determine) hard-coded and has not been changed since 2005. FPC/Lazarus has
> no knowledge of C header files. there is NO practical means of changing
> this. is this going to be a problem in future?

Potentially yes.  You can avoid future problems by hard-coding the
symbol version on __libc_start_main (the requred version is
architecture-specific, though).  We currently only have one
implementation, despite t he two symbol versions, so this keeps working
for now.  The newer symbol version is only used as a marker that the
binary requires a sufficiently recent glibc version where
__libc_start_main has an additional capability.

> i take it the incompatibility you mention is to do with the parameters
> init and fini, where pre-2.34 these both MUST point to valid code,
> whereas for 2.34 and later init SHOULD be set to NULL? will there be
> some future requirement that init MUST be set to NULL?

Not for the existing symbol versions.  It is tempting to clean this up
eventually and simplify the startup code to just construct the address
of main and call the libc trampoline with just that, and not any other
arguments.  If that happens, we would probably call the function
something else, and not __libc_start_main.  Maybe we should have done
the same already in glibc 2.34.

>> Removing symbol versioning as a whole is probably not a good idea [...]
>> probably better to use the .symver assembler directive to specify the
>> symbol versions you want explicitly. (If you have your own assembler,
>> you might have to implement it there first.)
>
> FPC/Lazarus can handle versioned symbols OK, but the developers choose to
> NOT specify versions as they believe that it is far better to always use the
> most recent version of a symbol available at compile-time. this leaves 2.34
> and later symbols linked to old hard-coded prototypes (circa 2005).

Sorry, I don't understand.

> with FPC/Lazarus the Dynamic Symbol Table of the ELF header currently always
> ends up (without outside intervention) containing the  most recent symbol
> versions. my solution is to create a 'fake' libdl.so file that defines
> a set of unversioned symbols. the linker picks up these symbols in
> preference to the ones contained in libdl.so.2 or libc.so.6.

That may not work if there are other objects in the link that have been
linked against e.g. glibc 2.28 and reference versioned symbols in
libdl.so.2.  Some link editors might complain about missing symbols in
libdl.so.2 as a result, and the link fails.

>> > I am not aware of unversioned symbols normally being introduced into
>> > an application's Dynamic Symbol Table when a versioned one of the same
>> > name exists [...]
>> It's usually the result of buggy underlinking, not something done
>> deliberately [...]
>
> unfortunately, while  my 'fake' libdl.so file works 100% for injecting
> unversioned symbols, but can NOT successfully inject a GLIBC_2.2.5
> versioned __libc_start_main. i'm not quite sure why.

You can specific the requested symbol version directly in the object
file, that should work.  It's also the more conversative approach for
the dl* functions.

> excellent! this removes one of the the main objection raised over
> hard-coding to use GLIBC_2.2.5 symbols.

Note that you'll need an architecture-specific table with the required
symbol versions.  GLIBC_2.2.5 here is specific to x86-64.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-20  7:22     ` Florian Weimer
@ 2023-07-20  8:32       ` robert rozee
  2023-07-20 10:09         ` Florian Weimer
  0 siblings, 1 reply; 13+ messages in thread
From: robert rozee @ 2023-07-20  8:32 UTC (permalink / raw)
  To: libc-alpha

Sent: Thursday, July 20, 2023 at 7:22 PM
From: "Florian Weimer" <fweimer@redhat.com>
>>> Sent: Tuesday, July 18, 2023 at 8:00 PM
>>> From: "Florian Weimer" <fweimer@redhat.com>
>>>> A little background: I am a user of FPC/Lazarus, and use Lazarus to
>>>> create GUI applications to run on Linux desktop systems. When a GUI
>>>> application is compiled the resulting ELF binary ends up linked to a
>>>> couple of dozen versioned libc symbols, of particular interest to me
>>>> are the six symbols: __libc_start_main, dlopen, dlclose, dladdr,
>>>> dlsym, and dlerror. These six symbols are normally versioned as
>>>> GLIBC_2.34 if the compile is carried out on a recent Linux distro, and
>>>> versioned as GLIBC_2.2.5 if compiled on an older distro. This presents
>>>> a problem - a binary created on a recent distro will not run on an
>>>> older distro due to the symbol versioning. The generally accepted
>>>> workaround for this within the FPC/Lazarus community is to always keep
>>>> an 'old' Linux VM handy for compiling on, however over time this is
>>>> becoming a progressively more difficult solution.

>>> Starting with glibc 2.34, the statically linked startup code that calls
>>> __libc_start_main is incompatible with earlier glibc versions. So you'd
>>> have to bundle your own version of that.

>> with FPC the startup code that calls __libc_start_main is (as far as i can
>> determine) hard-coded and has not been changed since 2005. FPC/Lazarus has
>> no knowledge of C header files. there is NO practical means of changing
>> this. is this going to be a problem in future?

> Potentially yes. You can avoid future problems by hard-coding the
> symbol version on __libc_start_main (the required version is
> architecture-specific, though) [...]

the architecture is not a problem - my notion for a (proper) fix is to target
the fix at ONLY x86-64. once that is sorted, then at some later time others
can bring in other architectures.


>>> Removing symbol versioning as a whole is probably not a good idea [...]
>>> probably better to use the .symver assembler directive to specify the
>>> symbol versions you want explicitly. (If you have your own assembler,
>>> you might have to implement it there first.)

>> FPC/Lazarus can handle versioned symbols OK, but the developers choose to
>> NOT specify versions as they believe that it is far better to always use the
>> most recent version of a symbol available at compile-time. this leaves 2.34
>> and later symbols linked to old hard-coded prototypes (circa 2005).

> Sorry, I don't understand.

oops, my mistake for being unclear. what i meant was that FPC/Lazarus, within
the _existing_language_syntax_, CAN allow for the programmer to specify symbol
versions. FPC's RTL and Lazarus's LCL are themselves written in Pascal, but
currently DO NOT specify symbol versions within their Pascal source code. this
was a conscious decision made by the FPC/Lazarus developers some years ago.

for example, the current prototype for dlopen() is:
function dlopen(Name : PChar; Flags : longint) : Pointer; cdecl; external libdl;

"external" is what specifies that the function is contained in a shared library.

my proposed change is:
function dlopen(Name : PChar; Flags : longint) : Pointer; cdecl; external libdl name 'dlopen@GLIBC_2.2.5';

"external" optionally takes a library parameter, optionally followed by "name"
and an overriding function name - this function name may be versioned.

unfortunately if the library parameter has any numeric extension, this
extension is stripped off by design, but that is a whole other argument
with the FPC/Lazarus developers!

for the documentation of "external" that is probably clearer than my
attempted explanation, see:
https://www.freepascal.org/docs-html/ref/refse98.html


> You can specific the requested symbol version directly in the object
> file, that should work. It's also the more conservative approach for
> the dl* functions.

with FPC/Lazarus the programmer does not have easy access to the object
files. in general, it is essentially 'click one button' to go from Pascal
source code to runnable binary. while there are some limited means to
intervene in the build process, no one really knows how. what one may
call security by obscurity!


cheers,
rob   :-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-20  8:32       ` robert rozee
@ 2023-07-20 10:09         ` Florian Weimer
  0 siblings, 0 replies; 13+ messages in thread
From: Florian Weimer @ 2023-07-20 10:09 UTC (permalink / raw)
  To: robert rozee via Libc-alpha; +Cc: robert rozee

* robert rozee via Libc-alpha:

>>> FPC/Lazarus can handle versioned symbols OK, but the developers choose to
>>> NOT specify versions as they believe that it is far better to always use the
>>> most recent version of a symbol available at compile-time. this leaves 2.34
>>> and later symbols linked to old hard-coded prototypes (circa 2005).
>
>> Sorry, I don't understand.

> my proposed change is:
> function dlopen(Name : PChar; Flags : longint) : Pointer; cdecl; external libdl name 'dlopen@GLIBC_2.2.5';

Yes, that should work, except you need a different version for each
supported architecture.

>> You can specific the requested symbol version directly in the object
>> file, that should work. It's also the more conservative approach for
>> the dl* functions.
>
> with FPC/Lazarus the programmer does not have easy access to the object
> files. in general, it is essentially 'click one button' to go from Pascal
> source code to runnable binary. while there are some limited means to
> intervene in the build process, no one really knows how. what one may
> call security by obscurity!

Eh, in some way, that external specification will be transferred to the
object file.  That's what I meant.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-18  8:00 ` Florian Weimer
  2023-07-18  8:14   ` Andreas Schwab
  2023-07-20  5:44   ` robert rozee
@ 2023-07-20 11:47   ` robert rozee
  2023-07-20 12:03     ` Andreas Schwab
  2023-07-21  2:55     ` Fangrui Song
  2 siblings, 2 replies; 13+ messages in thread
From: robert rozee @ 2023-07-20 11:47 UTC (permalink / raw)
  To: libc-alpha

> Sent: Tuesday, July 18, 2023 at 8:00 PM
> From: "Florian Weimer" <fweimer@redhat.com>
>> (1) Is it OK to use unversioned libc symbols through 'manipulation' of
>> the compile-time linking process? This will result in the binary
>> picking up the latest version of each symbol at run-time.

> At run time, it really should be the earliest implemented (base)
> version, otherwise we have a bug.

> At static link time, the link editor picks the default symbol version,
> which is usually the most recent symbol version.

on first reading i missed the significance of this:
"At run time [...] the earliest implemented (base) version"

i had always assumed (incorrectly!) that at run-time an unversioned symbol
in an application binary was matched up with the most recent (@@) symbol
in libc.

using something like readelf, how does one check to see which is the base
version of a symbol? the below (against GLIBC 2.27) seems to show no
distinction:

$ readelf -a /lib/x86_64-linux-gnu/libc.so.6 | grep " sys_nerr"
  2074: 00000000001bc9dc     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@GLIBC_2.2.5
  2076: 00000000001bc9e4     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@GLIBC_2.4
  2077: 00000000001bc9d8     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@@GLIBC_2.12
  2079: 00000000001bc9e0     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@GLIBC_2.3


cheers,
rob   :-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-20 11:47   ` robert rozee
@ 2023-07-20 12:03     ` Andreas Schwab
  2023-07-21  2:55     ` Fangrui Song
  1 sibling, 0 replies; 13+ messages in thread
From: Andreas Schwab @ 2023-07-20 12:03 UTC (permalink / raw)
  To: robert rozee via Libc-alpha; +Cc: robert rozee

On Jul 20 2023, robert rozee via Libc-alpha wrote:

> using something like readelf, how does one check to see which is the base
> version of a symbol? the below (against GLIBC 2.27) seems to show no
> distinction:

Version inheritance is recorded in the .gnu.version_d section.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: question of compatibility between different GLIBC symbol versions
  2023-07-20 11:47   ` robert rozee
  2023-07-20 12:03     ` Andreas Schwab
@ 2023-07-21  2:55     ` Fangrui Song
  1 sibling, 0 replies; 13+ messages in thread
From: Fangrui Song @ 2023-07-21  2:55 UTC (permalink / raw)
  To: robert rozee; +Cc: libc-alpha

On Thu, Jul 20, 2023 at 4:47 AM robert rozee via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> > Sent: Tuesday, July 18, 2023 at 8:00 PM
> > From: "Florian Weimer" <fweimer@redhat.com>
> >> (1) Is it OK to use unversioned libc symbols through 'manipulation' of
> >> the compile-time linking process? This will result in the binary
> >> picking up the latest version of each symbol at run-time.
>
> > At run time, it really should be the earliest implemented (base)
> > version, otherwise we have a bug.
>
> > At static link time, the link editor picks the default symbol version,
> > which is usually the most recent symbol version.
>
> on first reading i missed the significance of this:
> "At run time [...] the earliest implemented (base) version"
>
> i had always assumed (incorrectly!) that at run-time an unversioned symbol
> in an application binary was matched up with the most recent (@@) symbol
> in libc.

https://maskray.me/blog/2020-11-26-all-about-symbol-versioning#rtld-behavior
has some description about this behavior near "When searching a
definition for foo," :)

The rtld behavior is to retains compatibility when a shared object
becomes versioned: the symbols with the smallest version (index 2)
indicate the previously unversioned symbols. If a new version of a
shared object needs to deprecate an unversioned bar, you can remove
bar and define bar@compat instead. Libraries using bar are unaffected
but new linking against bar is disallowed.

> using something like readelf, how does one check to see which is the base
> version of a symbol? the below (against GLIBC 2.27) seems to show no
> distinction:

% readelf -V =ld.so
...
Version definition section '.gnu.version_d' contains 7 entries:
 Addr: 0x0000000000000bd8  Offset: 0x00000bd8  Link: 5 (.dynstr)
  000000: Rev: 1  Flags: BASE  Index: 1  Cnt: 1  Name: ld-linux-x86-64.so.2
  0x001c: Rev: 1  Flags: none  Index: 2  Cnt: 1  Name: GLIBC_2.2.5
////////// base version

> $ readelf -a /lib/x86_64-linux-gnu/libc.so.6 | grep " sys_nerr"
>   2074: 00000000001bc9dc     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@GLIBC_2.2.5
>   2076: 00000000001bc9e4     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@GLIBC_2.4
>   2077: 00000000001bc9d8     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@@GLIBC_2.12
>   2079: 00000000001bc9e0     4 OBJECT  GLOBAL DEFAULT   16 sys_nerr@GLIBC_2.3
>
>
> cheers,
> rob   :-)



-- 
宋方睿

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2023-07-21  2:56 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-17 23:13 question of compatibility between different GLIBC symbol versions robert rozee
2023-07-17 23:34 ` Andrew Pinski
2023-07-17 23:36 ` DJ Delorie
2023-07-18  8:00 ` Florian Weimer
2023-07-18  8:14   ` Andreas Schwab
2023-07-18 12:24     ` Florian Weimer
2023-07-20  5:44   ` robert rozee
2023-07-20  7:22     ` Florian Weimer
2023-07-20  8:32       ` robert rozee
2023-07-20 10:09         ` Florian Weimer
2023-07-20 11:47   ` robert rozee
2023-07-20 12:03     ` Andreas Schwab
2023-07-21  2:55     ` Fangrui Song

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).