Commit 2f81505
committed
[lldb] Add test showing UnwindAssemblyInstEmulation can't handle backwards branches
If we have a conditional branch, followed by an epilogue, followed by
more code, LLDB will incorrectly compute unwind information through
instruction emulation. Consider this:
```
// ...
<+16>: b.ne ; <+52> DO_SOMETHING_AND_GOTO_AFTER_EPILOGUE
// epilogue start
<+20>: ldp x29, x30, [sp, #0x20]
<+24>: add sp, sp, #0x30
<+28>: ret
// epilogue end
AFTER_EPILOGUE:
<+32>: do something
// ...
<+48>: ret
DO_SOMETHING_AND_GOTO_AFTER_EPILOGUE:
<+52>: stp x22, x23, [sp, #0x10]
<+56>: mov x22, #0x1
<+64>: b ; <+32> AFTER_EPILOGUE
```
LLDB will think that the unwind state of +32 is the same as +28. This is
false, as +32 _never_ executes after +28.
The root cause of the problem is the order in which instructions are
visited; they are visited in the order they appear in the text, with
unwind state always being forwarded to positive branch offsets, but
never to negative offsets.
In the example above, `AFTER_EPILOGUE` should inherit the state of the
branch in +64, but it doesn't because `AFTER_EPILOGUE` is visited right
after the `ret` in +28.
Fixing this should be simple: maintain a stack of instructions to
visit. While the stack is not empty, take the next instruction on stack
and visit it.
* After visiting a non-branching instruction, push the next instruction
and forward unwind state to it.
* After visiting a branch with one or more known targets, push the known
branch targets and forward state to them.
* In all other cases (ret, or branch to register), don't push nor forward
anything.
Never push an instruction already on the stack. Like the algorithm
today, this new algorithm also assume that, if two instructions branch
to the same target, the unwind state in both better be the same.
(Note: yes, branch to register is also handled incorrectly today, and
will still be incorrect).1 parent 93a1327 commit 2f81505
File tree
1 file changed
+107
-0
lines changed- lldb/unittests/UnwindAssembly/ARM64
1 file changed
+107
-0
lines changedLines changed: 107 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
964 | 964 | | |
965 | 965 | | |
966 | 966 | | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
0 commit comments