public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* 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).