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