Skip to content

Commit e4c6fd0

Browse files
committed
Add support for CIL ldind and stind instructions
Introduces translation classes and tags for CIL ldind.* (load indirect) and stind.* (store indirect) instructions in the IR. Updates InstructionTag, TempVariableTag, and TranslatedElement to recognize and handle these new instruction types.
1 parent 628f191 commit e4c6fd0

4 files changed

Lines changed: 112 additions & 3 deletions

File tree

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction0/InstructionTag.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ newtype TInstructionTag =
5959
CilUnconditionalBranchTag() or
6060
CilUnconditionalBranchRefTag() or
6161
CilCallTag() or
62-
CilCallTargetTag()
62+
CilCallTargetTag() or
63+
CilLdindLoadTag() or
64+
CilStindStoreTag()
6365

6466
class InstructionTag extends TInstructionTag {
6567
final string toString() {
@@ -220,6 +222,12 @@ class InstructionTag extends TInstructionTag {
220222
or
221223
this = CilCallTargetTag() and
222224
result = "CilCallTarget"
225+
or
226+
this = CilLdindLoadTag() and
227+
result = "CilLdindLoad"
228+
or
229+
this = CilStindStoreTag() and
230+
result = "CilStindStore"
223231
}
224232
}
225233

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction0/TempVariableTag.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ newtype TTempVariableTag =
3232
CallReturnValueTag() or
3333
CilCallTargetVarTag() or
3434
CilLoadStringVarTag() or
35-
CilLoadArgVarTag()
35+
CilLoadArgVarTag() or
36+
CilLdindVarTag()
3637

3738
class TempVariableTag extends TTempVariableTag {
3839
string toString() {
@@ -137,5 +138,8 @@ class TempVariableTag extends TTempVariableTag {
137138
or
138139
this = CilLoadArgVarTag() and
139140
result = "ldarg"
141+
or
142+
this = CilLdindVarTag() and
143+
result = "ldind"
140144
}
141145
}

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction0/TranslatedElement.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ newtype TTranslatedElement =
122122
TTranslatedCilCall(Raw::CilCall call) { shouldTranslateCilInstr(call) } or
123123
TTranslatedCilLoadString(Raw::CilLdstr ldstr) { shouldTranslateCilInstr(ldstr) } or
124124
TTranslatedCilParameter(Raw::CilParameter param) { shouldTranslateCilParameter(param) } or
125-
TTranslatedCilLoadArg(Raw::CilLoadArgument ldstr) { shouldTranslateCilInstr(ldstr) }
125+
TTranslatedCilLoadArg(Raw::CilLoadArgument ldstr) { shouldTranslateCilInstr(ldstr) } or
126+
TTranslatedCilLoadIndirect(Raw::CilLoadIndirectInstruction ldind) { shouldTranslateCilInstr(ldind) } or
127+
TTranslatedCilStoreIndirect(Raw::CilStoreIndirectInstruction stind) { shouldTranslateCilInstr(stind) }
126128

127129
TranslatedElement getTranslatedElement(Raw::Element raw) {
128130
result.getRawElement() = raw and

binary/ql/lib/semmle/code/binary/ast/ir/internal/Instruction0/TranslatedInstruction.qll

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,3 +2372,98 @@ class TranslatedCilLoadArg extends TranslatedCilInstruction, TTranslatedCilLoadA
23722372
result = getTranslatedCilInstruction(instr.getABackwardPredecessor()).getStackElement(i - 1)
23732373
}
23742374
}
2375+
2376+
/**
2377+
* Translation for CIL ldind.* instructions (load indirect through pointer).
2378+
* These instructions pop an address from the stack and push the value at that address.
2379+
*/
2380+
class TranslatedCilLoadIndirect extends TranslatedCilInstruction, TTranslatedCilLoadIndirect {
2381+
override Raw::CilLoadIndirectInstruction instr;
2382+
2383+
TranslatedCilLoadIndirect() { this = TTranslatedCilLoadIndirect(instr) }
2384+
2385+
final override predicate hasInstruction(
2386+
Opcode opcode, InstructionTag tag, Option<Variable>::Option v
2387+
) {
2388+
opcode instanceof Opcode::Load and
2389+
tag = CilLdindLoadTag() and
2390+
v.asSome() = this.getTempVariable(CilLdindVarTag())
2391+
}
2392+
2393+
override predicate hasTempVariable(TempVariableTag tag) { tag = CilLdindVarTag() }
2394+
2395+
override predicate producesResult() { any() }
2396+
2397+
override Variable getVariableOperand(InstructionTag tag, OperandTag operandTag) {
2398+
tag = CilLdindLoadTag() and
2399+
operandTag instanceof LoadAddressTag and
2400+
result = getTranslatedCilInstruction(instr.getABackwardPredecessor()).getStackElement(0)
2401+
}
2402+
2403+
override Instruction getChildSuccessor(TranslatedElement child, SuccessorType succType) { none() }
2404+
2405+
override Instruction getSuccessor(InstructionTag tag, SuccessorType succType) {
2406+
tag = CilLdindLoadTag() and
2407+
succType instanceof DirectSuccessor and
2408+
result = getTranslatedInstruction(instr.getASuccessor()).getEntry()
2409+
}
2410+
2411+
override Instruction getEntry() { result = this.getInstruction(CilLdindLoadTag()) }
2412+
2413+
override Variable getResultVariable() { result = this.getTempVariable(CilLdindVarTag()) }
2414+
2415+
final override Variable getStackElement(int i) {
2416+
i = 0 and
2417+
result = this.getInstruction(CilLdindLoadTag()).getResultVariable()
2418+
or
2419+
i > 0 and
2420+
result = getTranslatedCilInstruction(instr.getABackwardPredecessor()).getStackElement(i)
2421+
}
2422+
}
2423+
2424+
/**
2425+
* Translation for CIL stind.* instructions (store indirect through pointer).
2426+
* These instructions pop a value and an address from the stack, then store the value at that address.
2427+
*/
2428+
class TranslatedCilStoreIndirect extends TranslatedCilInstruction, TTranslatedCilStoreIndirect {
2429+
override Raw::CilStoreIndirectInstruction instr;
2430+
2431+
TranslatedCilStoreIndirect() { this = TTranslatedCilStoreIndirect(instr) }
2432+
2433+
final override predicate hasInstruction(
2434+
Opcode opcode, InstructionTag tag, Option<Variable>::Option v
2435+
) {
2436+
opcode instanceof Opcode::Store and
2437+
tag = CilStindStoreTag() and
2438+
v.isNone()
2439+
}
2440+
2441+
override predicate producesResult() { any() }
2442+
2443+
override Variable getVariableOperand(InstructionTag tag, OperandTag operandTag) {
2444+
tag = CilStindStoreTag() and
2445+
exists(Raw::CilInstruction pred | pred = instr.getABackwardPredecessor() |
2446+
operandTag instanceof StoreAddressTag and
2447+
result = getTranslatedCilInstruction(pred).getStackElement(1)
2448+
or
2449+
operandTag instanceof StoreValueTag and
2450+
result = getTranslatedCilInstruction(pred).getStackElement(0)
2451+
)
2452+
}
2453+
2454+
override Instruction getChildSuccessor(TranslatedElement child, SuccessorType succType) { none() }
2455+
2456+
override Instruction getSuccessor(InstructionTag tag, SuccessorType succType) {
2457+
tag = CilStindStoreTag() and
2458+
succType instanceof DirectSuccessor and
2459+
result = getTranslatedInstruction(instr.getASuccessor()).getEntry()
2460+
}
2461+
2462+
override Instruction getEntry() { result = this.getInstruction(CilStindStoreTag()) }
2463+
2464+
override Variable getResultVariable() { none() }
2465+
2466+
final override Variable getStackElement(int i) {
2467+
result = getTranslatedCilInstruction(instr.getABackwardPredecessor()).getStackElement(i + 2)
2468+
}
2469+
}

0 commit comments

Comments
 (0)