Skip to content

Fix two incorrect conditions in the ARM packed exception handling#3541

Merged
colin-home merged 1 commit intoMicrosoftDocs:mainfrom
mstorsjo:arm-exception-packed
Dec 15, 2021
Merged

Fix two incorrect conditions in the ARM packed exception handling#3541
colin-home merged 1 commit intoMicrosoftDocs:mainfrom
mstorsjo:arm-exception-packed

Conversation

@mstorsjo
Copy link
Copy Markdown
Contributor

For the prologue, the distinction between mov r11, sp and
add r11, sp, #xx lies only in whether other registers are pushed
before R11 and LR in prologue instruction 2. (The condition
R==1 and PF==0 corresponds to no other registers pushed before
r11.) The L flag doesn't affect it (and the documentation explicit
says that when C is set, then L also must be set, thus C==1
and L==0 is tautological too).

This was correctly described in the textual form, but the conditions
in the table included one erronous case.

For the epilogue, when Ret!=0, the function doesn't return by
popping LR directly into PC, but with an explicit branch instruction
(10a or 10b). In this case, if L==1, the LR register is included
in the list of registers popped in instruction 8. If register
homing is used (H==1), then instruction 9a is used instead of 9b.

This case seemed to have been overlooked both in the textual
description and in the table.

CC @ThomsonTan who might be familiar with this area.

@PRMerger12
Copy link
Copy Markdown
Contributor

@mstorsjo : Thanks for your contribution! The author(s) have been notified to review your proposed change.

@ktoliver
Copy link
Copy Markdown
Contributor

#label:"aq-pr-triaged"

@PRMerger4 PRMerger4 added the aq-pr-triaged Tracking label for the PR review team label Nov 22, 2021
@colin-home
Copy link
Copy Markdown
Contributor

@mstorsjo
Thanks, Martin. The updates look good to me, but since I have only the barest familiarity with ARM exception unwinding , I need to defer to experts on the development team to review. In addition to @ThomsonTan , @pmsjt, @VCZYK, or @RussKeldorph may know, or possibly know who knows.

@ThomsonTan
Copy link
Copy Markdown
Contributor

Thanks, Martin. I defer this to @pmsjt.

@pmsjt
Copy link
Copy Markdown
Contributor

pmsjt commented Nov 25, 2021

Thanks for contributing. I'll look at this as soon as I can. It might take a couple of weeks tho.

I appreciate the patience.

@mstorsjo
Copy link
Copy Markdown
Contributor Author

Thanks for contributing. I'll look at this as soon as I can. It might take a couple of weeks tho.

I appreciate the patience.

Thanks!

I noticed another thing that needs clarifying too (I'll amend the patch in a moment): For prologue instruction 3a,mov r11, sp, the equivalent unwind code is specified as C0-CF/FB. This leaves an ambiguity - if my prologue strictly relies on restoring sp from r11, can I use this form? Empirical experimentation would make it seem like unwinding such packed info doesn't restore sp from r11, and thus, the only equivalent unwind code is FB (i.e. narrow nop). That also makes sense, because if form 3b is chosen, it's clear that sp isn't restored from r11 in any form.

@mstorsjo mstorsjo force-pushed the arm-exception-packed branch from c0a6ba1 to 7fab074 Compare November 25, 2021 12:18
@PRMerger8
Copy link
Copy Markdown
Contributor

@mstorsjo : Thanks for your contribution! The author(s) have been notified to review your proposed change.

@colin-home
Copy link
Copy Markdown
Contributor

Ping @pmsjt for a review before we all go on vacation. :)

|9b|*`H`*==1 and *`L`*==1|32|`ldr pc,[sp],#0x14`|
|8|*`C`*==1 or (*`L`*==1 and (*`H`*==0 or *`Ret`* !=0)) or *`R`*==0 or *`EF`*==1|16/32|`pop {registers}`|
|9a|*`H`*==1 and (*`L`*==0 or *`Ret`*!=0)|16|`add sp,sp,#0x10`|
|9b|*`H`*==1 and *`L`*==1 and *`Ret`*==0|32|`ldr pc,[sp],#0x14`|
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also add an explanation to the Ret==0 case saying that it could be pop {pc} OR it could also be ldr pc,[sp],#0x14?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On instruction 8? Maybe, but I'm not sure how to include that information without blowing up the table too much. Because if R==0 then you'd still have instruction 8 popping a number of registers, but not including pc. The logical condition, while complex, should be accurate for when this instruction is present though.

Instructions 7 and 8 use the same logic as the prologue to determine which registers are restored from the stack, but with these three changes: first, *`EF`* is used in place of *`PF`*; second, if *`Ret`* = 0 and *`H`* = 0, then LR is replaced with PC in the register list and the epilogue ends immediately; third, if *`Ret`* = 0 and *`H`* = 1, then LR is omitted from the register list and popped by instruction 9b.

If *`H`* is set, then either instruction 9a or 9b is present. Instruction 9a is used when *`L`* is 0, to indicate that the LR is not on the stack. In this case, the stack is manually adjusted and *`Ret`* must be 1 or 2 to specify an explicit return. Instruction 9b is used when *`L`* is 1, to indicate an early end to the epilogue, and to return and adjust the stack at the same time.
If *`H`* is set, then either instruction 9a or 9b is present. Instruction 9a is used when *`Ret`* is nonzero, when instruction 10a or 10b is present (if *`L`* is 1, it is popped as part of instruction 8). In this case, the stack is manually adjusted. Instruction 9b is used when *`L`* is 1 and *`Ret`* is zero, to indicate an early end to the epilogue, and to return and adjust the stack at the same time.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct but became too long of a sentence IMO. The two "when" make it hard to decode what is causal here. It is also not clear that the parenthesis part applies to the 10a vs 10b choice, not the 9a vs 9b.

How about something like:

"[...] 9a is used when Ret != 0, which also implies the presence of either 10a or 10b. If L=1, then LR was popped as part of instruction 8.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good, changing it that way.

@pmsjt
Copy link
Copy Markdown
Contributor

pmsjt commented Dec 15, 2021

The truth table for the registers saved is also not great. Lines [127, 130] refer to C=1, L=0 which is an invalid configuration. I wonder if we should just replace the cells on those 4 lines with "Invalid Encoding" or something like that.

@pmsjt
Copy link
Copy Markdown
Contributor

pmsjt commented Dec 15, 2021

Since you are already making changes here, I wonder if you would also mind fixing line 84: "required" -> "requires".

@mstorsjo
Copy link
Copy Markdown
Contributor Author

The truth table for the registers saved is also not great. Lines [127, 130] refer to C=1, L=0 which is an invalid configuration. I wonder if we should just replace the cells on those 4 lines with "Invalid Encoding" or something like that.

That would be good for consistency, yes, otherwise those lines can be misleading.

Since you are already making changes here, I wonder if you would also mind fixing line 84: "required" -> "requires".

Sure.

For the prologue, the distinction between `mov r11, sp` and
`add r11, sp, #xx` lies only in whether other registers are pushed
before R11 and LR in prologue instruction 2. (The condition
`R`==1 and `PF`==0 corresponds to no other registers pushed before
`r11`.) The `L` flag doesn't affect it (and the documentation explicit
says that when `C` is set, then `L` also must be set, thus `C`==1
and `L`==0 is tautological too).

This was correctly described in the textual form, but the conditions
in the table included one erronous case.

For the epilogue, when `Ret`!=0, the function doesn't return by
popping LR directly into PC, but with an explicit branch instruction
(10a or 10b). In this case, if `L`==1, the LR register is included
in the list of registers popped in instruction 8. If register
homing is used (`H`==1), then instruction 9a is used instead of 9b.

This case seemed to have been overlooked both in the textual
description and in the table.

Also, when prologue instruction form 3a is used, clarify that
it corresponds to the unwind code FB (narrow nop) only, that unwinding
such a prologue doesn't restore `sp` from `r11`.

Also fix a typo and clarify that encodings with C=1, L=0 are
invalid.
@mstorsjo mstorsjo force-pushed the arm-exception-packed branch from 7fab074 to 97c4dc2 Compare December 15, 2021 09:27
@PRMerger20
Copy link
Copy Markdown
Contributor

@mstorsjo : Thanks for your contribution! The author(s) have been notified to review your proposed change.

@mstorsjo
Copy link
Copy Markdown
Contributor Author

mstorsjo commented Dec 15, 2021

I applied most of the suggested changes, except for the extra explanation about there either being pop {pc} or ldr pc, [sp], #20 (as I'm unsure where you'd want that change and how it would fit in).

Thanks for the review!

Copy link
Copy Markdown
Contributor

@pmsjt pmsjt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for your contribution. Can't believe how badly broken this was, with contradictions no more than a paragraph apart.

@colin-home
Copy link
Copy Markdown
Contributor

Since this is a useful update as is, I'll leave the expansion on 9b for another update, and merge this now. Many thanks to @mstorsjo for your contributions and collaboration, and to @pmsjt for reviews and comments.

@colin-home colin-home merged commit 4fb4741 into MicrosoftDocs:main Dec 15, 2021
@mstorsjo mstorsjo deleted the arm-exception-packed branch December 21, 2021 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants