[FAQ18316]增大minidump地址范围

来源:互联网 发布:金蝶软件数据导出 编辑:程序博客网 时间:2024/05/01 10:09
[DESCRIPTION]
minidump是发生KE会抓取内容的elf文件,用于gdb、trace32解析。因此minidump对KE是非常重要的。
不过minidump保存的内容有限,范围也有限,导致有些问题的分析无法深入。范围是只允许PAGE_OFFSET~high_memory。
对于vmalloc区域和mem_map区域就不会被保存,导致发生在vmalloc、page struct的问题无法深入。
这里将提供增大minidump地址范围的修改方法。
[SOLUTION]
1. 修改alps/kernel/drivers/misc/mediatek/aee/mrdump/mrdump_mini.c里的
[C/C++]hide
1
#define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < (void *)high_memory && pfn_valid(__pa(kaddr) >> PAGE_SHIFT))
修改为:
[C/C++]hide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#define virt_addr_valid(kaddr) pfn_valid(virt_2_pfn((unsigned long)(kaddr)))
#include <linux/uaccess.h>
static unsigned long virt_2_pfn(unsignedlong addr)
{
pgd_t *pgd = pgd_offset_k(addr), _pgd_val = {0};
pud_t *pud, _pud_val = {0};
pmd_t *pmd, _pmd_val = 0;
pte_t *ptep, _pte_val = 0;
unsignedlong pfn = ~0UL;
#ifdef CONFIG_ARM64
if(addr < VMALLOC_START)
returnpfn;
#endif
if(!probe_kernel_address(pgd, _pgd_val) && !pgd_none(_pgd_val)) {
pud = pud_offset(pgd, addr);
if(!probe_kernel_address(pud, _pud_val) && !pud_none(_pud_val)) {
pmd = pmd_offset(pud, addr);
if(!probe_kernel_address(pmd, _pmd_val) && !pmd_none(_pmd_val)) {
ptep = pte_offset_map(pmd, addr);
if(!probe_kernel_address(ptep, _pte_val) && pte_present(_pte_val))
pfn = pte_pfn(_pte_val);
pte_unmap(ptep);
}
}
}
returnpfn;
}
2. 用以下2个函数替换mrdump_mini_add_entry()函数:
[C/C++]hide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
static void mrdump_mini_add_entry_ext(unsigned longstart, unsigned longend, unsigned longpa)
{
unsignedlong laddr, haddr;
structelf_phdr *phdr;
inti;
for(i = 0; i < MRDUMP_MINI_NR_SECTION; i++) {
phdr = &mrdump_mini_ehdr->phdrs[i];
if(phdr->p_type == PT_NULL)
break;
if(phdr->p_type != PT_LOAD)
continue;
laddr = phdr->p_vaddr;
haddr = laddr + phdr->p_filesz;
if(start >= laddr && end <= haddr)
return;
if(start >= haddr || end <= laddr)
continue;
if(laddr < start) {
start = laddr;
pa = phdr->p_paddr;
}
if(haddr > end)
end = haddr;
break;
}
if(i < MRDUMP_MINI_NR_SECTION)
fill_elf_load_phdr(phdr, end - start, start, pa);
}
void mrdump_mini_add_entry(unsigned long addr, unsigned long size)
{
unsignedlong start = 0, __end, pa, end_pfn = 0, _pfn;
if(!pfn_valid(virt_2_pfn(addr)))
return;
for(addr = (addr - size / 2)&PAGE_MASK, __end = ALIGN(addr + size, PAGE_SIZE); addr < __end; addr += PAGE_SIZE) {
_pfn = virt_2_pfn(addr);
if(pfn_valid(_pfn)) {
if(!start || _pfn != end_pfn) {
if(start)
mrdump_mini_add_entry_ext(start, start + (__pfn_to_phys(end_pfn) - pa), pa);
start = addr;
pa = __pfn_to_phys(_pfn);
end_pfn = _pfn + 1;
}else {
end_pfn++;
}
}else {
if(start)
mrdump_mini_add_entry_ext(start, start + (__pfn_to_phys(end_pfn) - pa), pa);
start = 0;
}
}
if(start)
mrdump_mini_add_entry_ext(start, start + (__pfn_to_phys(end_pfn) - pa), pa);
}
3. 在mrdump_mini_add_loads()添加dump其他cpu寄存器信息,注意是在dump_all_cpus的if语句的下面而不是里面。
[C/C++]hide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
static void mrdump_mini_add_loads(void)
{
......
if(dump_all_cpus) {
......
}
/* add block start */
for(id = 0; id < NR_CPUS + 1; id++) {
if(!strncmp(mrdump_mini_ehdr->prstatus[id].name,"NA", 2))
continue;
prstatus = &mrdump_mini_ehdr->prstatus[id].data;
if(prstatus->pr_pid > NR_CPUS)
continue;
memcpy(&regs, &prstatus->pr_reg,sizeof(prstatus->pr_reg));
for(i = 0; i < ELF_NGREG; i++)
mrdump_mini_add_entry(((unsignedlong *)&regs)[i], MRDUMP_MINI_SECTION_SIZE);
}
/* add block end */
......
}
0 0