* DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
@ 2004-05-28 15:24 David Poole
2004-05-28 15:33 ` Daniel Jacobowitz
0 siblings, 1 reply; 9+ messages in thread
From: David Poole @ 2004-05-28 15:24 UTC (permalink / raw)
To: binutils
(I'm far from an expert, ARM, ELF, or otherwise, so if I'm using some
wrong terms, bear with me.)
I'm working with ARM Linux and uClibc. The uClibc shared library loader
segfaults. I've tracked the problem down to the loader attempting to
modify a R_ARM_PC24 call in uClibc/ldso/ldso/arm/resolve.S. The
location needing the modification is in a .rel.text section and the
page is read-only. The loader attempts to modify a branch instruction
to include the correct offset and the CPU rightly faults.
The linker code needing relocation is:
_dl_linux_resolve:
stmdb sp!, {r0, r1, r2, r3, sl, fp}
sub r1, ip, lr
sub r1, r1, #4
add r1, r1, r1
ldr r0, [lr, #-4]
mov r3,r0
bl _dl_linux_resolver
mov ip, r0
ldmia sp!, {r0, r1, r2, r3, sl, fp, lr}
mov pc,ip
.size _dl_linux_resolve, .-_dl_linux_resolve
The "bl _dl_linux_resolver" is causing the problem.
The loader will mprotect() the text pages to read/write if the .dynamic
section contains a DT_TEXTREL. I've hacked the loader to always
mprotect read/write the pages and the loader works. Independently of
the first hack, I've hacked the linker to always add a DT_TEXTREL and
the loader works.
The current problem I'm trying to solve is to understand why the
DT_TEXTREL isn't appearing in the executable and whether it should be
there. I'm poking around in bfd/elf32-arm.h -
elf32_arm_size_dynamic_sections().
Is there a better way to write this code that won't require fixup
later? Is DT_TEXTREL supposed to be in .dynamic in this case? In a
nutshel, is this a glitch with the way the loader is implemented or is
this a glitch with the linker?
Thanks.
--
David Poole <dpoole *at* mobl.com>
Mobility Electronics, Idaho http://www.mobl.com
960 Broadway Avenue, Suite 300
Boise, ID 83706
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-05-28 15:24 DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux David Poole
@ 2004-05-28 15:33 ` Daniel Jacobowitz
2004-05-28 15:54 ` David Poole
2004-05-29 6:21 ` Alan Modra
0 siblings, 2 replies; 9+ messages in thread
From: Daniel Jacobowitz @ 2004-05-28 15:33 UTC (permalink / raw)
To: David Poole; +Cc: binutils
On Fri, May 28, 2004 at 08:52:58AM -0600, David Poole wrote:
> (I'm far from an expert, ARM, ELF, or otherwise, so if I'm using some
> wrong terms, bear with me.)
>
> I'm working with ARM Linux and uClibc. The uClibc shared library loader
> segfaults. I've tracked the problem down to the loader attempting to
> modify a R_ARM_PC24 call in uClibc/ldso/ldso/arm/resolve.S. The
> location needing the modification is in a .rel.text section and the
> page is read-only. The loader attempts to modify a branch instruction
> to include the correct offset and the CPU rightly faults.
>
> The linker code needing relocation is:
>
> _dl_linux_resolve:
> stmdb sp!, {r0, r1, r2, r3, sl, fp}
> sub r1, ip, lr
> sub r1, r1, #4
> add r1, r1, r1
> ldr r0, [lr, #-4]
> mov r3,r0
>
> bl _dl_linux_resolver
>
> mov ip, r0
> ldmia sp!, {r0, r1, r2, r3, sl, fp, lr}
> mov pc,ip
> .size _dl_linux_resolve, .-_dl_linux_resolve
>
> The "bl _dl_linux_resolver" is causing the problem.
> The current problem I'm trying to solve is to understand why the
> DT_TEXTREL isn't appearing in the executable and whether it should be
> there. I'm poking around in bfd/elf32-arm.h -
> elf32_arm_size_dynamic_sections().
I don't know why DT_TEXTREL isn't there for this case. It should be.
But this case shouldn't be happening at all - is the linker built with
-shared? If so binutils 2.15 has all the magic to create a PLT entry
automatically.
Please create a complete linkable testcase that shows this.
If you write bl _dl_linux_resolver(PLT), normally you'd get a PLT
entry. But in binutils 2.15 I made that unnecessary.
--
Daniel Jacobowitz
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-05-28 15:33 ` Daniel Jacobowitz
@ 2004-05-28 15:54 ` David Poole
2004-05-28 22:58 ` David Poole
2004-05-29 6:21 ` Alan Modra
1 sibling, 1 reply; 9+ messages in thread
From: David Poole @ 2004-05-28 15:54 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: binutils
On May 28, 2004, at 8:56 AM, Daniel Jacobowitz wrote:
> I don't know why DT_TEXTREL isn't there for this case. It should be.
> But this case shouldn't be happening at all - is the linker built with
> -shared?
Here's the link command and it is being linked with -shared.
/home/davep/src/toolchain/gcc-3.3.x/toolchain_arm_nofpu/bin/arm-linux-
uclibc-ld -EL -shared --warn-common --export-dynamic --sort-common -z
combreloc --discard-locals --discard-all --no-undefined -s -e _dl_boot
-soname=ld-uClibc.so.0 \
-o ld-uClibc-0.9.26.so arm/resolve.o ldso.o dl-startup.o
/home/davep/src/toolchain/gcc-3.3.x/toolchain_arm_nofpu/usr/bin/../lib/
gcc-lib/arm-linux-uclibc/3.3.3/libgcc.a;
> Please create a complete linkable testcase that shows this.
I'll get this today.
> If you write bl _dl_linux_resolver(PLT), normally you'd get a PLT
> entry. But in binutils 2.15 I made that unnecessary.
uClibc "officially" uses binutils 2.14+patches which is where I
originally found the problem. I upgraded to 2.15 to see if the problem
"went away" but it's the same.
--
David Poole <dpoole !at! mobl.com>
Mobility Electronics, Idaho http://www.mobl.com
960 Broadway Avenue, Suite 300
Boise, ID 83706
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-05-28 15:54 ` David Poole
@ 2004-05-28 22:58 ` David Poole
0 siblings, 0 replies; 9+ messages in thread
From: David Poole @ 2004-05-28 22:58 UTC (permalink / raw)
To: binutils; +Cc: Daniel Jacobowitz
[-- Attachment #1: Type: text/plain, Size: 126 bytes --]
>> Please create a complete linkable testcase that shows this.
This is as simple as I can make it and still think it works.
[-- Attachment #2: mk --]
[-- Type: application/octet-stream, Size: 933 bytes --]
#!/bin/sh
set -x
CC=arm-linux-uclibc-gcc
STRIP=arm-linux-uclibc-strip
LD=arm-linux-uclibc-ld
#LD=/home/davep/src/binutils-2.15/build/ld/ld-new
$CC -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fstrict-aliasing -Os -mlittle-endian -mtune=arm9tdmi -march=armv4 -msoft-float -fPIC -DUCLIBC_RUNTIME_PREFIX=\"/\" -fno-builtin -nostdinc -c resolve.S -o resolve.o
$STRIP -x -R .note -R .comment resolve.o
$CC -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fstrict-aliasing -Os -mlittle-endian -mtune=arm9tdmi -march=armv4 -msoft-float -fPIC -DUCLIBC_RUNTIME_PREFIX=\"/\" -fno-builtin -nostdinc -c test_dl-startup.c -o test_dl-startup.o
$STRIP -x -R .note -R .comment test_dl-startup.o
$LD -EL -shared --warn-common --export-dynamic --sort-common -z combreloc --discard-locals --discard-all --no-undefined -s -e _dl_boot -soname=uclibctest.so -o uclibctest.so resolve.o test_dl-startup.o
[-- Attachment #3: resolve.S --]
[-- Type: application/octet-stream, Size: 1420 bytes --]
/*
* This function is _not_ called directly. It is jumped to (so no return
* address is on the stack) when attempting to use a symbol that has not yet
* been resolved. The first time a jump symbol (such as a function call inside
* a shared library) is used (before it gets resolved) it will jump here to
* _dl_linux_resolve. When we get called the stack looks like this:
* reloc_entry
* tpnt
*
* This function saves all the registers, puts a copy of reloc_entry and tpnt
* on the stack (as function arguments) then make the function call
* _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out
* where the jump symbol is _really_ supposed to have jumped to and returns
* that to us. Once we have that, we overwrite tpnt with this fixed up
* address. We then clean up after ourselves, put all the registers back how we
* found them, then we jump to the fixed up address, which is where the jump
* symbol that got us here really wanted to jump to in the first place.
* -Erik Andersen
*/
#define sl r10
#define fp r11
#define ip r12
.text
.globl _dl_linux_resolve
.type _dl_linux_resolve,%function
.align 4;
_dl_linux_resolve:
stmdb sp!, {r0, r1, r2, r3, sl, fp}
sub r1, ip, lr
sub r1, r1, #4
add r1, r1, r1
ldr r0, [lr, #-4]
mov r3,r0
bl _dl_linux_resolver
mov ip, r0
ldmia sp!, {r0, r1, r2, r3, sl, fp, lr}
mov pc,ip
.size _dl_linux_resolve, .-_dl_linux_resolve
[-- Attachment #4: test_dl-startup.c --]
[-- Type: text/plain, Size: 81 bytes --]
unsigned long _dl_linux_resolver(void *tpnt, int reloc_entry)
{
return 0;
}
[-- Attachment #5: Type: text/plain, Size: 140 bytes --]
--
David Poole <dpoole !at! mobl.com>
Mobility Electronics, Idaho http://www.mobl.com
960 Broadway Avenue, Suite 300
Boise, ID 83706
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-05-28 15:33 ` Daniel Jacobowitz
2004-05-28 15:54 ` David Poole
@ 2004-05-29 6:21 ` Alan Modra
2004-06-01 16:59 ` David Poole
1 sibling, 1 reply; 9+ messages in thread
From: Alan Modra @ 2004-05-29 6:21 UTC (permalink / raw)
To: binutils
On Fri, May 28, 2004 at 10:56:09AM -0400, Daniel Jacobowitz wrote:
> I don't know why DT_TEXTREL isn't there for this case. It should be.
Perhaps because elf32-arm.h doesn't have something like
readonly_dynrelocs as implemented in other backends.
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-05-29 6:21 ` Alan Modra
@ 2004-06-01 16:59 ` David Poole
2004-10-29 20:13 ` Daniel Jacobowitz
0 siblings, 1 reply; 9+ messages in thread
From: David Poole @ 2004-06-01 16:59 UTC (permalink / raw)
To: binutils
[-- Attachment #1: Type: text/plain, Size: 441 bytes --]
On May 29, 2004, at 12:06 AM, Alan Modra wrote:
> On Fri, May 28, 2004 at 10:56:09AM -0400, Daniel Jacobowitz wrote:
>> I don't know why DT_TEXTREL isn't there for this case. It should be.
>
> Perhaps because elf32-arm.h doesn't have something like
> readonly_dynrelocs as implemented in other backends.
Looking at elf32-i386.c and elf32-s390.c, I copied the
readonly_dynrelocs() and the call in
elf_(i386|s390)_size_dynamic_sections.
[-- Attachment #2: binutils-2.15-elf32-arm-textrel.patch --]
[-- Type: application/octet-stream, Size: 2009 bytes --]
diff -uNr binutils-2.15.orig/ binutils-2.15
diff -uNr binutils-2.15.orig/bfd/elf32-arm.h binutils-2.15/bfd/elf32-arm.h
--- binutils-2.15.orig/bfd/elf32-arm.h 2004-05-17 13:35:58.000000000 -0600
+++ binutils-2.15/bfd/elf32-arm.h 2004-06-01 10:44:52.000000000 -0600
@@ -87,6 +87,8 @@
#endif
static bfd_boolean allocate_dynrelocs
PARAMS ((struct elf_link_hash_entry *h, PTR inf));
+static bfd_boolean elf32_arm_readonly_dynrelocs
+ PARAMS ((struct elf_link_hash_entry *, PTR));
static bfd_boolean create_got_section
PARAMS ((bfd * dynobj, struct bfd_link_info * info));
static bfd_boolean elf32_arm_create_dynamic_sections
@@ -3457,6 +3459,37 @@
return TRUE;
}
+/* Find any dynamic relocs that apply to read-only sections. */
+
+static bfd_boolean
+elf32_arm_readonly_dynrelocs (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct elf32_arm_link_hash_entry *eh;
+ struct elf32_arm_relocs_copied *p;
+
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ eh = (struct elf32_arm_link_hash_entry *) h;
+ for (p = eh->relocs_copied; p != NULL; p = p->next)
+ {
+ asection *s = p->section;
+
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ {
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
+
+ info->flags |= DF_TEXTREL;
+
+ /* Not an error, just cut short the traversal. */
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
/* Set the sizes of the dynamic sections. */
static bfd_boolean
@@ -3666,6 +3699,12 @@
return FALSE;
}
+ /* If any dynamic relocs apply to a read-only section,
+ then we need a DT_TEXTREL entry. */
+ if ((info->flags & DF_TEXTREL) == 0)
+ elf_link_hash_traverse (&htab->root, elf32_arm_readonly_dynrelocs,
+ (PTR) info);
+
if ((info->flags & DF_TEXTREL) != 0)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
[-- Attachment #3: Type: text/plain, Size: 1627 bytes --]
Solves my DT_TEXTREL problem but needs more testing.
As a related question, in the original elf32-arm.h, the check for
DF_TEXTREL was done outside the if(relocs):
if (relocs)
{
if ( !add_dynamic_entry (DT_REL, 0)
|| !add_dynamic_entry (DT_RELSZ, 0)
|| !add_dynamic_entry (DT_RELENT, sizeof
(Elf32_External_Rel)))
return FALSE;
}
if ((info->flags & DF_TEXTREL) != 0)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
return FALSE;
info->flags |= DF_TEXTREL;
}
but in elf32-i386.c and elf32-s390.c, the DF_TEXTREL handling is done
inside the if(relocs):
if (relocs)
{
if (!add_dynamic_entry (DT_REL, 0)
|| !add_dynamic_entry (DT_RELSZ, 0)
|| !add_dynamic_entry (DT_RELENT, sizeof
(Elf32_External_Rel)))
return FALSE;
/* If any dynamic relocs apply to a read-only section,
then we need a DT_TEXTREL entry. */
if ((info->flags & DF_TEXTREL) == 0)
elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
(PTR) info);
if ((info->flags & DF_TEXTREL) != 0)
{
if (!add_dynamic_entry (DT_TEXTREL, 0))
return FALSE;
}
}
Is this an issue in elf32-arm.h or a simply small optimization that
causes no trouble otherwise?
--
David Poole <dpoole _at_ mobl.com>
Mobility Electronics, Idaho http://www.mobl.com
960 Broadway Avenue, Suite 300
Boise, ID 83706
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-06-01 16:59 ` David Poole
@ 2004-10-29 20:13 ` Daniel Jacobowitz
2004-10-30 13:17 ` Richard Earnshaw
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2004-10-29 20:13 UTC (permalink / raw)
To: David Poole; +Cc: binutils, nickc, Richard.Earnshaw
On Tue, Jun 01, 2004 at 10:59:08AM -0600, David Poole wrote:
> On May 29, 2004, at 12:06 AM, Alan Modra wrote:
>
> >On Fri, May 28, 2004 at 10:56:09AM -0400, Daniel Jacobowitz wrote:
> >>I don't know why DT_TEXTREL isn't there for this case. It should be.
> >
> >Perhaps because elf32-arm.h doesn't have something like
> >readonly_dynrelocs as implemented in other backends.
>
> Looking at elf32-i386.c and elf32-s390.c, I copied the
> readonly_dynrelocs() and the call in
> elf_(i386|s390)_size_dynamic_sections.
>
The patch from the message I'm quoting looks right to me:
http://sources.redhat.com/ml/binutils/2004-06/msg00010.html
However, to apply it, two things need to happen:
- An ARM maintainer needs to review it.
- Someone needs to decide whether it requires a copyright assignment
(my instinct is no, but I don't make these decisions).
BTW, you said you still needed the patch with 2.15. I didn't try 2.15,
but you definitely don't need it for HEAD; you'll get a PLT entry for
the branch. However, if I change the test to use .word instead of bl,
then it's obvious that your patch is needed.
--
Daniel Jacobowitz
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-10-29 20:13 ` Daniel Jacobowitz
@ 2004-10-30 13:17 ` Richard Earnshaw
2004-11-01 15:14 ` Nick Clifton
0 siblings, 1 reply; 9+ messages in thread
From: Richard Earnshaw @ 2004-10-30 13:17 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: David Poole, binutils, nickc
On Fri, 2004-10-29 at 21:13, Daniel Jacobowitz wrote:
> On Tue, Jun 01, 2004 at 10:59:08AM -0600, David Poole wrote:
> > On May 29, 2004, at 12:06 AM, Alan Modra wrote:
> >
> > >On Fri, May 28, 2004 at 10:56:09AM -0400, Daniel Jacobowitz wrote:
> > >>I don't know why DT_TEXTREL isn't there for this case. It should be.
> > >
> > >Perhaps because elf32-arm.h doesn't have something like
> > >readonly_dynrelocs as implemented in other backends.
> >
> > Looking at elf32-i386.c and elf32-s390.c, I copied the
> > readonly_dynrelocs() and the call in
> > elf_(i386|s390)_size_dynamic_sections.
> >
>
> The patch from the message I'm quoting looks right to me:
> http://sources.redhat.com/ml/binutils/2004-06/msg00010.html
>
> However, to apply it, two things need to happen:
> - An ARM maintainer needs to review it.
I'm happy with this, especially if you are.
> - Someone needs to decide whether it requires a copyright assignment
> (my instinct is no, but I don't make these decisions).
>
I agree, but let's give Nick a couple of days in case he wants to raise
an objection.
R.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux
2004-10-30 13:17 ` Richard Earnshaw
@ 2004-11-01 15:14 ` Nick Clifton
0 siblings, 0 replies; 9+ messages in thread
From: Nick Clifton @ 2004-11-01 15:14 UTC (permalink / raw)
To: Richard Earnshaw, Daniel Jacobowitz, David Poole; +Cc: binutils
Hi Richard,Hi Daniel,
>> - Someone needs to decide whether it requires a copyright assignment
>> (my instinct is no, but I don't make these decisions).
> I agree, but let's give Nick a couple of days in case he wants to raise
> an objection.
He doesn't. :-) I believe that this patch is short enough and simple
enough to be covered under the "obvious" patch rule, and so a copyright
assignment is not needed.
So please go ahead one of you and apply this patch.
Cheers
Nick
PS. David: If you plan to submit any future patches it would really help
if you did obtain an FSF copyright assignment. I can tell you how if
you are interested.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2004-11-01 15:14 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-05-28 15:24 DT_TEXTREL/.dynamic issue with the binutils 2.15 linker on ARM and Linux David Poole
2004-05-28 15:33 ` Daniel Jacobowitz
2004-05-28 15:54 ` David Poole
2004-05-28 22:58 ` David Poole
2004-05-29 6:21 ` Alan Modra
2004-06-01 16:59 ` David Poole
2004-10-29 20:13 ` Daniel Jacobowitz
2004-10-30 13:17 ` Richard Earnshaw
2004-11-01 15:14 ` Nick Clifton
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).