精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Linux內核KGDB進階:源碼級調試實戰演練

系統 Linux
KGDB,即 Kernel GNU Debugger,是 Linux 內核官方支持的調試框架,就像是一位隱藏在幕后的超級特工,專門深入 Linux 內核的神秘世界,幫助開發者揪出那些隱藏極深的 Bug 。它采用 “雙機調試” 的獨特模型,這就好比一場精心策劃的秘密行動,需要兩個關鍵角色:目標機和開發機。

在 Linux 內核開發的廣袤領域中,調試工作堪稱一場充滿挑戰的冒險。用printk排障時對著日志猜邏輯,用ftrace跟蹤卻抓不到關鍵代碼執行路徑——這大概是每個Linux內核開發者都踩過的坑。內核空間的“黑盒”特性,讓多核競態、驅動死鎖這類問題成了調試路上的“硬骨頭”。而KGDB的出現,終于讓我們能像調試應用程序一樣,深入內核源碼逐行跟蹤、斷點調試。

不同于入門級的環境搭建,本文聚焦KGDB進階實戰:從串口調試到網絡調試的切換技巧,多核環境下斷點綁定核心的關鍵操作,再到驅動模塊動態加載后的符號匹配難題,全是一線開發中高頻遇到的場景。我們會以真實的網卡驅動異常案例為線索,演示如何用KGDB定位中斷處理函數的邏輯漏洞,如何通過觀察寄存器狀態還原問題現場。無論你是剛接觸內核調試的新手,還是被復雜問題困住的資深開發者,這份實戰指南都能幫你打通KGDB使用的“任督二脈”,讓內核調試不再靠“猜”。

一、什么是KGDB?

1.1KGDB概述

KGDB,即 Kernel GNU Debugger,是 Linux 內核官方支持的調試框架,就像是一位隱藏在幕后的超級特工,專門深入 Linux 內核的神秘世界,幫助開發者揪出那些隱藏極深的 Bug 。它采用 “雙機調試” 的獨特模型,這就好比一場精心策劃的秘密行動,需要兩個關鍵角色:目標機和開發機。目標機是運行著需要被調試內核的 “任務現場”,可以是一臺物理機器,也可以是虛擬機,它通過特定的 I/O 端口,通常是串口 ttyS0 或者以太網,悄無聲息地輸出調試信息,同時時刻準備接收來自開發機的調試指令 。

開發機則是運行著 GDB(或 LLDB)的 “指揮中心”,通過相同的 I/O 端口與目標機緊密相連,向目標機發送各種調試命令,比如讀取內存數據、設置斷點等,然后等待目標機反饋的 “情報” 。

  • 開發機(Development Machine):運行GDB調試器,負責發送調試命令并接收目標機反饋,需部署內核源碼及編譯產物。
  • 目標機(Target Machine):運行待調試內核,通過串口或以太網與開發機通信,內核需集成KGDB調試Stub(實現調試協議解析與環境交互的內核模塊)。

目前KGDB已支持x86_64、i386、32-bit PPC等主流架構,適用于內核崩潰排查、驅動開發調試、內存越界分析等核心場景。在這個過程中,目標機內核中的 KGDB stub(存根)起著至關重要的作用,它就像是目標機和開發機之間的 “秘密聯絡官”。KGDB stub 與開發機的 GDB 之間通過一種基于包的特定協議進行通信,這個協議就像是他們之間的 “秘密語言”,運行在串行線或以太網之上 。當目標機內核啟動后,KGDB stub 就開始靜靜地等待開發機的連接,如同潛伏的特工等待總部的指令。

一旦目標機遇到斷點、異常,或者通過魔術鍵(Magic SysRq)手動觸發調試,內核的執行會立即完全停止,就像時間突然靜止一樣。此時,控制權迅速移交給 KGDB stub,stub 通過通信端口向開發機的 GDB 發送一個 “異常” 信號,仿佛在向總部報告:“發現情況,請求指示!” 開發機的 GDB 接收到信號后,立即進入交互模式,開發者就可以像指揮官一樣,開始下達各種調試命令了。在 GDB 中輸入 c(continue)命令后,調試指令就會被發送回目標機,內核從停止的地方繼續執行,就像按下了播放鍵,時間又開始流動。

1.2KGDB 相比其他工具的優勢

與傳統的 printk 調試方式相比,KGDB 簡直就是降維打擊。printk 就像是在黑暗中摸索,只能通過打印一些簡單的日志信息來猜測程序的運行狀態,一旦遇到復雜的問題,這些零散的信息就如同大海撈針,很難從中找到關鍵線索 。而 KGDB 則擁有 “上帝視角”,它允許開發者設置斷點,就像在程序的關鍵位置埋下了 “監控攝像頭”,可以讓程序在特定的位置暫停執行,方便開發者仔細檢查此時的變量值、寄存器狀態等信息 。例如,當調試一個復雜的內核模塊時,如果使用 printk,可能需要在代碼中到處添加打印語句,不僅繁瑣,而且可能會因為打印過多的信息而導致系統性能下降。而使用 KGDB,只需要在關鍵函數或代碼行設置斷點,就可以輕松地查看程序在斷點處的詳細狀態,大大提高了調試效率。

再看看 ftrace,它雖然能夠跟蹤函數的調用關系,幫助開發者了解程序的執行流程,但在調試復雜問題時,還是顯得力不從心 。ftrace 無法像 KGDB 那樣,精確地控制程序的執行,進行單步調試,也不能直接查看寄存器和內存的詳細信息 。比如,當遇到一個涉及到硬件寄存器操作的內核問題時,ftrace 就很難提供有效的幫助,而 KGDB 卻可以直接查看寄存器的值,分析問題的根源。

在面對多核競態問題時,KGDB 的優勢更是凸顯。它可以在多線程同時訪問共享資源的關鍵代碼處設置斷點,然后通過單步執行,仔細觀察每個線程在不同時刻對共享資源的操作,從而找出競態條件產生的原因 。而其他工具,如 printk 和 ftrace,很難在這種復雜的多線程環境中,準確地定位問題。例如,在一個多核處理器的文件系統驅動中,當多個線程同時讀寫文件緩存時,可能會出現數據不一致的問題。使用 KGDB,開發者可以在緩存操作的關鍵函數處設置斷點,逐步跟蹤每個線程的執行過程,找到導致數據不一致的具體操作步驟。

二、KGDB 調試內核核心原理

2.1基本原理剖析

KGDB 的工作基于 GDB 遠程調試協議,其運行機制依賴于兩臺機器的協同工作,即調試主機(Host)和目標機(Target) 。在調試過程中,調試主機上運行著 GDB 調試器,它就像是一位經驗豐富的指揮官,負責向目標機發送各種調試指令,掌控整個調試流程的節奏。而目標機則運行著被調試的 Linux 內核以及 KGDB,它如同一位正在執行任務的士兵,按照 GDB 的指令行事,并將自身的狀態信息及時反饋給調試主機。

當在目標機的內核代碼中設置斷點后,一旦程序執行到斷點位置,目標機內核就會立刻暫停當前的執行流程。此時,它會將當前的執行環境,包括寄存器值、內存狀態等關鍵信息,按照 GDB 遠程調試協議的規定,通過串口或網絡發送給調試主機上的 GDB 。GDB 收到這些信息后,就如同收到了前線傳來的戰報,會根據開發者輸入的調試命令,如繼續執行、單步執行、查看變量等,進行相應的分析和處理,并向目標機內核發送對應的指令。

目標機內核在接收到這些指令后,會如同接到新的作戰任務一樣,迅速做出響應,執行相應的操作,并將操作結果再次返回給 GDB 。通過這樣緊密的交互過程,開發者就能夠像操控自己手中的玩具一樣,對 Linux 內核進行高效的調試,精準地定位和解決問題。

2.2安裝KGDB

(1)安裝環境要求

設備)類型

核心配置

必備軟件

開發機

x86_64架構,2核4G以上配置

GDB(7.12+)、內核源碼、補丁工具(patch)、SCP工具

目標機

支持的架構,與開發機通信鏈路正常

待調試Linux內核、串口驅動(或網卡驅動)

(2)通信鏈路準備

KGDB支持串口和以太網兩種通信方式,需根據場景選擇并完成物理連接或網絡配置:

  • 串口連接(推薦嵌入式場景):使用RS-232交叉串口線,連接兩臺機器的串口接口,線序為"開發機TXD-目標機RXD、開發機RXD-目標機TXD、雙方GND直連"。
  • 以太網連接(推薦云服務器/VPS場景):確保開發機與目標機處于同一局域網或網絡可達,開放調試端口(如1234)防火墻權限。

核心文件準備:

  • 1. 內核源碼與KGDB補丁:需確保補丁版本與內核版本匹配,補丁命名規則為"linux-A-kgdb-B"(A為內核版本,B為KGDB版本),例如linux-2.6.7對應kgdb-2.2補丁。
  • 2. 下載地址參考:內核源碼從http://kernel.org獲取,KGDB補丁可從內核官方補丁庫或嵌入式社區獲取。

(3)安裝與配置步驟

通信鏈路測試(串口場景必做),完成串口物理連接后,通過以下命令驗證通信可用性(以/dev/ttyS0為例,波特率115200):

  • 開發機配置串口參數:stty ispeed 115200 ospeed 115200 -F /dev/ttyS0
  • 目標機配置串口參數:stty ispeed 115200 ospeed 115200 -F /dev/ttyS0
  • 開發機發送測試數據:echo "kgdb test" > /dev/ttyS0
  • 目標機接收數據:cat /dev/ttyS0,若輸出"kgdb test"則連接正常。

②內核補丁應用(開發機操作)

解壓內核源碼與KGDB補丁:

tar -jxvf linux-2.6.7.tar.bz2
tar -jxvf linux-2.6.7-kgdb-2.2.tar.bz2
cd linux-2.6.7

按補丁包內series文件指定順序應用補丁(i386架構示例),避免順序錯誤導致沖突:

patch -p1 < ../linux-2.6.7-kgdb-2.2/core-lite.patch
patch -p1 < ../linux-2.6.7-kgdb-2.2/i386-lite.patch
patch -p1 < ../linux-2.6.7-kgdb-2.2/8250.patch  # 串口驅動補丁
patch -p1 < ../linux-2.6.7-kgdb-2.2/eth.patch   # 以太網調試需加此補丁
patch -p1 < ../linux-2.6.7-kgdb-2.2/core.patch
patch -p1 < ../linux-2.6.7-kgdb-2.2/i386.patch

檢查補丁應用結果:若未生成*.rej文件,說明補丁應用成功。

③內核配置(開發機操作),通過內核配置菜單啟用KGDB相關功能,確保調試符號完整保留:

  • 啟動配置界面:make menuconfig
  • 進入"Kernel hacking"菜單,勾選以下選項: (*) KGDB: kernel debugging with remote gdb(啟用KGDB核心功能)
  • Method for KGDB communication → 選擇通信方式(串口選"KGDB: On generic serial port (8250)",以太網選對應網卡選項)
  • (*) KGDB: Thread analysis(線程分析支持)
  • (*) KGDB: Console messages through gdb(調試過程中控制臺消息轉發)
  • (*) Compile the kernel with debug info(保留調試符號,CONFIG_DEBUG_INFO=y)
  • (*) KGDB_KDB(可選,啟用KDB本地調試輔助)
  • 保存配置并退出(默認保存至.config文件)。

④內核編譯與部署

  • 調整編譯優化級別:打開內核目錄下的Makefile,將-O2優化級別改為-O(避免編譯器重排代碼導致調試錯位),不可完全移除-O選項(會導致編譯失敗)。
  • 編譯內核與模塊:
make -j$(nproc)  # 多線程編譯,$(nproc)為CPU核心數
make modules -j$(nproc)
make modules_install  # 安裝內核模塊
make install  # 安裝內核
  • 生成initrd鏡像(若驅動未編譯進內核):mkinitrd /boot/initrd-2.6.7-kgdb 2.6.7
  • 部署至目標機:通過SCP將內核文件、System.map和initrd鏡像拷貝到目標機/boot目錄:
scp arch/x86_64/boot/bzImage root@目標機IP:/boot/vmlinuz-2.6.7-kgdb
scp System.map root@目標機IP:/boot/System.map-2.6.7-kgdb
scp /boot/initrd-2.6.7-kgdb root@目標機IP:/boot/initrd-2.6.7-kgdb

⑤目標機啟動配置,通過修改GRUB配置,讓目標機使用帶KGDB的內核啟動并加載調試參數:

  • 編輯GRUB配置文件:vim /etc/default/grub
  • 修改GRUB_CMDLINE_LINUX參數,根據通信方式添加對應配置: 串口調試:GRUB_CMDLINE_LINUX="kgdbwait kgdboc=ttyS0,115200" 參數說明:kgdbwait(內核啟動時等待GDB連接)、kgdboc(指定通信設備與波特率)
  • 以太網調試(VPS場景):GRUB_CMDLINE_LINUX="kgdbwait kgdboc=eth0,192.168.1.100:1234" 若用串口轉TCP:在開發機執行socat -d -d TCP-LISTEN:1234,reuseaddr,fork FILE:/dev/ttyS0,raw,echo=0實現端口轉發
  • 更新GRUB配置:update-grub(Debian/Ubuntu)或grub2-mkconfig -o /boot/grub2/grub.cfg(CentOS/RHEL)
  • 重啟目標機:reboot,啟動時選擇帶"kgdb"標識的內核,系統會掛起并等待GDB連接(屏幕顯示"Waiting for connection from remote gdb")。

2.3關鍵功能部件解析

GDB stub:GDB stub,又被親切地稱為調試插樁,它可是 KGDB 調試器的核心部件,就像是人體的心臟一樣重要 。它是一段巧妙嵌入 Linux 內核中的代碼,雖然身材短小,但卻肩負著重大的使命。它主要負責處理主機上 GDB 發來的各種請求,這些請求就像是來自上級的各種任務,GDB stub 需要準確無誤地理解并執行。比如,當 GDB 要求查看某個變量的值時,GDB stub 就得迅速在目標機的內核中找到該變量,并將其值反饋給 GDB。同時,在內核處于被調試狀態時,GDB stub 還承擔著控制目標機上處理器的重任,它就像是一位嚴謹的交通警察,指揮著處理器的每一個動作,確保調試過程的順利進行。

陷阱處理:陷阱處理在 KGDB 調試中扮演著至關重要的角色,它就像是一位時刻保持警惕的衛士。當開發者在代碼中設置斷點時,KGDB 會迅速提供一個異常處理函數,這個函數就像是一個神奇的魔法棒,它會將斷點位置的指令替換成一條異常指令。當程序執行到該斷點時,異常就會如同警報一樣被觸發,內核就會立即將 CPU 的控制權交給 KGDB 調試器。此時,程序就會進入 KGDB 提供的異常處理函數中,在這個函數里,開發者就像是進入了一個神秘的實驗室,可以對內核代碼的各種情況進行深入的分析和研究,比如查看變量的值、檢查寄存器的狀態等,從而找到問題的根源。

串口通信:串口通信是 KGDB 實現調試主機與目標機之間信息交互的重要橋梁,它基于 gdb 串行協議進行工作。gdb 串行協議是一種精心設計的基于消息的 ASCII 碼協議,它就像是一種特殊的語言,包含了各種調試命令。調試主機和目標機就像是兩個用這種特殊語言交流的伙伴,通過串口發送和接收這些包含調試命令和執行結果的消息。例如,當調試主機上的 GDB 發送一個設置斷點的命令時,這個命令就會通過串口,按照 gdb 串行協議的格式,被準確地傳送到目標機的 KGDB stub。KGDB stub 在接收到這個命令后,會根據命令的要求進行相應的操作,并將操作結果再通過串口,按照協議格式返回給 GDB 。串口通信的穩定性和準確性直接影響著調試的效果,就像道路的暢通與否會影響交通的效率一樣。

三、準備工作:用KGDB調試內核

3.1環境搭建

為了開啟這場 KGDB 的實戰之旅,我們首先需要搭建一個合適的環境。這里我們以 QEMU 虛擬機作為目標機,它就像是一個虛擬的實驗室,讓我們可以在其中自由地調試內核,而不用擔心對真實的物理設備造成影響 。

配置串口是第一步,這就好比在兩座城市之間搭建一條通信線路。在啟動 QEMU 虛擬機時,我們通過添加 “-serial tcp:[127.0.0.1:1234](127.0.0.1:1234),server,nowait” 參數,創建了一個 TCP 連接的虛擬串口 。這個串口就像是一座橋梁,將目標機(QEMU 虛擬機)和開發機連接起來,使得它們之間能夠進行調試信息的傳輸。

在虛擬機內部,我們還需要啟用串口設備。這一步就像是在城市內部鋪設道路,讓信息能夠順利地在虛擬機內部傳遞。我們可以通過修改虛擬機的引導配置文件,比如在 GRUB 配置文件 “/boot/grub/grub.cfg” 中,添加以下內容:

serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
terminal_input serial
terminal_output serial

這樣,虛擬機就啟用了串口設備,并將終端輸入 / 輸出都重定向到了串口上,為后續的調試通信做好了準備。

接下來是準備根文件系統,它就像是虛擬機的 “倉庫”,存儲著運行所需的各種文件和程序 。我們可以從網上下載一個已經預先構建好的根文件系統鏡像,比如 “rootfs_deb.img.7z”,當然,你也可以自己動手構建一個最小化的根文件系統,使用 busybox 來實現基本的命令功能 。如果選擇下載,下載完成后,我們需要將其解壓到合適的目錄,比如 “/home/user/rootfs”。這個過程就像是把貨物搬進倉庫,為虛擬機的運行提供必要的資源。

3.2內核配置與編譯

進入內核源碼目錄,就像是踏入了一個神秘的代碼王國。在這里,我們使用 “make menuconfig” 命令,開啟內核配置的大門 。這是一個基于文本的圖形界面,就像是一個商品琳瑯滿目的超市,我們可以在其中自由地選擇需要的功能。在這個界面中,我們要開啟幾個關鍵的選項,就像是在超市中挑選必備的商品。首先是 CONFIG_KGDB,它是 KGDB 的核心功能開關,啟用它就像是啟動了一臺強大的機器CONFIG_KGDB_SERIAL_CONSOLE,這個選項用于通過串口進行 KGDB 通信,就像是連接了一條穩定的通信線路;還有 CONFIG_DEBUG_INFO,它至關重要,會包含 DWARF 調試信息,使 GDB 能夠識別符號和源代碼,就像是給代碼王國中的每個物品都貼上了標簽,方便我們查找和識別 。此外,CONFIG_DEBUG_INFO_DWARF4(推薦使用較新的 DWARF 格式)和 CONFIG_FRAME_POINTER(生成更可靠的調用棧回溯)等選項也可以根據需要開啟。

完成配置后,我們就可以保存配置并開始編譯內核了。編譯內核的過程就像是一場緊張的生產活動,需要消耗一定的時間和系統資源 。我們執行 “make -j$$(nproc)”命令,其中“-$$(nproc)” 表示使用多個線程并行編譯,這樣可以大大加快編譯速度,就像是工廠里增加了生產線,提高了生產效率。編譯完成后,不要忘記安裝新內核,執行 “make modules_install” 和 “make install” 命令,將新編譯的內核模塊和內核安裝到系統中,就像是把生產好的產品擺放到合適的位置,讓系統能夠使用它們。

3.3設置啟動參數

設置啟動參數是使用 KGDB 調試內核的重要環節,它就像是給一艘船設定航行的方向,只有方向設定正確了,船才能順利到達目的地。在設置啟動參數之前,我們需要為 KGDB 內核創建一個新的啟動項,這個新的啟動項就像是為我們的調試之旅開辟了一條新的航道。

我們可以通過修改系統的啟動配置文件來創建新啟動項。在大多數 Linux 系統中,這個文件通常是/etc/grub.conf或/boot/grub/grub.cfg。在這個文件中,我們要添加一些關鍵參數。首先是kgdboc參數,它用于指定串口和波特率,比如kgdboc=ttyS0,115200,這就像是給調試主機和目標機之間的通信通道設定了一個標準,讓它們能夠以相同的頻率進行交流。如果我們想要調試內核的啟動階段,還需要添加kgdbwait參數,它會使目標機在啟動時等待調試連接,就像一個耐心的伙伴,在原地等待我們的到來 。

在修改啟動配置文件時,一定要注意備份原有的啟動項和相關文件,這就像是在進行一次重要的旅行之前,備份好所有重要的文件和資料。因為一旦修改出現問題,我們還可以恢復到原來的狀態,避免因為配置錯誤而導致系統無法啟動的情況發生。修改完成后,我們需要保存文件,并重啟目標機,使新的啟動參數生效,這樣我們就完成了啟動參數的設置,可以進入下一步的調試工作了。

3.4建立調試連接

在完成前面的準備工作后,接下來就進入了建立調試連接的關鍵步驟,這一步就像是在調試主機和目標機之間搭建一座橋梁,讓兩者能夠進行順暢的通信。

我們首先要在開發機上啟動 GDB。GDB 作為調試的核心工具,就像是一位經驗豐富的領航員,將帶領我們深入探索目標機內核的奧秘。在啟動 GDB 時,我們可以通過在終端中輸入gdb命令,然后加載目標二進制文件,比如gdb vmlinux,這里的vmlinux就是我們之前從目標機拷貝到開發機上的內核二進制文件,它包含了內核的所有代碼和數據,是我們調試的主要對象 。

啟動 GDB 后,我們需要設置遠程調試相關參數。如果我們使用串口連接進行調試,就需要設置串口連接參數。在 GDB 界面中,我們可以使用set remotebaud命令來設置波特率,使其與之前在目標機啟動參數中設置的波特率一致,比如set remotebaud 115200,確保通信的速率匹配。然后使用target remote命令來指定連接的串口設備,例如target remote /dev/ttyS0,這里的/dev/ttyS0就是我們之前配置好的串口設備,通過這兩個命令,我們就像在調試主機和目標機之間的串口通信線路上安裝了正確的信號發射器和接收器,讓它們能夠準確無誤地傳輸調試信息。

如果我們使用網絡連接進行調試,設置過程會稍有不同。我們需要使用target remote命令指定目標機的 IP 地址和端口號,比如target remote 192.168.1.10:1234,其中192.168.1.10是目標機的 IP 地址,1234是預先設置好的端口號,這就像是在調試主機和目標機之間的網絡通道上設置了正確的門牌號,讓調試信息能夠準確地找到目標機。

設置好遠程調試參數后,GDB 就會嘗試與目標機建立連接。如果一切順利,我們會看到 GDB 界面顯示已經成功連接到目標機,并且可能會顯示當前斷點停在kgdb_breakpoint函數處,這就表明我們成功地在調試主機和目標機之間搭建起了調試橋梁,接下來就可以進行各種調試操作了 。但如果連接過程中出現問題,比如提示無法連接或者通信錯誤,我們就需要仔細檢查之前的配置步驟,包括串口或網絡連接是否正確、啟動參數是否設置無誤等,確保每一個環節都沒有問題,直到成功建立調試連接。

四、KGDB 實戰演練

4.1連接與初始化

現在,所有的準備工作已經就緒,就像是一場大戰前的一切戰略部署都已完成,我們終于要開啟這場激動人心的 KGDB 實戰之旅了 。

①首先,在開發機上,我們要啟動 GDB,這就像是啟動了一臺強大的武器。打開終端,進入之前準備好的內核源碼目錄,執行 “gdb vmlinux” 命令,GDB 就被成功啟動,并且加載了內核的調試符號 ,就像給武器裝上了精準的瞄準鏡,讓我們能夠更準確地定位問題。你需要有與目標機完全一致的、包含調試信息的vmlinux文件(編譯內核時在源碼根目錄生成的那個,不是/boot下的壓縮鏡像)。

cd /path/to/linux-kernel-source
gdb ./vmlinux

②接下來,要建立與目標機的連接,這一步至關重要,就像是搭建起一座通往問題核心的橋梁。由于我們之前在 QEMU 虛擬機中配置了串口通信,這里使用 “target remote /dev/pts/XX” 命令,其中 “/dev/pts/XX” 是 QEMU 啟動時分配的串口設備,這個命令就像是在向目標機發出連接請求 。當連接成功時,你會看到 GDB 的界面發生了變化,這表明我們已經成功地與目標機建立了聯系,就像兩個秘密特工成功接頭一樣,為后續的調試工作奠定了基礎。

對于串口:

(gdb) set serial baud 115200
(gdb) target remote /dev/ttyS0  # 請替換為開發機上的實際串口設備

對于QEMU創建的TCP端口:

(gdb) target remote 127.0.0.1:1234

連接成功后,我們就可以開始設置斷點了,斷點就像是我們在程序執行路徑上設置的 “關卡”,可以讓程序在特定的位置暫停,方便我們進行調試 。假設我們懷疑內核中處理網絡包接收的函數 “netif_receive_skb” 存在問題,就可以在 GDB 中執行 “b netif_receive_skb” 命令,這樣就在 “netif_receive_skb” 函數的入口處設置了一個斷點 。當程序執行到這個函數時,就會停在斷點處,等待我們進一步的調試指令,就像車輛行駛到關卡時,會被攔下接受檢查一樣。

常用GDB命令

  • break function_name 或 b function_name:在函數處設置斷點(例如:b sys_open)。
  • break filename.c:linenumber:在指定文件的指定行設置斷點。
  • c (continue):繼續執行。
  • next 或 n:單步跳過。
  • step 或 s:單步進入。
  • print variable_name 或 p variable_name:打印變量值。
  • bt (backtrace):打印調用棧回溯,這是分析Panic/Oops的利器。
  • info registers:顯示所有寄存器內容。
  • lx-symbols (需要手動加載):極其重要! 如果你需要調試內核模塊,在連接上目標機后,在GDB中執行:
(gdb) lx-symbols /path/to/target-machine-kernel-modules/

這個命令(內核提供的GDB腳本)會自動加載所有已加載模塊的符號表。

在運行時手動觸發調試會話

如果啟動時沒有加kgdbwait,你可以在目標機系統運行過程中,通過魔術SysRq鍵強制它進入調試狀態。

  • 確保已啟用SysRq:echo 1 > /proc/sys/kernel/sysrq
  • 在目標機鍵盤上按下:Alt + SysRq + g(在某些系統上,可能是 Alt + PrintScreen + g,或者通過 echo g > /proc/sysrq-trigger)

按下后,目標機內核會凍結,并通過調試端口等待GDB連接。此時你再從開發機用GDB連上去即可。

4.2調試過程演示

以調試網絡驅動為例,當我們設置好斷點后,就可以在目標機上觸發網絡包的輸入了。在另一個終端中,對 QEMU 虛擬機執行 “ping [10.0.2.15](10.0.2.15)” 命令,向虛擬機發送網絡數據包 ,這就像是向目標機的網絡驅動 “發起挑戰”,看看它能否正確處理這些數據包。

當網絡包到達目標機時,內核開始處理網絡包的接收流程。由于我們之前在 “netif_receive_skb” 函數設置了斷點,程序執行到這里時,會立即停住 ,就像時間突然靜止了一樣。此時,GDB 的界面會顯示當前停住的位置以及相關的函數調用信息 ,就像給我們展示了一張程序執行的 “快照”。

我們可以使用 “info args” 命令查看當前函數的參數,這就像是查看一個神秘包裹里的物品清單 。比如,在 “netif_receive_skb” 函數斷點處執行 “info args”,可以看到傳遞給這個函數的網絡數據包的相關參數,如數據包的指針、長度等信息,通過這些信息,我們可以初步判斷數據包是否正確地傳遞到了這個函數中 。“p” 命令也是非常有用的,它可以打印變量的值,就像一個神奇的放大鏡,讓我們能夠看清程序內部的細節 。例如,執行 “p skb”,這里 “skb” 是網絡數據包的結構體變量,通過這個命令,我們可以查看數據包的具體內容,包括數據的長度、包頭的信息等,從而進一步分析問題 。如果發現數據包的某個字段值異常,就可以順著這個線索繼續深入調試。

單步跟蹤也是調試過程中常用的技巧,通過 “n”(next)命令可以單步執行下一條語句,“s”(step)命令則可以進入函數內部執行 。當我們懷疑某個函數內部的代碼存在問題時,就可以使用 “s” 命令進入函數,一步一步地查看代碼的執行過程,觀察變量的變化情況,就像偵探在案發現場仔細地尋找線索一樣 。比如,在 “netif_receive_skb” 函數中,我們發現某個變量的值在某一步之后出現了異常,就可以使用單步跟蹤,逐步分析是哪一條語句導致了這個異常的發生。

4.3問題解決與驗證

經過一番細致的調試和分析,我們終于定位到了問題所在。假設我們發現是網絡驅動在處理接收緩沖區時,存在內存越界的問題,導致數據包丟失 。那么,我們就需要提出解決方案,這就像是醫生為病人開出治療方案一樣。針對這個內存越界的問題,我們可以修改代碼邏輯,在訪問接收緩沖區之前,增加對緩沖區邊界的檢查 。打開內核源碼中網絡驅動的相關文件,找到處理接收緩沖區的代碼部分,添加如下檢查代碼:

if (skb->len + offset > buffer_size) {
    // 處理內存越界的情況,比如返回錯誤或者調整緩沖區
    return -EINVAL;
}

修改完代碼后,我們需要重新編譯內核,這就像是對修改后的程序進行 “組裝”,讓它能夠正常運行 。在目標機的內核源碼目錄中,執行 “make -j$(nproc)” 命令進行編譯,編譯完成后,執行 “make modules_install” 和 “make install” 命令,將新編譯的內核模塊和內核安裝到系統中 。

重新啟動目標機,再次進行網絡包的測試,執行 “ping [10.0.2.15](10.0.2.15)” 命令 。如果之前的丟包問題得到了解決,ping 命令能夠正常返回響應,就說明我們的修改是有效的,問題得到了成功解決 。為了進一步驗證問題是否徹底解決,我們還可以進行壓力測試,比如使用 “iperf” 工具,向目標機發送大量的網絡數據包,觀察在高并發情況下,網絡驅動是否還會出現丟包的問題 。如果在壓力測試中,網絡驅動能夠穩定地工作,沒有出現丟包現象,那么就可以確定我們的解決方案是正確的,這場 KGDB 的實戰調試也取得了圓滿的成功 。

五、使用 KGDB 的小竅門

5.1常用命令與技巧

在使用 KGDB 進行內核調試時,熟練掌握一些常用的 GDB 命令和技巧,能夠讓你的調試工作事半功倍 。首先是斷點設置命令 “b”(break),它是我們調試的 “偵察兵”,可以在函數或特定代碼行設置斷點 。比如 “b sys_read”,這會在系統調用 “sys_read” 的入口處設置斷點,當內核執行到這個函數時,就會停下來,方便我們進行檢查 。如果要在某個源文件的具體行號設置斷點,比如 “b fs/read_write.c:50”,就會在 “read_write.c” 文件的第 50 行設置斷點 。

“c”(continue)命令就像是調試的 “加速器”,它會讓內核從當前斷點繼續執行,直到遇到下一個斷點或程序結束 。當我們查看完當前斷點處的信息,想要繼續觀察程序的執行時,就可以使用這個命令 。

“n”(next)和 “s”(step)命令則是我們深入程序內部的 “放大鏡” 。“n” 命令會單步執行下一條語句,但不會進入函數內部,適合快速跳過一些我們不關心的函數調用 。而 “s” 命令會進入當前函數的下一個語句,直到遇到新的一行或函數結束,當我們想要深入研究某個函數內部的執行邏輯時,“s” 命令就派上用場了 。例如,在調試一個網絡驅動時,我們可以使用 “s” 命令進入網絡包處理函數,一步一步地查看數據的處理過程 。“p”(print)命令是查看變量值的利器,它就像是一個神奇的 “透視鏡”,能夠讓我們看清程序內部變量的狀態 。執行 “p my_variable”,就可以打印出 “my_variable” 這個變量的值 。如果變量是一個復雜的結構體,我們還可以通過 “p my_struct.member” 的方式,查看結構體中某個成員的值 。比如,在調試一個文件系統驅動時,我們可以使用 “p inode->i_size”,查看文件節點的大小 。

“bt”(backtrace)命令是分析程序執行流程的 “時間軸”,它會打印出當前的調用棧回溯信息,幫助我們了解函數的調用關系 。當內核出現崩潰或異常時,通過 “bt” 命令,我們可以看到函數的調用順序,從而找到問題的根源 。比如,在分析一個內核 Oops 錯誤時,“bt” 命令可以顯示出錯誤發生時的函數調用棧,讓我們能夠快速定位到出錯的函數 。

除了這些基本命令,設置觀察點也是一個非常有用的技巧 。觀察點就像是一個 “監控攝像頭”,可以監視某個變量的變化,當變量的值發生改變時,程序就會暫停執行 。使用 “watch variable_name” 命令,就可以設置一個觀察點,當 “variable_name” 這個變量的值發生變化時,GDB 會自動暫停,讓我們可以檢查變量變化的原因 。比如,在調試一個多線程程序時,我們可以設置觀察點來監視共享變量的變化,從而找出競態條件的問題 。

使用 GDB 腳本也是提高調試效率的好方法 。GDB 腳本就像是一個自動化的 “助手”,可以預先設置一系列的調試命令,然后一次性執行 。我們可以將一些常用的斷點設置、變量查看等命令編寫成腳本,每次調試時直接加載腳本,就可以快速進入調試狀態 。例如,我們可以編寫一個腳本,在啟動 GDB 時自動連接到目標機,并設置好常用的斷點 。創建一個名為 “my_script.gdb” 的文件,在其中寫入以下內容:

target remote /dev/pts/XX
b sys_open
b sys_close

5.2常見問題與解決方法

在使用 KGDB 的過程中,難免會遇到一些問題 。首先是斷點設置失敗的問題,這可能是由于多種原因導致的 。如果目標代碼位于優化后的函數或被內聯(inlined)執行,就會導致源碼行與實際指令地址不匹配,從而使斷點無法命中 。此時,我們可以在源碼中添加 “attribute((noinline))” 來強制禁用內聯,或者在編譯內核時使用 “-fno-inline” 選項 。例如,在某個函數定義前添加 “attribute((noinline)) static void my_function () {... }”,這樣在編譯時這個函數就不會被內聯 。

如果內核配置未啟用調試信息(如未定義 CONFIG_DEBUG_INFO),GDB 就無法正確解析符號和行號,也會導致斷點設置失敗 。我們需要重新配置內核,確保 CONFIG_DEBUG_INFO 選項被啟用 。在 “make menuconfig” 的配置界面中,找到 “Kernel hacking -> Compile the kernel with debug info”,將其設置為 “y” 。

斷點設置在尚未加載的模塊代碼中,也會導致斷點無法生效 。對于動態加載的模塊,我們需要先加載模塊,然后再設置斷點 。可以使用 “add-symbol-file” 命令,告知 GDB 模塊的符號位置 。例如,執行 “(gdb) add-symbol-file /path/to/module.ko 0xc0008000”,其中 “/path/to/module.ko” 是模塊文件的路徑,“0xc0008000” 是模塊的加載地址 。

串口沖突也是一個常見的問題 。如果串口被其他程序占用,比如 getty 或 minicom,就會導致 KGDB 無法正常通信 。我們需要確保串口僅被 KGDB 獨占 。可以通過查看系統日志,檢查串口設備是否被其他程序打開 。在 Linux 系統中,可以使用 “lsof /dev/ttyS0” 命令(假設串口設備是 ttyS0),查看哪些程序在使用這個串口 。如果發現有其他程序占用,可以先關閉這些程序,或者修改 KGDB 的配置,使用其他未被占用的串口 。

符號文件不匹配也可能引發問題 。調試時使用的 vmlinux 文件必須與目標內核完全一致,包括編譯時間戳和配置 。如果 vmlinux 文件不匹配,GDB 可能無法正確解析符號,導致調試錯誤 。每次編譯內核后,我們都要確保保留對應的 vmlinux 文件,并通過 “file vmlinux” 命令驗證其 Build ID 。如果發現 vmlinux 文件不匹配,需要重新拷貝正確的 vmlinux 文件到開發機上 。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2021-10-17 19:52:40

Python:源碼編譯器

2025-10-27 01:55:00

2014-08-28 15:08:35

Linux內核

2010-01-22 11:01:04

linux內核模塊

2017-09-25 08:04:31

Linux調試器源碼級斷點

2022-05-23 09:22:20

Go語言調試器Delve

2011-08-22 13:56:09

Linux虛擬

2017-08-28 15:29:19

Linux調試器源碼級逐步執行

2017-01-12 19:15:03

Linux內核調試自構proc

2021-07-11 06:45:18

Linux內核靜態

2022-02-08 15:15:26

OpenHarmonlinux鴻蒙

2017-03-17 15:05:05

Linux內核源碼do_fork

2009-09-18 14:31:33

CLR觸發器

2009-08-09 20:39:11

Linux內核虛擬環境虛擬主機

2023-04-10 09:44:22

內核鼠標調試鴻蒙

2016-08-23 09:17:08

LinuxD狀態TASK_RUNNIN

2025-03-05 00:49:00

Win32源碼malloc

2025-05-27 08:20:00

Linux內核參數調優系統

2021-12-29 11:51:15

Linux 內核源碼Linux 系統

2023-04-28 08:42:08

Linux內核SPI驅動
點贊
收藏

51CTO技術棧公眾號

国产69精品久久久久久久| 国产精选久久久久久| 在线观看免费视频国产| 国语对白在线刺激| av中文字幕亚洲| 97香蕉超级碰碰久久免费软件| 在线天堂www在线国语对白| 久草在线资源福利站| 久久久精品国产免大香伊| 国产精品www色诱视频| 久久精品一区二区免费播放| 亚洲www啪成人一区二区| 国产精品伦一区| 91精品视频在线播放| 日本天堂中文字幕| 日韩精品丝袜美腿| 欧美色手机在线观看| 只有这里有精品| 天天射天天操天天干| 首页国产欧美日韩丝袜| 久久久电影免费观看完整版| 国产51自产区| 69堂免费精品视频在线播放| 欧美—级在线免费片| 99视频国产精品免费观看| 国语对白永久免费| 亚洲一区色图| 亚洲乱码国产乱码精品精| 99视频在线视频| 精品一性一色一乱农村| 久久久精品一品道一区| 成人高清在线观看| 欧美日韩在线视频播放| 欧美成人午夜| 亚洲理论在线a中文字幕| 狠狠干狠狠操视频| 性欧美18~19sex高清播放| 国产精品国产自产拍在线| 国内外成人免费视频| 中文字幕在线观看高清| 亚洲精品三级| 最近2019免费中文字幕视频三 | 爱爱免费小视频| 播放一区二区| 亚洲成人av一区二区三区| 亚洲欧洲一区二区| 天堂91在线| 国产成a人亚洲| 国产日韩在线看| 性无码专区无码| 欧美人与禽猛交乱配视频| 亚洲一区二区国产| 亚洲人成网站77777在线观看| 国产综合久久久久久久久久久久| 欧美一级免费看| 一级性生活免费视频| 国产欧美日韩精品一区二区免费| 欧美mv日韩mv国产| 不卡的在线视频| 日韩三区免费| 日韩欧美a级成人黄色| 欧美视频在线观看视频| 在线看一级片| 亚洲人被黑人高潮完整版| 天堂av一区二区| 你懂的免费在线观看| 成人av电影在线| 成人9ⅰ免费影视网站| 亚洲一区二区天堂| 葵司免费一区二区三区四区五区| 97色在线观看| 99免费在线观看| 欧美色123| 久久91精品国产91久久久| 97精品在线播放| 99久久久久久中文字幕一区| 日韩黄色高清视频| 波多野结衣一本| 国产ts一区| 精品久久久久久最新网址| 可以看的av网址| 亚洲开心激情| 欧美mv和日韩mv的网站| 成人欧美精品一区二区| 66精品视频在线观看| 3d动漫精品啪啪一区二区竹菊| 欧美三级午夜理伦三级富婆| 日本成人在线网站| 91精品在线麻豆| 老熟女高潮一区二区三区| 老司机亚洲精品一区二区| 日韩一区二区三区免费观看| 国产一级二级av| 久久激情av| 亚洲免费一在线| 日本japanese极品少妇| 欧美精美视频| 亚洲视频在线观看| 亚洲欧美另类日本| 国内综合精品午夜久久资源| 97久久久久久| 中文字幕av网站| 九色porny丨国产精品| 亚洲最大福利视频| 神马午夜一区二区| 国产欧美日韩中文久久| 色一情一区二区三区四区 | 成人性生交大片免费看午夜| 国产精品福利在线播放| 国产精品一色哟哟| 毛片无码国产| 欧美一级国产精品| 欧美成人三级伦在线观看| 日韩有码一区| 久久精品国产欧美激情| 国产精品19乱码一区二区三区| 久久国产欧美| 韩日午夜在线资源一区二区| 久操视频在线观看| 色欲综合视频天天天| 中国特级黄色片| 日韩精品福利一区二区三区| 久久69精品久久久久久久电影好 | 国产一区导航| 91麻豆国产精品| 成黄免费在线| 欧美性猛交xxxx乱大交蜜桃| 美女扒开腿免费视频| 亚洲欧美日韩高清在线| 国产精品福利无圣光在线一区| 神马久久久久久久久久| 亚洲专区一二三| 日本高清免费在线视频| 久久中文亚洲字幕| 国产精品成熟老女人| 日本精品999| 亚洲成人综合视频| 手机在线观看日韩av| 99久久久久| 成人国产精品日本在线| 91网在线播放| 欧美三区在线观看| 中国女人特级毛片| 日韩电影在线一区二区| 欧美高清视频一区二区三区在线观看| 日本不卡影院| 日韩一区二区三区观看| av成人免费网站| 国模少妇一区二区三区| 综合久久国产| 懂色av色香蕉一区二区蜜桃| 精品国产美女在线| 国产jzjzjz丝袜老师水多| 亚洲日本中文字幕区| 在线播放黄色av| 亚洲女同一区| 国产成人一区二区三区免费看| 成年视频在线观看| 精品国内片67194| 日韩欧美大片在线观看| 不卡一卡二卡三乱码免费网站| 每日在线观看av| 先锋影音国产精品| 国产成人精品免费视频| www黄在线观看| 4hu四虎永久在线影院成人| 婷婷色中文字幕| gogogo免费视频观看亚洲一| 国产又黄又大又粗视频| 成人免费三级在线| 国产一区香蕉久久| 国产激情在线视频| 日韩精品专区在线影院观看| 国产一级在线视频| 91老师国产黑色丝袜在线| 男人插女人下面免费视频| 久久在线电影| 国产精品视频免费观看| 欧美大片免费| 久久精品国产一区二区三区| 精品国产乱码一区二区三| 疯狂做受xxxx欧美肥白少妇| 欧美老女人性生活视频| 国产精品99久久久久久宅男| 青青草视频在线免费播放 | 日韩欧美国产综合一区| 亚洲视频免费播放| 国产精品美女一区二区三区| 国产麻豆剧传媒精品国产| 国产亚洲高清视频| 致1999电视剧免费观看策驰影院| 伊人久久大香线蕉av超碰| 欧美整片在线观看| 秋霞a级毛片在线看| 亚洲第一区第二区| 中文字幕人妻一区二区三区视频| 亚洲精品乱码久久久久久久久| 国产国语性生话播放| 激情六月婷婷久久| 五十路熟女丰满大屁股| 国产高清久久| 国产精品推荐精品| a日韩av网址| 久久精品久久久久| 日本又骚又刺激的视频在线观看| 制服丝袜一区二区三区| 久草视频一区二区| 一区二区成人在线| 美女网站视频色| 91影院在线观看| 18深夜在线观看免费视频| 日本伊人午夜精品| 久久久久久久久久网| 91av精品| 亚洲.欧美.日本.国产综合在线| 电影一区二区在线观看| 亚洲一区二区三区四区视频| 波多野结衣亚洲| 午夜精品理论片| 超鹏97在线| 日韩中文视频免费在线观看| 日本国产在线| 亚洲精品一区二区三区影院| 国产又粗又黄又爽| 在线观看精品一区| 日韩一区二区视频在线| 亚洲专区一二三| 国产十六处破外女视频| 国产精品视频线看| 亚洲午夜精品久久久久久高潮| 99精品桃花视频在线观看| 精品人妻二区中文字幕| 国产资源在线一区| 久久精品久久99| 老司机免费视频一区二区| 妓院一钑片免看黄大片| 老鸭窝毛片一区二区三区| 国模无码视频一区二区三区| 在线观看的日韩av| 久久久久久久久久伊人| 亚洲色图二区| 免费观看中文字幕| 伊人久久大香线蕉综合四虎小说| 亚洲一区二区三区免费观看| 日本大胆欧美| 天天人人精品| 精品国产aⅴ| 视频一区亚洲 | 色999五月色| 国产精品一区二区99| 欧美伦理一区二区| 国产亚洲电影| 视频一区二区精品| 日韩美女一区二区三区在线观看| 亚洲精品一区二区三区四区五区 | 国产白丝精品91爽爽久久 | 久久综合九色欧美综合狠狠| 中国一级特黄录像播放| 久久综合色之久久综合| 国产 欧美 在线| 国产精品污www在线观看| av资源在线免费观看| 亚洲欧洲无码一区二区三区| 裸体武打性艳史| 无吗不卡中文字幕| 久久亚洲精品石原莉奈| 欧美日韩亚洲综合一区二区三区| 亚洲天堂免费av| 精品日韩在线一区| 午夜性色福利影院| 中文欧美日本在线资源| 黄网页免费在线观看| 久久久久久国产免费| 少妇视频一区| 国产精品久久久久久久久久 | 欧美在线观看视频在线| 一级片一区二区三区| 日韩精品一区二区三区在线播放| 天天色综合久久| 一区二区三区回区在观看免费视频| 香蕉视频在线看| 欧美人成在线视频| 中文字幕乱码中文乱码51精品| 国产精品欧美一区二区三区奶水| 国产精品3区| 久久久久久久久四区三区| 青草国产精品| 丰满的少妇愉情hd高清果冻传媒| 亚洲欧美久久久| 久久久久久久久久一区二区| 成人福利视频在线看| 美国黑人一级大黄| 亚洲一区二区在线视频| 波多野结衣高清在线| 精品国产髙清在线看国产毛片| 青青草免费观看免费视频在线| 精品国产一区av| 中文在线аv在线| 亚洲一区二区三区xxx视频| 久久最新网址| 秋霞无码一区二区| 久久精品免费观看| jlzzjizz在线播放观看| 亚洲人亚洲人成电影网站色| av一级在线观看| 精品剧情在线观看| 香蕉视频在线播放| 欧美亚洲另类激情另类| 北岛玲精品视频在线观看| 欧美综合77777色婷婷| 国产精品地址| 中文字幕日韩综合| 国产视频亚洲色图| 日本特黄特色aaa大片免费| 欧美蜜桃一区二区三区| 日韩国产福利| 欧美激情网站在线观看| 日韩毛片免费视频一级特黄| 蜜桃精品久久久久久久免费影院| 欧美韩国一区| 红桃视频 国产| 欧美国产激情一区二区三区蜜月| 成年人午夜视频| 日韩美女在线视频 | 亚洲欧洲成人自拍| 亚洲国产av一区二区三区| 亚洲第一页在线| 香蕉成人app免费看片| 91久久在线视频| 99久久精品费精品国产风间由美| 欧美日韩在线成人| 26uuu国产一区二区三区| 豆国产97在线 | 亚洲| 欧美成人伊人久久综合网| 免费在线观看av| 国产精品稀缺呦系列在线| 蜜桃国内精品久久久久软件9| 男人天堂手机在线视频| 国产不卡一区视频| 男人与禽猛交狂配| 日韩视频免费观看高清完整版在线观看 | 小视频免费在线观看| 成人精品水蜜桃| 欧美日韩ab| 岛国大片在线免费观看| 樱花影视一区二区| 亚洲第一视频在线播放| 久久久久久国产精品三级玉女聊斋 | 国产精品视频午夜| 精品理论电影在线| 欧美三级理论片| 国产精品国产三级国产专播品爱网| 最近中文字幕在线免费观看| 国产亚洲欧美日韩一区二区| 少妇精品视频一区二区免费看| 日韩欧美在线观看强乱免费| 美女视频第一区二区三区免费观看网站| 怡红院一区二区三区| 欧美天天综合网| 国产原创在线观看| 操人视频欧美| 国产欧美大片| 五月天综合视频| 欧美精品久久一区二区三区| 中文字幕在线播放网址| 国产一区二区三区av在线| 国产日韩1区| 国产美女永久免费无遮挡| 欧美妇女性影城| 美洲精品一卡2卡三卡4卡四卡| 国精产品一区二区| 久久性天堂网| 午夜爽爽爽男女免费观看| 日韩免费一区二区| 欧美一级鲁丝片| 相泽南亚洲一区二区在线播放| 韩国三级电影一区二区| 国产午夜福利精品| 亚洲天堂免费在线| 国产精品久久久久久久久久久久久久久 | 欧美日韩免费做爰大片| 国产日韩av高清| 狠狠色狠狠色综合日日tαg| 一本色道久久综合亚洲精品图片| 欧美日韩大陆在线| a毛片不卡免费看片| 日韩电影天堂视频一区二区| 国产一区二区三区免费播放| 日本一二三区不卡| 国产一区二区日韩精品欧美精品| 久久久91麻豆精品国产一区| 久久精品视频16| 亚洲天堂免费看| 亚洲aⅴ在线观看| 91免费国产网站| 男人的天堂亚洲| 欧美日韩精品亚洲精品| 永久555www成人免费| 红杏视频成人| 中文字幕国产免费|