in src/OpenDebugAD7/Tracepoint.cs [120:250]
private string InterpolateToken(string token, IDebugThread2 pThread, IDebugStackFrame2 topFrame, uint radix, string processName, int processId)
{
switch (token)
{
case "$FUNCTION":
{
int hr = topFrame.GetCodeContext(out IDebugCodeContext2 pCodeContext);
if (hr >= 0)
{
CONTEXT_INFO[] pInfo = new CONTEXT_INFO[1];
hr = pCodeContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION, pInfo);
if (hr >= 0)
{
return pInfo[0].bstrFunction;
}
}
return string.Format(CultureInfo.InvariantCulture, "<No Function Found>");
}
case "$ADDRESS":
{
int hr = topFrame.GetCodeContext(out IDebugCodeContext2 pCodeContext);
if (hr >= 0)
{
CONTEXT_INFO[] pInfo = new CONTEXT_INFO[1];
hr = pCodeContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, pInfo);
if (hr >= 0)
{
return pInfo[0].bstrAddress;
}
}
return string.Format(CultureInfo.InvariantCulture, "<No Address Found>");
}
case "$FILEPOS":
{
int hr = topFrame.GetDocumentContext(out IDebugDocumentContext2 pDocumentContext);
if (hr >= 0)
{
hr = pDocumentContext.GetName(enum_GETNAME_TYPE.GN_FILENAME, out string fileName);
if (hr >= 0)
{
TEXT_POSITION[] textPosBeg = new TEXT_POSITION[1];
TEXT_POSITION[] textPosEnd = new TEXT_POSITION[1];
hr = pDocumentContext.GetStatementRange(textPosBeg, textPosEnd);
if (hr >= 0)
{
return string.Format(CultureInfo.InvariantCulture, "{0}:{1}", fileName, textPosBeg[0].dwLine + 1);
}
}
}
return string.Format(CultureInfo.InvariantCulture, "<No File Position>");
}
case "$CALLER":
{
IEnumDebugFrameInfo2 frameInfoEnum;
int hr = pThread.EnumFrameInfo(enum_FRAMEINFO_FLAGS.FIF_FRAME | enum_FRAMEINFO_FLAGS.FIF_FLAGS, Constants.EvaluationRadix, out frameInfoEnum);
if (hr >= 0)
{
FRAMEINFO[] frames = new FRAMEINFO[2];
uint fetched = 0;
hr = frameInfoEnum.Next(2, frames, ref fetched);
if (hr < 0 && fetched == 2)
{
return frames[1].m_bstrFuncName;
}
}
return string.Format(CultureInfo.InvariantCulture, "<No Caller Avaliable>");
}
case "$TID":
{
int hr = pThread.GetThreadId(out uint threadId);
if (hr == 0)
{
if (radix == 16)
{
return string.Format(CultureInfo.InvariantCulture, "{0:X}", threadId);
}
else
{
return string.Format(CultureInfo.InvariantCulture, "{0}", threadId);
}
}
return string.Format(CultureInfo.InvariantCulture, "<No Thread Id>");
}
case "$TNAME":
{
int hr = pThread.GetName(out string name);
if (hr == 0)
{
return name;
}
return string.Format(CultureInfo.InvariantCulture, "<No Thread Name>");
}
case "$PID":
{
if (processId != Constants.InvalidProcessId)
{
return processId.ToString(CultureInfo.InvariantCulture);
}
return string.Format(CultureInfo.InvariantCulture, "<Unknown PID>", token);
}
case "$PNAME":
{
return processName;
}
case "$CALLSTACK":
{
IEnumDebugFrameInfo2 frameInfoEnum;
int hr = pThread.EnumFrameInfo(enum_FRAMEINFO_FLAGS.FIF_FRAME | enum_FRAMEINFO_FLAGS.FIF_FLAGS, Constants.EvaluationRadix, out frameInfoEnum);
int count = 0;
StringBuilder sb = new StringBuilder();
while (count < Constants.DefaultTracepointCallstackDepth)
{
FRAMEINFO[] frames = new FRAMEINFO[1];
uint fetched = 0;
hr = frameInfoEnum.Next(1, frames, ref fetched);
if (fetched == 1)
{
// TODO: Do we want function arguments?
frames[0].m_pFrame.GetName(out string name);
sb.AppendLine(name);
}
count++;
}
return sb.ToString();
}
case "$TICK":
return string.Format(CultureInfo.InvariantCulture, "{0}", Environment.TickCount);
default:
return string.Format(CultureInfo.InvariantCulture, "<Unknown Token: ${0}>", token);
}
}