core文件分析
2015-06-10 19:52
381 查看
刚开通博客,想写博客很久了,今天终于开通了。先把之前写的学习笔记贴上来吧。
在程序运行出现segmentfault后,我们会通过gdb来调试core文件定位问题,下面我们来分析下core文件是什么?
首先需要明确的一点就是core文件也是ELF格式的,ELF的格式如下:
ELF文件参与程序的链接和运行,从链接的角度看有上面左边所示的Linking View,从程序运行的角度看为右边所示的Execution View(执行视图)。Core的ELF文件格式是按照执行视图的格式组织的。
下面是core文件的ELF头信息
以内核代码elf_core_dump函数为入口分析core文件怎么生成的:
elf_core_dump-àfill_note_info-àfill_elf_header
这里填入的ELF头信息就是用readelf –h读取到的。下面我们看下生成的core文件
、
上面表格中是core文件的ELF头的详细信息,分别用不同的颜色表明了不同的成员值。
从上面信息可知,core文件程序头表从0x34位置开始,每个程序头表的大小为32字节
下面看下core文件程序头表的信息
截图只是程序头表的部分信息,因为有161个程序头表这里无法全部显示。
分析下core文件中第一个程序头表的信息,第一个程序头表的偏移是0x34
上面表格中是第一个程序头表的详细信息,分别用不同的颜色表明了不同的成员值。
从上面的程序头表信息可知,第一个段类型为NOTE段,偏移为0x1454,大小为0x3904。
PT_NOTE类型的段用于存放线程信息和寄存器信息。由于PT_NOTE段是辅助信息,不存在与内存中。
那么PT_NOTE段信息是怎么存储的呢?
去内核中看下相应代码fill_note_info函数
fill_note_info函数代码片段:
接着分析elf_dump_thread_status函数
elf_dump_thread_status函数代码:
上面就是填充PT_NOTE段的主要代码流程,回过头来我们看下PT_NOTE段的数据结构:
下面分析core文件的PT_NOTE段信息:
上面的寄存器信息正好与gdb看到的寄存器信息一致
上面只是分析了PT_NOTE段的一部分,我们定位coredump的问题也不需要这样脑神费力的分析二进制core文件。
在程序运行出现segmentfault后,我们会通过gdb来调试core文件定位问题,下面我们来分析下core文件是什么?
首先需要明确的一点就是core文件也是ELF格式的,ELF的格式如下:
ELF文件参与程序的链接和运行,从链接的角度看有上面左边所示的Linking View,从程序运行的角度看为右边所示的Execution View(执行视图)。Core的ELF文件格式是按照执行视图的格式组织的。
下面是core文件的ELF头信息
以内核代码elf_core_dump函数为入口分析core文件怎么生成的:
elf_core_dump-àfill_note_info-àfill_elf_header
static void fill_elf_header(struct elfhdr *elf, int segs, u16 machine, u32 flags, u8 osabi) { memset(elf, 0, sizeof(*elf)); memcpy(elf->e_ident, ELFMAG, SELFMAG); elf->e_ident[EI_CLASS] = ELF_CLASS; elf->e_ident[EI_DATA] = ELF_DATA; elf->e_ident[EI_VERSION] = EV_CURRENT; elf->e_ident[EI_OSABI] = ELF_OSABI; elf->e_type = ET_CORE; elf->e_machine = machine; elf->e_version = EV_CURRENT; elf->e_phoff = sizeof(struct elfhdr); elf->e_flags = flags; elf->e_ehsize = sizeof(struct elfhdr); elf->e_phentsize = sizeof(struct elf_phdr); elf->e_phnum = segs; return; |
、
上面表格中是core文件的ELF头的详细信息,分别用不同的颜色表明了不同的成员值。
成员 | 值 | 含义 |
e_ident | "\177ELF" | magic |
0x1 | ELF32 | |
0x1 | 2's complement, little endian | |
0x1 | 1 (current) | |
0 | UNIX - System V | |
0 | ||
e_type | 4 | ELF类型,ET_CORE表示为core文件 |
e_machine | 0x28 | ELF文件的平台属性 |
e_version | 1 | |
e_entry | 0 | ELF程序的入口虚拟地址 |
e_phoff | 0x34 | 程序头表的偏移,程序头从0x34开始,紧跟在ELF头后面 |
e_shoff | 0 | |
e_flags | 0 | |
e_ehsize | 0x34 | ELF文件头本身的大小,52字节 |
e_phentsize | 0x20 | 每个程序头占用的大小为32字节 |
e_phnum | 0xa1 | 程序头表的个数,161个 |
e_shentsize | 0 | 段描述符的大小 |
e_shnum | 0 | 段描述符的个数 |
e_shstrndx | 0 |
下面看下core文件程序头表的信息
截图只是程序头表的部分信息,因为有161个程序头表这里无法全部显示。
typedef struct elf32_phdr{ Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align; } Elf32_Phdr; |
上面表格中是第一个程序头表的详细信息,分别用不同的颜色表明了不同的成员值。
成员 | 值 | 含义 |
p_type | 0x4 | 段的类型,这里为PT_NOTE |
p_offset | 0x1454 | 段的位置相对于文件开始的偏移 |
p_vaddr | 0 | 段在内存中的首字节地址 |
p_paddr | 0 | |
p_filesz | 0x3904 | 段在文件映像栈的字节数 |
p_memsz | 0 | 段在内存映像中的字节数 |
p_flags | 0 | |
p_align | 0 |
PT_NOTE类型的段用于存放线程信息和寄存器信息。由于PT_NOTE段是辅助信息,不存在与内存中。
那么PT_NOTE段信息是怎么存储的呢?
去内核中看下相应代码fill_note_info函数
fill_note_info函数代码片段:
//首先将所有的线程加入到info-> thread_list for (ct = current->mm->core_state->dumper.next; ct; ct = ct->next) { ets = kzalloc(sizeof(*ets), GFP_KERNEL); if (!ets) return 0; ets->thread = ct->task; list_add(&ets->list, &info->thread_list); } //遍历链表,调用elf_dump_thread_status保存线程的信息 list_for_each(t, &info->thread_list) { int sz; ets = list_entry(t, struct elf_thread_status, list); sz = elf_dump_thread_status(signr, ets); info->thread_status_size += sz; } |
elf_dump_thread_status函数代码:
static int elf_dump_thread_status(long signr, struct elf_thread_status *t) { int sz = 0; struct task_struct *p = t->thread; t->num_notes = 0; fill_prstatus(&t->prstatus, p, signr); //获取线程的状态,包括signal和pid等 elf_core_copy_task_regs(p, &t->prstatus.pr_reg); //获取线程的寄存器信息 fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), &(t->prstatus)); //将信息存入memelfnote的notes数组中 t->num_notes++; sz += notesize(&t->notes[0]); … return sz; } |
/* Note header in a PT_NOTE section */ typedef struct elf32_note { Elf32_Word n_namesz; /* Name size */ Elf32_Word n_descsz; /* Content size */ Elf32_Word n_type; /* Content type */ } Elf32_Nhdr; struct elf_note_info { struct memelfnote *notes; struct elf_prstatus *prstatus; /* NT_PRSTATUS */ struct elf_prpsinfo *psinfo; /* NT_PRPSINFO */ struct list_head thread_list; elf_fpregset_t *fpu; int thread_status_size; int numnote; }; |
上面的寄存器信息正好与gdb看到的寄存器信息一致
上面只是分析了PT_NOTE段的一部分,我们定位coredump的问题也不需要这样脑神费力的分析二进制core文件。
相关文章推荐
- oracle的oci和thin区别
- 认识自己——我所丧失的能力2
- Python之global
- tabBarItem动画
- MYSQL数据库学习十 单表数据记录查询
- MySql模糊查询like通配符简介
- git, github使用
- ubuntu开启 SSH服务
- httpwatch详解
- Group by与having理解(转)
- P269 3
- Windows 7修改时间命令
- csdn博客开通了 -_- |
- java实现简易计算器
- 第十四周 项目三--OOP版电子词典
- 单高斯背景建模
- codeforces 549C
- P269 2
- 各种在线手册
- Android的selector,背景选择器 以及.9.png