如果您只需要打印一个常量值,py print(expr128) 的想法非常有效,因为 Python 具有任意整数精度。
但是,如果您需要使用 __int128 类型的实际 C 变量,则需要将其临时转换为 unsigned long long[2] 之类的东西,以便在 GDB 中对其执行操作,但请记住,您是然后使用 2 个 64 位值的数组,因此 X[0] << 64 不会像使用真正的 128 位 __int128 类型那样工作。 GDB可以打印值;它只是无法操纵它的位。 GCC 允许你操作它的位;您的 libc 无法使用 printf 打印该值,甚至可能没有任何 GCC 特定的代码允许它这样做。
这是一个示例 shell 会话,显示了在 GDB 中使用这种特定于编译器的类型是多么麻烦:
$ nl bar.c
1 int main(void)
2 {
3 __int128 v = 1;
4 v <<= 62;
5 v <<= 2;
6 }
$ gcc -g -o bar bar.c
$ gdb -q ./bar
Reading symbols from ./bar...done.
(gdb) break 5
Breakpoint 1 at 0x5e8: file bar.c, line 5.
(gdb) run
Starting program: /home/luser/bar
Breakpoint 1, main () at bar.c:5
5 v <<= 2;
(gdb) print/x *(long long(*)[2])&v
$1 = {0x4000000000000000, 0x0}
(gdb) print/x (*(long long(*)[2])&v)[0]+1
$2 = {0x4000000000000001, 0x0}
(gdb) next
6 }
(gdb) print/x *(long long(*)[2])&v
$3 = {0x0, 0x1}
(gdb) print/x (*(long long(*)[2])&v)[0]+1
$4 = {0x1, 0x1}
考虑到我机器的小端 CPU,结果(有点)清楚:
$1 = 0x0000 0000 0000 0000
4000 0000 0000 0000 # 1<<62
$2 = 0x0000 0000 0000 0000
4000 0000 0000 0001 #(1<<62) + 1
$3 = 0x0000 0000 0000 0001
0000 0000 0000 0000 # 1<<64
$4 = 0x0000 0000 0000 0001
0000 0000 0000 0001 #(1<<64) + 1
对于这么大的值,即使是十六进制也变得有点麻烦,但您明白了:在 GDB 中使用这些值可能是您需要处理的所有括号的问题,而且您需要保留在操作值以及跟踪溢出时要考虑目标机器的字节顺序。
我的建议:链接一些与__int128 值一起使用的算术例程以帮助调试,因此您可以在GDB 中使用call negate128 (value) 之类的东西来获取C 表达式-value 的结果,其中value 具有类型__int128。也不需要溢出检查,因为机器会像处理任何其他类型一样为您处理,所以继续写这样的东西(假设您正在使用溢出不会杀死您的程序或整个系统的系统)机器):
__int128 add128(__int128 a, __int128 b) { return a + b; }
__int128 sub128(__int128 a, __int128 b) { return a - b; }
__int128 shl128(__int128 a, int n) { return a << n; }
__int128 shr128(__int128 a, int n) { return a >> n; }