M3 R3.2: instrument-grpc-nonstream also captures out/ref byte[] responses
Extends the IL-rewrite to log out (byref) byte[] params at method exit (ldarg + ldind.ref), not just byte[] inputs. This captured GetTagInfosFromName's response, which located the per-tag GUID at offset 8 = exactly where ParseTagInfoRecord reads "typeId" — proving the SDK already parses the GUID AddStreamValues needs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
@@ -1401,7 +1401,7 @@ static int InstrumentGrpcNonStream(string[] args)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Input byte[] params are "System.Byte[]"; out/ref byte[] are "System.Byte[]&".
|
||||
// ENTRY: log non-byref byte[] inputs ("System.Byte[]").
|
||||
foreach (dnlib.DotNet.Parameter bufParam in method.Parameters
|
||||
.Where(p => !p.IsHiddenThisParameter && p.Type.FullName == "System.Byte[]")
|
||||
.ToArray())
|
||||
@@ -1425,10 +1425,49 @@ static int InstrumentGrpcNonStream(string[] args)
|
||||
Type = type.Name.String,
|
||||
Method = method.Name.String,
|
||||
Phase = phase,
|
||||
Param = bufParam.Name,
|
||||
Direction = "in",
|
||||
Token = "0x" + method.MDToken.Raw.ToString("X8"),
|
||||
});
|
||||
}
|
||||
|
||||
// EXIT: log out/ref byte[] responses ("System.Byte[]&") before each ret. ldarg loads the
|
||||
// managed pointer; ldind.ref dereferences it to the byte[]. (RPC wrappers set the out
|
||||
// param right before a single ret, so branch-to-ret skew is not a concern here.)
|
||||
dnlib.DotNet.Parameter[] outParams = method.Parameters
|
||||
.Where(p => !p.IsHiddenThisParameter && p.Type.FullName == "System.Byte[]&")
|
||||
.ToArray();
|
||||
if (outParams.Length > 0)
|
||||
{
|
||||
Instruction[] rets = method.Body.Instructions.Where(i => i.OpCode == OpCodes.Ret).ToArray();
|
||||
foreach (Instruction ret in rets)
|
||||
{
|
||||
var exit = new List<Instruction>();
|
||||
foreach (dnlib.DotNet.Parameter op in outParams)
|
||||
{
|
||||
exit.Add(Instruction.Create(OpCodes.Ldstr, $"{type.Name}.{method.Name}.{op.Name}.out"));
|
||||
exit.Add(Instruction.Create(OpCodes.Ldarg, op));
|
||||
exit.Add(Instruction.Create(OpCodes.Ldind_Ref));
|
||||
exit.Add(Instruction.Create(OpCodes.Call, logByteArray));
|
||||
}
|
||||
int retIndex = method.Body.Instructions.IndexOf(ret);
|
||||
foreach (Instruction instruction in ((IEnumerable<Instruction>)exit).Reverse())
|
||||
{
|
||||
method.Body.Instructions.Insert(retIndex, instruction);
|
||||
}
|
||||
}
|
||||
method.Body.MaxStack = (ushort)Math.Max((int)method.Body.MaxStack, 8);
|
||||
foreach (dnlib.DotNet.Parameter op in outParams)
|
||||
{
|
||||
instrumented.Add(new
|
||||
{
|
||||
Type = type.Name.String,
|
||||
Method = method.Name.String,
|
||||
Phase = $"{type.Name}.{method.Name}.{op.Name}.out",
|
||||
Direction = "out",
|
||||
Token = "0x" + method.MDToken.Raw.ToString("X8"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user