Discussion:
[Android] The reason why -Bsymbolic is turned on by default
Alexander Ivchenko
2013-03-29 18:55:50 UTC
Permalink
Hi,

When compiling a shared library with "-mandroid -shared" the option
-Bsymbolic for linker is turned on by default. What was the reason
behind that default? Isn't using of -Bsymbolic somehow dangerous and
should be avoided..? (as e.g. is explained in the mail from Richard
Henderson http://gcc.gnu.org/ml/gcc/2001-05/msg01551.html).

Since there is no (AFAIK) option like -Bno-symbolic we cannot use
-fno-pic binary with COPY relocations in it (android dynamic loader
will throw an error when there is COPY relocation against DT_SYMBOLIC
library..)

(I'm sorry for sending it twice to Maxim - new google interface made
my text too "rich")

thank you in advance,

Alexander
Maxim Kuvyrkov
2013-04-03 07:58:50 UTC
Permalink
Post by Alexander Ivchenko
Hi,
When compiling a shared library with "-mandroid -shared" the option
-Bsymbolic for linker is turned on by default. What was the reason
behind that default? Isn't using of -Bsymbolic somehow dangerous and
should be avoided..? (as e.g. is explained in the mail from Richard
Henderson http://gcc.gnu.org/ml/gcc/2001-05/msg01551.html).
Since there is no (AFAIK) option like -Bno-symbolic we cannot use
-fno-pic binary with COPY relocations in it (android dynamic loader
will throw an error when there is COPY relocation against DT_SYMBOLIC
library..)
I don't know the exact reason behind -Bsymbolic (it came as a requirement from Google's Android team), but I believe it produces slightly faster code (and fancy symbol preemption is not required on phones and TVs). Also, it might be that kernel can share more memory pages of libraries compiled with -Bsymbolic, but I'm not sure.

Now, it appears the problem is that an application cannot use COPY relocation to fetch a symbol out of shared -Bsymbolic library. I don't quite understand why this is forbidden by Bionic's linker. I understand why COPY relocations shouldn't be applied to the inside of DT_SYMBOLIC library. However, I don't immediately see the problem of applying COPY relocation against symbol from DT_SYMBOLIC library to the inside of an executable.

Ard, you committed 5ae44f302b7d1d19f25c4c6f125e32dc369961d9 to Bionic that adds handling of ARM COPY relocations. Can you comment on why COPY relocations from executables to DT_SYMBOLIC libraries are forbidden?

Thank you,

--
Maxim Kuvyrkov
KugelWorks
Ard Biesheuvel
2013-04-03 08:51:08 UTC
Permalink
Post by Maxim Kuvyrkov
Now, it appears the problem is that an application cannot use COPY
relocation to fetch a symbol out of shared -Bsymbolic library. I don't
quite understand why this is forbidden by Bionic's linker. I understand why
COPY relocations shouldn't be applied to the inside of DT_SYMBOLIC library.
However, I don't immediately see the problem of applying COPY relocation
against symbol from DT_SYMBOLIC library to the inside of an executable.
Ard, you committed 5ae44f302b7d1d19f25c4c6f125e32dc369961d9 to Bionic that
adds handling of ARM COPY relocations. Can you comment on why COPY
relocations from executables to DT_SYMBOLIC libraries are forbidden?
Hi all,

The reason that COPY relocations should not be used against shared libraries
built with -Bsymbolic is that *all* references to the source symbol
(including internal ones and ones from other shared libraries) should be
preempted and made to use the copied version that lives inside the address
range of the executable proper. However, a library built with -Bsymbolic
resolves all its internal references at build time, so any reference held by
the library itself is not preemptible, resulting in two live instances of
the same symbol.

The other way around should not be a problem in the same way, but I don't
think the ELF spec (at least the ARM one) allows it, nor is it very
meaningful (assuming external symbols are referenced through the GOT)

Regards,
Ard.
Andrew Haley
2013-04-03 09:25:59 UTC
Permalink
Post by Alexander Ivchenko
When compiling a shared library with "-mandroid -shared" the option
-Bsymbolic for linker is turned on by default. What was the reason
behind that default? Isn't using of -Bsymbolic somehow dangerous and
should be avoided..?
Yes indeed, -Bsymbolic is dangerous.
Post by Alexander Ivchenko
(as e.g. is explained in the mail from Richard
Henderson http://gcc.gnu.org/ml/gcc/2001-05/msg01551.html).
Since there is no (AFAIK) option like -Bno-symbolic we cannot use
-fno-pic binary with COPY relocations in it (android dynamic loader
will throw an error when there is COPY relocation against DT_SYMBOLIC
library..)
Sure, that's true. If a library is built with -Bsymbolic then you
must build executables PIC. That's just how it is.

As to why Android turned it on by default -- we are not clairvoyant!
:-)

Andrew.
Alexander Ivchenko
2013-04-03 10:02:24 UTC
Permalink
Hi,

Thank you for your answers, seems that the question about the reason
with default -Bsymbolic is still open.. we are not clairvoyant, but it
is implemented in GCC so we should understand the reason :)

Having that in mind, we have:
1) All shared libraries for Android are built with -Bsymbolic
2) Dynamic loader throws an error if we are doing COPY relocation
against DT_SYMBOLIC libs.

So any COPY relocation is doomed to failure.. Ard, what was the reason
for introducing the support of this type of relocations in dynamic
loader in the first place?
Post by Ard Biesheuvel
range of the executable proper. However, a library built with
-Bsymbolic resolves all its internal references at build time, so any
reference held by the library itself is not preemptible, resulting in
two live instances of the same symbol.
I totally agree that it is potentially dangerous situation and dynamic
loader must somehow let the user know about that (btw linux dynamic
loader silently allows copy against DT_SYMBOLIC).

thanks,
Alexander
Post by Ard Biesheuvel
Post by Alexander Ivchenko
When compiling a shared library with "-mandroid -shared" the option
-Bsymbolic for linker is turned on by default. What was the reason
behind that default? Isn't using of -Bsymbolic somehow dangerous and
should be avoided..?
Yes indeed, -Bsymbolic is dangerous.
Post by Alexander Ivchenko
(as e.g. is explained in the mail from Richard
Henderson http://gcc.gnu.org/ml/gcc/2001-05/msg01551.html).
Since there is no (AFAIK) option like -Bno-symbolic we cannot use
-fno-pic binary with COPY relocations in it (android dynamic loader
will throw an error when there is COPY relocation against DT_SYMBOLIC
library..)
Sure, that's true. If a library is built with -Bsymbolic then you
must build executables PIC. That's just how it is.
As to why Android turned it on by default -- we are not clairvoyant!
:-)
Andrew.
Andrew Haley
2013-04-03 10:26:24 UTC
Permalink
Post by Alexander Ivchenko
Thank you for your answers, seems that the question about the reason
with default -Bsymbolic is still open.. we are not clairvoyant, but it
is implemented in GCC so we should understand the reason :)
I suppose so, but we always follow the platform ABI, whatever it is.
Doug Kwan was the original author.
Post by Alexander Ivchenko
1) All shared libraries for Android are built with -Bsymbolic
2) Dynamic loader throws an error if we are doing COPY relocation
against DT_SYMBOLIC libs.
So any COPY relocation is doomed to failure.. Ard, what was the reason
for introducing the support of this type of relocations in dynamic
loader in the first place?
Well, I could opine that the true breakage is copy relocs, not -Bsymbolic.
Copy relocs are an ingenious solution to a problem, but they're a kludge.

-Bsymbolic allows you to do something that's not strictly compatible with
Standard C/C++, and it's somewhat risky. However, it's not really a
terrible idea for shared libraries directly to reference their own data,
and for executables to reference the data in the shared library. The
linker doesn't only link C programs, and not all languages have the one
definition rule.

One could also argue that -Bsymbolic and PIC can be safer, because it
doesn't bind the size of a data symbol at compile time.

Andrew.
Ard Biesheuvel
2013-04-04 07:08:16 UTC
Permalink
Post by Andrew Haley
Post by Alexander Ivchenko
Thank you for your answers, seems that the question about the reason
with default -Bsymbolic is still open.. we are not clairvoyant, but it
is implemented in GCC so we should understand the reason :)
Bionic's loader does not support lazy binding nor GNU hash, and
Android's zygote maps about every .so on the system when it boots, so
enabling Bsymbolic saves significant time (the internal relocations
against named symbols are all converted into relative relocations
which only carry a numeric offset, and processing them does not
involve looking up the symbol).
Post by Andrew Haley
Post by Alexander Ivchenko
1) All shared libraries for Android are built with -Bsymbolic
2) Dynamic loader throws an error if we are doing COPY relocation
against DT_SYMBOLIC libs.
So any COPY relocation is doomed to failure.. Ard, what was the reason
for introducing the support of this type of relocations in dynamic
loader in the first place?
The original implementation allowed them, but was broken. Disallowing
them would break BC, so fixing them was considered the best option.
(I think the initial support predates the default Bsymbolic setting.)
Post by Andrew Haley
Well, I could opine that the true breakage is copy relocs, not -Bsymbolic.
Copy relocs are an ingenious solution to a problem, but they're a kludge.
Agreed. Especially on Android, where all static libs are built with
PIC and the default is PIE for executables, copy relocations really
have no place anymore.
(Note that there is a '-z nocopyrelocs' switch on ld which tries to
avoid them, or at least errors out at build time if it fails to)
Post by Andrew Haley
-Bsymbolic allows you to do something that's not strictly compatible with
Standard C/C++, and it's somewhat risky. However, it's not really a
terrible idea for shared libraries directly to reference their own data,
and for executables to reference the data in the shared library. The
linker doesn't only link C programs, and not all languages have the one
definition rule.
Note that this preemption not only applies to copy relocations.
Without -Bsymbolic, a shared library will prefer to use a global
defined in your executable over one it defines itself it they happen
to have the same name. This can easily lead to unexpected results.
--
Ard.
Post by Andrew Haley
One could also argue that -Bsymbolic and PIC can be safer, because it
doesn't bind the size of a data symbol at compile time.
Andrew.
Alexander Ivchenko
2013-04-04 09:45:48 UTC
Permalink
Thank you very much for clarification.
Post by Ard Biesheuvel
Post by Alexander Ivchenko
1) All shared libraries for Android are built with -Bsymbolic
2) Dynamic loader throws an error if we are doing COPY relocation
against DT_SYMBOLIC libs.
So any COPY relocation is doomed to failure.. Ard, what was the reason
for introducing the support of this type of relocations in dynamic
loader in the first place?
The original implementation allowed them, but was broken. Disallowing
them would break BC, so fixing them was considered the best option.
(I think the initial support predates the default Bsymbolic setting.)
Oh, I see now. Since x86 port started when Bsymbolic was the default I
don't see any point of implementing R_386_COPY relocation in dynamic
loader for it. (same can be applied for R_MIPS_COPY)

best regards,
Alexander

Loading...