亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

蟲蟲首頁| 資源下載| 資源專輯| 精品軟件
登錄| 注冊

您現(xiàn)在的位置是:首頁 > 技術(shù)閱讀 >  高端 | 如何快速定位程序Core?

高端 | 如何快速定位程序Core?

時間:2024-02-11
導(dǎo)讀:程序core是指應(yīng)用程序無法保持正常running狀態(tài)而發(fā)生的崩潰行為。程序core時會生成相關(guān)的core-dump文件,是程序崩潰時程序狀態(tài)的數(shù)據(jù)備份。core-dump文件中包含內(nèi)存、處理器、寄存器、程序計數(shù)器、棧指針等狀態(tài)信息。本文將介紹一些利用core-dump文件定位程序core原因的方法和技巧。
全文7023字,預(yù)計閱讀時間 13分鐘。

一、程序Core定義及分類


程序core是指應(yīng)用程序無法保持正常running狀態(tài)而發(fā)生的崩潰行為。程序core時會生成相關(guān)的core-dump文件,core-dump文件是程序崩潰時程序狀態(tài)的狀態(tài)數(shù)據(jù)備份。core-dump文件包含內(nèi)存、處理器、寄存器、程序計數(shù)器、棧指針等狀態(tài)信息。我們可以借助core-dump文件來分析定位程序Core的原因。

這里我們從三個方面對程序Core進(jìn)行分類:機(jī)器、資源、程序Bug。下表對常見的Core原因進(jìn)行了分類:


二、函數(shù)棧介紹

當(dāng)我們打開core文件時,首先關(guān)注的是程序崩潰時的函數(shù)調(diào)用棧狀態(tài),為了方便理解后續(xù)定位core的一些技巧,這里先簡單介紹一下函數(shù)棧。

2.1 寄存器介紹

目前生產(chǎn)環(huán)境都為64位機(jī),這里只介紹64位機(jī)的寄存器,如下:



對于x86-64架構(gòu),共有16個64位寄存器,每個寄存器的用途并不單一,如%rax通常保存函數(shù)返回結(jié)果,但也被應(yīng)用于imul和idiv指令。這里重點(diǎn)關(guān)注%rsp(棧頂指針寄存器)、%rbp(棧底指針寄存器)、%rdi、%rsi、%rdx、%rcx、%r8、%r9(分別對應(yīng)第1~6函數(shù)參數(shù))。

Callee Save說明是否需要被調(diào)用者保存寄存器的值。

2.2 函數(shù)調(diào)用


2.2.1 調(diào)用函數(shù)棧幀:

在調(diào)用一個函數(shù)時首先進(jìn)行的是參數(shù)壓棧,參數(shù)壓棧的順序跟參數(shù)定義的順序相反。注意,并不是參數(shù)一定會壓棧,在x86-64架構(gòu)中會針對可以使用寄存器傳遞的變量,直接通過寄存器傳值,如數(shù)字、指針、引用等。

接著是返回地址壓棧,返回地址為被調(diào)用函數(shù)執(zhí)行完后,調(diào)用函數(shù)執(zhí)行的下一個指令地址。這里牢記返回地址的位置,后續(xù)章節(jié)會利用到這個返回地址的特性。

針對上面的介紹舉個例子說明:



如上圖,在main函數(shù)中調(diào)用了foo函數(shù),首先對參數(shù)壓棧,三個參數(shù)都可以直接用寄存器傳遞(分別對應(yīng)%edi、%esi、%edx),然后call指令將下一個指令壓棧。

2.2.2 被調(diào)用函數(shù)棧幀:

被調(diào)用函數(shù)首先會將上一個函數(shù)的棧底指針(%rbp)保存,即%rbp壓棧。然后再保存需要被保存的寄存器值,即Callee Save為True的寄存器。接著為臨時變量、局部變量申請??臻g。


針對被調(diào)用函數(shù),舉個例子說明


如上圖,在foo函數(shù)執(zhí)行時,先對main函數(shù)的%rbp壓棧,再把寄存器中的參數(shù)值存放到局部變量(a, b, c)中。

2.3 總結(jié)

通過對函數(shù)調(diào)用的簡單介紹,我們可以發(fā)現(xiàn)函數(shù)棧是一個縝密且脆弱的結(jié)構(gòu),內(nèi)存結(jié)構(gòu)必須按照嚴(yán)格的方式被訪問,如稍有不慎就可能導(dǎo)致程序崩潰。

三、GDB定位Core

這一節(jié)將介紹從core文件打開到定位全流程中可能會遇到的問題以及解決技巧。

3.1 Core文件

core文件在哪里?

查看“/proc/sys/kernel/core_pattern”確定core文件生成規(guī)則。


3.2 變量打印

程序debug過程中常常要查看各種變量(內(nèi)存、寄存器、函數(shù)表等)的值是否正確,維持單獨(dú)用一節(jié)介紹下常用的變量打印方法以及一些冷門小技巧。

3.2.1 print命令

print [Expression]print $[Previous value number]print {[Type]}[Address]print [First element]@[Element count]print /[Format] [Expression]

Format格式:o - 8進(jìn)制x - 16進(jìn)制u - 無符號十進(jìn)制t - 二進(jìn)制f - 浮點(diǎn)數(shù)a - 地址c - 字符s - 字符串

3.2.2 x命令

x /<n/f/u>  <addr>n:是正整數(shù),表示需要顯示的內(nèi)存單元的個數(shù),即從當(dāng)前地址向后顯示n個內(nèi)存單元的內(nèi)容,一個內(nèi)存單元的大小由第三個參數(shù)u定義。
f:表示addr指向的內(nèi)存內(nèi)容的輸出格式,s對應(yīng)輸出字符串,此處需特別注意輸出整型數(shù)據(jù)的格式: x 按十六進(jìn)制格式顯示變量. d 按十進(jìn)制格式顯示變量。 u 按十進(jìn)制格式顯示無符號整型。 o 按八進(jìn)制格式顯示變量。 t 按二進(jìn)制格式顯示變量。 a 按十六進(jìn)制格式顯示變量。 c 按字符格式顯示變量。 f 按浮點(diǎn)數(shù)格式顯示變量。
u:就是指以多少個字節(jié)作為一個內(nèi)存單元-unit,默認(rèn)為4。u還可以用被一些字符表示: 如b=1 byte, h=2 bytes,w=4 bytes,g=8 bytes.
<addr>:表示內(nèi)存地址。

3.2.3 容器對象打印

利用上面的print和x命令,再結(jié)合容器的數(shù)據(jù)結(jié)構(gòu),我們就能知道容器的詳細(xì)信息。這里舉個完整打印二進(jìn)制string的例子,string的數(shù)據(jù)結(jié)構(gòu)如下:



string為空時,_M_dataplus._M_p是指向nullptr的。當(dāng)賦值后會在堆上申請一段內(nèi)存,分為兩段,前半段是meta信息(類型為std::string::_Rep),如length、capacity、refcount,后半段為數(shù)據(jù)區(qū),_M_p指向數(shù)據(jù)區(qū)。

通常情況下非二進(jìn)制的string,直接print即可顯示數(shù)據(jù)內(nèi)容,但當(dāng)數(shù)據(jù)為二進(jìn)制時,'\0'會截斷打印內(nèi)容。因此,打印二進(jìn)制string的首要任務(wù)是確認(rèn)string的size。

string的size信息保存在std::string::_Rep結(jié)構(gòu)體中,根據(jù)上面的數(shù)據(jù)結(jié)構(gòu)可以發(fā)現(xiàn),_Rep與_M_dataplus._M_p相差一個結(jié)構(gòu)體大小,因此打印_Rep結(jié)構(gòu)體的命令為:

#先把_M_p轉(zhuǎn)成_Rep指針,再讓指針向低地址偏移一個結(jié)構(gòu)體大小p *((std::string::_Rep*)(s._M_dataplus._M_p) - 1)


找到string的size(_M_length)后,再通過x命令打印相關(guān)的內(nèi)存區(qū)即可,命令為:

#這里的n是_Rep._M_lengthx /ncb s._M_dataplus._M_p


運(yùn)行效果如下:


為了方便,這里推薦一個方便的腳本:stl-views.gdb(鏈接:https://sourceware.org/gdb/wiki/STLSupport?action=AttachFile&do=view&target=stl-views-1.0.3.gdb,直接在gdb終端source stl-views.gdb即可,支持常見的容器打印,如vector、map、list、string等。

3.2.4 靜態(tài)變量打印

程序中經(jīng)常會使用到靜態(tài)變量,有時我們需要查看某個靜態(tài)對象的值是否正確,就涉及到靜態(tài)對象的打印??慈缦吕樱?/span>

void foo() {    static std::string s_foo("foo");}


這里可以借助nm -C ./bin  | grep xx找到靜態(tài)變量的內(nèi)存地址,再通過gdb的print打印。

3.2.5 內(nèi)存dump

dump [format] memory filename start_addr end_addrdump [format] value filename exprformat一般使用binary,其他的可以查看gdb手冊。
比如我們可以結(jié)合上面查看string內(nèi)容的例子dump整個string數(shù)據(jù)到文件中。dump binary memory file1 s._M_dataplus._M_p s._M_dataplus._M_p + length
如果想查看文件內(nèi)容的話可把vim -b和xxd結(jié)合使用。

接上面string的例子,舉一個dump string內(nèi)存數(shù)據(jù)到文件的例子:

3.3 定位代碼行

定位core的原因,首先要定位崩潰時正在執(zhí)行的代碼行,這一節(jié)主要介紹一些定位代碼行的方法。通常情況下直接通過gdb的breaktrace即可一覽整個函數(shù)棧,但有時候函數(shù)棧信息并非如此清晰明了,這時就可利用一些小技巧來查看函數(shù)棧。

3.3.1 去編譯優(yōu)化

有時候會發(fā)現(xiàn)core的函數(shù)棧跟實(shí)際的代碼行不匹配,如果是在線下環(huán)境中,可以嘗試把編譯優(yōu)化設(shè)置成-O0,然后再重新復(fù)現(xiàn)core問題。

3.3.2 程序計數(shù)器 + addr2line

對于線上core問題,一般沒法再對程序進(jìn)行去編譯優(yōu)化操作,只能在現(xiàn)有的core文件基礎(chǔ)上進(jìn)行代碼定位。這一節(jié)我們采用一個例子來介紹如何使用程序計數(shù)器 + addr2line來定位代碼行。



從截圖可以發(fā)現(xiàn)frame 20指示的代碼行與實(shí)際的代碼行是不匹配的,定位步驟如下:


# 跳轉(zhuǎn)到第20號棧frame 20 # 使用display命令顯示程序計數(shù)器display /i $rip # 使用addrline工具做地址轉(zhuǎn)換shell /opt/compiler/gcc-8.2/bin/addr2line -e bin address


3.3.3 函數(shù)棧修復(fù)

有時候我們會發(fā)現(xiàn)函數(shù)調(diào)用棧里面會出現(xiàn)很多??的情況,這常發(fā)生于棧被寫花,某些情況下手動進(jìn)行修復(fù)。函數(shù)棧的修復(fù)利用的函數(shù)棧內(nèi)存分布知識,見第一節(jié)。


-----------------------------------Low addresses-----------------------------------0(%rsp)  | top of the stack frame          | (this is the same as -n(%rbp))---------|--------------------------n(%rbp) | variable sized stack frame-8(%rbp) | varied0(%rbp)  | previous stack frame address8(%rbp)  | return address-----------------------------------High addresses


從上面的棧示意圖可以發(fā)現(xiàn),利用%rbp寄存器即可找到上一個函數(shù)的返回地址棧底指針,再利用addr2line命令找到對應(yīng)的代碼行。這里舉一個例子:


#首先找到當(dāng)前被調(diào)用棧上一個棧的棧底指針值和返回地址x /2ag $rbp # 2個單位,a=十六進(jìn)制,g=8字節(jié)單元  #使用上一條命令得到的棧底指針值依次遞歸x /2ag address

3.3.4 無規(guī)律core棧

無規(guī)律core棧問題一般發(fā)生于堆內(nèi)存寫壞。函數(shù)調(diào)用是一個非常精密的過程,任何一個位置發(fā)生非預(yù)期的讀寫都會導(dǎo)致程序崩潰。這里可以舉個小例子來說明:


int main(int argc, char* argv[]) {    std::string s("abcd");    *reinterpret_cast<uint64_t*>(&s) = 0x11;    return 0;}


上面的例子core在string析構(gòu)上,原因是因?yàn)閟tring的_M_ptr被改寫成了0x11,析構(gòu)流程變成了非法內(nèi)存操作。

同理,由于進(jìn)程堆空間是共享的,一個線程對堆的非法操作就可能會影響另一個線程的正常操作,由于堆分配的隨機(jī)性,表現(xiàn)出來的現(xiàn)象就是無規(guī)律core棧。

針對無規(guī)律core棧最好的方式還是借助AddressSanitizer


#設(shè)置編譯參數(shù)CXXFLAGSCXXFLAGS="-fPIC -fsanitize=address  -fno-omit-frame-pointer" #設(shè)置鏈接參數(shù)LDFLAGS="-lasan" # 設(shè)置啟動環(huán)境變量export ASAN_OPTIONS=halt_on_error=0:abort_on_error=1:disable_coredump=0 # 啟動LD_PRELOAD=/opt/compiler/gcc-8.2/lib/libasan.so ./bin/xxx


3.3.5 總結(jié)

上面提到的幾種方法都是為了找到具體的問題代碼行,為后續(xù)分析core的具體原因提供線索。


3.4 定位Core原因

這一節(jié)主要介紹定位Core原因的方法以及一些常見原因的介紹。


3.4.1 確認(rèn)信號量

從上面的Core分類我們可以發(fā)現(xiàn)某些場景的core是由于機(jī)器故障導(dǎo)致的,如SIGBUS,因此可以先通過信號量排除掉一些core原因。


3.4.2 定位異常匯編指令

通過上面的代碼行定位我們可以大致找到程序core在哪一行,比較簡單的core直接print程序上下文即可找到core的原因。

但有些場景下,通過排查上下文無任何異常,這個時候就需要準(zhǔn)確定位具體的異常匯編指令,根據(jù)指令找原因。

查看匯編指令比較簡單的方法是使用layout asm命令,frame指向那個棧,就顯示對應(yīng)棧的匯編。這里舉個core例子,如下:



程序顯示core在start函數(shù),查看相關(guān)上下文變量均無異常。使用layout asm打開正在執(zhí)行的匯編指令,如下:

查看匯編定位到程序core在mov指令,mov指令上一個指令為sub,為棧申請了3M空間,懷疑是??臻g不足。采用frame 0的%rsp - frame N的%rbp排查為棧空間不足。

通過上面的例子,可以發(fā)現(xiàn)定位異常匯編指令位置后,我們能夠把異常點(diǎn)進(jìn)一步壓縮,定位到是哪個指令、變量、地址導(dǎo)致的core問題。


3.4.3 排查異常變量

通過上面的操作我們可以準(zhǔn)確定位到具體是哪一行代碼的哪一條指令出現(xiàn)了問題,根據(jù)異常指令我們可以排查相關(guān)的變量,確定變量值是否符合預(yù)期。


這里舉一個比較經(jīng)典的空指針例子,如下:

int main(int argc, char* argv[]) {    int* a = nullptr;    *a = 1;    return *a;}


通過匯編指令我們可以發(fā)現(xiàn)是movl $0x1, (%rax)出現(xiàn)了問題,%rax的值來自于0x8(%rbp),x命令打印相關(guān)的地址就可以發(fā)現(xiàn)為空指針錯誤。


3.4.4 查看被優(yōu)化變量

通常情況下程序都是開啟了編譯優(yōu)化的,就會出現(xiàn)變量無法被print,提示變量被優(yōu)化,有時可利用匯編 + 寄存器的方式查看被優(yōu)化的變量。

這里舉一個例子說明下:

void foo(char const* str) {    char buf[1024] = {'\0'};    memcpy(buf, str, sizeof(buf));}
int main(int argc, char* argv[]) {    foo("abcd");    return 0;}


通常情況下在foo函數(shù)內(nèi)部,str變量是會直接別優(yōu)化掉的,因?yàn)榭梢灾苯永?rdi寄存器傳遞參數(shù)。為了能夠打印出str的值,這個時候我們可以借助匯編 + 寄存器的方式找到具體的變量值,如下:



首先找到main函數(shù)調(diào)用foo函數(shù)的參數(shù)壓棧匯編:mov $0x402011, %edi,這里的0x402011即為str的內(nèi)存地址,通過x命令即可顯示str的值了。

比較復(fù)雜的場景可能沒法直接找到被優(yōu)化變量,這時可以采用匯編回溯的方式找到變量。


3.4.5 異常函數(shù)地址排查

有時的core問題是因?yàn)閿?shù)據(jù)異常導(dǎo)致,有時也可能是優(yōu)化函數(shù)地址導(dǎo)致,如調(diào)用虛函數(shù)地址錯誤、函數(shù)返回地址錯誤、函數(shù)指針值錯誤。

異常函數(shù)地址排查同理于異常變量排查,根據(jù)匯編指令確認(rèn)調(diào)用是否異常即可。這里舉一個虛函數(shù)地址異常的例子,如下:

classA {public:    virtual ~A() = default;    virtual void foo() = 0;};classB : public A {public:    void foo() {}}; int main(int argc, char* argv[]){    A* a = new B;    a->foo();    A* b = new B;    *reinterpret_cast<void**>(b) = 0x0;    b->foo();     return 0;}


從匯編指令看是core在了mov (%rax), %rax,結(jié)合指令上下文可發(fā)現(xiàn)是在虛函數(shù)地址尋址操作,對比兩個變量的虛函數(shù)表即可發(fā)現(xiàn)是函數(shù)地址load錯誤導(dǎo)致的core。


3.4.6 總結(jié)

定位core的基本流程可總結(jié)為以下幾步:

  1. 明確core的大致觸發(fā)原因。機(jī)器問題?自身程序問題?
  2. 定位代碼行。哪一行代碼出現(xiàn)了問題。
  3. 定位執(zhí)行指令。哪一行指令干了什么事。
  4. 定位異常變量。指令不會有問題,是指令操作的變量不符合預(yù)期。
善于利用匯編指令以及打印指令(x、print、display)可以更有效的定位Core。

參考資料:

匯編查看工具:https://godbolt.org/ https://cppinsights.io/
標(biāo)準(zhǔn)GDB文檔:https://sourceware.org/gdb/current/onlinedocs/gdb/


往期推薦



推薦幾個開源庫

C 語言的那些坑!

高端知識點(diǎn) — socket fd 是什么?

Linux C++ 服務(wù)器端這條線怎么走?

百家號在線視頻編輯器的技術(shù)演進(jìn)


一鍵三連,好運(yùn)連連,bug不見????

亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲美女尤物影院| 久久免费视频在线观看| 激情久久综艺| 亚洲精品视频二区| 亚洲素人一区二区| 久久久av毛片精品| 欧美视频一区二区三区四区| 国产午夜精品一区二区三区视频| 精品成人一区二区三区四区| 午夜精品在线观看| 欧美性开放视频| 亚洲国产精品福利| 久久精品中文字幕一区二区三区| 女女同性精品视频| 国产日韩在线视频| 亚洲制服欧美中文字幕中文字幕| 母乳一区在线观看| 国产亚洲精品v| 亚洲欧美日韩爽爽影院| 欧美日韩精品一区二区| 亚洲电影免费观看高清| 欧美在线免费播放| 国产精品一区二区久激情瑜伽| 一区二区三区www| 欧美国产日韩视频| 91久久精品国产91久久性色tv| 久久人体大胆视频| 国产精品亚洲美女av网站| 亚洲一区二区三区涩| 欧美视频日韩视频在线观看| 一本到12不卡视频在线dvd| 欧美不卡视频一区发布| 亚洲大胆视频| 女主播福利一区| 亚洲福利视频二区| 免费欧美网站| 亚洲国产精品嫩草影院| 久久精品免费看| 国产一区美女| 卡通动漫国产精品| 亚洲欧洲美洲综合色网| 久久深夜福利| 亚洲国产一区二区三区高清 | 久久国产精品久久久久久久久久| 国产噜噜噜噜噜久久久久久久久| 亚洲综合视频在线| 黄色亚洲精品| 欧美日韩大片一区二区三区| 9久re热视频在线精品| 欧美午夜精品一区二区三区| 亚洲欧美成人精品| 国产一区二区黄色| 免费成人小视频| 99国产精品久久久| 国产精品午夜av在线| 欧美在线关看| 日韩视频中午一区| 国产精品青草久久久久福利99| 欧美一区二区三区婷婷月色| 激情小说亚洲一区| 欧美精品在线视频| 久久精品女人的天堂av| 亚洲精品日韩一| 国产精品免费视频xxxx| 男女激情久久| 午夜久久99| 亚洲精品日韩久久| 国产色综合网| 欧美日韩一区二区三区四区五区| 久久精品夜夜夜夜久久| 一区二区三区四区五区视频| 在线成人av网站| 国产精品婷婷| 欧美日韩国产系列| 免费观看国产成人| 欧美资源在线| 亚洲夜晚福利在线观看| 在线观看日韩av电影| 国产欧美一区二区精品性色| 巨胸喷奶水www久久久免费动漫| 亚洲一区二区动漫| 日韩一级精品视频在线观看| 国产视频欧美| 欧美系列电影免费观看| 欧美日本在线观看| 欧美成ee人免费视频| 久久久久这里只有精品| 欧美亚洲一区二区在线| 亚洲尤物视频网| 中文久久精品| 亚洲一区二区三区成人在线视频精品| 亚洲国产日韩欧美| 在线观看日韩| 1769国产精品| 亚洲电影在线看| 尤物网精品视频| 黄色成人在线免费| 精品999网站| 在线欧美视频| 亚洲国产欧美不卡在线观看| 亚洲第一黄色| 亚洲精品日韩一| 亚洲天堂av电影| 亚洲欧美日韩高清| 久久xxxx| 欧美二区在线播放| 欧美精品一区在线观看| 欧美三级第一页| 国产精品一区二区a| 国内精品视频在线观看| 在线精品观看| 99精品国产福利在线观看免费| 一区二区三欧美| 性色一区二区三区| 久久久久网站| 欧美激情一区二区三区不卡| 欧美三级在线视频| 国产视频综合在线| 在线国产日韩| 在线一区二区视频| 欧美在线一级视频| 欧美电影免费观看高清| 欧美日韩一区二区视频在线观看| 国产精品成人一区| 国产一区二区三区成人欧美日韩在线观看| 激情久久久久久久| 一区二区日韩精品| 久久久综合网站| 欧美视频精品一区| 国产综合色产| 在线一区二区日韩| 欧美不卡视频一区发布| 国产欧美精品在线观看| 在线精品国产欧美| 亚洲在线免费观看| 欧美aa国产视频| 国产农村妇女精品一区二区| 亚洲欧洲一区二区三区| 欧美影院成年免费版| 欧美国产精品劲爆| 国产婷婷精品| 亚洲欧美国产精品va在线观看 | 亚洲视频在线播放| 久久久久久久成人| 欧美三日本三级三级在线播放| 国内精品久久久久久 | 午夜国产不卡在线观看视频| 另类综合日韩欧美亚洲| 国产精品日韩一区| 亚洲激情国产| 久久久五月婷婷| 国产精品一区二区三区四区| 亚洲美女视频在线观看| 久久久另类综合| 国产精品欧美一区喷水| 亚洲精品乱码久久久久久日本蜜臀 | 日韩一级成人av| 久久高清一区| 欧美特黄a级高清免费大片a级| 激情综合在线| 久久精品99国产精品日本| 国产精品一区在线观看| 亚洲欧美国产77777| 欧美视频一区二区三区| 一二三区精品| 欧美日韩99| 91久久国产精品91久久性色| 美女精品在线| 亚洲欧洲日产国码二区| 欧美大片在线观看一区二区| 亚洲黄色在线观看| 欧美电影免费观看大全| 亚洲美女中出| 欧美日韩免费在线观看| 亚洲深爱激情| 国产精品一级久久久| 亚洲免费在线精品一区| 国产精品亚洲综合一区在线观看 | 国内精品嫩模av私拍在线观看| 亚洲综合精品一区二区| 国产乱码精品一区二区三区忘忧草| 亚洲一区二区成人在线观看| 国产精品久久毛片a| 午夜亚洲福利| 国产一区二区三区四区五区美女 | 欧美一区二区三区视频免费播放| 国产精品你懂的| 久久激情五月丁香伊人| 在线精品视频一区二区| 欧美成人精品1314www| 日韩一本二本av| 国产伦精品一区二区三区在线观看| 午夜精品999| 一区在线观看视频| 欧美日韩福利| 亚洲女同精品视频| 黄色国产精品| 欧美午夜在线一二页| 久久久久久久波多野高潮日日| 亚洲欧洲一区二区在线观看|