C++: Dynamic allocations in IR alias analysis

This commit is contained in:
Robert Marsh
2020-02-07 15:02:12 -08:00
parent 05c8610bbc
commit 7f69cdfb56
14 changed files with 135 additions and 32 deletions

View File

@@ -82,6 +82,7 @@ private newtype TOpcode =
TSizedBufferReadSideEffect() or
TSizedBufferMustWriteSideEffect() or
TSizedBufferMayWriteSideEffect() or
TInitializeDynamicAllocation() or
TChi() or
TInlineAsm() or
TUnreached() or
@@ -695,6 +696,10 @@ module Opcode {
final override string toString() { result = "SizedBufferMayWriteSideEffect" }
}
class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode, TInitializeDynamicAllocation {
final override string toString() { result = "InitializeDynamicAllocation" }
}
class Chi extends Opcode, TChi {
final override string toString() { result = "Chi" }

View File

@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
/**
*
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
InitializeDynamicAllocationInstruction() {
getOpcode() instanceof Opcode::InitializeDynamicAllocation
}
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
}
/**
* An instruction representing a GNU or MSVC inline assembly statement.
*/

View File

@@ -7,6 +7,9 @@ private newtype TAllocation =
TVariableAllocation(IRVariable var) or
TIndirectParameterAllocation(IRAutomaticUserVariable var) {
exists(InitializeIndirectionInstruction instr | instr.getIRVariable() = var)
} or
TDynamicAllocation(CallInstruction call) {
exists(InitializeDynamicAllocationInstruction instr | instr.getPrimaryInstruction() = call)
}
/**
@@ -95,3 +98,31 @@ class IndirectParameterAllocation extends Allocation, TIndirectParameterAllocati
final override predicate alwaysEscapes() { none() }
}
class DynamicAllocation extends Allocation, TDynamicAllocation {
CallInstruction call;
DynamicAllocation() { this = TDynamicAllocation(call) }
final override string toString() {
result = call.toString() + " at " + call.getLocation() // TODO: make this both short and unique
}
final override CallInstruction getABaseInstruction() { result = call }
final override IRFunction getEnclosingIRFunction() { result = call.getEnclosingIRFunction() }
final override Language::Location getLocation() { result = call.getLocation() }
final override string getUniqueId() { result = call.getUniqueId() }
final override IRType getIRType() {
result instanceof IRUnknownType // TODO: look at casts and sizes?
}
final override predicate isReadOnly() { none() }
final override predicate isAlwaysAllocatedOnStack() { none() }
final override predicate alwaysEscapes() { none() }
}

View File

@@ -68,8 +68,12 @@ private newtype TMemoryLocation =
) and
languageType = type.getCanonicalLanguageType()
} or
TEntireAllocationMemoryLocation(IndirectParameterAllocation var, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
TEntireAllocationMemoryLocation(Allocation var, boolean isMayAccess) {
(
var instanceof IndirectParameterAllocation or
var instanceof DynamicAllocation
) and
(isMayAccess = false or isMayAccess = true)
} or
TUnknownMemoryLocation(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true

View File

@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
/**
*
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
InitializeDynamicAllocationInstruction() {
getOpcode() instanceof Opcode::InitializeDynamicAllocation
}
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
}
/**
* An instruction representing a GNU or MSVC inline assembly statement.
*/

View File

@@ -341,16 +341,31 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects {
)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
expr.getTarget() instanceof AllocationFunction and
opcode instanceof Opcode::InitializeDynamicAllocation and
tag = OnlyInstructionTag() and
type = getUnknownType() // TODO: precise type
}
override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() }
override Instruction getFirstInstruction() {
if expr.getTarget() instanceof AllocationFunction
then result = getInstruction(OnlyInstructionTag())
else result = getChild(0).getFirstInstruction()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
kind = gotoEdge() and
if exists(getChild(0))
then result = getChild(0).getFirstInstruction()
else result = getParent().getChildSuccessor(this)
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() }
override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
none()
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
operandTag = addressOperand() and
result = getPrimaryInstructionForSideEffect(OnlyInstructionTag())
}
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {

View File

@@ -411,7 +411,9 @@ newtype TTranslatedElement =
TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or
// The side effects of a `Call`
TTranslatedSideEffects(Call expr) {
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or expr instanceof ConstructorCall
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or
expr instanceof ConstructorCall or
expr.getTarget() instanceof AllocationFunction
} or // A precise side effect of an argument to a `Call`
TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) {
(

View File

@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
/**
*
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
InitializeDynamicAllocationInstruction() {
getOpcode() instanceof Opcode::InitializeDynamicAllocation
}
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
}
/**
* An instruction representing a GNU or MSVC inline assembly statement.
*/

View File

@@ -8,12 +8,6 @@
| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | AST only |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | AST only |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:85:8:85:11 | copy | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:9:86:12 | copy | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | AST only |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | AST only |

View File

@@ -40,9 +40,15 @@
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | |
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | |
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:17:83:24 | userName | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:33 | call to getenv | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:46 | (const char *)... | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:2:86:7 | call to strcpy | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:15:86:22 | userName | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | |
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | |

View File

@@ -1261,21 +1261,22 @@ ssa.cpp:
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_9
# 269| m269_7(unknown) = Chi : total:m268_9, partial:m269_6
# 269| m269_8(void *) = Store : &:r269_1, r269_5
# 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5
# 269| m269_9(void *) = Store : &:r269_1, r269_5
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
# 270| r270_3(void *) = Load : &:r270_2, m269_8
# 270| r270_3(void *) = Load : &:r270_2, m269_9
# 270| r270_4(glval<void *>) = VariableAddress[s] :
# 270| r270_5(void *) = Load : &:r270_4, m268_7
# 270| r270_6(glval<int>) = VariableAddress[size] :
# 270| r270_7(int) = Load : &:r270_6, m268_11
# 270| r270_8(void *) = Call : func:r270_1, 0:r270_3, 1:r270_5, 2:r270_7
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_7
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_8
# 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
# 270| m270_11(unknown) = Chi : total:m269_7, partial:m270_10
# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
# 271| r271_3(void *) = Load : &:r271_2, m269_8
# 271| r271_3(void *) = Load : &:r271_2, m269_9
# 271| m271_4(void *) = Store : &:r271_1, r271_3
# 268| v268_12(void) = ReturnIndirection : &:r268_8, ~m270_11
# 268| r268_13(glval<void *>) = VariableAddress[#return] :

View File

@@ -1256,10 +1256,11 @@ ssa.cpp:
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_4
# 269| m269_7(unknown) = Chi : total:m268_4, partial:m269_6
# 269| m269_8(void *) = Store : &:r269_1, r269_5
# 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5
# 269| m269_9(void *) = Store : &:r269_1, r269_5
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
# 270| r270_3(void *) = Load : &:r270_2, m269_8
# 270| r270_3(void *) = Load : &:r270_2, m269_9
# 270| r270_4(glval<void *>) = VariableAddress[s] :
# 270| r270_5(void *) = Load : &:r270_4, m268_7
# 270| r270_6(glval<int>) = VariableAddress[size] :
@@ -1267,14 +1268,14 @@ ssa.cpp:
# 270| r270_8(void *) = Call : func:r270_1, 0:r270_3, 1:r270_5, 2:r270_7
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m268_9
# 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
# 270| m270_11(unknown) = Chi : total:m269_7, partial:m270_10
# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
# 271| r271_3(void *) = Load : &:r271_2, m269_8
# 271| r271_3(void *) = Load : &:r271_2, m269_9
# 271| m271_4(void *) = Store : &:r271_1, r271_3
# 268| v268_12(void) = ReturnIndirection : &:r268_8, m268_9
# 268| r268_13(glval<void *>) = VariableAddress[#return] :
# 268| v268_14(void) = ReturnValue : &:r268_13, m271_4
# 268| v268_15(void) = UnmodeledUse : mu*
# 268| v268_16(void) = AliasedUse : ~m270_11
# 268| v268_16(void) = AliasedUse : ~m269_7
# 268| v268_17(void) = ExitFunction :

View File

@@ -1168,10 +1168,11 @@ ssa.cpp:
# 269| r269_4(int) = Load : &:r269_3, m268_10
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
# 269| mu269_6(unknown) = ^CallSideEffect : ~mu268_4
# 269| m269_7(void *) = Store : &:r269_1, r269_5
# 269| mu269_7(unknown) = ^InitializeDynamicAllocation : &:r269_5
# 269| m269_8(void *) = Store : &:r269_1, r269_5
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
# 270| r270_3(void *) = Load : &:r270_2, m269_7
# 270| r270_3(void *) = Load : &:r270_2, m269_8
# 270| r270_4(glval<void *>) = VariableAddress[s] :
# 270| r270_5(void *) = Load : &:r270_4, m268_6
# 270| r270_6(glval<int>) = VariableAddress[size] :
@@ -1181,7 +1182,7 @@ ssa.cpp:
# 270| mu270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
# 271| r271_3(void *) = Load : &:r271_2, m269_7
# 271| r271_3(void *) = Load : &:r271_2, m269_8
# 271| m271_4(void *) = Store : &:r271_1, r271_3
# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4
# 268| r268_12(glval<void *>) = VariableAddress[#return] :

View File

@@ -1168,10 +1168,11 @@ ssa.cpp:
# 269| r269_4(int) = Load : &:r269_3, m268_10
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
# 269| mu269_6(unknown) = ^CallSideEffect : ~mu268_4
# 269| m269_7(void *) = Store : &:r269_1, r269_5
# 269| mu269_7(unknown) = ^InitializeDynamicAllocation : &:r269_5
# 269| m269_8(void *) = Store : &:r269_1, r269_5
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
# 270| r270_3(void *) = Load : &:r270_2, m269_7
# 270| r270_3(void *) = Load : &:r270_2, m269_8
# 270| r270_4(glval<void *>) = VariableAddress[s] :
# 270| r270_5(void *) = Load : &:r270_4, m268_6
# 270| r270_6(glval<int>) = VariableAddress[size] :
@@ -1181,7 +1182,7 @@ ssa.cpp:
# 270| mu270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
# 271| r271_3(void *) = Load : &:r271_2, m269_7
# 271| r271_3(void *) = Load : &:r271_2, m269_8
# 271| m271_4(void *) = Store : &:r271_1, r271_3
# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4
# 268| r268_12(glval<void *>) = VariableAddress[#return] :