【求助】汇编高手进
说一下背景,最近Android M的项目中在进行mtp拷贝时死机。 kernel panic ,dump出来的obj如下,我尝试着翻译了一下还是没看明白。希望达成的目标是将下面的指令对和具体的函数调用匹配上。
函数如下:
struct page *follow_page_mask(struct vm_area_struct *vma,
unsigned long address, unsigned int flags,
unsigned int *page_mask)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
spinlock_t *ptl;
struct page *page;
struct mm_struct *mm = vma->vm_mm;
*page_mask = 0;
page = follow_huge_addr(mm, address, flags & FOLL_WRITE);
if (!IS_ERR(page)) {
BUG_ON(flags & FOLL_GET);
return page;
}
pgd = pgd_offset(mm, address);
if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
return no_page_table(vma, flags);
pud = pud_offset(pgd, address);
if (pud_none(*pud))
return no_page_table(vma, flags);
if (pud_huge(*pud) && vma->vm_flags & VM_HUGETLB) {
page = follow_huge_pud(mm, address, pud, flags);
if (page)
return page;
return no_page_table(vma, flags);
}
if (unlikely(pud_bad(*pud)))
return no_page_table(vma, flags);
pmd = pmd_offset(pud, address);
if (pmd_none(*pmd))
return no_page_table(vma, flags);
if (pmd_huge(*pmd) && vma->vm_flags & VM_HUGETLB) {
page = follow_huge_pmd(mm, address, pmd, flags);
if (page)
return page;
return no_page_table(vma, flags);
}
if ((flags & FOLL_NUMA) && pmd_numa(*pmd))
return no_page_table(vma, flags);
if (pmd_trans_huge(*pmd)) {
if (flags & FOLL_SPLIT) {
split_huge_page_pmd(vma, address, pmd);
return follow_page_pte(vma, address, pmd, flags);
}
ptl = pmd_lock(mm, pmd);
if (likely(pmd_trans_huge(*pmd))) {
if (unlikely(pmd_trans_splitting(*pmd))) {
spin_unlock(ptl);
wait_split_huge_page(vma->anon_vma, pmd);
} else {
page = follow_trans_huge_pmd(vma, address,
pmd, flags);
spin_unlock(ptl);
*page_mask = HPAGE_PMD_NR - 1;
return page;
}
} else
spin_unlock(ptl);
}
return follow_page_pte(vma, address, pmd, flags);
}
ffffffc00018e9b4 <__get_user_pages.part.22>:
ffffffc00018e724: a9b97bfd stp x29, x30, [sp,#-112]! //将x29 x30 存储器的数据地址存储到sp-112 并将sp-112地址存储到sp
ffffffc00018e728: 910003fd mov x29, sp //将栈指针移动到存储器x29里
ffffffc00018e72c: a90153f3 stp x19, x20, [sp,#16] //将x19 x20 存储器的数据地址存储到sp+16
ffffffc00018e730: a9025bf5 stp x21, x22, [sp,#32] //将x21 x22 存储器的数据地址存储到sp+32
ffffffc00018e734: a9046bf9 stp x25, x26, [sp,#64] //将x25 x26 存储器的数据地址存储到sp+64
ffffffc00018e738: a90363f7 stp x23, x24, [sp,#48] //将x23 x24 存储器的数据地址存储到sp+48
ffffffc00018e73c: a90573fb stp x27, x28, [sp,#80] //将x27 x28 存储器的数据地址存储到sp+80
ffffffc00018e740: aa0003f5 mov x21, x0 //将x0存储器内容移动到x21中
ffffffc00018e744: aa0103fa mov x26, x1 //将x1存储器内容移动到x26中
ffffffc00018e748: f9402000 ldr x0, [x0,#64] //将x0+64后的内容读入到x0
ffffffc00018e74c: d35e9821 ubfx x1, x1, #30, #9 //?
ffffffc00018e750: b900007f str wzr, [x3] //丢弃结果?也许是
ffffffc00018e754: 2a0203f4 mov w20, w2 //移动w2到w20
ffffffc00018e758: f9402000 ldr x0, [x0,#64] //将寄存器x0+64的字数据后读入到x0
ffffffc00018e75c: f8617800 ldr x0, [x0,x1,lsl #3] //将存储器地址为x0+x1*3的字数据读入寄存器x0
ffffffc00018e760: b4001060 cbz x0, ffffffc00018e96c <follow_page_mask+0x248> x0的字数句为0进行跳转
ffffffc00018e764: 36081040 tbz w0, #1, ffffffc00018e96c <follow_page_mask+0x248>
ffffffc00018e768: d000c393 adrp x19, ffffffc001a00000 <reset_devices>
ffffffc00018e76c: 92748c00 and x0, x0, #0xfffffffff000
ffffffc00018e770: b25a67f7 mov x23, #0xffffffc000000000 // #-274877906944
ffffffc00018e774: f943de61 ldr x1, [x19,#1976] //将x19+1976字数据读入寄存器x1
ffffffc00018e778: cb010000 sub x0, x0, x1 //x0 = x0 -x1
ffffffc00018e77c: d3557741 ubfx x1, x26, #21, #9 //?
ffffffc00018e780: 8b170000 add x0, x0, x23 //x0 = x0 + x23
ffffffc00018e784: d37df021 lsl x1, x1, #3 //lsl alias ubfm ?
ffffffc00018e788: 8b010019 add x25, x0, x1 //x25 = x1 + 3
ffffffc00018e78c: f8616800 ldr x0, [x0,x1] //将寄存器地址为x0 + x1的字数据读入到x0
ffffffc00018e790: b4000ee0 cbz x0, ffffffc00018e96c <follow_page_mask+0x248> //条件跳转
ffffffc00018e794: f94022a0 ldr x0, [x21,#64] //将地址为x21+64的字数据读入到寄存器x0
ffffffc00018e798: d34c5358 ubfx x24, x26, #12, #9 //?
ffffffc00018e79c: f90037a0 str x0, [x29,#104] //x0的字数据写入x29+104
ffffffc00018e7a0: d280161b mov x27, #0xb0 // #176
ffffffc00018e7a4: d37df300 lsl x0, x24, #3 //ubfm
ffffffc00018e7a8: 1216005c and w28, w2, #0x400 //w2与上0x400
ffffffc00018e7ac: f90033a0 str x0, [x29,#96] //x0的字数据写入到x29+400
ffffffc00018e7b0: f9400320 ldr x0, [x25] //x25的字数据读入x0
ffffffc00018e7b4: 36080dc0 tbz w0, #1, ffffffc00018e96c <follow_page_mask+0x248>
ffffffc00018e7b8: f943de61 ldr x1, [x19,#1976] // x19+1976读入到x1
ffffffc00018e7bc: 92748c02 and x2, x0, #0xfffffffff000 x2 = x0 与 0xfffffff000
ffffffc00018e7c0: d34cbc00 ubfx x0, x0, #12, #36 //?
ffffffc00018e7c4: cb0102e1 sub x1, x23, x1 //x1 = x23 -x1
ffffffc00018e7c8: 8b020038 add x24, x1, x2 //x24 = x1 + x2
ffffffc00018e7cc: d2a80002 mov x2, #0x40000000 // #1073741824
ffffffc00018e7d0: f2dff742 movk x2, #0xffba, lsl #32 //Move with Keep (extended immediate): Xt<pos+15:pos> = uimm16.
ffffffc00018e7d4: f2ffffe2 movk x2, #0xffff, lsl #48
ffffffc00018e7d8: 9b1b0800 madd x0, x0, x27, x2
ffffffc00018e7dc: f9401816 ldr x22, [x0,#48] //将寄存器地址x0+48的字数据读入寄存器x22
- STP Wt1, Wt2, addr
Store Pair Registers: stores two words from Wt1 and Wt2 to
memory addressed by addr.
- STP Xt1, Xt2, addr
Store Pair Registers (extended): stores two doublewords
from Xt1 and Xt2 to memory addressed by addr.
- UBFX Xd, Xn, #lsb, #width
Unsigned Bitfield Extract (extended): alias for UBFM Xd,Xn,#lsb,#(lsb+width-1).
Preferred for disassembly when s >= r.
- UBFM Xd, Xn, #r, #s
Unsigned Bitfield Move: if s>=r then Xd<s-r:0> = Xn<s:r>,
else Xd<32+s-r,32-r> = Xn<s:0>. Sets bits to the left and
right of the destination bitfield to zero.
- STR Xt, addr
Store Register (extended): stores doubleword from Xt to
memory addressed by addr.
寄存器r31是一个特殊的寄存器:
Zero Register: 在大多数情况下,作为源寄存器使用时, r31读出来的值 是0; 作为目标寄存器使用时, 丢弃结果。
WZR(word zero rigiser)或者XZR(64位)
- CBZ Xn, label
Compare and Branch Zero (extended): conditionally jumps to
label if Xn is equal to zero.
- TBZ Xn|Wn, #uimm6, label
Test and Branch Zero: conditionally jumps to label if bit
number uimm6 in register Xn is zero. The bit
number implies the width of the register, which may be
written and should be disassembled as Wn if
uimm6 is less than 32. Limited to a branch offset range
of ±32KiB.
- ADRP Xd, label
Address of Page: sign extends a 21-bit offset, shifts it
left by 12 and adds it to the value of the PC with its
bottom 12 bits cleared, writing the result to register Xd.
This computes the base address of the 4KiB aligned memory region
containing label, and is designed to be used in conjunction with a load, store or
ADD instruction which supplies the bottom 12 bits of the label’s address.
This permits positionindependent addressing of any location
within ±4GiB of the PC using two instructions, providing
that dynamic relocation is done with a minimum granularity of 4KiB
(i.e. the bottom 12 bits of the label’s address are
unaffected by the relocation). The term “page” is short-
hand for the 4KiB relocation granule,and is not necessarily
related to the virtual memory page size.
- LSL Xd, Xn, #uimm
Logical Shift Left (extended immediate): alias for
UBFM Xd,Xn,#((64-uimm)&63),#(63-uimm)
- MOVK Wt, #uimm16{, LSL #pos}
Move with Keep (immediate): Wt<pos+15:pos> = uimm16.
- MOVK Xt, #uimm16{, LSL #pos}
Move with Keep (extended immediate): Xt<pos+15:pos> = uimm16.