This is an archive of the discontinued LLVM Phabricator instance.

[Backend][AsmPrinter][CFI] Generate unwind table entries in .eh_frame when the uwtable attribute is present.
AbandonedPublic

Authored by jmmartinez on Nov 30 2022, 9:18 AM.

Details

Summary

This patch forces the emission of CFI information when the uwtable attribute is present and the ExceptionModel is None.

The uwtable attribute is set by the the frontend when, for example, the address sanitizer is used.

I think few things are missing in this patch:

  • a test on a target different from amdgpu that also uses cfi for the unwind tables, but that doesn't use DwarfCFI as exception model
  • a test on clang's side to ensure that -fsanitize=address adds the -unwind-tables=2 attribute on amdgpu (this should probably go o a separate patch)

Diff Detail

Event Timeline

jmmartinez created this revision.Nov 30 2022, 9:18 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 30 2022, 9:18 AM
jmmartinez requested review of this revision.Nov 30 2022, 9:18 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 30 2022, 9:18 AM

Removed change that shouldn't have been commmited.

jmmartinez edited the summary of this revision. (Show Details)Dec 1 2022, 3:01 AM

Can you describe the clang command line?

If AMDGPU doesn't use ExceptionHandling::DwarfCFI, why suppress .cfi_sections .debug_frame? .eh_frame seems inappropriate.
The change modifies the ExceptionHandling::None behavior for AMDGPU's own use case, which may not be desired by other ExceptionHandling::None targets.

@jmmartinez

http://logan.tw/llvm/nounwind.html might be helpful in throwing some light on the problem being solved here.

jmmartinez added a comment.EditedDec 12 2022, 6:46 AM

Hi ! Thanks for the comment (and sorry for the delay).

Can you describe the clang command line?

The objective is to emit an entry in the .eh_frame section when the function is marked as uwtable (and CFI is supported by the target).
This is used by sanitizers that use async unwind tables (address, hwaddress, thread, memory and dataflow according to https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/SanitizerArgs.cpp#L42, and used here https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/Clang.cpp#L5395).

Then, when -fsanitize=address is used, clang would pass the -funwind-tables=2 flag to the clang -cc1 process. Then, every function definition coming clang's code-generation should have the uwtable attribute.

The change modifies the ExceptionHandling::None behavior for AMDGPU's own use case, which may not be desired by other ExceptionHandling::None targets.

I do agree that this may affect other targets, but I thought that it could affect them in a positive way (the uwtable forces the emission of an entry in the uwtable as it says it does). I might be misinterpreting the uwtable attribute.

Hi ! Thanks for the comment (and sorry for the delay).

Can you describe the clang command line?

The objective is to emit an entry in the .eh_frame section when the function is marked as uwtable (and CFI is supported by the target).
This is used by sanitizers that use async unwind tables (address, hwaddress, thread, memory and dataflow according to https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/SanitizerArgs.cpp#L42, and used here https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/Clang.cpp#L5395).

Then, when -fsanitize=address is used, clang would pass the -funwind-tables=2 flag to the clang -cc1 process. Then, every function definition coming clang's code-generation should have the uwtable attribute.

-fsanitize=address used to need unwind tables for error reporting. It no longer does after https://reviews.llvm.org/D102046

The change modifies the ExceptionHandling::None behavior for AMDGPU's own use case, which may not be desired by other ExceptionHandling::None targets.

I do agree that this may affect other targets, but I thought that it could affect them in a positive way (the uwtable forces the emission of an entry in the uwtable as it says it does). I might be misinterpreting the uwtable attribute.

I am still unclear what you want to do. A .c source with a command line in the commit message will help, though I guess this patch may not be needed at all.

I'm coming back to this issue after a long time.


I am still unclear what you want to do. A .c source with a command line in the commit message will help, though I guess this patch may not be needed at all.

Here's an example of what I would like to achieve:

Consider the vadd_hip.cpp example
but with the bounds check at line 18 removed.

The user can compile this code using the command line below:

hipcc -fsanitize=address vec_add.cpp

The previous command triggers two clang invocations:

  • For the device: clang-15 -cc1 -triple amdgcn-amd-amdhsa -target-cpu gfx90a ... vadd_hip.cpp -funwind-tables=2 -fsanitize=address
  • For the host: clang-15 -cc1 -triple x86_64_unknown-linux-gnu ... -fsanitize=address

Ideally, during the execution the out-of-bounds memory access would be detected by asan on the device side and a stacktrace reported.

At the moment, unwinding is not supported on the device side (neither fast nor slow), but having the CFI entries in the .eh_frame would remove a block to advance towards it.


When I started addressing the problem I realized two things:

  • On clang's driver side, -fsanitize=address seems to imply that asynchronous unwind tables are used. Which sets all function with the attribute uwtable
  • On targets that support DwarfCFI, unless the EH-type is DwarfCFI, CFI entries in are not generated for functions marked as uwtable.

I would have expectedt that functions marked with the uwtable attribute would get their entry regardles of the target's EH-type (doing this is the solution I propose).

An alternative solution could be to make the EH-type of AMDGPU be DwarfCFI (this could work, but I don't know if there are other consequences).


-fsanitize=address used to need unwind tables for error reporting. It no longer does after https://reviews.llvm.org/D102046

Finally, since I hace many blindspots on this part of LLVM, and for my curiosity, would you mind explaining the tradeoff between the slow and fast unwind?
If I understand, there is a difference in performance; and that there slow-unwind uses libunwind, while fast-unwind is implemented directly in compiler-rt. But I'm not sure if there are other implications from this tradeoff.

jmmartinez added subscribers: respindola, rengolin.

@respindola & @rengolin, I've added you as reviewers since I've read your discussion from 2014 about Unwind behaviour in Clang/LLVM and I've though this issue is related.

In this patch I propose to generate entries using DwarfCFI in the .eh_frame region for functions with the uwtable attribute; when the target's EH type is either None or DwarfCFI.
I have the feeling that this last condition could be relaxed and these entries could be generated for all targets that support DwarfCFI (I ran some quick tests on my development setup and it didn't break any test).

What's my motivation for this? In my particular case, to support unwinding with the sanitizers on AMDGPU in the future.

Do you have some advice?

jmmartinez added inline comments.Mar 22 2023, 8:37 AM
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
1295

Could this condition be relaxed to any EHType as long as DwarfCFI is supported?

jmmartinez abandoned this revision.May 31 2023, 2:31 AM