This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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




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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]