我有一堆别名用于访问代码中的全局调试变量,它们看起来像这样:
aS _dbg_log_last "dx mymodule!g_dbg_variable_with_a_long_name->logger.log_buffer[mymodule!g_dbg_variable_with_a_long_name->logger.size - 1]"
我显然不喜欢最后一个重复的内容,所以我尝试将其重构为以下内容:
aS _dbg_log "mymodule!g_dbg_variable_with_a_long_name->logger"
aS _dbg_log_last "dx ${_dbg_log} .log_buffer[${_dbg_log}.size - 1]"
如果我复制
_dbg_log_last
别名的内容并手动运行它,一切都会正常。但如果我真的尝试调用它,我会收到错误:
错误:{_dbg_log} 处出现意外标记...
所以看起来它在执行别名时吞下了
$
字符。我也尝试过取消引用其中一个或两个别名,使用 as
而不是 aS
,向别名解释器添加 /f
和其他标志,用 $
或 \$
转义 $$
,没有任何效果。
最小重现:
aS _foo "1"
aS _bar "dx ${_foo} ,x"
dx ${_foo} ,x
_bar
预期:
1 ,x : 0x1
1 ,x : 0x1
实际:
1 ,x : 0x1
Error: Unexpected token at '{_foo} ,x'
我无法直接回答你的问题,我推测问题在于你正在使用“旧”alias方案和新的
dx
(对象模型表达式)。
只使用新的 dx 命令会更容易。这是一个简单的重现示例:
#include <iostream>
typedef struct Logger
{
unsigned fooLogger;
unsigned barLogger;
unsigned size;
const char* log_buffer[1];
} Logger;
typedef struct MyStruct
{
unsigned foo;
unsigned bar;
Logger logger;
} MyStruct;
MyStruct* g_dbg_variable_with_a_long_name;
void DumpStruct()
{
std::printf("foo: 0x%08x\n", g_dbg_variable_with_a_long_name->foo);
std::printf("bar: 0x%08x\n", g_dbg_variable_with_a_long_name->bar);
std::printf("fooLogger: 0x%08x\n", g_dbg_variable_with_a_long_name->logger.fooLogger);
std::printf("barLogger: 0x%08x\n", g_dbg_variable_with_a_long_name->logger.barLogger);
std::printf("size: %d\n", g_dbg_variable_with_a_long_name->logger.size);
for (unsigned i = 0; i < g_dbg_variable_with_a_long_name->logger.size; i++)
{
std::printf("log_buffer[%d]: %s\n", i, g_dbg_variable_with_a_long_name->logger.log_buffer[i]);
}
}
int main(void)
{
MyStruct myStruct;
myStruct.foo = 0x12345678;
myStruct.bar = 0xdeadbeef;
myStruct.logger.fooLogger = 0x11111111;
myStruct.logger.barLogger = 0x22222222;
myStruct.logger.size = 2;
myStruct.logger.log_buffer[0] = "Hello";
myStruct.logger.log_buffer[1] = "World";
g_dbg_variable_with_a_long_name = &myStruct;
DumpStruct();
return 0;
}
在
DumpStruct
上设置一个 BP(这个想法是有一个已知结构被初始化的点;是的,它是用局部初始化的全局......)。
bp test!DumpStruct
现在,使用
dx
分配您想要的内容(而不是通过 sa
别名):
dx @$_dbg_log = test!g_dbg_variable_with_a_long_name->logger
dx @$_dbg_log_last = @$_dbg_log.log_buffer[@$_dbg_log.size - 1]
(旁注:这些分配在技术上是对调试器寄存器进行的,您可以使用
dx @$vars
获取它们;只是不要忘记它们带有 @$
前缀,这可能是您的情况下 dx 命令的混乱根源) .
输出:
0:000> dx @$vars
@$vars
_dbg_log [Type: Logger]
_dbg_log_last : 0x7ff7af61aca8 : "World" [Type: char *]
0:000> dx @$_dbg_log
@$_dbg_log [Type: Logger]
[+0x000] fooLogger : 0x11111111 [Type: unsigned int]
[+0x004] barLogger : 0x22222222 [Type: unsigned int]
[+0x008] size : 0x2 [Type: unsigned int]
[+0x010] log_buffer [Type: char * [1]]
0:000> dx @$_dbg_log_last
@$_dbg_log_last : 0x7ff7af61aca8 : "World" [Type: char *]
87 'W' [Type: char]
$$ same as:
0:000> dx @$_dbg_log_last,s
@$_dbg_log_last,s : 0x7ff7af61aca8 : "World" [Type: char *]
87 'W' [Type: char]
你也可以做一些不同的事情:
0:000> dx @$first = 0
@$first = 0 : 0
0:000> dx @$last = @$_dbg_log.size - 1
@$last = @$_dbg_log.size - 1 : 0x1
0:000> dx @$_dbg_log.log_buffer[@$first]
@$_dbg_log.log_buffer[@$first] : 0x7ff7af61aca0 : "Hello" [Type: char *]
72 'H' [Type: char]
0:000> dx @$_dbg_log.log_buffer[@$last]
@$_dbg_log.log_buffer[@$last] : 0x7ff7af61aca8 : "World" [Type: char *]
87 'W' [Type: char]
或一次性记录所有内容:
(注意:由于缓冲区仅用一个元素声明,因此我们需要告诉 Windbg 表有多少元素;这是无法传递变量的少数情况之一......我们需要在这里传递一个标量)
0:000> dx *(char* (*)[2])@$_dbg_log.log_buffer
*(char* (*)[2])@$_dbg_log.log_buffer [Type: char * [2]]
[0] : 0x7ff7af61aca0 : "Hello" [Type: char *]
[1] : 0x7ff7af61aca8 : "World" [Type: char *]
$$ !!! DOES NOT WORK !!! :(
0:000> dx *(char* (*)[@$_dbg_log.size])@$_dbg_log.log_buffer
Error: Unexpected token at '@$_dbg_log.size])@$_dbg_log.log_buffer'