核心文件内存分析验证
core file memory analysis verification
应用程序正在生成核心文件。
这是核心信息。
已获取错误堆栈,objective 将检查 myStruct 变量中的数据内容,因为这是在核心发生时传递到 myFunction 的内容。
(gdb) where
#0 0x000000000041bba1 in myFunction (myStruct=0x7ffff9dd0c20) at myTest.c:344
:
:
:
从上面我得到了myStruct的地址0x7ffff9dd0c20并转储了200个字。
(gdb) x/200x 0x7ffff9dd0c20
0x7ffff9dd0c20: 0x01938640 0x00000000 0x00001c34 0x000002c8
0x7ffff9dd0c30: 0x00000400 0x00000000 0x01939760 0x00000000
0x7ffff9dd0c40: 0x00000014 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c50: 0x00000000 0x0005000c 0x00000000 0x000d0000
0x7ffff9dd0c60: 0x00000004 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c70: 0x00000000 0x00000000 0x00040000 0x00000000
0x7ffff9dd0c80: 0x0001000c 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c90: 0x00000000 0x00000000 0x00000009 0x00000000
0x7ffff9dd0ca0: 0x00000000 0x00000000 0x410d999a 0x418d999a
0x7ffff9dd0cb0: 0x40b80000 0x41380000 0x000010cc 0x00000000
0x7ffff9dd0cc0: 0x0192edd0 0x00000000 0x00000a30 0x00000158
:
:
:
现在我想验证我是否正确读取数据输出。
这是结构信息。
typedef struct
{
char *a;
unsigned int b;
unsigned int c;
int d;
} structA;
typedef struct
{
structA e;
char *f;
} myStruct; <----------This is what gets passed in and what I am trying to examine.
正在处理 Linux,一个程序正在 运行 验证数据类型大小。
Size of char* : 8
Size of int : 4
知道地址是0x7ffff9dd0c20,结构是myStruct,我假设
我从分析 structA 开始,因为它是第一个。
因为 char *a 是 structA 的第一部分,而 char * 是 2 个词,所以我看这个:
0x01938640 0x00000000
接下来基本上有 3 个整数(2 个无符号整数和 1 个整数),我从输出中看到了这些:
0x00001c34
0x000002c8
0x00000400
这让我回到 structB 和 char *f 属性,它应该是 2 个单词。
这是否意味着这是正确的地址:
0x00000000 0x01939760
为了方便参考,我又把内存信息复制了一遍
(gdb) x/200x 0x7ffff9dd0c20
0x7ffff9dd0c20: 0x01938640 0x00000000 0x00001c34 0x000002c8
0x7ffff9dd0c30: 0x00000400 0x00000000 0x01939760 0x00000000
0x7ffff9dd0c40: 0x00000014 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c50: 0x00000000 0x0005000c 0x00000000 0x000d0000
0x7ffff9dd0c60: 0x00000004 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c70: 0x00000000 0x00000000 0x00040000 0x00000000
0x7ffff9dd0c80: 0x0001000c 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c90: 0x00000000 0x00000000 0x00000009 0x00000000
0x7ffff9dd0ca0: 0x00000000 0x00000000 0x410d999a 0x418d999a
0x7ffff9dd0cb0: 0x40b80000 0x41380000 0x000010cc 0x00000000
0x7ffff9dd0cc0: 0x0192edd0 0x00000000 0x00000a30 0x00000158
这是检查和解析数据的正确方法吗?
这里是另一种结构的定义。
typedef struct
{
short w;
unsigned long x;
short y;
short z;
} otherStruct;
这是预期存储在 f 中的内容。
char *f;
在 gdb 中,我尝试了以下操作:
p (otherStruct *)0x1939760
它打印出来:
= (otherStruct *) 0x1939760
奇怪的是,当我最初打印数据时,它显示 *f 如下所示,它看起来不像结构:
f = 0x1939760 "544@"
您正在以艰难的方式阅读数据。 gdb 知道结构定义,所以你可以告诉它使用 p
命令直接打印结构。
例如,假设此代码使用您的结构:
int main()
{
myStruct s = { { "aaa", 4, 5, 6 }, "bbb" };
printf("hello\n");
}
运行gdb下的代码:
(gdb) start
Temporary breakpoint 1 at 0x400535: file x1.c, line 19.
Starting program: /home/dbush/./x1
Temporary breakpoint 1, main () at x1.c:19
19 myStruct s = { { "aaa", 4, 5, 6 }, "bbb" };
Missing separate debuginfos, use: debuginfo-install glibc-2.17-292.el7.x86_64
(gdb) step
20 printf("hello\n");
(gdb) p s
= {e = {a = 0x400600 "aaa", b = 4, c = 5, d = 6}, f = 0x400604 "bbb"}
(gdb)
关于实际上包含 otherStruct *
的字段 f
,您可以通过强制转换 f
并取消引用结果来打印其中包含的内容:
p *(otherStruct *)myStruct->f
也就是说,您没有考虑结构中的填充。因为 structA
包含一个大小为 8 字节的 char *
,所以结构必须在 8 字节边界上对齐。查看布局,这意味着 4 个字节的填充位于结构的末尾。
因此转储中的第 6 个 32 位字 (0x00000000) 实际上就是那个填充。所以组成f
的字节实际上是0x01939760 0x00000000
.
查看上面示例代码的转储:
(gdb) p s
= {e = {a = 0x400600 "aaa", b = 4, c = 5, d = 6}, f = 0x400604 "bbb"}
(gdb) p &s
= (myStruct *) 0x7fffffffde50
(gdb) x/20x 0x7fffffffde50
0x7fffffffde50: 0x00400600 0x00000000 0x00000004 0x00000005
0x7fffffffde60: 0x00000006 0x00007fff 0x00400604 0x00000000
0x7fffffffde70: 0x00000000 0x00000000 0xf7a2f505 0x00007fff
0x7fffffffde80: 0x00000000 0x00000000 0xffffdf58 0x00007fff
0x7fffffffde90: 0x00000000 0x00000001 0x0040052d 0x00000000
您可以看到 e
字段中的值与原始转储匹配。
接下来您会看到填充字节,在本例中其值为 0x00007fff
。接下来的 8 个字节匹配 f
.
的值
应用程序正在生成核心文件。
这是核心信息。
已获取错误堆栈,objective 将检查 myStruct 变量中的数据内容,因为这是在核心发生时传递到 myFunction 的内容。
(gdb) where
#0 0x000000000041bba1 in myFunction (myStruct=0x7ffff9dd0c20) at myTest.c:344
:
:
:
从上面我得到了myStruct的地址0x7ffff9dd0c20并转储了200个字。
(gdb) x/200x 0x7ffff9dd0c20
0x7ffff9dd0c20: 0x01938640 0x00000000 0x00001c34 0x000002c8
0x7ffff9dd0c30: 0x00000400 0x00000000 0x01939760 0x00000000
0x7ffff9dd0c40: 0x00000014 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c50: 0x00000000 0x0005000c 0x00000000 0x000d0000
0x7ffff9dd0c60: 0x00000004 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c70: 0x00000000 0x00000000 0x00040000 0x00000000
0x7ffff9dd0c80: 0x0001000c 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c90: 0x00000000 0x00000000 0x00000009 0x00000000
0x7ffff9dd0ca0: 0x00000000 0x00000000 0x410d999a 0x418d999a
0x7ffff9dd0cb0: 0x40b80000 0x41380000 0x000010cc 0x00000000
0x7ffff9dd0cc0: 0x0192edd0 0x00000000 0x00000a30 0x00000158
:
:
:
现在我想验证我是否正确读取数据输出。
这是结构信息。
typedef struct
{
char *a;
unsigned int b;
unsigned int c;
int d;
} structA;
typedef struct
{
structA e;
char *f;
} myStruct; <----------This is what gets passed in and what I am trying to examine.
正在处理 Linux,一个程序正在 运行 验证数据类型大小。
Size of char* : 8
Size of int : 4
知道地址是0x7ffff9dd0c20,结构是myStruct,我假设 我从分析 structA 开始,因为它是第一个。
因为 char *a 是 structA 的第一部分,而 char * 是 2 个词,所以我看这个:
0x01938640 0x00000000
接下来基本上有 3 个整数(2 个无符号整数和 1 个整数),我从输出中看到了这些:
0x00001c34
0x000002c8
0x00000400
这让我回到 structB 和 char *f 属性,它应该是 2 个单词。
这是否意味着这是正确的地址:
0x00000000 0x01939760
为了方便参考,我又把内存信息复制了一遍
(gdb) x/200x 0x7ffff9dd0c20
0x7ffff9dd0c20: 0x01938640 0x00000000 0x00001c34 0x000002c8
0x7ffff9dd0c30: 0x00000400 0x00000000 0x01939760 0x00000000
0x7ffff9dd0c40: 0x00000014 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c50: 0x00000000 0x0005000c 0x00000000 0x000d0000
0x7ffff9dd0c60: 0x00000004 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c70: 0x00000000 0x00000000 0x00040000 0x00000000
0x7ffff9dd0c80: 0x0001000c 0x00000000 0x00000000 0x00000000
0x7ffff9dd0c90: 0x00000000 0x00000000 0x00000009 0x00000000
0x7ffff9dd0ca0: 0x00000000 0x00000000 0x410d999a 0x418d999a
0x7ffff9dd0cb0: 0x40b80000 0x41380000 0x000010cc 0x00000000
0x7ffff9dd0cc0: 0x0192edd0 0x00000000 0x00000a30 0x00000158
这是检查和解析数据的正确方法吗?
这里是另一种结构的定义。
typedef struct
{
short w;
unsigned long x;
short y;
short z;
} otherStruct;
这是预期存储在 f 中的内容。
char *f;
在 gdb 中,我尝试了以下操作:
p (otherStruct *)0x1939760
它打印出来:
= (otherStruct *) 0x1939760
奇怪的是,当我最初打印数据时,它显示 *f 如下所示,它看起来不像结构:
f = 0x1939760 "544@"
您正在以艰难的方式阅读数据。 gdb 知道结构定义,所以你可以告诉它使用 p
命令直接打印结构。
例如,假设此代码使用您的结构:
int main()
{
myStruct s = { { "aaa", 4, 5, 6 }, "bbb" };
printf("hello\n");
}
运行gdb下的代码:
(gdb) start
Temporary breakpoint 1 at 0x400535: file x1.c, line 19.
Starting program: /home/dbush/./x1
Temporary breakpoint 1, main () at x1.c:19
19 myStruct s = { { "aaa", 4, 5, 6 }, "bbb" };
Missing separate debuginfos, use: debuginfo-install glibc-2.17-292.el7.x86_64
(gdb) step
20 printf("hello\n");
(gdb) p s
= {e = {a = 0x400600 "aaa", b = 4, c = 5, d = 6}, f = 0x400604 "bbb"}
(gdb)
关于实际上包含 otherStruct *
的字段 f
,您可以通过强制转换 f
并取消引用结果来打印其中包含的内容:
p *(otherStruct *)myStruct->f
也就是说,您没有考虑结构中的填充。因为 structA
包含一个大小为 8 字节的 char *
,所以结构必须在 8 字节边界上对齐。查看布局,这意味着 4 个字节的填充位于结构的末尾。
因此转储中的第 6 个 32 位字 (0x00000000) 实际上就是那个填充。所以组成f
的字节实际上是0x01939760 0x00000000
.
查看上面示例代码的转储:
(gdb) p s
= {e = {a = 0x400600 "aaa", b = 4, c = 5, d = 6}, f = 0x400604 "bbb"}
(gdb) p &s
= (myStruct *) 0x7fffffffde50
(gdb) x/20x 0x7fffffffde50
0x7fffffffde50: 0x00400600 0x00000000 0x00000004 0x00000005
0x7fffffffde60: 0x00000006 0x00007fff 0x00400604 0x00000000
0x7fffffffde70: 0x00000000 0x00000000 0xf7a2f505 0x00007fff
0x7fffffffde80: 0x00000000 0x00000000 0xffffdf58 0x00007fff
0x7fffffffde90: 0x00000000 0x00000001 0x0040052d 0x00000000
您可以看到 e
字段中的值与原始转储匹配。
接下来您会看到填充字节,在本例中其值为 0x00007fff
。接下来的 8 个字节匹配 f
.