This is an archive of the discontinued LLVM Phabricator instance.

Graph builder implementation.
ClosedPublic

Authored by hctim on Sep 29 2017, 2:16 PM.

Details

Summary

Implement a localised graph builder for indirect control flow instructions. Main interface is through GraphBuilder::buildFlowGraph, which will build a flow graph around an indirect CF instruction. Various modifications to FileVerifier are also made to const-expose some members needed for machine code analysis done by the graph builder.

Event Timeline

hctim created this revision.Sep 29 2017, 2:16 PM
hctim updated this revision to Diff 117222.Sep 29 2017, 2:17 PM

Removed comments from CMakeLists.txt

hctim updated this revision to Diff 117435.Oct 2 2017, 3:06 PM

Update to only diff the prev in stack.

hctim updated this revision to Diff 117450.Oct 2 2017, 4:41 PM

Fix various warnings.

I'm having difficulty following this because you document what the GraphBuilder methods do but you never say how and I get lost before I figure that out. Maybe that could go in the GraphBuilder.cpp file header comments?

tools/llvm-cfi-verify/GraphBuilder.cpp
1 ↗(On Diff #117450)

Missing header

tools/llvm-cfi-verify/GraphBuilder.h
49 ↗(On Diff #117450)

Do these need to be externally visible?

67 ↗(On Diff #117450)

Should be a method of ConditionalBranchNode (also, prefer to accept a raw_ostream& instead of hardcoding outs() for print methods, dump() typically writes to dbgs() I think)

68 ↗(On Diff #117450)

ditto

76 ↗(On Diff #117450)

Why are these pointers?

hctim updated this revision to Diff 117718.Oct 4 2017, 1:07 PM
hctim added a comment.Oct 4 2017, 1:07 PM

Merged changes from previous in stack, updated for vlad.tsyrklevich's comments.

hctim updated this revision to Diff 117721.Oct 4 2017, 1:10 PM

Merged wrong CL, putting this back to the way it should be.

hctim updated this revision to Diff 117722.Oct 4 2017, 1:14 PM

Merged changes from upstream.

hctim updated this revision to Diff 117738.Oct 4 2017, 2:01 PM
hctim marked 4 inline comments as done.

Updated to fix vlad's comments.

hctim added inline comments.Oct 4 2017, 2:01 PM
tools/llvm-cfi-verify/GraphBuilder.h
49 ↗(On Diff #117450)

They're modified by the tests in order to guarantee behaviour, even if the default change.

76 ↗(On Diff #117450)

Don't want to mix storage (stack/heap) of nodes. Intermediate nodes cannot be stored on stack, as they are neither a branch node or an orphaned node. Consider the following:

[0x0: jmp 2]
       \
  [0x2: jmpq %rax]

0x2 is neither a branch node, nor an orphaned node. The only reference to it is via 0x0, which is a branch node.

Having all these nodes be heap-allocated makes the clean up much easier.

hctim updated this revision to Diff 117741.Oct 4 2017, 2:32 PM

Added header to GraphBuilder.cpp

hctim updated this revision to Diff 117881.Oct 5 2017, 1:50 PM
hctim marked an inline comment as done.

Backported D38564

hctim updated this revision to Diff 118111.Oct 6 2017, 5:24 PM

format was from prev in stack, put it down there.

tools/llvm-cfi-verify/GraphBuilder.cpp
232 ↗(On Diff #117881)

Reword this.

293 ↗(On Diff #117881)

Since the if() statement continue;s as the end, place the below without an else statement to avoid nesting (makes it a bit easier to read and understand.)

310 ↗(On Diff #117881)

Reword 'fall back on itself'

313 ↗(On Diff #117881)

Replace with std::find_if() ?

326 ↗(On Diff #117881)

Why not use createParentNode() here?

335 ↗(On Diff #117881)

Place the error first, and also avoid the nesting here as well.

tools/llvm-cfi-verify/GraphBuilder.h
53 ↗(On Diff #117881)

just print(

54 ↗(On Diff #117881)

just flatten(

62 ↗(On Diff #117881)

just print(

66 ↗(On Diff #117881)

instrument CFI protection?

104 ↗(On Diff #117881)

Would be nice to have a comment here that briefly explains the approach (e.g. there are some bits that build the graph backwards and some that build it forwards)

76 ↗(On Diff #117450)

Would it make sense to just place ConditionalBranchNodes in a vector without dynamically allocating them so they don't have to be manually freed?

hctim updated this revision to Diff 118252.Oct 9 2017, 12:29 PM
hctim marked 12 inline comments as done.

Updated with Vlad's comments.

tools/llvm-cfi-verify/GraphBuilder.h
76 ↗(On Diff #117450)

Yep, done :)

hctim updated this revision to Diff 118255.Oct 9 2017, 12:38 PM

Backported usesRegisterOperand.

hctim updated this revision to Diff 118423.Oct 10 2017, 10:44 AM

Merged updates from stack.

tools/llvm-cfi-verify/GraphBuilder.h
75 ↗(On Diff #118255)

Could we represent this as (1) a uint64_t SrcAddr -> uint64_t DstAddr mapping and (2) a std::vector<uint64_t> of orphaned nodes? Then you would not need the Next pointers, and presumably FlowLength can simply be maintained as an argument to buildFlowGraphImpl(). You could maintain O(1) lookup by using llvm::DenseMap which is hash-table based and lighter-weight than std::map (see http://llvm.org/docs/ProgrammersManual.html#llvm-adt-densemap-h) and that seems cleaner to me than the current structure, WDYT?

hctim updated this revision to Diff 118684.Oct 11 2017, 1:36 PM

Patched in previous changes to unit tests.

hctim updated this revision to Diff 118988.Oct 13 2017, 4:29 PM

Made GraphResult's members automatic storage duration.

hctim marked an inline comment as done.Oct 13 2017, 4:31 PM
tools/llvm-cfi-verify/lib/GraphBuilder.cpp
97

Why not just pass this in?

109

s/chain/basic block/?

153

ditto s/chain/basic block/?

155

ditto

177

ditto

197

nit: eliminate braces

228

This is executed here, 240, 253, 260, and 270. Any reason it can't just be done once above? Is it to avoid the ConditionalBranchNode case?

tools/llvm-cfi-verify/lib/GraphBuilder.h
58

Could this be reworded? I'm still not sure what it means.

87

Sentence cuts off

95

fully evaluated, or enumerated? Not sure what evaluated might refer to in this context.

109

s/acyclic/cycle/

tools/llvm-cfi-verify/lib/GraphBuilder.h
63

type: posible

69

It's not all keys, just keys for all valid instructions in that range right?

unittests/tools/llvm-cfi-verify/GraphBuilder.cpp
61

Why template it just for std::vector?

132

This is never reached since an unhandled Error (e.g. at destruction time) cause an immediate failure.

454

???

+----------+     +--------------+
|    20    | <-- |      0       |
+----------+     +--------------+
  |                |
  |                |
  v                v
+----------+     +--------------+
|    21    |     |      2       |
+----------+     +--------------+
  |                |
  |                |
  v                v
+----------+     +--------------+
| 22 (ud2) |  +> |      7       |
+----------+  |  +--------------+
  ^           |    |
  |           |    |
  |           |    v
+----------+  |  +--------------+
|    4     |  |  |      8       |
+----------+  |  +--------------+
  |           |    |
  |           |    |
  v           |    v
+----------+  |  +--------------+     +------------+
|    6     | -+  | 9 (indirect) | <-- |     13     |
+----------+     +--------------+     +------------+
                   ^                    |
                   |                    |
                   |                    v
                 +--------------+     +------------+
                 |      11      |     | 15 (error) |
                 +--------------+     +------------+
hctim updated this revision to Diff 119676.Oct 20 2017, 11:43 AM
hctim marked 14 inline comments as done.

Updated with Vlad's comments. Also patched the unit tests to succeed when x86 targets are not built, instead of not compiling.

tools/llvm-cfi-verify/lib/GraphBuilder.cpp
109

I've changed them all /s/chain/block. These blocks may contain direct unconditional branches as well :)

228

Yep, don't want to add a conditional branch to IntermediateNodes. I can't really see a good way to not repeat this LOC without introcuding a status variable which results in the same reuse.

tools/llvm-cfi-verify/lib/GraphBuilder.h
69

I think it's all keys, each key-value pair is built from the cross-references to the value. Invalid instructions (e.g. an indirect branch) will be an entry in OrphanedNodes, with a key-value pair between the invalid instruction -> its child.

unittests/tools/llvm-cfi-verify/GraphBuilder.cpp
61

Was initially using it to print IntermediateNodes (type: DenseMap) as well, now it's just printing vector's I'll remove the templating. Thanks!

454

It's beautiful!

hctim updated this revision to Diff 119725.Oct 20 2017, 4:42 PM

Rebased over master. Forgot to add the unit test patches to this CL.

unittests/tools/llvm-cfi-verify/FileAnalysis.cpp
70

Could we (1) break the x86 test changes out into a follow-up CL and (2) check the error message to make sure we only skip tests for the specific error message we expect to see? I want to make sure we don't break something else in the future that accidentally disables unit tests without us realizing.

vlad.tsyrklevich accepted this revision.Oct 20 2017, 5:31 PM
This revision is now accepted and ready to land.Oct 20 2017, 5:31 PM
hctim updated this revision to Diff 119731.Oct 20 2017, 6:18 PM
hctim marked an inline comment as done.

Patched out x86 test changes.

This revision was automatically updated to reflect the committed changes.

This patch causes the same unittest compilation failure which was fixed in https://reviews.llvm.org/D39020.

Please fix it asap or revert the patch.

llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt
17 ↗(On Diff #119928)

what is the reason you removed this line?

Actually I took a liberty to submit https://reviews.llvm.org/rL316422 to unblock myself. Feel free to re-write it as you need but please ensure that it does not restore the issue.