bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

problem with dynamic symbols forced to local on Itanium linker


From: Lowney, Geoff
Subject: problem with dynamic symbols forced to local on Itanium linker
Date: Mon, 4 Mar 2002 20:19:04 -0800

                                                3/4/02

I am running on an Itanium Linux system, using GNU ld version 020224
20020224, which I built locally.  I am writing a binary optimizer
for Itanium, and I have a problem with the linker.

I am preserving the relocations in the final output (-q or
--emit-relocs).  For dynamic symbols that are forced local, the linker
places a bad index into the relocation.  (It leaves a -2 there.)  The
linker also generates assertion failures when generating the image.

   xxx/ld/ld-new: BFD 020224 20020224 assertion fail elflink.h:4561
   xxx/ld/ld-new: BFD 020224 20020224 assertion fail elflink.h:456


Here is a scenario that generates the problem.  I call the linker
with the follow shell script:

     #!/bin/csh

     ~/myproj/gnu/ld/binutils-020224/ld/ld-new \
      -q \
      /proj/vssad/users/lowney/gnu/libc/ecc_static_build.1/csu/crt1.o \
      /proj/vssad/users/lowney/gnu/libc/ecc_static_build.1/csu/crti.o \
 
/proj/vssad/users/lowney/electron/libdev/libcprts/__distrib/ia64-RH7.1/lib/c
rtxi.o \
      -dynamic-linker \
      /lib/ld-linux-ia64.so.2 \
      -o \
      a.out \
      -relax \
      hello.o \
      -o \
      hello \
      -Qy \
      -u \
      ___pseudo_link \
      -L/opt/intel/compiler50/ia64/lib \
      -L/usr/lib \
      -lm \
 
/proj/vssad/users/lowney/electron/libdev/libcprts/__distrib/ia64-RH7.1/lib/l
ibcprts.a \
 
/proj/vssad/users/lowney/electron/libdev/libcprts/__distrib/ia64-RH7.1/lib/l
ibcxa.a \
 
/proj/vssad/users/lowney/electron/libdev/libcprts/__distrib/ia64-RH7.1/lib/l
ibcprts.a \
 
/proj/vssad/users/lowney/electron/libdev/libcprts/__distrib/ia64-RH7.1/lib/l
ibunwind.a \
      -lc \
 
/proj/vssad/users/lowney/electron/libdev/libcprts/__distrib/ia64-RH7.1/lib/c
rtxn.o \
      /proj/vssad/users/lowney/gnu/libc/ecc_static_build.1/csu/crtn.o


The problem symbol is __dso_handle.  Here are the references to the
symbol in the files that are linked, using nm.

    crt1.o
    crti.o
    crtxi.o
    0000000000000000 D __dso_handle
    libcprts.a
                 U __dso_handle
                 U __dso_handle
                 U __dso_handle
                 U __dso_handle
                 U __dso_handle
                 U __dso_handle
    libcxa.a
                 U __dso_handle
    libunwind.a
    libc.so.6.1
                 w __dso_handle
    crtxn.o
    0000000000000008 C __dso_handle
    crtn.o
    /lib/ld-linux-ia64.so.2


Here is my interpretation of what happens:

1. crtxi.o defines __dso_handle as a global symbol, and, in
   elf_link_add_object_symbols, it is entered into the
   elf_link_hash_table as ELF_LINK_HASH_DEF_REGULAR.

2. libc.so.6.1 defines __dso_handle as a weak symbol, and sets
   ELF_LINK_HASH_REF_REGULAR, ELF_LINK_HASH_REF_DYNAMIC, and then
   forces it to ELF_LINK_FORCED_LOCAL

3. crtxn.o defines __dso_handle as a common symbol, and adds
   ELF_LINK_HASH_REF_REGULAR_NONWEAK.

   After all the calls to elf_link_add_object_symbols, __dso_handle has
   the following flags:

      ELF_LINK_HASH_REF_REGULAR
      ELF_LINK_HASH_DEF_REGULAR
      ELF_LINK_HASH_REF_DYNAMIC
      ELF_LINK_HASH_REF_REGULAR_NONWEAK
      ELF_LINK_FORCED_LOCAL


4. In elf_link_input_bfd, we set the rel_hash entry 'indx' field to
   -2, to indicate that the symbol is used by a reloc.

5. In elf_bfd_final_link, we traverse the hash table
   (elf_link_hash_traverse) to output the global symbols (calling
   elf_link_output_extsym), but this routine explicitly skips over
   ELF_LINK_FORCED_LOCAL symbols.

       /* Decide whether to output this symbol in this pass.  */
         if (eoinfo->localsyms)
         {
           if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
             return true;
         }
         else
         {
            if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
              return true;
         }

6. And then in elf_link_adjust_relocs, we iterate over all the rel_hash
   entries, and assert on the indx field being set to -2.

         for (i = 0; i < count; i++, rel_hash++)
         {
           if (*rel_hash == NULL)
                continue;

           BFD_ASSERT ((*rel_hash)->indx >= 0);
           ...

7. And we output a file with bad symbol index for the two relocations
   which refer to __dso_handle.


    Relocation section '.rela.text' at offset 0x34318 contains 730 entries:
        Offset             Info            Type               Symbol's Value
Symbol's Name           Addend
    4000000000000832  0000000e0000002b R_IA64_GPREL64I
4000000000000820  .text                     + 20
    ...
    400000000002acf2  0000036000000049 R_IA64_PCREL21B
40000000000179e0  _Unwind_Resume            + 0
    400000000002ada0  fffffffe00000032 R_IA64_LTOFF22        bad symbol
index: fffffffe
    400000000002adf2  000003ee00000049 R_IA64_PCREL21B
0000000000000000  __cxa_finalize@@GLIBC_2.2 + 0
    ...

    Relocation section '.rela.data' at offset 0x3bb90 contains 249 entries:
        Offset             Info            Type               Symbol's Value
Symbol's Name           Addend
    600000000000edf0  fffffffe00000027 R_IA64_DIR64LSB       bad symbol
index: fffffffe
    600000000000ee00  0000032f00000047 R_IA64_FPTR64LSB
4000000000001ac0  _ZN25__Nexception_cpp_986 + 0
   ...


My fix:

I fixed this problem by removing the check for ELF_LINK_FORCED_LOCAL
for global symbols in elf_bfd_final_link.  This removes the assertion
failures in this simple link, and does not output bad symbol indices
in the relocations.

       /* Decide whether to output this symbol in this pass.  */
         if (eoinfo->localsyms)
         {
           if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
             return true;
         }
         else
         {
    #if 0
            if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
              return true;
    #endif
         }

Is this correct?  Why is the check there?

Is there more information I could provide that would clarify what the
linker should be doing in this case?







reply via email to

[Prev in Thread] Current Thread [Next in Thread]