Re: [PATCH PR gdb/22736] [aarch64] gdb crashes on a conditional breakpoint with cast return type

Alan Hayward
2018-03-05T15:57:32Z

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 2961 bytes --]

> On 2 Mar 2018, at 15:18, Joel Brobecker <brobecker@adacore.com> wrote:
>
>>>> The cast to (int) is causing this - remove the cast and it finds the type.
>>>> I’m assuming that’s causing it to drop the debug info.
>>>
>>> It sounds like a bug to me. If this bug "TYPE_TARGET_TYPE
>>> (func_type) becomes NULL caused by cast" is fixed, the GDB segfault
>>> will go away accordingly.
>>>
>>> To be clear, your patch here is fine to me. My suggestion is that
>>> we'd better dig it deeper.
>>
>> Agreed. I’ll raise a new bug, and have a look into it too whilst I’m
>> in the area.
>
> Having read what Yao said, and looking at the example you gave,
> I'm now thinking that one could very well be the cause of the other;
> it seems like the cast might indeed be returning a value with
> a struct type that's missing the return type. Even a subprogram
> which returns nothing has a TYPE_TARGET_TYPE set to a TYPE_CODE_VOID,
> right?

Been debugging this a little more (and learnt quite a few things about gdb along the way!)
Not sure if this reply is the best place to discuss, or if it should go onto the bug.
But….

On x86, for strcmp the type and it's target types, as received in amd64_push_dummy_call are:
TYPE_CODE_FUNC -> TYPE_CODE_INT -> 0x0
Whereas on aarch64 in aarch64_push_dummy_call we get:
TYPE_CODE_FUNC -> 0x0

It turns out this occurs because strcmp has IFUNC vs FUNC differences:

X86:
$ readelf -s /lib/x86_64-linux-gnu/libc-2.19.so | grep strcmp
2085: 0000000000087380 60 IFUNC GLOBAL DEFAULT 12 strcmp@@GLIBC_2.2.5

Aarch64:
$ readelf -s /lib/aarch64-linux-gnu/libc-2.23.so | grep strcmp
2043: 0000000000076380 164 FUNC GLOBAL DEFAULT 12 strcmp@@GLIBC_2.17

I decided to test this on X86 using a FUNC….

$ readelf -s /lib/x86_64-linux-gnu/libc-2.19.so | grep strlen
769: 0000000000088dd0 436 FUNC GLOBAL DEFAULT 12 strlen@@GLIBC_2.2.5

Changed my test to do:
(gdb) b foo if (int)strlen(name) == 3

...Now the type received by the target code is TYPE_CODE_FUNC -> 0, the same as aarch64.

However, x86 does not segfault. This is because amd64_push_dummy_call doesn’t bother to
check the function parameter.

Looking into the code, when reading a FUNC, readlf.c : elf_symtab_read() hits:

if (sym->flags & BSF_GNU_INDIRECT_FUNCTION)
ms_type = mst_text_gnu_ifunc;
else
ms_type = mst_text;

Setting the type to mst_text, which eventually causes find_minsym_type_and_address() to
set the type to objfile_type (objfile)->nodebug_text_symbol
Whereas an IFUNC gets set to objfile_type (objfile)->nodebug_text_gnu_ifunc_symbol.

So, I think probably either:
* Everything is correct
* mst_text needs handling differently
* FUNCs need a new minimal symbol type (mst_text_gnu_func?)
(I’m not familiar enough with this part of the code to give a definitive answer).

Alan.\x16º&Öéj×!zÊÞ¶êç×Ž{÷Ib²Ö«r\x18\x1dn–­r\x17¬