This is an archive of the discontinued LLVM Phabricator instance.

[AddressSanitizer] Fix for wrong argument values appearing in backtraces
ClosedPublic

Authored by vsk on Mar 31 2020, 3:48 PM.

Details

Summary

In some cases, ASan may insert instrumentation before function arguments
have been stored into their allocas. This causes two issues:

  1. The argument value must be spilled until it can be stored into the reserved alloca, wasting a stack slot.
  1. Until the store occurs in a later basic block, the debug location will point to the wrong frame offset, and backtraces will show an uninitialized value.

The proposed solution is to move instructions which initialize allocas
for arguments up into the entry block, before the position where ASan
starts inserting its instrumentation.

For the motivating test case, before the patch we see:

| 0033: movq %rdi, 0x68(%rbx)  |   | DW_TAG_formal_parameter     |
| ...                          |   |   DW_AT_name ("a")          |
| 00d1: movq 0x68(%rbx), %rsi  |   |   DW_AT_location (RBX+0x90) |
| 00d5: movq %rsi, 0x90(%rbx)  |   |        ^ not correct ...    |

and after the patch we see:

| 002f: movq %rdi, 0x70(%rbx)  |   | DW_TAG_formal_parameter     |
|                              |   |   DW_AT_name ("a")          |
|                              |   |   DW_AT_location (RBX+0x70) |

rdar://61122691

Diff Detail

Event Timeline

vsk created this revision.Mar 31 2020, 3:48 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 31 2020, 3:48 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
vsk added a reviewer: friss.Mar 31 2020, 4:20 PM
aprantl accepted this revision.Apr 1 2020, 11:00 AM
aprantl added inline comments.
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
3003

It's counterintuitive that this isn't !isInterestingAlloca(). Perhaps commen why we skip the interesting ones?

This revision is now accepted and ready to land.Apr 1 2020, 11:00 AM
eugenis added inline comments.Apr 1 2020, 11:43 AM
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
3023

What happens with

a = alloca
store arg, a
load a
store arg2, a

will the second store be moved across the aliasing load?

vsk planned changes to this revision.Apr 1 2020, 12:13 PM
vsk marked an inline comment as done.
vsk added inline comments.
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
3023

Yes, thanks for catching this.

I plan to address this by stopping the loop when an unknown instruction is seen. I.e., make it bail out if "I" is not a StoreInst or a CastInst that matches the known argument init cases. Does that sound ok?

Another more expensive/general option is to use the isSafeToMoveBefore utility from CodeMoverUtils (this requires DependenceInfo, DomTree, and PostDomTree).

eugenis added inline comments.Apr 1 2020, 12:58 PM
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
3023

Sounds fine.

vsk updated this revision to Diff 254302.Apr 1 2020, 1:42 PM

Do not reorder past unknown instructions.

This revision is now accepted and ready to land.Apr 1 2020, 1:42 PM
vsk edited the summary of this revision. (Show Details)Apr 1 2020, 1:43 PM
vsk planned changes to this revision.Apr 1 2020, 1:49 PM

Hm, this will not work if there's more than one interesting alloca for ASan to instrument. Should have a fix shortly.

vsk updated this revision to Diff 254306.Apr 1 2020, 1:58 PM

Handle case where there is more than one interesting alloca.

This revision is now accepted and ready to land.Apr 1 2020, 1:58 PM
Harbormaster completed remote builds in B51344: Diff 254302.
vsk added a comment.Apr 6 2020, 10:13 AM

@eugenis do you have any further feedback on this one? Thanks.

eugenis accepted this revision.Apr 6 2020, 10:33 AM

LGTM with 2 comments

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
2991

Mention "uninstrumented" (alloca) or something like that in the function name to make it clear that this function does not break regular alloca instrumentation by moving stores before stack poisoning.

This only really affects -O0 compilation, right?

3008

It looks like it would be simpler and cheaper to move this check down to the initializer of IsArgInitViaCast, and get rid of the vector update and lookup.

vsk marked 4 inline comments as done.Apr 6 2020, 2:35 PM
vsk added inline comments.
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
2991

Yes, with optimization enabled most allocas for arguments get promoted away.

3008

Sounds good. The only gotcha is to make sure the cast appears after InsBefore. I left a comment about this.

This revision was automatically updated to reflect the committed changes.
vsk marked 2 inline comments as done.