韩国保姆2_少女伦理电影_HD中文字幕在线观看,玩偶姐姐在线观看高清,8090新视觉电影免费播放在线观看,98蜜桃

沃趣科技技術(shù)社區(qū)
行業(yè)前沿信息一網(wǎng)打盡
技術(shù)社區(qū) > 故障分析|故障分析 | 系統(tǒng)崩潰分析小妙招

故障分析|故障分析 | 系統(tǒng)崩潰分析小妙招

2023年06月13日

前言



眾所周知,Linux系統(tǒng)可能會(huì)因?yàn)楫惓V噶睢⒃L問無效內(nèi)存地址、死鎖(soft lockup)等原因崩潰。而系統(tǒng)崩潰后,我們可以通過kdump將當(dāng)時(shí)的內(nèi)存信息dump下來并生成一個(gè)轉(zhuǎn)儲(chǔ)文件vmcore,同時(shí),crash工具可以幫助我們分析vmcore文件并找到問題所在。


本文將簡(jiǎn)單介紹「crash工具的安裝和常用命令」,并通過舉例講解如何使用crash工具定位內(nèi)核問題。



什么是crash工具


crash工具是Redhat提供的開源工具,主要用來離線分析Linux內(nèi)核轉(zhuǎn)存文件,它整合了gdb工具,可以查看堆棧,dmesg日志,內(nèi)核數(shù)據(jù)結(jié)構(gòu),反匯編等等,功能十分強(qiáng)大。



安裝crash工具

# 安裝crash工具
yum install crash
# 安裝debuginfo包
debuginfo-install kernel


# 運(yùn)行crash工具
crash /usr/lib/debug/lib/modules/<kernel>/vmlinux /var/crash/<timestamp>/vmcore


crash工具常用命令

1.jpg



CPU寄存器與函數(shù)棧幀結(jié)構(gòu)

在使用crash工具分析vmcore文件之前,我們還需要簡(jiǎn)單了解下CPU中的寄存器以及函數(shù)棧幀的結(jié)構(gòu),因?yàn)槎ㄎ粏栴}時(shí)我們經(jīng)常需要查看某個(gè)變量或參數(shù)的值,而這些線索往往就存在于寄存器或函數(shù)棧中,只有清楚了它們的作用和結(jié)構(gòu)才能準(zhǔn)確找到對(duì)應(yīng)的存放位置。除此之外還需要了解一些簡(jiǎn)單的匯編指令,大家可自行查詢。


x86-64寄存器作用

  • %rax : 存儲(chǔ)函數(shù)返回值

  • %rsp : 棧指針寄存器,指向棧頂

  • %rdi, %rsi, %rdx, %rcx, %r8, %r9 : 函數(shù)參數(shù),依次對(duì)應(yīng)param1, param2....

  • %rbx, %rbp, %r12~%r15 : 數(shù)據(jù)存儲(chǔ),遵循被調(diào)用者使用原則

  • %r10, %r11 : 數(shù)據(jù)存儲(chǔ),遵循調(diào)用者使用原則


被調(diào)用者使用原則:在函數(shù)調(diào)用時(shí),調(diào)用者不必保存這些寄存器的值而直接進(jìn)行子函數(shù)調(diào)用,進(jìn)入子函數(shù)后,子函數(shù)在覆蓋這些寄存器前,需要保存這些寄存器的值,即這些寄存器的值是由被調(diào)用者來保存和恢復(fù)的。 


調(diào)用者使用原則:在進(jìn)行子函數(shù)調(diào)用前,就需要由調(diào)用者提前保護(hù)好這些寄存器的值,保存方法通常是把寄存器的值壓入堆棧中,調(diào)用者保存完成后,在子函數(shù)中就可以隨意覆蓋這些寄存器的值了。


函數(shù)棧幀結(jié)構(gòu)

函數(shù)調(diào)用棧從高地址向下往低地址增長(zhǎng),其中rsp和rbp分別指向棧頂和棧底。在進(jìn)行函數(shù)調(diào)用時(shí),會(huì)將參數(shù)賦值到對(duì)應(yīng)寄存器中,同時(shí)將父函數(shù)的rbp地址壓棧,然后rsp賦值給rbp,隨后再依次將其他信息壓棧保存,這樣我們就可以通過bt -F命令再結(jié)合匯編指令,就可以知道被壓入棧中的信息了。

2.jpg





舉個(gè)栗子??


嘗試分析下面這個(gè)vmcore文件,我們先用crash工具打開vmcore文件,接著使用log或者bt命令查看最后的堆棧及寄存器信息。從第一行“unable to handle kernel paging request”,我們可以確定這是一個(gè)因?yàn)樵L問了非法地址引發(fā)crash的問題,接下來就需要定位這個(gè)非法地址是從哪里來的。


crash> log
[...]
[2221616.681792] BUG: unable to handle kernel paging request at 0000000000019600
[2221616.682227] IP: [<ffffffff810fdfa0>] native_queued_spin_lock_slowpath+0x110/0x200
[2221616.682565] PGD 0 
[2221616.682816] Oops: 0002 [#1] SMP 
[2221616.683060] Modules linked in: binfmt_misc nfsv3 rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache ipt_MASQUERADE nf_nat_masquerade_ipv4 xt_addrtype iptable_filter xt_nat iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack bonding emcpdm(POE) emcpgpx(POE) emcpmpx(POE) emcp(POE) vfat fat iTCO_wdt iTCO_vendor_support mxm_wmi dcdbas sb_edac edac_core intel_powerclamp coretemp intel_rapl iosf_mbi kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd pcspkr cdc_ether usbnet mii mei_me mei lpc_ich acpi_power_meter sg shpchp wmi ipmi_si ipmi_devintf ipmi_msghandler nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c sd_mod mgag200 i2c_algo_bit drm_kms_helper lpfc syscopyarea sysfillrect sysimgblt fb_sys_fops
[2221616.685213]  ttm drm crc32c_intel ahci i40e libahci crc_t10dif crct10dif_generic libata crct10dif_pclmul scsi_transport_fc megaraid_sas i2c_core scsi_tgt ptp pps_core crct10dif_common dm_mirror dm_region_hash dm_log dm_mod [last unloaded: emcpioc]
[2221616.686573] CPU: 39 PID: 101271 Comm: systemd-cgtop Tainted: P           OE  ------------   3.10.0-693.21.1.el7.x86_64 #1
[2221616.687011] Hardware name: Dell Inc. PowerEdge R630/02C2CP, BIOS 2.7.1 001/22/2018
[2221616.687509] task: ffff88158c812f70 ti: ffff88a4b502c000 task.ti: ffff88a4b502c000
[2221616.687982] RIP: 0010:[<ffffffff810fdfa0>]  [<ffffffff810fdfa0>] native_queued_spin_lock_slowpath+0x110/0x200
[2221616.688519] RSP: 0018:ffff88a4b502fdc8  EFLAGS: 00010006
[2221616.689011] RAX: 0000000000001fd4 RBX: ffffffff81abb3a0 RCX: 0000000001390000
[2221616.689520] RDX: 0000000000019600 RSI: 00000000fea18bd0 RDI: ffff88b68e104f98
[2221616.690044] RBP: ffff88a4b502fdc8 R08: ffff88befe2d9600 R09: 0000000000000000
[2221616.690618] R10: ffff8801bfc07300 R11: 0000000000000246 R12: 0000000000000000
[2221616.691175] R13: ffff88748b81be00 R14: ffffffff81318e90 R15: ffff88bed0d860c0
[2221616.691743] FS:  00007efd99b72740(0000) GS:ffff88befe2c0000(0000) knlGS:0000000000000000
[2221616.692299] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[2221616.692870] CR2: 0000000000019600 CR3: 0000009284026000 CR4: 00000000003607e0
[2221616.693498] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[2221616.694113] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[2221616.694719] Call Trace:
[2221616.695352]  [<ffffffff816a8ff4>] queued_spin_lock_slowpath+0xb/0xf
[2221616.695956]  [<ffffffff816b6758>] _raw_spin_lock_irq+0x28/0x30
[2221616.696615]  [<ffffffff81319654>] blkcg_print_blkgs+0x74/0xe0
[2221616.697260]  [<ffffffff8131f286>] cfqg_print_rwstat+0x36/0x40
[2221616.697899]  [<ffffffff8110cfd6>] cgroup_seqfile_show+0x76/0x80
[2221616.698527]  [<ffffffff8122ac87>] ? seq_buf_alloc+0x17/0x40
[2221616.699185]  [<ffffffff8122b1b0>] seq_read+0x110/0x3e0
[2221616.699849]  [<ffffffff812054ef>] vfs_read+0x9f/0x170
[2221616.700539]  [<ffffffff812063bf>] SyS_read+0x7f/0xe0
[2221616.701184]  [<ffffffff816c0715>] system_call_fastpath+0x1c/0x21
[2221616.701834] Code: 87 47 02 c1 e0 10 45 31 c9 85 c0 74 44 48 89 c2 c1 e8 13 48 c1 ea 0d 48 98 83 e2 30 48 81 c2 00 96 01 00 48 03 14 c5 a0 10 b2 81 <4c> 89 02 41 8b 40 08 85 c0 75 0f 0f 1f 44 00 00 f3 90 41 8b 40 
[2221616.703308] RIP  [<ffffffff810fdfa0>] native_queued_spin_lock_slowpath+0x110/0x200
[2221616.704014]  RSP <ffff88a4b502fdc8>
[2221616.704702] CR2: 0000000000019600



通常我們會(huì)先反匯編RIP寄存器中的指令,因?yàn)檫@是在系統(tǒng)崩潰時(shí)執(zhí)行的指令,是在執(zhí)行mov指令時(shí)出的問題。

crash> dis -lr ffffffff810fdfa0 | tail -n 10
/usr/src/debug/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/kernel/qspinlock.c: 107
0xffffffff810fdf85 <native_queued_spin_lock_slowpath+245>:  shr    $0x13,%eax
/usr/src/debug/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/kernel/qspinlock.c: 110
0xffffffff810fdf88 <native_queued_spin_lock_slowpath+248>:  shr    $0xd,%rdx
0xffffffff810fdf8c <native_queued_spin_lock_slowpath+252>:  cltq   
0xffffffff810fdf8e <native_queued_spin_lock_slowpath+254>:  and    $0x30,%edx
0xffffffff810fdf91 <native_queued_spin_lock_slowpath+257>:  add    $0x19600,%rdx
0xffffffff810fdf98 <native_queued_spin_lock_slowpath+264>:  add    -0x7e4def60(,%rax,8),%rdx
/usr/src/debug/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/include/linux/compiler.h: 208
0xffffffff810fdfa0 <native_queued_spin_lock_slowpath+272>:  mov    %r8,(%rdx)  <--- crashed here



在對(duì)應(yīng)版本的內(nèi)核代碼中,我們找到blkcg_print_blkgs這個(gè)函數(shù),在調(diào)用spin_lock_irq的地方看到自旋鎖是來自“blkcg_gq”結(jié)構(gòu)體,接下來我們希望找到blkg->q->queue_lock的地址,判斷這個(gè)地址是否有問題。


void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg,
            u64 (*prfill)(struct seq_file *,
                struct blkg_policy_data *, int),
            const struct blkcg_policy *pol, int data,
            bool show_total)
{
  struct blkcg_gq *blkg;
  u64 total = 0;

  rcu_read_lock();
  hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
     spin_lock_irq(blkg->q->queue_lock);
     if (blkcg_policy_enabled(blkg->q, pol))
        total += prfill(sf, blkg->pd[pol->plid], data);
     spin_unlock_irq(blkg->q->queue_lock);
  }
  rcu_read_unlock();

  if (show_total)
     seq_printf(sf, "Total %llu\n", (unsigned long long)total);
}



繼續(xù)用dis命令反匯編blkcg_print_blkgs的指令, 通過“l(fā)ea -0x18(%rcx),%r15”指令,我們可以知道blkg的地址存放在r15寄存器中。知道了blkg的地址,我們就可以找到最后queue_lock的地址啦。

crash> dis -lr ffffffff81319654 | tail -n 10
0xffffffff8131963c <blkcg_print_blkgs+92>:  test   %rcx,%rcx
0xffffffff8131963f <blkcg_print_blkgs+95>:  je     0xffffffff81319688 <blkcg_print_blkgs+168>
0xffffffff81319641 <blkcg_print_blkgs+97>:  lea    -0x18(%rcx),%r15
/usr/src/debug/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/block/blk-cgroup.c: 504
0xffffffff81319645 <blkcg_print_blkgs+101>: mov    (%r15),%rax
/usr/src/debug/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/include/linux/spinlock.h: 331
0xffffffff81319648 <blkcg_print_blkgs+104>: mov    0x458(%rax),%rdi
0xffffffff8131964f <blkcg_print_blkgs+111>: callq  0xffffffff816b6730 <_raw_spin_lock_irq>
/usr/src/debug/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/block/blk-cgroup.c: 505
0xffffffff81319654 <blkcg_print_blkgs+116>: mov    (%r15),%rdi



通過blkcg_gq結(jié)構(gòu)體的地址,我們可以先找到q的地址。

struct blkcg_gq {
   /* Pointer to the associated request_queue */
   struct request_queue      *q;
   struct list_head      q_node;
   struct hlist_node     blkcg_node;
   struct blkcg         *blkcg;
  ...
};


crash> blkcg_gq.q ffff88bed0d860c0
  q = 0xffff88bef3f1b4e0



接著再通過q找到queue_lock的地址。

struct request_queue {
   /*
    * Together with queue_head for cacheline sharing
    *
   struct list_head   queue_head;
   struct request    *last_merge;
   struct elevator_queue  *elevator;
   int          nr_rqs[2]; /* # allocated [a]sync rqs */
   int          nr_rqs_elvpriv;    /* # allocated rqs w/ elvpriv */
   ...
   spinlock_t     __queue_lock;
   spinlock_t    *queue_lock;   ...
};


crash> struct request_queue.queue_lock 0xffff88bef3f1b4e0
 queue_lock= 0xffff88b68e104f98



使用kmem命令查看當(dāng)先內(nèi)存的分配情況,可以看出0xffff88b68e104f98這個(gè)地址已超出已分配地址,確實(shí)是一個(gè)非法地址。

crash> kmem -s 0xffff88b68e104f98
CACHE            NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ffff8801bfc07a00 kmalloc-96                96      23531     34776    828     4k
  SLAB              MEMORY            NODE  TOTAL  ALLOCATED  FREE
  ffffea02da384100  ffff88b68e104000     1     42         10    32
  FREE / [ALLOCATED]
   ffff88b68e104f60



查看requset_queue結(jié)構(gòu)體,這個(gè)隊(duì)列已沒有設(shè)備在使用,但是從requeust_fn可以確認(rèn)它被emcp模塊使用。

crash> dev -d | grep ffff88bef3f1b4e0
crash> request_queue.dev,request_fn,nr_queues 0xffff88bef3f1b4e0
  dev = 0x0
  request_fn = 0xffffffffc09348b0
  nr_queues = 0x0
crash> sym 0xffffffffc09348b0
ffffffffc09348b0 (t) emcp_native_strategy_request_fn [emcp]


因此,我們可以得出結(jié)論:
由于emcp模塊沒有正確刪除request_queue」,導(dǎo)致自旋鎖操作訪問無效地址。



總結(jié)


綜上所述,可以看出crash工具非常強(qiáng)大,而學(xué)習(xí)使用crash工具不僅可以幫我們更快速地定位問題,更能夠幫助我們深入地理解linux內(nèi)核。

讓數(shù)據(jù)庫(kù)基礎(chǔ)設(shè)施更簡(jiǎn)單
加速企業(yè)數(shù)字化轉(zhuǎn)型建設(shè)及落地
立即咨詢

沃趣科技

中立的企業(yè)級(jí)數(shù)據(jù)庫(kù)云
十年磨一劍十年來始終如一的專注數(shù)據(jù)庫(kù)生態(tài)領(lǐng)域
夯實(shí)技術(shù)底蘊(yùn)打造最適合時(shí)代的數(shù)據(jù)庫(kù)基礎(chǔ)設(shè)施
業(yè)績(jī)持續(xù)領(lǐng)先目前已累計(jì)服務(wù)超3000家企業(yè)客戶

留言咨詢

完善信息,我們第一時(shí)間跟您聯(lián)系
姓名
手機(jī)
公司
所在地區(qū)
咨詢問題