problem relocating weak symbol on ARM

jeroen dobbelaere jeroen.dobbelaere@acunia.com
Fri Sep 6 06:27:00 GMT 2002


Hi,

I'm trying to get profiling working on ARM
(also see here : <http://gcc.gnu.org/ml/gcc/2002-09/msg00230.html> )

When I'm using shared libraries (glibc-2.2.5), I'm seeing strange results :

A small test file is compiled as follows :

root:~/tmp2# gcc -v -g -pg -fno-omit-frame-pointer -O3 gprof-test.c
Reading specs from /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/specs
Configured with: ../gcc-3.0.4/configure --prefix=/usr --with-cpu=xscale
Thread model: posix
gcc version 3.0.4
  /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/cc1 -lang-c -v -D__GNUC__=3 -D__GNUC_MINOR__=0 -D__GNUC_PATCHLEVEL__=4 -Dunix -Dlinux -D__ELF__ -D__unix__ -D__linux__ -D__ELF__ -D__unix -D__linux -Asystem=unix -Asystem=posix -Acpu=arm 
-Amachine=arm -D__CHAR_UNSIGNED__ -D__OPTIMIZE__ -D__STDC_HOSTED__=1 -D__ARM_ARCH_5TE__ -D__XSCALE__ -D__APCS_32__ -D__ARMEL__ -D__arm__ gprof-test.c -quiet -dumpbase gprof-test.c -g -O3 -version -p -fno-omit-frame-pointer -o /tmp/cc5oLUJK.s
GNU CPP version 3.0.4 (cpplib) (ARM GNU/Linux with ELF)
GNU C version 3.0.4 (armv5l-unknown-linux-gnu)
	compiled by GNU C version 3.0.4.
ignoring nonexistent directory "/usr/armv5l-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
  /usr/local/include
  /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/include
  /usr/include
End of search list.
  /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/../../../../armv5l-unknown-linux-gnu/bin/as -o /tmp/ccad2aLA.o /tmp/cc5oLUJK.s
  /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/collect2 -dynamic-linker /lib/ld-linux.so.2 -X -m armelf_linux -p /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/../../../gcrt1.o 
/usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/../../../crti.o /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/crtbegin.o -L/usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4 
-L/usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/../../../../armv5l-unknown-linux-gnu/lib -L/usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/../../.. /tmp/ccad2aLA.o -lgcc -lc -lgcc /usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/crtend.o 
/usr/lib/gcc-lib/armv5l-unknown-linux-gnu/3.0.4/../../../crtn.o




Following code is executed at the beginning of the executable :

[from glibc-2.2.5 ]
call_gmon_start(void)
{
   extern void __gmon_start__ (void) __attribute__ ((weak)); /*weak_extern (__gmon_start__);*/
   void (*gmon_start) (void) = __gmon_start__;

   if (gmon_start)
     gmon_start ();
}

In assembly, this looks like (using objdump --disassemble-all) :




Disassembly of section .init:

0000846c <_init>:
     846c:	e52de004 	str	lr, [sp, -#4]!
     8470:	eb000058 	bl	85d8 <call_gmon_start>
     8474:	eb00008e 	bl	86b4 <frame_dummy>
     8478:	eb0000dd 	bl	87f4 <__do_global_ctors_aux>
     847c:	e49df004 	ldr	pc, [sp], #4
[...]

00008594 <__gmon_start__>:
     8594:	e52de004 	str	lr, [sp, -#4]!
     8598:	e59f2028 	ldr	r2, [pc, #40]	; 85c8 <__gmon_start__+0x34>
     859c:	e59f0028 	ldr	r0, [pc, #40]	; 85cc <__gmon_start__+0x38>
     85a0:	e59f1028 	ldr	r1, [pc, #40]	; 85d0 <__gmon_start__+0x3c>
     85a4:	e5923000 	ldr	r3, [r2]
     85a8:	e3530000 	cmp	r3, #0	; 0x0
     85ac:	149df004 	ldrne	pc, [sp], #4
     85b0:	e3a03001 	mov	r3, #1	; 0x1
     85b4:	e5823000 	str	r3, [r2]
     85b8:	ebffffd4 	bl	8510 <_init+0xa4>
     85bc:	e59f0010 	ldr	r0, [pc, #16]	; 85d4 <__gmon_start__+0x40>
     85c0:	e49de004 	ldr	lr, [sp], #4
     85c4:	ea00007e 	b	87c4 <atexit>
     85c8:	000109e8 	andeq	r0, r1, r8, ror #19
     85cc:	00008560 	andeq	r8, r0, r0, ror #10
     85d0:	00008868 	andeq	r8, r0, r8, ror #16
     85d4:	000084d0 	ldreqd	r8, [r0], -r0

000085d8 <call_gmon_start>:
     85d8:	e92d4400 	stmdb	sp!, {sl, lr}
     85dc:	e59fa01c 	ldr	sl, [pc, #28]	; 8600 <call_gmon_start+0x28>
     85e0:	e59f301c 	ldr	r3, [pc, #28]	; 8604 <call_gmon_start+0x2c>
     85e4:	e08fa00a 	add	sl, pc, sl
     85e8:	e79a3003 	ldr	r3, [sl, r3]	(************)
     85ec:	e3530000 	cmp	r3, #0	; 0x0
     85f0:	0a000001 	beq	85fc <call_gmon_start+0x24>
     85f4:	e1a0e00f 	mov	lr, pc
     85f8:	e1a0f003 	mov	pc, r3
     85fc:	e8bd8400 	ldmia	sp!, {sl, pc}
     8600:	000083b4 	streqh	r8, [r0], -r4
     8604:	00000040 	andeq	r0, r0, r0, asr #32


sl = 0x83b4 + 0x85ec = 0x109a0
r3 = 0x40
[sl, r3] = [0x109a0+0x40] =  109e0

At code 85e8 (marked **********), for some reason, r3 is filled with 0x00000000 :

(using objdump -s) :

Contents of section .got:
  109a0 c8080100 00000000 00000000 80840000  ................
  109b0 80840000 80840000 80840000 80840000  ................
  109c0 80840000 80840000 80840000 80840000  ................
  109d0 80840000 80840000 80840000 80840000  ................
  109e0 00000000 00000000                    ........


Where it should have been filled in with the address of __gmon_start__ ...
(which is known in this executable (!))

readelf -a gives :

[...]
Relocation section '.rel.plt' at offset 0x404 contains 13 entries:
  Offset     Info    Type            Sym.Value  Sym. Name
000109ac  00000116 R_ARM_JUMP_SLOT   00008490   mcount
000109b0  00000216 R_ARM_JUMP_SLOT   00000000   __register_frame_info
000109b4  00000316 R_ARM_JUMP_SLOT   000084b0   __cxa_atexit
000109b8  00000416 R_ARM_JUMP_SLOT   00000000   __deregister_frame_inf
000109bc  00000516 R_ARM_JUMP_SLOT   000084d0   _mcleanup
000109c0  00000616 R_ARM_JUMP_SLOT   000084e0   puts
000109c4  00000716 R_ARM_JUMP_SLOT   00000000   __deregister_frame_inf
000109c8  00000816 R_ARM_JUMP_SLOT   00008500   abort
000109cc  00000916 R_ARM_JUMP_SLOT   00008510   __monstartup
000109d0  00000a16 R_ARM_JUMP_SLOT   00000000   __register_frame_info_
000109d4  00000b16 R_ARM_JUMP_SLOT   00008530   __libc_start_main
000109d8  00000c16 R_ARM_JUMP_SLOT   00008540   printf
000109dc  00000d16 R_ARM_JUMP_SLOT   00000000   __cxa_finalize

There are no unwind sections in this file.

Symbol table '.dynsym' contains 16 entries:
    Num:    Value  Size Type    Bind   Vis      Ndx Name
      0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
      1: 00008490    56 FUNC    GLOBAL DEFAULT  UND mcount@GLIBC_2.0 (2)
      2: 00000000    20 FUNC    WEAK   DEFAULT  UND __register_frame_info@GLIBC_2.0 (2)
      3: 000084b0    56 FUNC    GLOBAL DEFAULT  UND __cxa_atexit@GLIBC_2.1.3 (3)
      4: 00000000   340 FUNC    WEAK   DEFAULT  UND __deregister_frame_info_b@GCC_3.0 (4)
      5: 000084d0    76 FUNC    GLOBAL DEFAULT  UND _mcleanup@GLIBC_2.0 (2)
      6: 000084e0   396 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.0 (2)
      7: 00000000    12 FUNC    WEAK   DEFAULT  UND __deregister_frame_info@GLIBC_2.0 (2)
      8: 00008500   484 FUNC    GLOBAL DEFAULT  UND abort@GLIBC_2.0 (2)
      9: 00008510   392 FUNC    GLOBAL DEFAULT  UND __monstartup@GLIBC_2.0 (2)
     10: 00000000   184 FUNC    WEAK   DEFAULT  UND __register_frame_info_bas@GCC_3.0 (4)
     11: 00008530   256 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.0 (2)
     12: 00008540    60 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.0 (2)
     13: 00000000   188 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.1.3 (3)
     14: 00008868     4 OBJECT  GLOBAL DEFAULT   13 _IO_stdin_used
     15: 00008594    68 FUNC    GLOBAL DEFAULT   11 __gmon_start__
[...]

What could be the reason that __gmon_start__ is not being resolved ??
Could it be that an entry for it is missing in the above .rel.plt ??

Greetings,
-- 
Jeroen Dobbelaere
Embedded Software Engineer

ACUNIA Embedded Solutions
http://www.acunia.com/aes




More information about the Binutils mailing list