[PATCH 2/2] aarch64: Add workaround for GDB bug handling string literals

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Tue Jun 30 13:48:32 GMT 2026



On 30/06/26 06:47, Yury Khrustalev wrote:
> * Florian
> 
> On Mon, Jun 29, 2026 at 11:07:13PM +0200, Florian Weimer wrote:
>> When GDB evaluates an expression in the inferior, it first
>> creates a copy of the string using malloc.  For this malloc
>> call, GDB was not tracking properly if the malloc symbol is
>> actually an IFUNC resolver.  This means that the IFUNC
>> resolver gets called like the real malloc function.
>>
>> This change adds a kludge to detect this, which prevents GDB
>> from overwriting the __libc_malloc code with the user-supplied
>> string literal.
>>
>> ...
>>
>> diff --git a/sysdeps/aarch64/multiarch/malloc-ifuncs.c b/sysdeps/aarch64/multiarch/malloc-ifuncs.c
>> index 648fb617de..3552168ecd 100644
>>
>> ...
>>
>> +/* Return true if the resolver function has been called through GDB.
>> +   This used below to determine if GDB incorrectly calls the malloc
>> +   IFUNC resolver instead of the resolver result.  The trampoline
>> +   address is either on the stack, or the kernel-provided entry point,
>> +   depending on architecture.
>> +
>> +   A fixed GDB will get the malloc address from the GOT.  Calling
>> +   malloc before relocation processing is complete should use the
>> +   ld.so malloc, which does not involve an IFUNC.  */
>> +static inline bool
>> +called_from_gdb (uintptr_t return_address, uintptr_t stack_frame)
>> +{
>> +#ifdef SHARED
>> +  /* Assume that the stack grows downwards.  */
>> +  if (stack_frame <= return_address && return_address <= stack_frame + 128)
>> +    return true;
>> +
>> +  /* GDB uses the kernel-provided entry point on some architectures
>> +     for the trampoline.  */
>> +  if (return_address == GLRO(dl_entry))
>> +    return true;
>> +#endif
>> +  return false;
>> +}
> 
> Although this does fix the regressions in GDB testsuite, I think this is
> a wrong approach and we should not do this.
> 

I don't like it either, but I don't see a better alternative to keep some
compatibility with old gdb.

But I also think this approach is fragile: it require some assumptions on how
gdb implements this and adds some magic number.  I think a better alternative
is invert the assumption: the only exactly legitimate caller of an IFUNC
resolver is the the dynamic loader's relocation machinery 
(elf_ifunc_invoke / _dl_fixup):

static inline bool
called_from_gdb (uintptr_t return_address)
{
#ifdef SHARED
  /* The only legitimate caller of an IFUNC resolver is the dynamic
     loader's relocation code, whose return address lies within ld.so's
     own load segments.  Anything else — notably GDB invoking the
     resolver as if it were malloc — falls outside that range.  */
  return !(_dl_rtld_map.l_map_start <= return_address
           && return_address < _dl_rtld_map.l_map_end);
#else
  return false;
#endif
}

Since it is only enable for SHARED now, and with this is no need to keep
GLRO(dl_entry), nor adding extra outside machinery on the code.  It should 
work on all supported scenarios as well:

Resolution mode					Function that runs the resolver
Eager IRELATIVE (defining object's own GOT)	elf_irel
Eager JUMP_SLOT/reloc to an ifunc		elf_machine_rela
Lazy PLT, first call				_dl_fixup — dl-runtime.c
Lazy PLT + audit/profile			_dl_profile_fixup

All cases are done by ld.so.  And I think this kludge should be generic,
afaik this gdb issue is neither aarch64 or malloc specific, so we might need
to extend this for other functions.



More information about the Libc-alpha mailing list