public inbox for
 help / color / mirror / Atom feed
From: Luis Machado <>
To: Yichao Yu <>
Subject: Re: Restoring pc to a different value than lr on aarch64
Date: Wed, 11 May 2022 16:10:10 +0100	[thread overview]
Message-ID: <> (raw)
In-Reply-To: <>

On 5/11/22 15:51, Luis Machado wrote:
> On 5/11/22 14:26, Yichao Yu wrote:
>> On Tue, May 10, 2022 at 10:49 AM Luis Machado <> 
>> wrote:
>>> On 5/9/22 15:24, Yichao Yu wrote:
>>>> On Mon, May 9, 2022 at 6:44 AM Luis Machado <> 
>>>> wrote:
>>>>> On 5/6/22 17:30, Yichao Yu wrote:
>>>>>> On Fri, May 6, 2022 at 12:11 PM Yichao Yu <> wrote:
>>>>>>>>> Actually I misspoke for that. It seems that sp is probably fine 
>>>>>>>>> and
>>>>>>>>> the only thing missing causing pc to not work is that
>>>>>>>>> aarch64_dwarf_reg_to_regnum doesn't understand the PC dwarf reg
>>>>>>>>> number. It seems that the only thing needed is to add a
>>>>>>>>> +  if (reg == AARCH64_DWARF_PC)
>>>>>>>>> +    return AARCH64_PC_REGNUM;
>>>>>>>>> to that function.
>>>>>>>> Yes, GDB always assumes the PC from the previous frame is the LR 
>>>>>>>> from
>>>>>>>> the current frame. That is what GCC generates.
>>>>>>>> If a different setup is needed, GDB needs to be taught about it.
>>>>>>> I agree the current code makes sense for what gcc generates. 
>>>>>>> However,
>>>>>>> I think given the document from arm, explicitly setting the PC value
>>>>>>> in the unwind info should also work.
>>>>>>> Would a patch similar to the one above be acceptable to fix this 
>>>>>>> issue?
>>>>>>> A related issue is that gdb also seems to be ignoring the return
>>>>>>> address register in CIE. There is at least one use of it in glibc[2]
>>>>>>> where the return address register is set to x15 instead.
>>>>>>> I've verified that gdb is currently unable to unwind after the 
>>>>>>> call to
>>>>>>> `strlen` from `rawmemchr` even though the return address is still in
>>>>>>> x15.
>>>>>>> I thought this can be fixed by chaiming that PC is RA just like the
>>>>>>> fallback case but that is apparently not working...
>>>>>> Actually this did work but the address is wrong before the value was
>>>>>> written to x15... So it was just due to incorrect unwind info (the
>>>>>> glibc implementation should specify how to find x15 on the entry of
>>>>>> rawmemchr).
>>>>>> Is the current implementation due to some edge cases? (like old
>>>>>> compiler version doesn't put a valid value in the CIE for the return
>>>>>> address register). It seems that many other architecture simply use
>>>>>> _RA so I don't see why this would have broader problems...
>>> This looks like a genuine bug, one that is not hit that often given it
>>> is not very common for frame to change the return address column. This
>>> will need to be fixed eventually. Thanks for spotting that.
>>>>> It is probably historical that this has been handled like this. If 
>>>>> there
>>>>> is a use case for having a PC column containing distinct data, then we
>>>>> could support that.
>>>> I couldn't find any existed code using this, but it seems that this is
>>>> the intent from ARM and I really can't think of any other way to
>>>> restore everything including both pc and lr so I'd like to support
>>>> that at least....
>>>>> It wouldn't be as simple as that change you mentioned though, as other
>>>>> parts of the code assume PC comes from the LR.
>>> I take that back. I investigated this further and I think this should
>>> work, although it is a use case that is not so common.
>>>> There are indeed other unwinders (the prologue unwinder) that assumes
>>>> this, which I think should be fine. Specifying the PC explicitly
>>>> should only apply to the dwarf unwinder. The only other place where I
>>>> can find that relies on this is aarch64_gen_return_address. It doesn't
>>>> seem that this function is used in most of the other logics and if the
>>>> return address column is somehow accessible from here it should also
>>>> not be too hard to fix.
>>> I think it is only the case for the dwarf unwinder, as that is the
>>> unwinder that has access to the CFI information.
>> Sorry what did you mean by "it" here? (being able to handle PC != LR
>> during unwinding?) Do I need to worry about gen_return_address?
> Sorry, I meant that we only need to worry about the dwarf unwinder 
> functions. The other code not relying on CFI information doesn't need to 
> be touched (prologue unwinder, aarch64_gen_return_address etc).
> At this point, we'd like to augment aarch64_dwarf_reg_to_regnum to 
> return a valid number for the dwarf PC register.
>>>> Is there any other cases that I'm missing? I've also tested with my
>>>> simple change and it seems that unwinding from normal functions still
>>>> works as intended.
>>> Yes, I tried it on my end as well and it does work. What I was worried
>>> about is that we need to adjust the LR value in some cases.
>>> For aarch32 we need to remove the LSB, and for aarch64 we need to unmask
>>> the value of LR if it is signed through PAC. This is the reason why we
>>> have a custom dwarf2_prev_register implementation.
>> Is the aarch64-tdep code used for aarch32 tracee as well?
> The aarch64 code is not shared by aarch32 (that would be arm-tdep.c). I 
> just mentioned it because both arm-tdep.c and aarch64-tdep.c use the 
> same mechanism for unwinding PC. That is, they return LR instead.
>>> gcc and clang emit the return address column as r30. If we don't specify
>>> any initialization rule for PC, then the dwarf2 unwinder will go through
>>> the route of fetching LR and adjusting the values.
>>> On the other hand, if PC is available in a CFI column, then the dwarf
>>> unwinder won't call the custom hook and will instead proceed to
>>> calculate PC from the CFI expression at that column, which should give
>>> the result that you want.
>> Right, and I guess that means that the custom unwind rule needs to
>> take the pointer authentication into account?
>> (I've never used any machines with that enabled so I'm not 100% how
>> it's supposed to work....)
> It does need to take that into account. But using a custom function for 
> unwinding PC means we will not have access to

Sorry, this got truncated. With a custom function for unwinding PC, it 
means that we only invoke such function if CFI is not available for a PC 
column. If it is, then we follow the CFI rule but don't do any 
additional processing that would've taken place in the custom function.

Given the case of having a PC column is not so common, this should be OK 
for now.

>>> We can't initialize PC to DWARF2_FRAME_REG_RA though (not yet, anyway),
>>> as that would default to mapping PC to the return address column. For
>>> gcc and clang, this would be x30. That would give GDB no chance of
>>> adjusting the LR values if required (for PAC-signed LR values).
>> Just so that I understand, if LR is signed, then upon return it should
>> still have the signed value. (Or in the case a different register is
>> used for return address, `ret xn` would not change xn value)
>> Only the resulting PC should have the signed part masked off. That's
>> why the unwinding of LR is correct without any post-processing logic
>> as-is but the unwinding of PC needs to be treated specially. >
> That's correct.
>>> It would be nice to have a testcase for this, alongside your patch, to
>>> make sure GDB is always doing the correct unwinding.
>> The part for returning the name of PC is easy. I assume the test would
>> be mainly throwing in a aarch64-xxx.{c,exp} and to check if explicitly
>> specifying the PC in the unwind info result in valid unwinding. I'll
>> try look for some but any examples that I can follow?
> I think gdb/testsuite/gdb.arch/arm-disp-step.{S,exp} is a good example. 
> Basically, some .S file that contains some random instructions and CFI 
> directives that we single-step over and check if GDB is following the 
> values of the registers correctly. The .S file gives us more control 
> over those CFI directives.
>> This should fix the case where PC is explicitly specified but wont fix
>> the case where a return column is specified. Handling that requires a
>> different way to post-processing the PC.
> Correct. That is a separate bug and I'll need to investigate that.
> Thanks!
> Luis

  reply	other threads:[~2022-05-11 15:10 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-06 12:05 Yichao Yu
2022-05-06 12:46 ` Yichao Yu
2022-05-06 13:32   ` Luis Machado
2022-05-06 16:11     ` Yichao Yu
2022-05-06 16:30       ` Yichao Yu
2022-05-09 10:44         ` Luis Machado
2022-05-09 14:24           ` Yichao Yu
2022-05-10 14:48             ` Luis Machado
2022-05-11 13:26               ` Yichao Yu
2022-05-11 14:51                 ` Luis Machado
2022-05-11 15:10                   ` Luis Machado [this message]
2022-05-13 12:34                   ` Yichao Yu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \ \ \ \ \

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).