Does the LD --wrap feature work for library internal references?

Sebastian Huber sebastian.huber@embedded-brains.de
Fri Jan 25 08:37:00 GMT 2019



On 23/01/2019 10:11, Sebastian Huber wrote:
> On 18/01/2019 14:41, Alan Modra wrote:
>> On Fri, Jan 18, 2019 at 10:04:36AM +0100, Sebastian Huber wrote:
>>> On 18/01/2019 01:24, Alan Modra wrote:
>>>> No, -ffunction-sections will make no difference.  Really, --wrap was
>>>> intended for wrapping system functions, which I guess is why the
>>>> feature was implemented only for undefined symbols.  I don't see a
>>>> fundamental reason why --wrap couldn't be made to work with defined
>>>> symbols, provided the compiler and assembler don't optimise references
>>>> to local functions.
>>> In case it is acceptable to extend --wrap to work also for defined 
>>> symbol
>>> references, then I would have a look at this and try to implement 
>>> it. If you
>>> already have an idea which functions needs to be touched for this new
>>> feature, then this would be helpful for me.
>> It might just be a matter of calling bfd_wrapped_link_hash_lookup in
>> more places where we currently call bfd_link_hash_lookup and its
>> derivatives like elf_link_hash_lookup.  Knowing which places to change
>> is the difficult part.  Anything involved with relocation processing
>> for a start.
>>
>
> I think to wrap defined references you have to add things to other 
> places than spots which call bfd_link_hash_lookup() or 
> bfd_wrapped_link_hash_lookup(). I built ld with -O0 -g and used the 
> following test program:
>
> void f(void)
> {
> }
>
> void g(void);
>
> void _start(void)
> {
>     f();
>     g();
> }
>
> I use this GDB script:
>
> b bfd_wrapped_link_hash_lookup  if string[0] != '.' && (string[0] == 
> 'f' || string[7] == 'f' || string[0] == 'g' || string[7] == 'g')
> commands
> c
> end
> b bfd_link_hash_lookup if string[0] != '.' && (string[0] == 'f' || 
> string[7] == 'f' || string[0] == 'g' || string[7] == 'g')
> commands
> c
> end
> r
>
> This yields:
>
> gdb --command=main.gdb --args ld-new -wrap=f -wrap=g main.o -o main.exe
> Breakpoint 2, bfd_link_hash_lookup (table=0x8df4f0, string=0x8f2bd0 
> "f", create=1, copy=0, follow=0) at ../../bfd/linker.c:511
> 511       if (table == NULL || string == NULL)
>
> Breakpoint 2, bfd_link_hash_lookup (table=0x8df4f0, string=0x8f2bd2 
> "_start", create=1, copy=0, follow=0) at ../../bfd/linker.c:511
> 511       if (table == NULL || string == NULL)
>
> Breakpoint 1, bfd_wrapped_link_hash_lookup (abfd=0x8eec40, 
> info=0x8c2de0 <link_info>, string=0x8f2bd9 "g", create=1, copy=0, 
> follow=0) at ../../bfd/linker.c:541
> 541       if (info->wrap_hash != NULL)
>
> Breakpoint 2, bfd_link_hash_lookup (table=0x8df4f0, string=0x8f35c0 
> "__wrap_g", create=1, copy=1, follow=0) at ../../bfd/linker.c:511
> 511       if (table == NULL || string == NULL)
> /home/EB/sebastian_h/archive/binutils-git/build/ld/ld-new: main.o: in 
> function `_start':
> main.c:(.text+0x11): undefined reference to `__wrap_g'
>
> The lookup is performed only once for "f". I think this is when ld 
> finds the definition of f(). For the call in _start() we end up in 
> other areas of ld.
>

Wrapping of undefined symbol references are dealt with during load_symbols()
which is performed early during the link process.

For defined symbols references we have to look at the relocations. 
During the
final link performed by bfd_elf_final_link() which calls 
elf_link_input_bfd()
which calls the architecture-specific elf_x86_64_relocate_section() we 
end up
in (elf-bfd.h):

/* This macro is to avoid lots of duplicated code in the body
    of xxx_relocate_section() in the various elfxx-xxxx.c files.  */
#define RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,    \
                 r_symndx, symtab_hdr, sym_hashes,    \
                 h, sec, relocation,            \
                 unresolved_reloc, warned, ignored)    \
   do                                    \
     {                                    \
       /* It seems this can happen with erroneous or unsupported     \
      input (mixing a.out and elf in an archive, for example.)  */ \
       if (sym_hashes == NULL)                        \
     return FALSE;                            \
                                     \
       h = sym_hashes[r_symndx - symtab_hdr->sh_info]; \
                                     \
       if (info->wrap_hash != NULL                    \
       && (input_section->flags & SEC_DEBUGGING) != 0)        \
     h = ((struct elf_link_hash_entry *)                \
          unwrap_hash_lookup (info, input_bfd, &h->root));     \

Why is there a special case for input_section->flags & SEC_DEBUGGING) != 
0 here?

If I extend this macro in case info->wrap_hash != NULL to do the symbol 
wrapping, then there is an issue with the __real_SYMBOL references which 
are no longer visible here. We only see SYMBOL and __wrap_SYMBOL. The 
SYMBOL could be a defined reference or a former __real_SYMBOL undefined 
reference.

Would it be feasible to the the wrapping at the relocation step and not 
during load_symbols()?

-- 
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.



More information about the Binutils mailing list