From dbc45587f2c0024f0bc801a967bed9bd8d9f218c Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Wed, 22 Feb 2023 14:32:09 +0800 Subject: [PATCH 78/89] Fix for "search -u" option failing in maple tree kernel Kernel with maple tree enabled doesn't have mmap as a member of mm_struct[1], so OFFSET(mm_struct_mmap) case needed to be handled differently for maple tree kernel. Before: crash> search -u a search: invalid structure member offset: mm_struct_mmap FILE: memory.c LINE: 14255 FUNCTION: address_space_start() [crash] error trace: 549500 => 548fff => 5f1c91 => 5f1c13 5f1c13: OFFSET_verify.part.36+51 5f1c91: OFFSET_verify+49 548fff: address_space_start+106 549500: cmd_search+855 search: invalid structure member offset: mm_struct_mmap FILE: memory.c LINE: 14255 FUNCTION: address_space_start() After: crash> search -u a 7ffea63e6440: a [1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763ecb035029f500d7e6dc99acd1ad299b7726a1 Signed-off-by: Tao Liu Signed-off-by: Lianbo Jiang --- memory.c | 89 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 24 deletions(-) diff --git a/memory.c b/memory.c index d9cd616f19de..c4a6ecd18004 100644 --- a/memory.c +++ b/memory.c @@ -14245,14 +14245,28 @@ vaddr_type(ulong vaddr, struct task_context *tc) static int address_space_start(struct task_context *tc, ulong *addr) { - ulong vma; + ulong mm_mt, entry_num, i, vma = 0; char *vma_buf; + struct list_pair *entry_list; if (!tc->mm_struct) return FALSE; - fill_mm_struct(tc->mm_struct); - vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); + if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) { + mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt); + entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL); + entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair)); + do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list); + for (i = 0; i < entry_num; i++) { + if (!!(vma = (ulong)entry_list[i].value)) + break; + } + FREEBUF(entry_list); + } else { + fill_mm_struct(tc->mm_struct); + vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); + } + if (!vma) return FALSE; vma_buf = fill_vma_cache(vma); @@ -15491,6 +15505,30 @@ search_physical(struct searchinfo *si) FREEBUF(pagebuf); } +static bool +check_vma(ulong vma, ulong vaddr, ulong *vm_next, ulong *nextvaddr) +{ + char *vma_buf; + ulong vm_start, vm_end; + + vma_buf = fill_vma_cache(vma); + + vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start)); + vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end)); + if (vm_next) + *vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); + + if (vaddr <= vm_start) { + *nextvaddr = vm_start; + return TRUE; + } + + if ((vaddr > vm_start) && (vaddr < vm_end)) { + *nextvaddr = vaddr; + return TRUE; + } + return FALSE; +} /* * Return the next mapped user virtual address page that comes after @@ -15500,37 +15538,40 @@ static int next_upage(struct task_context *tc, ulong vaddr, ulong *nextvaddr) { ulong vma, total_vm; - char *vma_buf; - ulong vm_start, vm_end; ulong vm_next; + ulong mm_mt, entry_num, i; + struct list_pair *entry_list; if (!tc->mm_struct) return FALSE; - fill_mm_struct(tc->mm_struct); - vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); + fill_mm_struct(tc->mm_struct); + vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */ total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm)); - - if (!vma || (total_vm == 0)) + if (!total_vm) return FALSE; - vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */ - - for ( ; vma; vma = vm_next) { - vma_buf = fill_vma_cache(vma); - - vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start)); - vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end)); - vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); - - if (vaddr <= vm_start) { - *nextvaddr = vm_start; - return TRUE; + if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) { + mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt); + entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL); + entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair)); + do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list); + for (i = 0; i < entry_num; i++) { + if (!!(vma = (ulong)entry_list[i].value) && + check_vma(vma, vaddr, NULL, nextvaddr)) { + FREEBUF(entry_list); + return TRUE; + } } + FREEBUF(entry_list); + } else { + vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap)); - if ((vaddr > vm_start) && (vaddr < vm_end)) { - *nextvaddr = vaddr; - return TRUE; + if (!vma) + return FALSE; + for ( ; vma; vma = vm_next) { + if (check_vma(vma, vaddr, &vm_next, nextvaddr)) + return TRUE; } } -- 2.37.1