foss-for-synopsys-dwc-arc-processors/toolchain

ARCv2 relocation failure

Opened this issue · 2 comments

While testing QEMU FPUv2 a GLibC test (test-fpucw-static) that didn't fail a few months ago, started failing with the most recent toolchain.

The issue seems to be because a relocation isn't completed with success.

The invocation line found by running make test t=math/test-fpucw-static inside glibc-build folder is:

$ arc-linux-gnu-gcc -o $GLIBC_BUILD_PATH/math/test-fpucw-static        \
                    -nostdlib                                          \
                    -nostartfiles                                      \
                    -static                                            \
                    $GLIBC_BUILD_PATH/csu/crt1.o                       \
                    $GLIBC_BUILD_PATH/csu/crti.o                       \
                    `arc-linux-gnu-gcc  --print-file-name=crtbeginT.o` \
                    $GLIBC_BUILD_PATH/math/test-fpucw-static.o         \
                    $GLIBC_BUILD_PATH/support/libsupport_nonshared.a   \
                    $GLIBC_BUILD_PATH/math/libm.a                      \
                    -Wl,--start-group                                  \
                      $GLIBC_BUILD_PATH/libc.a                         \
                      -lgcc                                            \
                      -lgcc_eh                                         \
                    -Wl,--end-group                                    \
                    `arc-linux-gnu-gcc --print-file-name=crtend.o`     \
                    $GLIBC_BUILD_PATH/csu/crtn.o

We can see with arc-linux-gnu-objdump -d -r that in libc.a the relocation is supposed to be

126:   0802 0000               bl      0       ;0 <__pthread_initialize_minimal>
                       126: R_ARC_S25W_PCREL_PLT       __pthread_initialize_minimal

Linking seems to fail as the final binary has:

112d2:       0802 0000               bl      0       ;112d0 <__libc_start_main+0x74>

The symbol in question here is:

// sysdeps/generic/ldsodefs.h

# define weak_function __attribute__ ((weak))
void __pthread_initialize_minimal (void) weak_function;
// csu/libc-start.c

void
__pthread_initialize_minimal (void)
{
  _init_routine (__libc_stack_end);  // <-- static void function
}

And the problematic usage:

// csu/libc-start.c

  if (__pthread_initialize_minimal != NULL)
    __pthread_initialize_minimal ();

Attachment:
comp.1.zip
comp.2.zip

$ cat comp.{1,2}.zip > comp.tar.xz

There are a number of R_ARC_GOTPC32 which are resolved to point to the first entry in the .got section. Here are the symbols in cause:

	__call_tls_dtors
	__mq_notify_fork_subprocess
	__nss_database_fork_prepare_parent
	__nss_database_fork_subprocess
	__pthread_initialize_minimal
	stderr
	__timer_fork_subprocess

All the above with the exception of stderr are weak undefined symbols. Needless to say the first location of .got is initialized with the value of stderr namely 00088398 D stderr.

One of the errors is seen bellow:

   112b0:       2730 7f82 0007 6b10     ld      r2,[pcl,0x76b10]        ;87dc0 <.got>
                        112b4: R_ARC_GOTPC32    __pthread_initialize_minimal
   112b8:       7a4b                    tst_s   r2,r2
   112ba:       1100 2002               ld      r2,[r17]
   112be:       2700 7f83 0007 5d48     add     r3,pcl,0x75d48  ;87004 <__stack_chk_guard>
                        112c2: R_ARC_PC32       __stack_chk_guard
   112c6:       4244                    ld_s    r2,[r2,0]
   112c8:       226c 01c2               bmskn   r2,r2,0x7
   112cc:       000a 0021               beq.d   10      ;112d6 <__libc_start_main+0x7a>
   112d0:       a340                    st_s    r2,[r3,0]
   112d2:       0802 0000               bl      0       ;112d0 <__libc_start_main+0x74>
                        112d2: R_ARC_S25W_PCREL_PLT     __pthread_initialize_minimal

The R_ARC_S25W_PCREL_PLT is correctly resolved to zero, as the __pthread_initialize_minimal symbol is undefined weak. However, the R_ARC_GOTPC32 is pointing to the first entry of .got section which is actually the entry for stderr. Thus, instead of returning zero in r2 register, it returns stderr value. Hence, the error.

A reduced test case:

#include <stddef.h>
#include <stdio.h>

# define weak_function __attribute__ ((weak))
void __pthread_initialize_minimal (void) weak_function;

extern void abort (void);

int main (void)
{
  if (stderr == NULL)
    abort ();
  if (__pthread_initialize_minimal != NULL)
    __pthread_initialize_minimal ();

  return 0;
}