3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 可执行文件的分析(gcc GUN BUILEIN)

發布時間:2023/12/18 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 可执行文件的分析(gcc GUN BUILEIN) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、GCC

The History of GCC


?

1984年,Richard Stallman發起了自由軟件運動,GNU (Gnu's Not Unix)項目應運而生,3年后,最初版的GCC橫空出世,成為第一款可移植、可優化、支持ANSI C的開源C編譯器。
GCC最初的全名是GNU C Compiler,之后,隨著GCC支持的語言越來越多,它的名稱變成了GNU Compiler Collection。
這里介紹的gcc是GCC的前端,C編譯器.


警告信息


-Wall : 顯示所有常用的編譯警告信息。
?? ?-W??? : 顯示更多的常用編譯警告,如:變量未使用、一些邏輯錯誤。
?? ?-Wconversion : 警告隱式類型轉換。
?? ?-Wshadow : 警告影子變量(在代碼塊中再次聲明已聲明的變量)
?? ?-Wcast-qual :警告指針修改了變量的修飾符。如:指針修改const變量。
?? ?-Wwrite-strings : 警告修改const字符串。
?? ?-Wtraditional : 警告ANSI編譯器與傳統C編譯器有不同的解釋。
?? ?-Werror : 即使只有警告信息,也不編譯。(gcc默認:若只有警告信息,則進行編譯,若有錯誤信息,則不編譯)


C語言標準


你可以在gcc的命令行中通過指定選項來選擇相應的C語言標準: 從傳統c到最新的GNU擴展C. 默認情況下, gcc使用最新的GNU C擴展.

?? ?-ansi : 關閉GNU擴展中與ANSI C相抵觸的部分。
?? ?-pedantic????????? : 關閉所有的GNU擴展。
?? ?-std=c89?????????? : 遵循C89標準
?? ?-std=c99?????????? : 遵循C99標準
??? -std=traditional : 使用原始C
注意:后4個選項可以與-ansi結合使用,也可以單獨使用。

可在gcc中使用大量GNU C擴展.

生成特定格式的文件


以hello.c為例子,可以設置選項生成hello.i, hello.s, hello.o以及最終的hello文件:

?? ?hello.c : 最初的源代碼文件;
?? ?hello.i : 經過編譯預處理的源代碼;
?? ?hello.s : 匯編處理后的匯編代碼;
?? ?hello.o : 編譯后的目標文件,即含有最終編譯出的機器碼,但它里面所引用的其他文件中函數的內存位置尚未定義。
??? hello / a.out : 最終的可執行文件
??? (還有.a(靜態庫文件), .so(動態庫文件), .s(匯編源文件)留待以后討論)

如果你不通過-o指定生成可執行文件名,那么會默認生成a.out. 不指定生成文件名肯能覆蓋你上次生成的a.out.

e.g.
$ gcc hello.c
在不給gcc傳遞任何參數的情況下, gcc執行默認的操作: 將源文件編譯為目標文件--> 將目標文件連接為可執行文件(名為a.out) --> 刪除目標文件.

-c生成.o文件時,默認生成與源代碼的主干同名的.o文件。比如對應hello.c生成hello.o. 但也可在生成目標文件時指定目標文件名(注意同時要給出.o后綴): $gcc -c -o demo.o demo.c

??? $ gcc -Wall -c hello.c????????????? : 生成hello.o
?? ?$ gcc -Wall -c -save-temps hello.c? : 生成hello.i, hello.s, hello.o
?? ?注意-Wall 選項的使用場合:僅在涉及到編譯(即會生成.o文件時,用-Wall)??

多文件編譯、連接


如果原文件分布于多個文件中:file1.c, file2,c
?? ?$ gcc -Wall file1.c file2.c -o name

若對其中一個文件作了修改,則可只重新編譯該文件,再連接所有文件:
?? ?$ gcc -Wall -c file2.c
?? ?$ gcc file1.c file2.o -c name

注意:若編譯器在命令行中從左向右順序讀取.o文件,則它們的出現順序有限制:含有某函數定義的文件必須出現在含有調用該函數的文件之后。好在GCC無此限制。

編譯預處理


以上述的hello.c為例, 要對它進行編譯預備處理, 有兩種方法: 在gcc中指定-E選項, 或直接調用cpp.gcc的編譯預處理命令程序為cpp,比較新版本的gcc已經將cpp集成了,但仍提供了cpp命令. 可以直接調用cpp命令, 也可以在gcc中指定-E選項指定它只進行編譯預處理.

$ gcc -E hello.c??????????????????????????? ==? $ cpp hello.c
上述命令馬上將預處理結果顯示出來. 不利于觀看. 可采用-c將預處理結果保存:
$ gcc -E -c hello.i hello.c????????????? ==? $ cpp -o hello.i hello.c
注意, -c指定名稱要給出".i"后綴.

另外, gcc針對編譯預處理提供了一些選項:
(1) 除了直接在源代碼中用 #define NAME來定義宏外,gcc可在命令行中定義宏:-DNAME(其中NAME為宏名),? 也可對宏賦值: -DNAME=value 注意等號兩邊不能有空格! 由于宏擴展只是一個替換過程,也可以將value換成表達式,但要在兩邊加上雙括號: -DNAME="statement"
e.g. $ gcc -Wall -DVALUE="2+2" tmp.c -o tmp
如果不顯示地賦值,如上例子,只給出:-DVALUE,gcc將使用默認值:1.

(2) 除了用戶定義的宏外, 有一些宏是編譯器自動定義的,它們以__開頭,運行: $ cpp -dM /dev/null, 可以看到這些宏. 注意, 其中含有不以__開頭的非ANSI宏,它們可以通過-ansi選項被禁止。
?
查看宏擴展

1, 運行 $ gcc -E test.c ,gcc對test.c進行編譯預處理,并立馬顯示結果. (不執行編譯) 2, 運行 $gcc -c -save-temps test.c ,不光產生test.o,還產生test.i, test.s,前者是編譯預處理結果, 后者是匯編結果.
???
利用Emacs查看編譯預處理結果

針對含有編譯預處理命令的代碼,可以利用emacs方便地查看預處理結果,而不需執行編譯,更為方便的是,可以只選取一段代碼,而非整個文件:
1,選擇想要查看的代碼
2,C-c C-e (M-x c-macro-expand)
這樣,就自動在一個名為"Macroexpansion"的buffer中顯示pre-processed結果.

生成匯編代碼

使用"-S"選項指定gcc生成以".s"為后綴的匯編代碼:
$ gcc -S hello.c
$ gcc -S -o hello.s hello.c

生成匯編語言的格式取決于目標平臺. 另外, 如果是多個.c文件, 那么針對每一個.c文件生成一個.s文件.

包含頭文件在程序中包含與連接庫對應的頭文件是很重要的方面,要使用庫,就一定要能正確地引用頭文件。一般在代碼中通過#include引入頭文件, 如果頭文件位于系統默認的包含路徑(/usr/includes), 則只需在#include中給出頭文件的名字, 不需指定完整路徑.? 但若要包含的頭文件位于系統默認包含路徑之外, 則有其它的工作要做: 可以(在源文件中)同時指定頭文件的全路徑. 但考慮到可移植性,最好通過-I在調用gcc的編譯命令中指定。

?

?

下面看這個求立方的小程序(陰影語句表示剛開始不存在):

#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[])
{
? double x = pow (2.0, 3.0);
? printf("The cube of 2.0 is %f/n", x);
? return 0;
}

使用gcc-2.95來編譯它(-lm選項在后面的連接選項中有介紹, 這里只討論頭文件的包含問題):
$ gcc-2.95 -Wall pow.c -lm -o pow_2.95
pow.c: In function `main':
pow.c:5: warning: implicit declaration of function `pow'

程序編譯成功,但gcc給出警告: pow函數隱式聲明。
$ ./pow_2.95
The cube of 2.0 is 1.000000

明顯執行結果是錯誤的,在源程序中引入頭文件(#include <math.h>),消除了錯誤。

不要忽略Warning信息!它可能預示著,程序雖然編譯成功,但運行結果可能有錯。故,起碼加上"-Wall"編譯選項!并盡量修正Warning警告。

搜索路徑

首先要理解 #include<file.h>和#include"file.h"的區別:
#include<file.h>只在默認的系統包含路徑搜索頭文件
#include"file.h"首先在當前目錄搜索頭文件, 若頭文件不位于當前目錄, 則到系統默認的包含路徑搜索頭文件.

UNIX類系統默認的系統路徑為:

頭文件,包含路徑: /usr/local/include/? or? /usr/include/
庫文件,連接路徑: /usr/local/lib/????????? or? /usr/lib/???

對于標準c庫(glibc或其它c庫)的頭文件, 我們可以直接在源文件中使用#include <file.h>來引入頭文件.

如果要在源文件中引入自己的頭文件, 就需要考慮下面的問題:

1, 如果使用非系統頭文件, 頭文件和源文件位于同一個目錄, 如何引用頭文件呢?
——我們可以簡單地在源文件中使用 #include "file.h", gcc將當前目錄的file.h引入到源文件. 如果你很固執, 仍想使用#include <file.h>語句, 可以在調用gcc時添加"-I."來將當前目錄添加到系統包含路徑. 細心的朋友可能會想到: 這樣對引用其它頭文件會不會有影響? 比如, #include<file.h>之后緊接著一個#include<math.h>, 它能正確引入math.h嗎? 答案是: 沒有影響. 仍然能正確引用math.h. 我的理解是: "-I."將當前目錄作為包含路徑的第一選擇, 若在當前目錄找不到頭文件, 則在默認路徑搜索頭文件. 這實際上和#include"file.h"是一個意思.

2, 對于比較大型的工程, 會有許多用戶自定義的頭文件, 并且頭文件和.c文件會位于不同的目錄. 又該如何在.c文件中引用頭文件呢?
—— 可以直接在.c文件中利用#include“/path/file.h", 通過指定頭文件的路徑(可以是絕對路徑, 也可以是相對路徑)來包含頭文件. 但這明顯降低了程序的可移植性. 在別的系統環境下編譯可能會出現問題. 所以還是利用"-I"選項指定頭文件完整的包含路徑.

針對頭文件比較多的情況, 最好把它們統一放在一個目錄中, 比如~/project/include. 這樣就不需為不同的頭文件指定不同的路徑. 如果你嫌每次輸入這么多選項太麻煩, 你可以通過設置環境變量來添加路徑:
$ C_INCLUDE_PATH=/opt/gdbm-1.8.3/include
$ export C_INCLUDE_PATH
$ LIBRART_PATH=/opt/gdbm-1.8.3/lib
$ export LIBRART_PATH

可一次指定多個搜索路徑,":"用于分隔它們,"."表示當前路徑,如:
$ C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include
$ LIBRARY_PATH=.:/opt/gdbm-1.8.3/lib:/net/lib
(可以添加多個路徑,路徑之間用:相隔,.代表當前目錄,若.在最前頭,也可省略)

當然,若想永久地添加這些路徑,可以在.bash_profile中添加上述語句.

3, 還有一個比較猥瑣的辦法: 系統默認的包含路徑不是/usr/include或/usr/local/include么? 我把自己的頭文件拷貝到其中的一個目錄, 不就可以了么? 的確可以這樣, 如果你只想在你自己的機器上編譯運行這個程序的話.

前面介紹了三種添加搜索路徑的方法,如果這三種方法一起使用,優先級如何呢?
命令行設置 > 環境變量設置 > 系統默認

與外部庫連接


前面介紹了如何包含頭文件. 而頭文件和庫是息息相關的, 使用庫時, 要在源代碼中包含適當的頭文件,這樣才能聲明庫中函數的原型(發布庫時, 就需要給出相應的頭文件).

和包含路徑一樣, 系統也有默認的連接路徑:
頭文件,包含路徑: /usr/local/include/? or? /usr/include/
庫文件,連接路徑: /usr/local/lib/????????? or? /usr/lib/??

同樣地, 我們想要使用某個庫里的函數, 必須將這個庫連接到使用那些函數的程序中.

有一個例外: libc.a或libc.so (C標準庫,它包含了ANSI C所定義的C函數)是不需要你顯式連接的, 所有的C程序在運行時都會自動加載c標準庫.

除了C標準庫之外的庫稱之為"外部庫", 它可能是別人提供給你的, 也可能是你自己創建的(后面有介紹如何創建庫的內容).

外部庫有兩種:(1)靜態連接庫lib.a
???????????????????? (2)共享連接庫lib.so

兩者的共同點:
??? .a, .so都是.o目標文件的集合,這些目標文件中含有一些函數的定義(機器碼),而這些函數將在連接時會被最終的可執行文件用到。

兩者的區別:
?? ?靜態庫.a? : 當程序與靜態庫連接時,庫中目標文件所含的所有將被程序使用的函數的機器碼被copy到最終的可執行文件中. 靜態庫有個缺點: 占用磁盤和內存空間. 靜態庫會被添加到和它連接的每個程序中, 而且這些程序運行時, 都會被加載到內存中. 無形中又多消耗了更多的內存空間.

??? 共享庫.so : 與共享庫連接的可執行文件只包含它需要的函數的引用表,而不是所有的函數代碼,只有在程序執行時, 那些需要的函數代碼才被拷貝到內存中, 這樣就使可執行文件比較小, 節省磁盤空間(更進一步,操作系統使用虛擬內存,使得一份共享庫駐留在內存中被多個程序使用).共享庫還有個優點: 若庫本身被更新, 不需要重新編譯與它連接的源程序。

靜態庫

下面我們來看一個簡單的例子,計算2.0的平方根(假設文件名為sqrt.c):

#include <math.h>
#include <stdio.h>
int
main (void)
{
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f/n", x);
return 0;
}

用gcc將它編譯為可執行文件:
$ gcc -Wall sqrt.c -o sqrt
編譯成功,沒有任何警告或錯誤信息。執行結果也正確。
$ ./sqrt
The square root of 2.0 is 1.414214
????
下面我們來看看剛才使用的gcc版本:
$ gcc --version
??gcc (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)

現在我用2.95版的gcc把sqrt.c再編譯一次:
$ gcc-2.95 -Wall sqrt.c -o sqrt_2.95
??/tmp/ccVBJd2H.o: In function `main':
??sqrt.c:(.text+0x16): undefined reference to `sqrt'
???? collect2: ld returned 1 exit status
????
編譯器會給出上述錯誤信息,這是因為sqrt函數不能與外部數學庫"libm.a"相連。sqrt函數沒有在程序中定義,也不存在于默認C庫 "libc.a"中,如果用gcc-2.95,應該顯式地選擇連接庫。上述出錯信息中的"/tmp/ccVBJd2H.o"是gcc創造的臨時目標文件,用作連接時用。

使用下列的命令可以成功編譯:
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.a -o sqrt_2.95
它告知gcc:在編譯sqrt.c時,加入位于/usr/lib中的libm.a庫(C數學庫)。

C庫文件默認位于/usr/lib, /usr/local/lib系統目錄中; gcc默認地從/usr/local/lib, /usr/lib中搜索庫文件。(在我的Ubuntu系統中,C庫文件位于/urs/lib中。

這里還要注意連接順序的問題,比如上述命令,如果我改成:
$ gcc-2.95 -Wall /usr/lib/libm.asqrt.c -o sqrt_2.95
gcc會給出出錯信息:
?/tmp/cc6b3bIa.o: In function `main':
?sqrt.c:(.text+0x16): undefined reference to `sqrt'
?collect2: ld returned 1 exit status

正如讀取目標文件的順序,gcc也在命令行中從左向右讀取庫文件——任何包含某函數定義的庫文件必須位于調用該函數的目標文件之后!

指定庫文件的絕對路徑比較繁瑣,有一種簡化方法,相對于上述命令,可以用下面的命令來替代:
$ gcc-2.95 -Wall sqrt.c -lm -o sqrt_2.95
其中的"-l"表示與庫文件連接,"m"代表"libm.a"中的m。一般而言,"-lNAME"選項會使gcc將目標文件與名為"libNAME.a"的庫文件相連。(這里假設使用默認目錄中的庫,對于其他目錄中的庫文件,參考后面的“搜索路徑”。)

上面所提到的"libm.a"就是靜態庫文件,所有靜態庫文件的擴展名都是.a!
$ whereis libm.a
??libm: /usr/lib/libm.a /usr/lib/libm.so

正如前面所說,默認的庫文件位于/usr/lib/或/usr/local/lib/目錄中。其中,libm.a是靜態庫文件,libm.so是后面會介紹的動態共享庫文件。

如果調用的函數都包含在libc.a中(C標準庫被包含在/usr/lib/libc.a中,它包含了ANSI C所定義的C函數)。那么沒有必要顯式指定libc.a:所有的C程序運行時都自動包含了C標準庫!(試試 $ gcc-2.95 -Wall hello.c -o hello)。

共享庫

正因為共享庫的優點,如果系統中存在.so庫,gcc默認使用共享庫(在/usr/lib/目錄中,庫文件以共享和靜態兩種版本存在)。?

運行:$ gcc -Wall -L. hello.c -lNAME -o hello
gcc先檢查是否有替代的libNAME.so庫可用。???

正如前面所說,共享庫以.so為擴展名(so == shared object)。

那么,如果不想用共享庫,而只用靜態庫呢?可以加上 -static選項
$ gcc -Wall -static hello.c -lNAME -o hello
它等價于:
$ gcc -Wall hello.c libNAME.a -o hello

$ gcc-2.95 -Wall sqrt.c -static -lm -o sqrt_2.95_static
$ gcc-2.95 -Wall sqrt.c -lm -o sqrt_2.95_default
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.a -o sqrt_2.95_a
$ gcc-2.95 -Wall sqrt.c /usr/lib/libm.so -o sqrt_2.95_so

$ ls -l sqrt*
-rwxr-xr-x? 1 zp zp? 21076 2006-04-25 14:52 sqrt_2.95_a
-rwxr-xr-x? 1 zp zp?? 7604 2006-04-25 14:52 sqrt_2.95_default
-rwxr-xr-x? 1 zp zp?? 7604 2006-04-25 14:52 sqrt_2.95_so
-rwxr-xr-x? 1 zp zp 487393 2006-04-25 14:52 sqrt_2.95_static

上述用四種方式編譯sqrt.c,并比較了可執行文件的大小。奇怪的是,-static -lm 和 /lib/libm.a為什么有區別?有知其原因著,懇請指明,在此謝謝了! :)

如果libNAME.a在當前目錄,應執行下面的命令:
$ gcc -Wall -L. hello.c -lNAME -o hello
-L.表示將當前目錄加到連接路徑。

利用GNU archiver創建庫

$ ar cr libhello.a hello_fn.o by_fn.o
從hello_fn.o和by_fn.o創建libihello.a,其中cr表示:creat & replace
$ ar t libhello.a
列出libhello.a中的內容,t == table
(也可創建libhello.so)

關于創建庫的詳細介紹,可參考本blog的GNU binutils筆記


調試

?


一般地,可執行文件中是不包含任何對源代碼的參考的,而debugger要工作,就要知道目標文件/可執行文件中的機器碼對應的源代碼的信息(如:哪條語句、函數名、變量名...). debugger工作原理:將函數名、變量名,對它們的引用,將所有這些對象對應的代碼行號儲存到目標文件或可執行文件的符號表中。

?

GCC提供-g選項,將調試信息加入到目標文件或可執行文件中。
$ gcc -Wall -g hello.c -o hello

注意:若發生了段錯誤,但沒有core dump,是由于系統禁止core文件的生成!
$ ulimit -c  ,若顯示為0,則系統禁止了core dump

解決方法:
$ ulimit -c unlimited  (只對當前shell進程有效)
或在~/.bashrc 的最后加入: ulimit -c unlimited (一勞永逸)

優化


GCC具有優化代碼的功能,代碼的優化是一項比較復雜的工作,它可歸為:源代碼級優化、速度與空間的權衡、執行代碼的調度。

?

GCC提供了下列優化選項:
??? -O0? : 默認不優化(若要生成調試信息,最好不優化)
??? -O1? : 簡單優化,不進行速度與空間的權衡優化;???
??? -O2? : 進一步的優化,包括了調度。(若要優化,該選項最適合,它是GNU發布軟件的默認優化級別;
??? -O3? : 雞肋,興許使程序速度更慢;
??? -funroll-loops? : 展開循環,會使可執行文件增大,而速度是否增加取決于特定環境;
??? -Os? : 生成最小執行文件;

一般來說,調試時不優化,一般的優化選項用-O2(gcc允許-g與-O2聯用,這也是GNU軟件包發布的默認選項),embedded可以考慮-Os。

注意:此處為O!(非0或小寫的o,-o是指定可執行文件名)。

檢驗優化結果的方法:$ time ./prog

time測量指定程序的執行時間,結果由三部分組成:
??? real : 進程總的執行時間, 它和系統負載有關(包括了進程調度,切換的時間)
??? user: 被測量進程中用戶指令的執行時間
??? sys? : 被測量進程中內核代用戶指令執行的時間

user和sys的和被稱為CPU時間.

注意:對代碼的優化可能會引發警告信息,移出警告的辦法不是關閉優化,而是調整代碼。


2、ar


??? ar用于建立、修改、提取檔案文件(archive)。archive是一個包含多個被包含文件的單一文件(也稱之為庫文件),其結構保證了可以從中檢索并得到原始的被包含文件(稱之為archive中的member)。member的原始文件內容、模式(權限)、時間戳、所有著和組等屬性都被保存在 archive中。member被提取后,他們的屬性被恢復到初始狀態。
???
??? ar主要用于創建C庫文件

?

創建靜態庫?
??? (1) 生成目標文件:??

$ gcc -Wall -c file1.c file2.c file3.c
???
??? 不用指定生成.o文件名(默認生成file1.o, file2.o, file3.o)。

??? (2) 從.o目標文件創建靜態連接庫:
???
$ ar rv libNAME.a file1.o file2.o file3.o
???
??? ar生成了libNAME.a庫,并列出庫中的文件。
??? r : 將flie1.o, file2,o, file3.o插入archive,如故原先archive中已經存在某文件,則先將該文件刪除。
??? v : 顯示ar操作的附加信息(如被處理的member文件名)

注: 對于BSD系統, 還需要在創建靜態庫之后創建索引: $ ranlib libNAME.a Linux中不需要這一步(運行它也是無害的).

創建動態庫(利用gcc,未用ar)

(1) 生成目標文件

$ gcc -Wall -c -fpic file1.c file2.c file3.c

-fpic: 指定生成的.o目標文件可被重定址. pic是position idependent code的縮寫: 位置無關代碼.

(2)生成動態庫文件

$ gcc -shared -o libNAME.so file1.o file2.o file3.o

一般地, 連接器使用main()函數作為程序入口. 但在動態共享庫中沒有這樣的入口. 所以就要指定-shared選項來避免編譯器顯示出錯信息.

實際上, 上述的兩條命令可以合并為下面這條:

$ gcc -Wall -shared -fpic -o libNAME.so file1.c file2.c file3.c


此后,將main函數所在的程序與libNAME.so連接(注意庫連接路徑和頭文件包含路徑,以及連接順序!參考 gcc筆記)
???
至此,與動態庫連接的函數編譯成了一個可執行文件。貌似成功了,但還差最后一步。如果直接運行該程序,會給出這樣的錯誤信息:

error while loading shared libraries: libhello.so:
cannot open shared object file: No such file or directory

這是因為與動態庫連接的程序在運行時,首先將該動態庫加載到內存中,而gcc默認加載動態庫文件所在目錄為/usr/local/lib, /usr/lib。剛才的程序雖然能編譯成功,但如果我們自己建立的動態庫沒有位于默認目錄中,則執行時會應為無法找到它而失敗。
??
解決辦法:改變加載路徑對應的環境變量,然后再執行。
???
export LD_LIBRARY_PATH=動態庫所在目錄:$LD_LIBRARY_PATH

查看archive內容

$ ar tv archiveNAME

t : 顯示archive中member的內容,若不指定member,則列出所有。
v : 與t結合使用時,顯示member的詳細信息。

要想進了解ar的詳細選項,參考ar的 on-line manual


nm

??? nm用來列出目標文件中的符號,可以幫助程序員定位和分析執行程序和目標文件中的符號信息和它的屬性。
??? 如果沒有目標文件作為參數傳遞給nm, nm假定目標文件為a.out.
??? 這里用一個簡單的示例程序來介紹nm的用法:

main.c:

int main(int argc, char *argv[])
{
? hello();
? bye();
? return 0;
}

hello.c:??
void hello(void)
{
? printf("hello!/n");
}

bye.c:
???
void bye(void)
{
? printf("good bye!/n");
}

??? 運行下列命令:
??? $ gcc -Wall -c main.c hello.c bye.c
??? gcc生成main.o, hello.o, bye.o三個目標文件(這里沒有聲明函數原型,加了-Wall,gcc會給出警告)
??? $ nm main.o hello.o bye.o

結果顯示如下:??
main.o:
???????????????? U bye
???????????????? U hello
00000000 T main

hello.o:
00000000 T hello
??????? ? ? ? ?? U puts

bye.o:
00000000 T bye
???????????????? U puts

??? 結合這些輸出結果,以及程序代碼,可以知道:
??? 對于main.o, bye和hello未被定義, main被定義了
??? 對于hello.o, hello被定義了, puts未被定義
??? 對于bye.o, bye被定義了,puts未被定義

幾個值得注意的問題:
??? (1)"目標文件"指.o文件, 庫文件, 最終的可執行文件
??? .o? : 編譯后的目標文件,即含有最終編譯出的機器碼,但它里面所引用的其他文件中函數的內存位置尚未定義.
??? (2)如果用nm查看可執行文件, 輸出會比較多, 仔細研究輸出, 可以對nm用法有更清醒的認識.
??? (3)在上述hello.c, bye.c中, 調用的是printf(), 而nm輸出中顯示調用的是puts(), 說明最終程序實際調用的puts(), 如果令hello.c或bye.c中的printf()使用格式化輸出,則nm顯示調用printf(). ( 如: printf("%d", 1); )
???
??? 關于nm的參數選項,參考 on-line manual


objcopy

??? objcopy可以將一種格式的目標文件轉化為另外一種格式的目標文件. 它使用GNU BFD庫進行讀/寫目標文件.使用BFD, objcopy就能將原格式的目標文件轉化為不同格式的目標文件.
??? 以我們在nm中使用的hello.o目標文件和hello可執行為例:

$ file hello.o hello
??
??? file命令用來判別文件類型, 輸出如下:
???
hello.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
hello:? ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), not stripped
???
??? 現在運行objcopy來改變hello的文件類型: 原先它是ELF格式的可執行程序, 現將它轉換為srec格式. srec格式文件是Motolora S-Record格式的文件, 主要用來在主機和目標機之間傳輸數據.
???
$ objcopy -O srec hello hello_srec
$ file hello.o hello

??? file命令結果: hello_srec: Motorola S-Record; binary data in text format

??? 注意objcopy的格式, "-O"指定輸出文件類型; 輸入文件名和輸出文件名位于命令末尾. 關于objcopy命令的詳細選項, 參考 on-line manual


objdump

??? objdump用來顯示目標文件的信息. 可以通過選項控制顯示那些特定信息. objdump一個最大的用處恐怕就是將C代碼反匯編了. 在嵌入式軟件開發過程中, 也可以用它查看執行文件或庫文件的信息.
??? 下面我們用上文提到的hello可執行文件和hello_srec可執行文件為例, 介紹objdump的簡單用法:
???

$ objdump -f hello hello_srec

輸出如下:
hello:???? file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080482c0

hello_srec:???? file format srec
architecture: UNKNOWN!, flags 0x00000000:
start address 0x00000000080482c0
???
-f : 顯示目標文件的頭文件概要信息.

生成反匯編代碼:
???

$ objdump -d hello.o

顯示如下:
hello.o:???? file format elf32-i386

Disassembly of section .text:

00000000 <hello>:
?? 0:?? 55????????????????????? push?? %ebp
?? 1:?? 89 e5?????????????????? mov??? %esp,%ebp
?? 3:?? 83 ec 08??????????????? sub??? $0x8,%esp
?? 6:?? 83 ec 0c??????????????? sub??? $0xc,%esp
?? 9:?? 68 00 00 00 00????????? push?? $0x0
?? e:?? e8 fc ff ff ff????????? call?? f <hello+0xf>
? 13:?? 83 c4 10??????????????? add??? $0x10,%esp
? 16:?? c9????????????????????? leave
? 17:?? c3????????????????????? ret

??? -d : 顯示目標文件中機器指令使用的匯編語言. 只反匯編那些應該含有指令機器碼的節(顯示.text段); 如果用-D, 則反匯編所有節的內容.
??? 關于objcopy命令的詳細選項, 參考 on-line manual


readelf

??? readelf用來顯示ELF格式目標文件的信息.可通過參數選項來控制顯示哪些特定信息.(注意: readelf不支持顯示archive文檔, 也不支持64位的ELF文件).
??? 下面利用先前的hello可執行文件演示readelf的簡單用法:
???

$ readelf -h hello

ELF Header:
? Magic:?? 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
? Class:??????????????????????????? ? ? ? ? ? ? ?? ELF32
? Data:??????????????????????????????????????????? 2's complement, little endian
? Version:??????????????????????????????????????? 1 (current)
? OS/ABI:????????????????????????? ? ? ? ? ? ? ? ? UNIX - System V
? ABI Version:???????????????????? ? ? ? ? ? ? ? 0
? Type:????????????????????????????????????????????? EXEC (Executable file)
? Machine:??????????????????????????????????????? Intel 80386
? Version:????????????????????????????????????????? 0x1
? Entry point address:?????????????????????? 0x80482c0
? Start of program headers:???????? ? ?? 52 (bytes into file)
? Start of section headers:???????? ? ? ? ? 3848 (bytes into file)
? Flags:?????????????????????????? ? ? ? ? ? ? ? ? ? ? 0x0
? Size of this header:????????????????????????? 52 (bytes)
? Size of program headers:???????? ? ? ?? 32 (bytes)
? Number of program headers:?????? ?? 7
? Size of section headers:????????? ? ? ? ? 40 (bytes)
? Number of section headers:??????????? 34
? Section header string table index:?? 31

注意: readelf只能用于ELF格式目標文件, 且選項中至少要指定一個(除V, H外)的選項!


gprof

??? gprof被用來測量程序的性能. 它記錄每個函數被調用的次數以及相應的執行時間. 這樣就能鎖定程序執行時花費時間最多的部分, 對程序的優化就可集中于對它們的優化.
???
??? 用一個簡單的數值計算程序來掩飾gprof的用法:

collatz.c:

#include <stdio.h>
/* Computes the length of Collatz sequences */
unsigned int step (unsigned int x)
{
???? if (x % 2 == 0)
???? {
??? ? return (x / 2);
???? }
???? else
???? {
??? ? return (3 * x + 1);
???? }
}

unsigned int nseq (unsigned int x0)
{
???? unsigned int i = 1, x;
???? if (x0 == 1 || x0 == 0)
??? ? return i;
???? x = step (x0);
???? while (x != 1 && x != 0)
???? {
??? ? x = step (x);
??? ? i++;
???? }
???? return i;
}

int main (void)
{
???? unsigned int i, m = 0, im = 0;
???? for (i = 1; i < 500000; i++)
???? {
??? ? unsigned int k = nseq (i);
??? ? if (k > m)
??? ? {
??? ?????? m = k;
??? ?????? im = i;
??? ?????? printf ("sequence length = %u for %u/n", m, im);
??? ? }
???? }
???? return 0;
}

??? 先將collatz.c編譯成目標文件collatz.o, gcc通過 -pg選項來打開gprof支持:
???
$ gcc -Wall -c -pg collatz.c

$ gcc -Wall -pg -o collatz collatz.o

??? 注意:兩條命令都要加 "-pg"選項。前一條命令生成collatz.o目標文件。后一條命令生成可執行文件,該可執行文件中包含了記錄函數執行時間的指令。
??? 生成collatz可執行文件后,現執行它,結果與一般程序的執行無疑。但此時在PWD目錄生成一個名為"gmon.out"的文件,gprof通過它來分析程序的執行。
??? 如果不現執行程序,而直接用gprof來分析它,會提示“gmon.out: No such file or directory”。
??? gprof用法:
???
$ gprof ./collatz

關于gprof更多的描述,參考gprof的 on-line manual

3、可執行文件格式

目標文件格式與類型

GNU C compiler根據源文件的后綴名來對文件進行預處理、匯編或編譯操作。在編譯鏈接時,生成的目標文件都是ELF格式的(可執行鏈接格式,Executable and Linking Format)。Object文件格式有三種類型:

(1)可重定位(relocatable)文件:用來和其他的object文件一起鏈接為一個可執行文件(executable)或一個共享文件(.so文件,shared object)。

(2)可執行(executable)文件;

(3)共享目標文件(shared object file):用于被下面的兩個鏈接器鏈接。一是鏈接編輯器(ld),可以和其他的relocatable或shared object file來創建其他的目標文件,例如.so共享庫(可用file命令查看其屬性);二是動態鏈接器,聯合一個可執行文件和其他的shared object file來創建一個進程映像

?

首先看看ELF文件的總體布局:

ELF header(ELF頭部)
Program header table(程序頭表)
Segment1(段1)
Segment2(段2)
………
Sengmentn(段n)
Setion header table(節頭表,可選)

段由若干個節(Section)構成,節頭表對每一個節的信息有相關描述。對可執行程序而言,節頭表是可選的。 參考資料 1中作者談到把節頭表的所有數據全部設置為0,程序也能正確運行!ELF頭部是一個關于本文件的路線圖(road map),從總體上描述文件的結構。下面是ELF頭部的數據結構:

typedef struct {unsigned char e_ident[EI_NIDENT]; /* 魔數和相關信息 */Elf32_Half e_type; /* 目標文件類型 */Elf32_Half e_machine; /* 硬件體系 */Elf32_Word e_version; /* 目標文件版本 */Elf32_Addr e_entry; /* 程序進入點 */Elf32_Off e_phoff; /* 程序頭部偏移量 */Elf32_Off e_shoff; /* 節頭部偏移量 */Elf32_Word e_flags; /* 處理器特定標志 */Elf32_Half e_ehsize; /* ELF頭部長度 */Elf32_Half e_phentsize; /* 程序頭部中一個條目的長度 */Elf32_Half e_phnum; /* 程序頭部條目個數 */Elf32_Half e_shentsize; /* 節頭部中一個條目的長度 */Elf32_Half e_shnum; /* 節頭部條目個數 */Elf32_Half e_shstrndx; /* 節頭部字符表索引 */ } Elf32_Ehdr;

下面我們對ELF頭表中一些重要的字段作出相關說明,完整的ELF定義請參閱 參考資料6參考資料 7

e_ident[0]-e_ident[3]包含了ELF文件的魔數,依次是0x7f、'E'、'L'、'F'。注意,任何一個ELF文件必須包含此魔數。 參考資料 3中討論了利用程序、工具、/Proc文件系統等多種查看ELF魔數的方法。e_ident[4]表示硬件系統的位數,1代表32位,2代表64位。e_ident[5]表示數據編碼方式,1代表小印第安排序(最大有意義的字節占有最低的地址),2代表大印第安排序(最大有意義的字節占有最高的地址)。e_ident[6]指定ELF頭部的版本,當前必須為1。e_ident[7]到e_ident[14]是填充符,通常是0。ELF格式規范中定義這幾個字節是被忽略的,但實際上是這幾個字節完全可以可被利用。如病毒Lin/Glaurung.676/666(參考資料 1)設置e_ident[7]為0x21,表示本文件已被感染;或者存放可執行代碼(參考資料 2)。ELF頭部中大多數字段都是對子頭部數據的描述,其意義相對比較簡單。值得注意的是某些病毒可能修改字段e_entry(程序進入點)的值,以指向病毒代碼,例如上面提到的病毒Lin/Glaurung.676/666。

一個實際可執行文件的文件頭部形式如下:(利用命令readelf)

ELF Header:Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32Data: 2's complement, little endianVersion: 1 (current)OS/ABI: UNIX - System VABI Version: 0Type: EXEC (Executable file)Machine: Intel 80386Version: 0x1Entry point address: 0x80483ccStart of program headers: 52 (bytes into file)Start of section headers: 14936 (bytes into file)Flags: 0x0Size of this header: 52 (bytes)Size of program headers: 32 (bytes)Number of program headers: 6Size of section headers: 40 (bytes)Number of section headers: 34Section header string table index: 31

緊接ELF頭部的是程序頭表,它是一個結構數組,包含了ELF頭表中字段e_phnum定義的條目,結構描述一個段或其他系統準備執行該程序所需要的信息。

typedef struct {Elf32_Word p_type; /* 段類型 */Elf32_Off p_offset; /* 段位置相對于文件開始處的偏移量 */Elf32_Addr p_vaddr; /* 段在內存中的地址 */Elf32_Addr p_paddr; /* 段的物理地址 */Elf32_Word p_filesz; /* 段在文件中的長度 */Elf32_Word p_memsz; /* 段在內存中的長度 */Elf32_Word p_flags; /* 段的標記 */Elf32_Word p_align; /* 段在內存中對齊標記 */} Elf32_Phdr;

在詳細討論可執行文件程序頭表之前,首先查看一個實際文件的輸出:

Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4 INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1[Requesting program interpreter: /lib/ld-linux.so.2]LOAD 0x000000 0x08048000 0x08048000 0x00684 0x00684 R E 0x1000LOAD 0x000684 0x08049684 0x08049684 0x00118 0x00130 RW 0x1000DYNAMIC 0x000690 0x08049690 0x08049690 0x000c8 0x000c8 RW 0x4NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4Section to Segment mapping:Segment Sections...00 01 .interp 02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame 03 .data .dynamic .ctors .dtors .jcr .got .bss 04 .dynamic 05 .note.ABI-tag Section Headers:[Nr] Name Type Addr Off Size ES Flg Lk Inf Al[ 0] NULL 00000000 000000 000000 00 0 0 0[ 1] .interp PROGBITS 080480f4 0000f4 000013 00 A 0 0 1[ 2] .note.ABI-tag NOTE 08048108 000108 000020 00 A 0 0 4[ 3] .hash HASH 08048128 000128 000040 04 A 4 0 4[ 4] .dynsym DYNSYM 08048168 000168 0000b0 10 A 5 1 4[ 5] .dynstr STRTAB 08048218 000218 00007b 00 A 0 0 1[ 6] .gnu.version VERSYM 08048294 000294 000016 02 A 4 0 2[ 7] .gnu.version_r VERNEED 080482ac 0002ac 000030 00 A 5 1 4[ 8] .rel.dyn REL 080482dc 0002dc 000008 08 A 4 0 4[ 9] .rel.plt REL 080482e4 0002e4 000040 08 A 4 b 4[10] .init PROGBITS 08048324 000324 000017 00 AX 0 0 4[11] .plt PROGBITS 0804833c 00033c 000090 04 AX 0 0 4[12] .text PROGBITS 080483cc 0003cc 0001f8 00 AX 0 0 4[13] .fini PROGBITS 080485c4 0005c4 00001b 00 AX 0 0 4[14] .rodata PROGBITS 080485e0 0005e0 00009f 00 A 0 0 32[15] .eh_frame PROGBITS 08048680 000680 000004 00 A 0 0 4[16] .data PROGBITS 08049684 000684 00000c 00 WA 0 0 4[17] .dynamic DYNAMIC 08049690 000690 0000c8 08 WA 5 0 4[18] .ctors PROGBITS 08049758 000758 000008 00 WA 0 0 4[19] .dtors PROGBITS 08049760 000760 000008 00 WA 0 0 4[20] .jcr PROGBITS 08049768 000768 000004 00 WA 0 0 4[21] .got PROGBITS 0804976c 00076c 000030 04 WA 0 0 4[22] .bss NOBITS 0804979c 00079c 000018 00 WA 0 0 4[23] .comment PROGBITS 00000000 00079c 000132 00 0 0 1[24] .debug_aranges PROGBITS 00000000 0008d0 000098 00 0 0 8[25] .debug_pubnames PROGBITS 00000000 000968 000040 00 0 0 1[26] .debug_info PROGBITS 00000000 0009a8 001cc6 00 0 0 1[27] .debug_abbrev PROGBITS 00000000 00266e 0002cc 00 0 0 1[28] .debug_line PROGBITS 00000000 00293a 0003dc 00 0 0 1[29] .debug_frame PROGBITS 00000000 002d18 000048 00 0 0 4[30] .debug_str PROGBITS 00000000 002d60 000bcd 01 MS 0 0 1[31] .shstrtab STRTAB 00000000 00392d 00012b 00 0 0 1[32] .symtab SYMTAB 00000000 003fa8 000740 10 33 56 4[33] .strtab STRTAB 00000000 0046e8 000467 00 0 0 1

對一個ELF可執行程序而言,一個基本的段是標記p_type為PT_INTERP的段,它表明了運行此程序所需要的程序解釋器(/lib/ld-linux.so.2),實際上也就是動態連接器(dynamic linker)。最重要的段是標記p_type為PT_LOAD的段,它表明了為運行程序而需要加載到內存的數據。查看上面實際輸入,可以看見有兩個可LOAD段,第一個為只讀可執行(FLg為R E),第二個為可讀可寫(Flg為RW)。段1包含了文本節.text,注意到ELF文件頭部中程序進入點的值為0x80483cc,正好是指向節.text在內存中的地址。段二包含了數據節.data,此數據節中數據是可讀可寫的,相對的只讀數據節.rodata包含在段1中。ELF格式可以比COFF格式包含更多的調試信息,如上面所列出的形式為.debug_xxx的節。在I386平臺LINUX系統下,用命令file查看一個ELF可執行程序的可能輸出是:a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped。

ELF文件中包含了動態連接器的全路徑,內核定位"正確"的動態連接器在內存中的地址是"正確"運行可執行文件的保證, 參考資料 13討論了如何通過查找動態連接器在內存中的地址以達到顛覆(Subversiver)動態連接機制的方法。

最后我們討論ELF文件的動態連接機制。每一個外部定義的符號在全局偏移表(Global Offset Table GOT)中有相應的條目,如果符號是函數則在過程連接表(Procedure Linkage Table PLT)中也有相應的條目,且一個PLT條目對應一個GOT條目。對外部定義函數解析可能是整個ELF文件規范中最復雜的,下面是函數符號解析過程的一個描述。

1:代碼中調用外部函數func,語句形式為call 0xaabbccdd,地址0xaabbccdd實際上就是符號func在PLT表中對應的條目地址(假設地址為標號.PLT2)。

2:PLT表的形式如下

.PLT0: pushl 4(%ebx) /* GOT表的地址保存在寄存器ebx中 */ jmp *8(%ebx)nop; nopnop; nop.PLT1: jmp *name1@GOT(%ebx)pushl $offsetjmp .PLT0@PC.PLT2: jmp *func@GOT(%ebx)pushl $offsetjmp .PLT0@PC

3:查看標號.PLT2的語句,實際上是跳轉到符號func在GOT表中對應的條目。

4:在符號沒有重定位前,GOT表中此符號對應的地址為標號.PLT2的下一條語句,即是pushl $offset,其中$offset是符號func的重定位偏移量。注意到這是一個二次跳轉。

5:在符號func的重定位偏移量壓棧后,控制跳到PLT表的第一條目,把GOT[1]的內容壓棧,并跳轉到GOT[2]對應的地址。

6:GOT[2]對應的實際上是動態符號解析函數的代碼,在對符號func的地址解析后,會把func在內存中的地址設置到GOT表中此符號對應的條目中。

7:當第二次調用此符號時,GOT表中對應的條目已經包含了此符號的地址,就可直接調用而不需要利用PLT表進行跳轉。

動態連接是比較復雜的,但為了獲得靈活性的代價通常就是復雜性。其最終目的是把GOT表中條目的值修改為符號的真實地址,這也可解釋節.got包含在可讀可寫段中。

動態連接是一個非常重要的進步,這意味著庫文件可以被升級、移動到其他目錄等等而不需要重新編譯程序(當然,這不意味庫可以任意修改,如函數入參的個數、數據類型應保持兼容性)。從很大程度上說,動態連接機制是ELF格式代替a.out格式的決定性原因。如果說面對對象的編程本質是面對接口(interface)的編程,那么動態連接機制則是這種思想的地一個非常典型的應用,具體的講,動態連接機制與設計模式中的橋接(BRIDGE)方法比較類似,而它的LAZY特性則與代理(PROXY)方法非常相似。動態連接操作的細節描述請參閱參考資料 8,9,10,11。通過閱讀命令readelf、objdump 的源代碼以及參考資料 14中所提及的相關軟件源代碼,可以對ELF文件的格式有更徹底的了解。

?

4. 鏈接與鏈接腳本

鏈接器ld把object文件中的每個section都作為一個整體,為其分配運行的地址(memory layout),這個過程就是重定位(relocation);最后把所有目標文件合并為一個目標文件。

?


鏈接通過一個linker script來控制,這個腳本描述了輸入文件的sections到輸出文件的映射,以及輸出文件的memory layout。

因此,linker總會使用一個linker script,如果不特別指定,則使用默認的script;可以使用‘-T’命令行選項來指定一個linker script。

?

*映像文件的輸入段與輸出段

linker把多個輸入文件合并為一個輸出文件。輸出文件和輸入文件都是目標文件(object file),輸出文件通常被稱為可執行文件(executable)。

每個目標文件都有一系列section,輸入文件的section稱為input section,輸出文件的section則稱為output section。

一個section可以是loadable的,即輸出文件運行時需要將這樣的section加載到memory(類似于RO&RW段);也可以是allocatable的,這樣的section沒有任何內容,某些時候用0對相應的memory區域進行初始化(類似于ZI段);如果一個section既非loadable也非allocatable,則它通常包含的是調試信息。

每個loadable或allocatable的output section都有兩個地址,一是VMA(virtual memory address),是該section的運行時域地址;二是LMA(load memory address),是該section的加載時域地址。

可以通過objdump工具附加'-h'選項來查看目標文件中的sections

*簡單的Linker script

(1) SECTIONS命令:

The SECTIONS command tells the linker how to map input sections into output sections, and how to place the output sections in memory.

命令格式如下:

SECTIONS

{

sections-command

sections-command

......

}

其中sections-command可以是ENTRY命令,符號賦值,輸出段描述,也可以是overlay描述。

?

(2) 地址計數器‘.’(location counter):

該符號只能用于SECTIONS命令內部,初始值為‘0’,可以對該符號進行賦值,也可以使用該符號進行計算或賦值給其他符號。它會自動根據SECTIONS命令內部所描述的輸出段的大小來計算當前的地址。

(3) 輸出段描述(output section description):

前面提到在SECTIONS命令中可以作輸出段描述,描述的格式如下:

section [address] [(type)] : [AT(lma)]

{

output-section-command

output-section-command

...

} [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]

很多附加選項是用不到的。其中的output-section-command又可以是符號賦值,輸入段描述,要直接包含的數據值,或者某一特定的輸出段關鍵字

?

*linker script 實例

==============================

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS {

??? . = 0xa3f00000;

??? __boot_start = .;

??? .start ALIGN(4) : {

??????? *(.text.start)

??? }


???

setup ALIGN(4) : {

??????? setup_block = .;

??????? *(.setup)

??????? setup_block_end = .;

??? }


??? .text ALIGN(4) : {

??????? *(.text)

??? }


??? .rodata ALIGN(4) : {

??????? *(.rodata)

??? }

??? .data ALIGN(4) : {

??????? *(.data)

??? }


??? .got ALIGN(4) : {

??????? *(.got)

??? }

??? __boot_end = .;


??? .bss ALIGN(16) : {

??????? bss_start = .;

??????? *(.bss)

??????? *(COMMON)

??????? bss_end = .;

??? }


??? .comment ALIGN(16) : {

??????? *(.comment)

??? }

??? stack_point = __boot_start + 0x00100000;

??? loader_size = __boot_end - __boot_start;

??? setup_size = setup_block_end - setup_block;

}

?

=============================??

在SECTIONS命令中的類似于下面的描述結構就是輸出段描述:

.start ALIGN(4) : {

??? *(.text.start)

}

.start為output section name,ALIGN(4)返回一個基于location counter(.)的4字節對齊的地址值。*(.text.start)是輸入段描述,*為通配符,意思是把所有被鏈接的object文件中的.text.start段都鏈接進這個名為.start的輸出段。

源文件中所標識的section及其屬性實際上就是對輸入段的描述,例如.text.start輸入段在源文件start.S中的代碼如下:

.section .text.start

.global _start

_start :

??? b start


--------------------------------------------------------------------------------
[推薦閱讀]
1.ARM學習報告002--GNU tool開發ARM程序及生成映象文件機理
2.Using ld, the GNU Linker

?

5、再議論 鏈接

?

1. 概論


每一個鏈接過程都由鏈接腳本(linker script, 一般以lds作為文件的后綴名)控制. 鏈接腳本主要用于規定如何把輸入文件內的section放入輸出文件內, 并控制輸出文件內各部分在程序地址空間內的布局. 但你也可以用連接命令做一些其他事情.

連接器有個默認的內置連接腳本, 可用ld --verbose查看. 連接選項-r和-N可以影響默認的連接腳本(如何影響?).

-T選項用以指定自己的鏈接腳本, 它將代替默認的連接腳本。你也可以使用<暗含的連接腳本>以增加自定義的鏈接命令.

以下沒有特殊說明,連接器指的是靜態連接器.


2. 基本概念


鏈接器把一個或多個輸入文件合成一個輸出文件.

輸入文件: 目標文件或鏈接腳本文件.
輸出文件: 目標文件或可執行文件.

目標文件(包括可執行文件)具有固定的格式, 在UNIX或GNU/Linux平臺下, 一般為ELF格式. 若想了解更多, 可參考 UNIX/Linux平臺可執行文件格式分析

有時把輸入文件內的section稱為輸入section(input section), 把輸出文件內的section稱為輸出section(output sectin).

目標文件的每個section至少包含兩個信息: 名字和大小. 大部分section還包含與它相關聯的一塊數據, 稱為section contents(section內容). 一個section可被標記為“loadable(可加載的)”或“allocatable(可分配的)”.

loadable section: 在輸出文件運行時, 相應的section內容將被載入進程地址空間中.

allocatable section: 內容為空的section可被標記為“可分配的”. 在輸出文件運行時, 在進程地址空間中空出大小同section指定大小的部分. 某些情況下, 這塊內存必須被置零.

如果一個section不是“可加載的”或“可分配的”, 那么該section通常包含了調試信息. 可用objdump -h命令查看相關信息.

每個“可加載的”或“可分配的”輸出section通常包含兩個地址: VMA(virtual memory address虛擬內存地址或程序地址空間地址)和LMA(load memory address加載內存地址或進程地址空間地址). 通常VMA和LMA是相同的.

在目標文件中, loadable或allocatable的輸出section有兩種地址: VMA(virtual Memory Address)和LMA(Load Memory Address). VMA是執行輸出文件時section所在的地址, 而LMA是加載輸出文件時section所在的地址. 一般而言, 某section的VMA == LMA. 但在嵌入式系統中, 經常存在加載地址和執行地址不同的情況: 比如將輸出文件加載到開發板的flash中(由LMA指定), 而在運行時將位于flash中的輸出文件復制到SDRAM中(由VMA指定).

可這樣來理解VMA和LMA, 假設:
(1) .data section對應的VMA地址是0x08050000, 該section內包含了3個32位全局變量, i、j和k, 分別為1,2,3.
(2) .text section內包含由"printf( "j=%d ", j );"程序片段產生的代碼.

連接時指定.data section的VMA為0x08050000, 產生的printf指令是將地址為0x08050004處的4字節內容作為一個整數打印出來。

如果.data section的LMA為0x08050000,顯然結果是j=2
如果.data section的LMA為0x08050004,顯然結果是j=1

還可這樣理解LMA:
.text section內容的開始處包含如下兩條指令(intel i386指令是10字節,每行對應5字節):

jmp 0x08048285
movl $0x1,%eax

如果.text section的LMA為0x08048280, 那么在進程地址空間內0x08048280處為“jmp 0x08048285”指令, 0x08048285處為movl $0x1,%eax指令. 假設某指令跳轉到地址0x08048280, 顯然它的執行將導致%eax寄存器被賦值為1.

如果.text section的LMA為0x08048285, 那么在進程地址空間內0x08048285處為“jmp 0x08048285”指令, 0x0804828a處為movl $0x1,%eax指令. 假設某指令跳轉到地址0x08048285, 顯然它的執行又跳轉到進程地址空間內0x08048285處, 造成死循環.

符號(symbol): 每個目標文件都有符號表(SYMBOL TABLE), 包含已定義的符號(對應全局變量和static變量和定義的函數的名字)和未定義符號(未定義的函數的名字和引用但沒定義的符號)信息.

符號值: 每個符號對應一個地址, 即符號值(這與c程序內變量的值不一樣, 某種情況下可以把它看成變量的地址). 可用nm命令查看它們. (nm的使用方法可參考本blog的 GNU binutils筆記)


3. 腳本格式

鏈接腳本由一系列命令組成, 每個命令由一個關鍵字(一般在其后緊跟相關參數)或一條對符號的賦值語句組成. 命令由分號‘;’分隔開.

文件名或格式名內如果包含分號';'或其他分隔符, 則要用引號‘"’將名字全稱引用起來. 無法處理含引號的文件名.
/* */之間的是注釋。


4. 簡單例子


在介紹鏈接描述文件的命令之前, 先看看下述的簡單例子:

以下腳本將輸出文件的text section定位在0x10000, data section定位在0x8000000:

SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}

解釋一下上述的例子:
. = 0x10000 : 把定位器符號置為0x10000 (若不指定, 則該符號的初始值為0).

.text : { *(.text) } : 將所有(*符號代表任意輸入文件)輸入文件的.text section合并成一個.text section, 該section的地址由定位器符號的值指定, 即0x10000.

. = 0x8000000 :把定位器符號置為0x8000000
.data : { *(.data) } : 將所有輸入文件的.text section合并成一個.data section, 該section的地址被置為0x8000000.

.bss : { *(.bss) } : 將所有輸入文件的.bss section合并成一個.bss section,該section的地址被置為0x8000000+.data section的大小.

連接器每讀完一個section描述后, 將定位器符號的值*增加*該section的大小. 注意: 此處沒有考慮對齊約束.


5. 簡單腳本命令


- 1 -

ENTRY(SYMBOL): 將符號SYMBOL的值設置成入口地址。

入口地址(entry point): 進程執行的第一條用戶空間的指令在進程地址空間的地址)

ld有多種方法設置進程入口地址, 按一下順序: (編號越前, 優先級越高)
1, ld命令行的-e選項
2, 連接腳本的ENTRY(SYMBOL)命令
3, 如果定義了start符號, 使用start符號值
4, 如果存在.text section, 使用.text section的第一字節的位置值
5, 使用值0

- 2 -
INCLUDE filename : 包含其他名為filename的鏈接腳本

相當于c程序內的的#include指令, 用以包含另一個鏈接腳本.

腳本搜索路徑由-L選項指定. INCLUDE指令可以嵌套使用, 最大深度為10. 即: 文件1內INCLUDE文件2, 文件2內INCLUDE文件3... , 文件10內INCLUDE文件11. 那么文件11內不能再出現 INCLUDE指令了.

- 3 -
INPUT(files): 將括號內的文件做為鏈接過程的輸入文件

ld首先在當前目錄下尋找該文件, 如果沒找到, 則在由-L指定的搜索路徑下搜索. file可以為 -lfile形式,就象命令行的-l選項一樣. 如果該命令出現在暗含的腳本內, 則該命令內的file在鏈接過程中的順序由該暗含的腳本在命令行內的順序決定.

- 4 -
GROUP(files) : 指定需要重復搜索符號定義的多個輸入文件

file必須是庫文件, 且file文件作為一組被ld重復掃描,直到不在有新的未定義的引用出現。

- 5 -
OUTPUT(FILENAME) : 定義輸出文件的名字

同ld的-o選項, 不過-o選項的優先級更高. 所以它可以用來定義默認的輸出文件名. 如a.out

- 6 -
SEARCH_DIR(PATH) :定義搜索路徑,

同ld的-L選項, 不過由-L指定的路徑要比它定義的優先被搜索。

- 7 -
STARTUP(filename) : 指定filename為第一個輸入文件

在鏈接過程中, 每個輸入文件是有順序的. 此命令設置文件filename為第一個輸入文件。

- 8 -
OUTPUT_FORMAT(BFDNAME) : 設置輸出文件使用的BFD格式

同ld選項-o format BFDNAME, 不過ld選項優先級更高.

- 9 -
OUTPUT_FORMAT(DEFAULT,BIG,LITTLE) : 定義三種輸出文件的格式(大小端)

若有命令行選項-EB, 則使用第2個BFD格式; 若有命令行選項-EL,則使用第3個BFD格式.否則默認選第一個BFD格式.

TARGET(BFDNAME):設置輸入文件的BFD格式

同ld選項-b BFDNAME. 若使用了TARGET命令, 但未使用OUTPUT_FORMAT命令, 則最用一個TARGET命令設置的BFD格式將被作為輸出文件的BFD格式.

另外還有一些:
ASSERT(EXP, MESSAGE):如果EXP不為真,終止連接過程

EXTERN(SYMBOL SYMBOL ...):在輸出文件中增加未定義的符號,如同連接器選項-u

FORCE_COMMON_ALLOCATION:為common symbol(通用符號)分配空間,即使用了-r連接選項也為其分配

NOCROSSREFS(SECTION SECTION ...):檢查列出的輸出section,如果發現他們之間有相互引用,則報錯。對于某些系統,特別是內存較緊張的嵌入式系統,某些section是不能同時存在內存中的,所以他們之間不能相互引用。

OUTPUT_ARCH(BFDARCH):設置輸出文件的machine architecture(體系結構),BFDARCH為被BFD庫使用的名字之一。可以用命令objdump -f查看。

可通過 man -S 1 ld查看ld的聯機幫助, 里面也包括了對這些命令的介紹.


6. 對符號的賦值

在目標文件內定義的符號可以在鏈接腳本內被賦值. (注意和C語言中賦值的不同!) 此時該符號被定義為全局的. 每個符號都對應了一個地址, 此處的賦值是更改這個符號對應的地址.

e.g. 通過下面的程序查看變量a的地址:
/* a.c */
#include <stdio.h>
int a = 100;
int main(void)
{
??? printf( "&a=0x%p ", &a );
??? return 0;
}

/* a.lds */
a = 3;

$ gcc -Wall -o a-without-lds a.c
&a = 0x8049598

$ gcc -Wall -o a-with-lds a.c a.lds
&a = 0x3

注意: 對符號的賦值只對全局變量起作用!

一些簡單的賦值語句
能使用任何c語言內的賦值操作:

SYMBOL = EXPRESSION ;
SYMBOL += EXPRESSION ;
SYMBOL -= EXPRESSION ;
SYMBOL *= EXPRESSION ;
SYMBOL /= EXPRESSION ;
SYMBOL <<= EXPRESSION ;
SYMBOL >>= EXPRESSION ;
SYMBOL &= EXPRESSION ;
SYMBOL |= EXPRESSION ;

除了第一類表達式外, 使用其他表達式需要SYMBOL被定義于某目標文件。
. 是一個特殊的符號,它是定位器,一個位置指針,指向程序地址空間內的某位置(或某section內的偏移,如果它在SECTIONS命令內的某section描述內),該符號只能在SECTIONS命令內使用。
注意:賦值語句包含4個語法元素:符號名、操作符、表達式、分號;一個也不能少。
被賦值后,符號所屬的section被設值為表達式EXPRESSION所屬的SECTION(參看11. 腳本內的表達式)
賦值語句可以出現在連接腳本的三處地方:SECTIONS命令內,SECTIONS命令內的section描述內和全局位置;如下,
floating_point = 0; /* 全局位置 */
SECTIONS
{
.text :
{
*(.text)
_etext = .; /* section描述內 */
}
_bdata = (. + 3) & ~ 4; /* SECTIONS命令內 */
.data : { *(.data) }
}

PROVIDE關鍵字
該關鍵字用于定義這類符號:在目標文件內被引用,但沒有在任何目標文件內被定義的符號。
例子:
SECTIONS
{
.text :
{
*(.text)
_etext = .;
PROVIDE(etext = .);
}
}
當目標文件內引用了etext符號,確沒有定義它時,etext符號對應的地址被定義為.text section之后的第一個字節的地址。


7. SECTIONS命令

SECTIONS命令告訴ld如何把輸入文件的sections映射到輸出文件的各個section: 如何將輸入section合為輸出section; 如何把輸出section放入程序地址空間(VMA)和進程地址空間(LMA).該命令格式如下:

SECTIONS
{
SECTIONS-COMMAND
SECTIONS-COMMAND
...
}

SECTION-COMMAND有四種:
(1) ENTRY命令
(2) 符號賦值語句
(3) 一個輸出section的描述(output section description)
(4) 一個section疊加描述(overlay description)

如果整個連接腳本內沒有SECTIONS命令, 那么ld將所有同名輸入section合成為一個輸出section內, 各輸入section的順序為它們被連接器發現的順序.

如果某輸入section沒有在SECTIONS命令中提到, 那么該section將被直接拷貝成輸出section。

輸出section描述
輸出section描述具有如下格式:

SECTION [ADDRESS] [(TYPE)] : [AT(LMA)]
{
OUTPUT-SECTION-COMMAND
OUTPUT-SECTION-COMMAND
...
} [>REGION] [AT>LMA_REGION] [:PHDR :PHDR ...] [=FILLEXP]

[ ]內的內容為可選選項, 一般不需要.
SECTION:section名字
SECTION左右的空白、圓括號、冒號是必須的,換行符和其他空格是可選的。
每個OUTPUT-SECTION-COMMAND為以下四種之一,
符號賦值語句
一個輸入section描述
直接包含的數據值
一個特殊的輸出section關鍵字

輸出section名字(SECTION):
輸出section名字必須符合輸出文件格式要求,比如:a.out格式的文件只允許存在.text、.data和.bss section名。而有的格式只允許存在數字名字,那么此時應該用引號將所有名字內的數字組合在一起;另外,還有一些格式允許任何序列的字符存在于 section名字內,此時如果名字內包含特殊字符(比如空格、逗號等),那么需要用引號將其組合在一起。

輸出section地址(ADDRESS):
ADDRESS是一個表達式,它的值用于設置VMA。如果沒有該選項且有REGION選項,那么連接器將根據REGION設置VMA;如果也沒有 REGION選項,那么連接器將根據定位符號‘.’的值設置該section的VMA,將定位符號的值調整到滿足輸出section對齊要求后的值,輸出 section的對齊要求為:該輸出section描述內用到的所有輸入section的對齊要求中最嚴格的。
例子:
.text . : { *(.text) }

.text : { *(.text) }
這兩個描述是截然不同的,第一個將.text section的VMA設置為定位符號的值,而第二個則是設置成定位符號的修調值,滿足對齊要求后的。
ADDRESS可以是一個任意表達式,比如ALIGN(0x10)這將把該section的VMA設置成定位符號的修調值,滿足16字節對齊后的。
注意:設置ADDRESS值,將更改定位符號的值。

輸入section描述:
最常見的輸出section描述命令是輸入section描述。
輸入section描述是最基本的連接腳本描述。
輸入section描述基礎:
基本語法:FILENAME([EXCLUDE_FILE (FILENAME1 FILENAME2 ...) SECTION1 SECTION2 ...)
FILENAME文件名,可以是一個特定的文件的名字,也可以是一個字符串模式。
SECTION名字,可以是一個特定的section名字,也可以是一個字符串模式
例子是最能說明問題的,
*(.text) :表示所有輸入文件的.text section
(*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors)) :表示除crtend.o、otherfile.o文件外的所有輸入文件的.ctors section。
data.o(.data) :表示data.o文件的.data section
data.o :表示data.o文件的所有section
*(.text .data) :表示所有文件的.text section和.data section,順序是:第一個文件的.text section,第一個文件的.data section,第二個文件的.text section,第二個文件的.data section,...
*(.text) *(.data) :表示所有文件的.text section和.data section,順序是:第一個文件的.text section,第二個文件的.text section,...,最后一個文件的.text section,第一個文件的.data section,第二個文件的.data section,...,最后一個文件的.data section
下面看連接器是如何找到對應的文件的。
當FILENAME是一個特定的文件名時,連接器會查看它是否在連接命令行內出現或在INPUT命令中出現。
當FILENAME是一個字符串模式時,連接器僅僅只查看它是否在連接命令行內出現。
注意:如果連接器發現某文件在INPUT命令內出現,那么它會在-L指定的路徑內搜尋該文件。

字符串模式內可存在以下通配符:
* :表示任意多個字符
? :表示任意一個字符
[CHARS] :表示任意一個CHARS內的字符,可用-號表示范圍,如:a-z
:表示引用下一個緊跟的字符

在文件名內,通配符不匹配文件夾分隔符/,但當字符串模式僅包含通配符*時除外。
任何一個文件的任意section只能在SECTIONS命令內出現一次。看如下例子,
SECTIONS {
.data : { *(.data) }
.data1 : { data.o(.data) }
}
data.o文件的.data section在第一個OUTPUT-SECTION-COMMAND命令內被使用了,那么在第二個OUTPUT-SECTION-COMMAND命令內將不會再被使用,也就是說即使連接器不報錯,輸出文件的.data1 section的內容也是空的。
再次強調:連接器依次掃描每個OUTPUT-SECTION-COMMAND命令內的文件名,任何一個文件的任何一個section都只能使用一次。
讀者可以用-M連接命令選項來產生一個map文件,它包含了所有輸入section到輸出section的組合信息。
再看個例子,
SECTIONS {
.text : { *(.text) }
.DATA : { [A-Z]*(.data) }
.data : { *(.data) }
.bss : { *(.bss) }
}
這個例子中說明,所有文件的輸入.text section組成輸出.text section;所有以大寫字母開頭的文件的.data section組成輸出.DATA section,其他文件的.data section組成輸出.data section;所有文件的輸入.bss section組成輸出.bss section。
可以用SORT()關鍵字對滿足字符串模式的所有名字進行遞增排序,如SORT(.text*)。
通用符號(common symbol)的輸入section:
在許多目標文件格式中,通用符號并沒有占用一個section。連接器認為:輸入文件的所有通用符號在名為COMMON的section內。
例子,
.bss { *(.bss) *(COMMON) }
這個例子中將所有輸入文件的所有通用符號放入輸出.bss section內。可以看到COMMOM section的使用方法跟其他section的使用方法是一樣的。
有些目標文件格式把通用符號分成幾類。例如,在MIPS elf目標文件格式中,把通用符號分成standard common symbols(標準通用符號)和small common symbols(微通用符號,不知道這么譯對不對?),此時連接器認為所有standard common symbols在COMMON section內,而small common symbols在.scommon section內。
在一些以前的連接腳本內可以看見[COMMON],相當于*(COMMON),不建議繼續使用這種陳舊的方式。
輸入section和垃圾回收:
在連接命令行內使用了選項--gc-sections后,連接器可能將某些它認為沒用的section過濾掉,此時就有必要強制連接器保留一些特定的 section,可用KEEP()關鍵字達此目的。如KEEP(*(.text))或KEEP(SORT(*)(.text))
最后看個簡單的輸入section相關例子:
SECTIONS {
outputa 0x10000 :
{
all.o
foo.o (.input1)
}
outputb :
{
foo.o (.input2)
foo1.o (.input1)
}
outputc :
{
*(.input1)
*(.input2)
}
}
本例中,將all.o文件的所有section和foo.o文件的所有(一個文件內可以有多個同名section).input1 section依次放入輸出outputa section內,該section的VMA是0x10000;將foo.o文件的所有.input2 section和foo1.o文件的所有.input1 section依次放入輸出outputb section內,該section的VMA是當前定位器符號的修調值(對齊后);將其他文件(非all.o、foo.o、foo1.o)文件的. input1 section和.input2 section放入輸出outputc section內。

在輸出section存放數據命令:
能夠顯示地在輸出section內填入你想要填入的信息(這樣是不是可以自己通過連接腳本寫程序?當然是簡單的程序)。
BYTE(EXPRESSION) 1 字節
SHORT(EXPRESSION) 2 字節
LOGN(EXPRESSION) 4 字節
QUAD(EXPRESSION) 8 字節
SQUAD(EXPRESSION) 64位處理器的代碼時,8 字節
輸出文件的字節順序big endianness 或little endianness,可以由輸出目標文件的格式決定;如果輸出目標文件的格式不能決定字節順序,那么字節順序與第一個輸入文件的字節順序相同。
如:BYTE(1)、LANG(addr)。
注意,這些命令只能放在輸出section描述內,其他地方不行。
錯誤:SECTIONS { .text : { *(.text) } LONG(1) .data : { *(.data) } }
正確:SECTIONS { .text : { *(.text) LONG(1) } .data : { *(.data) } }
在當前輸出section內可能存在未描述的存儲區域(比如由于對齊造成的空隙),可以用FILL(EXPRESSION)命令決定這些存儲區域的內容, EXPRESSION的前兩字節有效,這兩字節在必要時可以重復被使用以填充這類存儲區域。如FILE(0x9090)。在輸出section描述中可以有=FILEEXP屬性,它的作用如同FILE()命令,但是FILE命令只作用于該FILE指令之后的section區域,而=FILEEXP屬性作用于整個輸出section區域,且FILE命令的優先級更高!!!

輸出section內命令的關鍵字:
CREATE_OBJECT_SYMBOLS :為每個輸入文件建立一個符號,符號名為輸入文件的名字。每個符號所在的section是出現該關鍵字的section。
CONSTRUCTORS :與c++內的(全局對象的)構造函數和(全局對像的)析構函數相關,下面將它們簡稱為全局構造和全局析構。
對于a.out目標文件格式,連接器用一些不尋常的方法實現c++的全局構造和全局析構。當連接器生成的目標文件格式不支持任意section名字時,比如說ECOFF、XCOFF格式,連接器將通過名字來識別全局構造和全局析構,對于這些文件格式,連接器把與全局構造和全局析構的相關信息放入出現 CONSTRUCTORS關鍵字的輸出section內。
符號__CTORS_LIST__表示全局構造信息的的開始處,__CTORS_END__表示全局構造信息的結束處。
符號__DTORS_LIST__表示全局構造信息的的開始處,__DTORS_END__表示全局構造信息的結束處。
這兩塊信息的開始處是一字長的信息,表示該塊信息有多少項數據,然后以值為零的一字長數據結束。
一般來說,GNU C++在函數__main內安排全局構造代碼的運行,而__main函數被初始化代碼(在main函數調用之前執行)調用。是不是對于某些目標文件格式才這樣???
對于支持任意section名的目標文件格式,比如COFF、ELF格式,GNU C++將全局構造和全局析構信息分別放入.ctors section和.dtors section內,然后在連接腳本內加入如下,
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
如果使用GNU C++提供的初始化優先級支持(它能控制每個全局構造函數調用的先后順序),那么請在連接腳本內把CONSTRUCTORS替換成SORT (CONSTRUCTS),把*(.ctors)換成*(SORT(.ctors)),把*(.dtors)換成*(SORT(.dtors))。一般來說,默認的連接腳本已作好的這些工作。

輸出section的丟棄:
例子,.foo { *(.foo) },如果沒有任何一個輸入文件包含.foo section,那么連接器將不會創建.foo輸出section。但是如果在這些輸出section描述內包含了非輸入section描述命令(如符號賦值語句),那么連接器將總是創建該輸出section。
有一個特殊的輸出section,名為/DISCARD/,被該section引用的任何輸入section將不會出現在輸出文件內,這就是DISCARD的意思吧。如果/DISCARD/ section被它自己引用呢?想想看。

輸出section屬性:
終于講到這里了,呵呵。
我們再回顧以下輸出section描述的文法:
SECTION [ADDRESS] [(TYPE)] : [AT(LMA)]
{
OUTPUT-SECTION-COMMAND
OUTPUT-SECTION-COMMAND
...
} [>REGION] [AT>LMA_REGION] [:PHDR :PHDR ...] [=FILLEXP]
前面我們瀏覽了SECTION、ADDRESS、OUTPUT-SECTION-COMMAND相關信息,下面我們將瀏覽其他屬性。

TYPE :每個輸出section都有一個類型,如果沒有指定TYPE類型,那么連接器根據輸出section引用的輸入section的類型設置該輸出section的類型。它可以為以下五種值,
NOLOAD :該section在程序運行時,不被載入內存。
DSECT,COPY,INFO,OVERLAY :這些類型很少被使用,為了向后兼容才被保留下來。這種類型的section必須被標記為“不可加載的”,以便在程序運行不為它們分配內存。

輸出section的LMA :默認情況下,LMA等于VMA,但可以通過關鍵字AT()指定LMA。
用關鍵字AT()指定,括號內包含表達式,表達式的值用于設置LMA。如果不用AT()關鍵字,那么可用AT>LMA_REGION表達式設置指定該section加載地址的范圍。
這個屬性主要用于構件ROM境象。
例子,
SECTIONS
{
.text 0x1000 : { *(.text) _etext = . ; }
.mdata 0x2000 :
AT ( ADDR (.text) + SIZEOF (.text) )
{ _data = . ; *(.data); _edata = . ; }
.bss 0x3000 :
{ _bstart = . ; *(.bss) *(COMMON) ; _bend = . ;}
}
程序如下,
extern char _etext, _data, _edata, _bstart, _bend;
char *src = &_etext;
char *dst = &_data;

/* ROM has data at end of text; copy it. */
while (dst < &_edata) {
*dst++ = *src++;
}

/* Zero bss */
for (dst = &_bstart; dst< &_bend; dst++)
*dst = 0;

此程序將處于ROM內的已初始化數據拷貝到該數據應在的位置(VMA地址),并將為初始化數據置零。
讀者應該認真的自己分析以上連接腳本和程序的作用。

輸出section區域:可以將輸出section放入預先定義的內存區域內,例子,
MEMORY { rom : ORIGIN = 0x1000, LENGTH = 0x1000 }
SECTIONS { ROM : { *(.text) } >rom }

輸出section所在的程序段:可以將輸出section放入預先定義的程序段(program segment)內。如果某個輸出section設置了它所在的一個或多個程序段,那么接下來定義的輸出section的默認程序段與該輸出 section的相同。除非再次顯示地指定。例子,
PHDRS { text PT_LOAD ; }
SECTIONS { .text : { *(.text) } :text }
可以通過:NONE指定連接器不把該section放入任何程序段內。詳情請查看PHDRS命令

輸出section的填充模版:這個在前面提到過,任何輸出section描述內的未指定的內存區域,連接器用該模版填充該區域。用法:=FILEEXP,前兩字節有效,當區域大于兩字節時,重復使用這兩字節以將其填滿。例子,
SECTIONS { .text : { *(.text) } =0x9090 }

覆蓋圖(overlay)描述:
覆蓋圖描述使兩個或多個不同的section占用同一塊程序地址空間。覆蓋圖管理代碼負責將section的拷入和拷出。考慮這種情況,當某存儲塊的訪問速度比其他存儲塊要快時,那么如果將section拷到該存儲塊來執行或訪問,那么速度將會有所提高,覆蓋圖描述就很適合這種情形。文法如下,
SECTIONS {
...

OVERLAY [START] : [NOCROSSREFS] [AT ( LDADDR )]
{
SECNAME1
{
OUTPUT-SECTION-COMMAND
OUTPUT-SECTION-COMMAND
...
} [:PHDR...] [=FILL]
SECNAME2
{
OUTPUT-SECTION-COMMAND
OUTPUT-SECTION-COMMAND
...
} [:PHDR...] [=FILL]
...
} [>REGION] [:PHDR...] [=FILL]

...
}
由以上文法可以看出,同一覆蓋圖內的section具有相同的VMA。SECNAME2的LMA為SECTNAME1的LMA加上SECNAME1的大小,同理計算SECNAME2,3,4...的LMA。SECNAME1的LMA由LDADDR決定,如果它沒有被指定,那么由START決定,如果它也沒有被指定,那么由當前定位符號的值決定。
NOCROSSREFS關鍵字指定各section之間不能交叉引用,否則報錯。
對于OVERLAY描述的每個section,連接器將定義兩個符號__load_start_SECNAME和__load_stop_SECNAME,這兩個符號的值分別代表SECNAME section的LMA地址的開始和結束。
連接器處理完OVERLAY描述語句后,將定位符號的值加上所有覆蓋圖內section大小的最大值。
看個例子吧,
SECTIONS{
...

OVERLAY 0x1000 : AT (0x4000)
{
.text0 { o1/*.o(.text) }
.text1 { o2/*.o(.text) }
}
...
}
.text0 section和.text1 section的VMA地址是0x1000,.text0 section加載于地址0x4000,.text1 section緊跟在其后。
程序代碼,拷貝.text1 section代碼,
extern char __load_start_text1, __load_stop_text1;
memcpy ((char *) 0x1000, &__load_start_text1,
&__load_stop_text1 - &__load_start_text1);


8. 內存區域命令
---------------

注意:以下存儲區域指的是在程序地址空間內的。
在默認情形下,連接器可以為section分配任意位置的存儲區域。你也可以用MEMORY命令定義存儲區域,并通過輸出section描述的> REGION屬性顯示地將該輸出section限定于某塊存儲區域,當存儲區域大小不能滿足要求時,連接器會報告該錯誤。
MEMORY命令的文法如下,
MEMORY {
NAME1 [(ATTR)] : ORIGIN = ORIGIN1, LENGTH = LEN2
NAME2 [(ATTR)] : ORIGIN = ORIGIN2, LENGTH = LEN2
...
}
NAME :存儲區域的名字,這個名字可以與符號名、文件名、section名重復,因為它處于一個獨立的名字空間。
ATTR :定義該存儲區域的屬性,在講述SECTIONS命令時提到,當某輸入section沒有在SECTIONS命令內引用時,連接器會把該輸入 section直接拷貝成輸出section,然后將該輸出section放入內存區域內。如果設置了內存區域設置了ATTR屬性,那么該區域只接受滿足該屬性的section(怎么判斷該section是否滿足?輸出section描述內好象沒有記錄該section的讀寫執行屬性)。ATTR屬性內可以出現以下7個字符,
R 只讀section
W 讀/寫section
X 可執行section
A ‘可分配的’section
I 初始化了的section
L 同I
! 不滿足該字符之后的任何一個屬性的section
ORIGIN :關鍵字,區域的開始地址,可簡寫成org或o
LENGTH :關鍵字,區域的大小,可簡寫成len或l

例子,
MEMORY
{
rom (rx) : ORIGIN = 0, LENGTH = 256K
ram (!rx) : org = 0x40000000, l = 4M
}
此例中,把在SECTIONS命令內*未*引用的且具有讀屬性或寫屬性的輸入section放入rom區域內,把其他未引用的輸入section放入 ram。如果某輸出section要被放入某內存區域內,而該輸出section又沒有指明ADDRESS屬性,那么連接器將該輸出section放在該區域內下一個能使用位置。


9. PHDRS命令
------------

該命令僅在產生ELF目標文件時有效。
ELF目標文件格式用program headers程序頭(程序頭內包含一個或多個segment程序段描述)來描述程序如何被載入內存。可以用objdump -p命令查看。
當在本地ELF系統運行ELF目標文件格式的程序時,系統加載器通過讀取程序頭信息以知道如何將程序加載到內存。要了解系統加載器如何解析程序頭,請參考ELF ABI文檔。
在連接腳本內不指定PHDRS命令時,連接器能夠很好的創建程序頭,但是有時需要更精確的描述程序頭,那么PAHDRS命令就派上用場了。
注意:一旦在連接腳本內使用了PHDRS命令,那么連接器**僅會**創建PHDRS命令指定的信息,所以使用時須謹慎。
PHDRS命令文法如下,
PHDRS
{
NAME TYPE [ FILEHDR ] [ PHDRS ] [ AT ( ADDRESS ) ]
[ FLAGS ( FLAGS ) ] ;
}
其中FILEHDR、PHDRS、AT、FLAGS為關鍵字。
NAME :為程序段名,此名字可以與符號名、section名、文件名重復,因為它在一個獨立的名字空間內。此名字只能在SECTIONS命令內使用。
一個程序段可以由多個‘可加載’的section組成。通過輸出section描述的屬性:PHDRS可以將輸出section加入一個程序段,: PHDRS中的PHDRS為程序段名。在一個輸出section描述內可以多次使用:PHDRS命令,也即可以將一個section加入多個程序段。
如果在一個輸出section描述內指定了:PHDRS屬性,那么其后的輸出section描述將默認使用該屬性,除非它也定義了:PHDRS屬性。顯然當多個輸出section屬于同一程序段時可簡化書寫。
在TYPE屬性后存在FILEHDR關鍵字,表示該段包含ELF文件頭信息;存在PHDRS關鍵字,表示該段包含ELF程序頭信息。
TYPE可以是以下八種形式,
PT_NULL 0
表示未被使用的程序段
PT_LOAD 1
表示該程序段在程序運行時應該被加載
PT_DYNAMIC 2
表示該程序段包含動態連接信息
PT_INTERP 3
表示該程序段內包含程序加載器的名字,在linux下常見的程序加載器是ld-linux.so.2
PT_NOTE 4
表示該程序段內包含程序的說明信息
PT_SHLIB 5
一個保留的程序頭類型,沒有在ELF ABI文檔內定義
PT_PHDR 6
表示該程序段包含程序頭信息。
EXPRESSION 表達式值
以上每個類型都對應一個數字,該表達式定義一個用戶自定的程序頭。
AT(ADDRESS)屬性定義該程序段的加載位置(LMA),該屬性將**覆蓋**該程序段內的section的AT()屬性。
默認情況下,連接器會根據該程序段包含的section的屬性(什么屬性?好象在輸出section描述內沒有看到)設置FLAGS標志,該標志用于設置程序段描述的p_flags域。
下面看一個典型的PHDRS設置,
PHDRS
{
headers PT_PHDR PHDRS ;
interp PT_INTERP ;
text PT_LOAD FILEHDR PHDRS ;
data PT_LOAD ;
dynamic PT_DYNAMIC ;
}
SECTIONS
{
. = SIZEOF_HEADERS;
.interp : { *(.interp) } :text :interp
.text : { *(.text) } :text
.rodata : { *(.rodata) } /* defaults to :text */
...
. = . + 0x1000; /* move to a new page in memory */
.data : { *(.data) } :data
.dynamic : { *(.dynamic) } :data :dynamic
...
}


10. 版本號命令
--------------

當使用ELF目標文件格式時,連接器支持帶版本號的符號。
讀者可以發現僅僅在共享庫中,符號的版本號屬性才有意義。
動態加載器使用符號的版本號為應用程序選擇共享庫內的一個函數的特定實現版本。
可以在連接腳本內直接使用版本號命令,也可以將版本號命令實現于一個特定版本號描述文件(用連接選項--version-script指定該文件)。
該命令的文法如下,
VERSION { version-script-commands }
以下內容直接拷貝于以前的文檔,
===================== 開始 ==================================
內容簡介
---------
0 前提
1 帶版本號的符號的定義
2 連接到帶版本的符號
3 GNU擴充
4 我的疑問
5 英文搜索關鍵字
6 我的參考


0. 前提

-- 只限于ELF文件格式
-- 以下討論用gcc

1. 帶版本號的符號的定義(共享庫內)

文件b.c內容如下,
int old_true()
{
return 1;
}

int new_true()
{
return 2;
}

寫連接器的版本控制腳本,本例中為b.lds,內容如下
VER1.0{
new_true;
};
VER2.0{
};

$gcc -c b.c
$gcc -shared -Wl,--version-script=b.lds -o libb.so b.o

可以在{}內填入要綁定的符號,本例中new_true符號就與VER1.0綁定了。
那么如果有一個應用程序連接到該庫的new_true符號,那么它連接的就是VER1.0版本的new_true符號

如果把b.lds更改為,
VER1.0{
};
VER2.0{
new_true;
};

然后在生成libb.so文件,在運行那個連接到VER1.0版本的new_true符號的應用程序,可以發現該應用程序不能運行了,
因為庫內沒有VER1.0版本的new_true,只有VER2.0版本的new_true。


2. 連接到帶版本的符號
寫一個簡單的應用(名為app)連接到libb.so,應用符號new_true
假設libb.so的版本控制文件為,
VER1.0{
};
VER2.0{
new_true;
};

$ nm app | grep new_true
U new_true@@VER1.0
$
用nm命令發現app連接到VER1.0版本的new_true

3. GNU的擴充
它允許在程序文件內綁定 *符號* 到 *帶版本號的別名符號*

文件b.c內容如下,
int old_true()
{
return 1;
}

int new_true()
{
return 2;
}
__asm__( ".symver old_true,true@VER1.0" );
__asm__( ".symver new_true,true@@VER2.0" );


其中,帶版本號的別名符號是true,其默認的版本號為VER2.0

供連接器用的版本控制腳本b.lds內容如下,
VER1.0{
};
VER2.0{
};

版本控制文件內必須包含版本VER1.0和版本VER2.0的定義,因為在b.c文件內有對他們的引用

****** 假定libb.so與app.c在同一目錄下 ********

以下應用程序app.c連接到該庫,
int true();
int main()
{
printf( "%d ", true );
}

$ gcc app.c libb.so
$ LD_LIBRARY_PATH=. ./app
2
$ nm app | grep true
U true@@VER2.0
$

很明顯,程序app使用的是VER2.0版本的別名符號true,如果在b.c內沒有指明別名符號true的默認版本,
那么gcc app.c libb.so將出現連接錯誤,提示true沒有定義。

也可以在程序內指定特定版本的別名符號true,程序如下,
__asm__( ".symver true,true@VER1.0" );
int true();
int main()
{
printf( "%d ", true );
}

$ gcc app.c libb.so
$ LD_LIBRARY_PATH=. ./app
1
$ nm app | grep true
U true@VER1.0
$

顯然,連接到了版本號為VER1.0的別名符號true。其中只有一個@表示,該版本不是默認的版本




我的疑問:
版本控制腳本文件中,各版本號節點之間的依賴關系


英文搜索關鍵字:
.symver
versioned symbol
version a shared library

參考:
info ld, Scripts node
===================== 結束 ==================================


11. 表達式
----------

表達式的文法與C語言的表達式文法一致,表達式的值都是整型,如果ld的運行主機和生成文件的目標機都是32位,則表達式是32位數據,否則是64位數據。
能夠在表達式內使用符號的值,設置符號的值。
下面看六項表達式相關內容,

常表達式:
_fourk_1 = 4K; /* K、M單位 */
_fourk_2 = 4096; /* 整數 */
_fourk_3 = 0x1000; /* 16 進位 */
_fourk_4 = 01000; /* 8 進位 */
1K=1024 1M=1024*1024
符號名:
沒有被引號""包圍的符號,以字母、下劃線或'.'開頭,可包含字母、下劃線、'.'和'-'。當符號名被引號包圍時,符號名可以與關鍵字相同。如,
"SECTION"=9
"with a space" = "also with a space" + 10;
定位符號'.':
只在SECTIONS命令內有效,代表一個程序地址空間內的地址。
注意:當定位符用在SECTIONS命令的輸出section描述內時,它代表的是該section的當前**偏移**,而不是程序地址空間的絕對地址。
先看個例子,
SECTIONS
{
output :
{
file1(.text)
. = . + 1000;
file2(.text)
. += 1000;
file3(.text)
} = 0x1234;
}
其中由于對定位符的賦值而產生的空隙由0x1234填充。其他的內容應該容易理解吧。
再看個例子,
SECTIONS
{
. = 0x100
.text: {
*(.text)
. = 0x200
}
. = 0x500
.data: {
*(.data)
. += 0x600
}
} .text section在程序地址空間的開始位置是0x
表達式的操作符:
與C語言一致。
優先級 結合順序 操作符
1 left ! - ~ (1)
2 left * / %
3 left + -
4 left >> <<
5 left == != > < <= >=
6 left &
7 left |
8 left &&
9 left ||
10 right ? :
11 right &= += -= *= /= (2)
(1)表示前綴符,(2)表示賦值符。
表達式的計算:
連接器延遲計算大部分表達式的值。
但是,對待與連接過程緊密相關的表達式,連接器會立即計算表達式,如果不能計算則報錯。比如,對于section的VMA地址、內存區域塊的開始地址和大小,與其相關的表達式應該立即被計算。
例子,
SECTIONS
{
.text 9+this_isnt_constant :
{ *(.text) }
}
這個例子中,9+this_isnt_constant表達式的值用于設置.text section的VMA地址,因此需要立即運算,但是由于this_isnt_constant變量的值不確定,所以此時連接器無法確立表達式的值,此時連接器會報錯。
相對值與絕對值:
在輸出section描述內的表達式,連接器取其相對值,相對與該section的開始位置的偏移
在SECTIONS命令內且非輸出section描述內的表達式,連接器取其絕對值
通過ABSOLUTE關鍵字可以將相對值轉化成絕對值,即在原來值的基礎上加上表達式所在section的VMA值。
例子,
SECTIONS
{
.data : { *(.data) _edata = ABSOLUTE(.); }
}
該例子中,_edata符號的值是.data section的末尾位置(絕對值,在程序地址空間內)。
內建函數:
ABSOLUTE(EXP) :轉換成絕對值
ADDR(SECTION) :返回某section的VMA值。
ALIGN(EXP) :返回定位符'.'的修調值,對齊后的值,(. + EXP - 1) & ~(EXP - 1)
BLOCK(EXP) :如同ALIGN(EXP),為了向前兼容。
DEFINED(SYMBOL) :如果符號SYMBOL在全局符號表內,且被定義了,那么返回1,否則返回0。例子,
SECTIONS { ...
.text : {
begin = DEFINED(begin) ? begin : . ;
...
}
...
}
LOADADDR(SECTION) :返回三SECTION的LMA
MAX(EXP1,EXP2) :返回大者
MIN(EXP1,EXP2) :返回小者
NEXT(EXP) :返回下一個能被使用的地址,該地址是EXP的倍數,類似于ALIGN(EXP)。除非使用了MEMORY命令定義了一些非連續的內存塊,否則NEXT(EXP)與ALIGH(EXP)一定相同。
SIZEOF(SECTION) :返回SECTION的大小。當SECTION沒有被分配時,即此時SECTION的大小還不能確定時,連接器會報錯。
SIZEOF_HEADERS :
sizeof_headers :返回輸出文件的文件頭大小(還是程序頭大小),用以確定第一個section的開始地址(在文件內)。???


12. 暗含的連接腳本


輸入文件可以是目標文件,也可以是連接腳本,此時的連接腳本被稱為 暗含的連接腳本
如果連接器不認識某個輸入文件,那么該文件被當作連接腳本被解析。更進一步,如果發現它的格式又不是連接腳本的格式,那么連接器報錯。
一個暗含的連接腳本不會替換默認的連接腳本,僅僅是增加新的連接而已。
一般來說,暗含的連接腳本符號分配命令,或INPUT、GROUP、VERSION命令。
在連接命令行中,每個輸入文件的順序都被固定好了,暗含的連接腳本在連接命令行內占住一個位置,這個位置決定了由該連接腳本指定的輸入文件在連接過程中的順序。
典型的暗含的連接腳本是libc.so文件,在GNU/linux內一般存在/usr/lib目錄下。


References


1, gnu ld在線手冊

2, 程序的鏈接和裝入及Linux下動態鏈接的實現

3, UNIX/Linux平臺可執行文件格式分析

4, John R. Levine.《Linkers & Loaders》

總結

以上是生活随笔為你收集整理的linux 可执行文件的分析(gcc GUN BUILEIN)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

极品嫩模高潮叫床 | 人妻少妇精品久久 | 免费无码一区二区三区蜜桃大 | 樱花草在线播放免费中文 | 欧美人与善在线com | 亚洲 日韩 欧美 成人 在线观看 | 日本爽爽爽爽爽爽在线观看免 | 综合网日日天干夜夜久久 | 日本又色又爽又黄的a片18禁 | 久青草影院在线观看国产 | 亚洲国产高清在线观看视频 | 亚洲欧美日韩国产精品一区二区 | 精品久久综合1区2区3区激情 | 久久久中文久久久无码 | 精品夜夜澡人妻无码av蜜桃 | 久久综合给久久狠狠97色 | 国产美女极度色诱视频www | 伊人久久大香线蕉av一区二区 | 亚洲精品一区二区三区四区五区 | 国产午夜无码视频在线观看 | 亚洲国产欧美国产综合一区 | 色偷偷人人澡人人爽人人模 | 日本精品少妇一区二区三区 | 亚洲中文字幕成人无码 | 久久久久亚洲精品中文字幕 | 鲁大师影院在线观看 | 亚洲狠狠色丁香婷婷综合 | 精品乱子伦一区二区三区 | 澳门永久av免费网站 | 亚洲精品综合五月久久小说 | 无码任你躁久久久久久久 | 香蕉久久久久久av成人 | 图片小说视频一区二区 | 亚洲欧美国产精品专区久久 | 偷窥村妇洗澡毛毛多 | 精品人妻人人做人人爽 | 久久国产精品偷任你爽任你 | 黑人粗大猛烈进出高潮视频 | 性色欲情网站iwww九文堂 | 国产麻豆精品精东影业av网站 | 中国大陆精品视频xxxx | 久久精品中文字幕一区 | 97色伦图片97综合影院 | 人妻无码αv中文字幕久久琪琪布 | 久久亚洲中文字幕精品一区 | 强奷人妻日本中文字幕 | 亚洲日韩精品欧美一区二区 | 国产三级精品三级男人的天堂 | 一本大道伊人av久久综合 | 日产国产精品亚洲系列 | 3d动漫精品啪啪一区二区中 | 女人被男人躁得好爽免费视频 | 一本一道久久综合久久 | 人妻少妇精品无码专区动漫 | 在线观看免费人成视频 | 精品久久久无码人妻字幂 | 亚洲另类伦春色综合小说 | 久久综合九色综合欧美狠狠 | 丝袜足控一区二区三区 | 无码纯肉视频在线观看 | 国产精品99久久精品爆乳 | 国产美女精品一区二区三区 | 国产手机在线αⅴ片无码观看 | 精品国产青草久久久久福利 | 无码成人精品区在线观看 | 中文字幕中文有码在线 | 亚洲一区二区三区含羞草 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲午夜福利在线观看 | 中文无码成人免费视频在线观看 | 亚洲娇小与黑人巨大交 | 青青青爽视频在线观看 | 国产精品高潮呻吟av久久 | 性色av无码免费一区二区三区 | 粗大的内捧猛烈进出视频 | 久久精品一区二区三区四区 | 男人的天堂2018无码 | 国产精品手机免费 | 内射后入在线观看一区 | 国产精品怡红院永久免费 | 亚洲色成人中文字幕网站 | 久久久国产精品无码免费专区 | 日韩视频 中文字幕 视频一区 | 久久久久人妻一区精品色欧美 | 伊人久久婷婷五月综合97色 | 成熟人妻av无码专区 | 精品厕所偷拍各类美女tp嘘嘘 | 久久精品女人的天堂av | 欧美日本免费一区二区三区 | 欧洲熟妇色 欧美 | 亚洲а∨天堂久久精品2021 | 亚洲熟妇色xxxxx欧美老妇y | 东北女人啪啪对白 | 内射后入在线观看一区 | 波多野结衣乳巨码无在线观看 | 欧洲vodafone精品性 | 日本精品久久久久中文字幕 | 国产精品久久久久7777 | 激情亚洲一区国产精品 | 又黄又爽又色的视频 | 中国女人内谢69xxxxxa片 | 给我免费的视频在线观看 | 久久久亚洲欧洲日产国码αv | 久久久无码中文字幕久... | 青春草在线视频免费观看 | 亚洲精品鲁一鲁一区二区三区 | √8天堂资源地址中文在线 | 国产成人综合在线女婷五月99播放 | 图片小说视频一区二区 | 久久99精品久久久久久 | 丝袜 中出 制服 人妻 美腿 | 99国产欧美久久久精品 | 亚洲精品无码国产 | 亚洲の无码国产の无码步美 | 正在播放老肥熟妇露脸 | 在线播放亚洲第一字幕 | 亚洲成av人片在线观看无码不卡 | 人人爽人人澡人人人妻 | 性开放的女人aaa片 | 欧美喷潮久久久xxxxx | 特黄特色大片免费播放器图片 | 鲁一鲁av2019在线 | 国产一区二区三区日韩精品 | 亚洲中文无码av永久不收费 | 国产97色在线 | 免 | 色诱久久久久综合网ywww | 99在线 | 亚洲 | 亚洲 欧美 激情 小说 另类 | 亚洲一区二区三区偷拍女厕 | 狠狠色欧美亚洲狠狠色www | 日本免费一区二区三区最新 | 精品国产成人一区二区三区 | 又大又紧又粉嫩18p少妇 | 久久国产自偷自偷免费一区调 | 狠狠色欧美亚洲狠狠色www | 国产免费无码一区二区视频 | 日日干夜夜干 | 无码av岛国片在线播放 | 夜夜躁日日躁狠狠久久av | 在线观看国产一区二区三区 | 色五月丁香五月综合五月 | 中文字幕人妻无码一区二区三区 | 欧美丰满老熟妇xxxxx性 | 久久亚洲日韩精品一区二区三区 | 99精品久久毛片a片 | 免费观看又污又黄的网站 | 精品无码国产一区二区三区av | 亚洲人成网站在线播放942 | 精品国产一区av天美传媒 | 丰满少妇女裸体bbw | 波多野结衣乳巨码无在线观看 | 在线а√天堂中文官网 | 国产精品无码一区二区桃花视频 | 欧美黑人性暴力猛交喷水 | 天天摸天天透天天添 | 亚洲小说春色综合另类 | 国产亚洲tv在线观看 | 久久久久99精品成人片 | 亚洲中文字幕成人无码 | 国产一区二区不卡老阿姨 | 丰满护士巨好爽好大乳 | 欧美乱妇无乱码大黄a片 | 欧美性色19p | 午夜精品久久久内射近拍高清 | 色婷婷香蕉在线一区二区 | 在线观看免费人成视频 | 亚洲日韩中文字幕在线播放 | 国产人妻精品一区二区三区不卡 | 欧美xxxxx精品 | 国产小呦泬泬99精品 | 国产亚洲精品久久久久久国模美 | 国产在线aaa片一区二区99 | 无码任你躁久久久久久久 | 狂野欧美性猛xxxx乱大交 | 亚洲一区二区三区国产精华液 | 国产精品手机免费 | 夜夜躁日日躁狠狠久久av | 久久久久久久久蜜桃 | 亚洲a无码综合a国产av中文 | 人人妻人人澡人人爽人人精品浪潮 | 成人影院yy111111在线观看 | 99久久久无码国产aaa精品 | 久久亚洲国产成人精品性色 | 亚洲小说春色综合另类 | 少妇一晚三次一区二区三区 | 欧美野外疯狂做受xxxx高潮 | 久久99精品国产麻豆蜜芽 | 国产无遮挡又黄又爽又色 | 国产九九九九九九九a片 | 国产美女精品一区二区三区 | 亚洲欧美中文字幕5发布 | 中文亚洲成a人片在线观看 | 日韩人妻无码一区二区三区久久99 | 亚洲精品中文字幕 | 国产精品igao视频网 | 国产亚洲欧美日韩亚洲中文色 | 无码人妻丰满熟妇区五十路百度 | 国产亚洲tv在线观看 | 日本va欧美va欧美va精品 | 亚洲成av人综合在线观看 | 欧美成人高清在线播放 | 国产热a欧美热a在线视频 | 中文字幕乱码人妻无码久久 | 97久久超碰中文字幕 | 欧美 日韩 人妻 高清 中文 | 欧美 丝袜 自拍 制服 另类 | 久久这里只有精品视频9 | 少妇一晚三次一区二区三区 | 黑人大群体交免费视频 | 国产香蕉尹人视频在线 | 国产莉萝无码av在线播放 | 人妻尝试又大又粗久久 | 国内综合精品午夜久久资源 | 国产免费观看黄av片 | 97无码免费人妻超级碰碰夜夜 | 少妇性l交大片欧洲热妇乱xxx | 国产成人综合色在线观看网站 | 久久亚洲精品中文字幕无男同 | 在线观看国产午夜福利片 | 男女爱爱好爽视频免费看 | 国模大胆一区二区三区 | 久久熟妇人妻午夜寂寞影院 | 亚洲成a人片在线观看无码3d | 欧美日韩色另类综合 | 亚洲国产av精品一区二区蜜芽 | 天海翼激烈高潮到腰振不止 | 亚洲精品一区国产 | 人妻少妇被猛烈进入中文字幕 | 日本大乳高潮视频在线观看 | 男人扒开女人内裤强吻桶进去 | 99er热精品视频 | 四虎国产精品一区二区 | 国产av无码专区亚洲a∨毛片 | 国产亚洲美女精品久久久2020 | 亚洲国产精品成人久久蜜臀 | 美女张开腿让人桶 | 久久午夜无码鲁丝片秋霞 | 国产精品多人p群无码 | 日日橹狠狠爱欧美视频 | 欧美性猛交内射兽交老熟妇 | 国内揄拍国内精品人妻 | 色综合久久中文娱乐网 | 奇米影视888欧美在线观看 | 久久久精品国产sm最大网站 | 强开小婷嫩苞又嫩又紧视频 | 欧美三级a做爰在线观看 | 精品无码一区二区三区的天堂 | 亚洲区欧美区综合区自拍区 | 国产精品久久久久影院嫩草 | 激情内射亚州一区二区三区爱妻 | 欧美亚洲国产一区二区三区 | 免费国产成人高清在线观看网站 | 精品无码av一区二区三区 | 免费观看激色视频网站 | 亚洲成av人综合在线观看 | 亚洲欧美日韩成人高清在线一区 | 成人精品一区二区三区中文字幕 | 在线精品国产一区二区三区 | 色狠狠av一区二区三区 | 久久精品人人做人人综合试看 | 少妇性l交大片欧洲热妇乱xxx | 欧美精品国产综合久久 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产人成高清在线视频99最全资源 | 国产97人人超碰caoprom | 激情国产av做激情国产爱 | 久久综合香蕉国产蜜臀av | 一区二区传媒有限公司 | 国产av无码专区亚洲a∨毛片 | 亚洲 另类 在线 欧美 制服 | 99精品视频在线观看免费 | 男人的天堂av网站 | 丰满肥臀大屁股熟妇激情视频 | 亚洲gv猛男gv无码男同 | 国内揄拍国内精品人妻 | 小泽玛莉亚一区二区视频在线 | 精品一区二区三区无码免费视频 | 东北女人啪啪对白 | 人妻尝试又大又粗久久 | 性生交大片免费看l | 水蜜桃av无码 | 波多野结衣高清一区二区三区 | 亚洲中文字幕成人无码 | 18禁黄网站男男禁片免费观看 | 无码人妻丰满熟妇区五十路百度 | 正在播放老肥熟妇露脸 | 色 综合 欧美 亚洲 国产 | 成熟妇人a片免费看网站 | 乱码午夜-极国产极内射 | 精品久久综合1区2区3区激情 | 国产精品久久国产精品99 | 国产国产精品人在线视 | 999久久久国产精品消防器材 | 国产农村妇女高潮大叫 | 3d动漫精品啪啪一区二区中 | 国精产品一区二区三区 | 十八禁真人啪啪免费网站 | 在教室伦流澡到高潮hnp视频 | 国产亚洲人成在线播放 | 国产精品久久久久久亚洲影视内衣 | 国内精品一区二区三区不卡 | 麻豆人妻少妇精品无码专区 | 久久综合给久久狠狠97色 | 国内精品人妻无码久久久影院蜜桃 | 性啪啪chinese东北女人 | 清纯唯美经典一区二区 | 永久黄网站色视频免费直播 | 全黄性性激高免费视频 | 乱人伦人妻中文字幕无码久久网 | 人人超人人超碰超国产 | 久久久久久久人妻无码中文字幕爆 | 无码国产色欲xxxxx视频 | 少女韩国电视剧在线观看完整 | 国产免费无码一区二区视频 | 国产免费观看黄av片 | 久久99精品国产麻豆 | 精品欧美一区二区三区久久久 | 亚洲中文字幕久久无码 | 国产亚洲精品久久久久久久 | 日韩av无码一区二区三区不卡 | 装睡被陌生人摸出水好爽 | 亚洲一区二区观看播放 | 性欧美牲交在线视频 | 少妇无码一区二区二三区 | 国产偷自视频区视频 | 麻花豆传媒剧国产免费mv在线 | 精品国产aⅴ无码一区二区 | 日本精品高清一区二区 | 精品国产青草久久久久福利 | 乱人伦中文视频在线观看 | 国产精品丝袜黑色高跟鞋 | 亚洲中文字幕无码一久久区 | 久久五月精品中文字幕 | 国产成人无码av在线影院 | 四虎4hu永久免费 | 亚洲理论电影在线观看 | 亚洲自偷自偷在线制服 | 成年女人永久免费看片 | 白嫩日本少妇做爰 | 图片区 小说区 区 亚洲五月 | 中文字幕乱码人妻无码久久 | 强开小婷嫩苞又嫩又紧视频 | 国产熟妇另类久久久久 | 久久综合激激的五月天 | 一个人免费观看的www视频 | 国产成人综合在线女婷五月99播放 | 午夜理论片yy44880影院 | 三级4级全黄60分钟 | 欧美老妇交乱视频在线观看 | 国产精品亚洲一区二区三区喷水 | 日本一区二区更新不卡 | 又大又硬又爽免费视频 | 蜜桃臀无码内射一区二区三区 | 色 综合 欧美 亚洲 国产 | 蜜臀aⅴ国产精品久久久国产老师 | 国产绳艺sm调教室论坛 | 成人综合网亚洲伊人 | 久久精品国产一区二区三区 | 狠狠综合久久久久综合网 | 欧美成人高清在线播放 | 国产真人无遮挡作爱免费视频 | 久久久国产精品无码免费专区 | 国产精品久久久久久亚洲影视内衣 | 国产成人无码av片在线观看不卡 | 狠狠躁日日躁夜夜躁2020 | 天天爽夜夜爽夜夜爽 | 又大又紧又粉嫩18p少妇 | 超碰97人人做人人爱少妇 | 国产97色在线 | 免 | 性开放的女人aaa片 | 国产热a欧美热a在线视频 | 欧美老妇交乱视频在线观看 | 国产舌乚八伦偷品w中 | a国产一区二区免费入口 | 最新国产麻豆aⅴ精品无码 | 国产97人人超碰caoprom | 亚洲日韩一区二区三区 | 日韩欧美群交p片內射中文 | 最新国产麻豆aⅴ精品无码 | 一本加勒比波多野结衣 | a在线亚洲男人的天堂 | 亚洲精品综合一区二区三区在线 | 中文字幕乱码人妻无码久久 | 天天爽夜夜爽夜夜爽 | 亚洲精品欧美二区三区中文字幕 | 国产一区二区三区影院 | 国产精品对白交换视频 | 国产一区二区不卡老阿姨 | 国产乱码精品一品二品 | √天堂资源地址中文在线 | 全黄性性激高免费视频 | 人妻体内射精一区二区三四 | 精品无人区无码乱码毛片国产 | 亚洲爆乳无码专区 | 亚洲 激情 小说 另类 欧美 | 乱人伦人妻中文字幕无码久久网 | 强奷人妻日本中文字幕 | 国产免费观看黄av片 | 国产av无码专区亚洲a∨毛片 | 日韩成人一区二区三区在线观看 | 色一情一乱一伦 | www一区二区www免费 | 蜜桃臀无码内射一区二区三区 | 亚洲熟妇色xxxxx欧美老妇 | 精品久久久无码中文字幕 | 成人精品视频一区二区三区尤物 | 国产精品亚洲专区无码不卡 | 亚洲精品久久久久久一区二区 | 青春草在线视频免费观看 | 久久久久免费精品国产 | 激情内射日本一区二区三区 | 成人片黄网站色大片免费观看 | 精品人妻人人做人人爽 | 午夜熟女插插xx免费视频 | 亚洲熟妇色xxxxx欧美老妇y | 日本熟妇浓毛 | 一本色道久久综合亚洲精品不卡 | 久久综合激激的五月天 | 精品久久久无码中文字幕 | 久久亚洲日韩精品一区二区三区 | 久热国产vs视频在线观看 | 露脸叫床粗话东北少妇 | 人妻天天爽夜夜爽一区二区 | 中文字幕无码视频专区 | 国产激情精品一区二区三区 | 亚洲人成影院在线无码按摩店 | 欧美人与善在线com | 婷婷丁香五月天综合东京热 | 麻豆人妻少妇精品无码专区 | 欧美 丝袜 自拍 制服 另类 | 日日干夜夜干 | 青青青爽视频在线观看 | 激情综合激情五月俺也去 | 任你躁国产自任一区二区三区 | 国产精品久久久午夜夜伦鲁鲁 | 日韩无套无码精品 | 学生妹亚洲一区二区 | 人人妻人人澡人人爽精品欧美 | 福利一区二区三区视频在线观看 | 无码纯肉视频在线观看 | 久久综合狠狠综合久久综合88 | 久久国产精品二国产精品 | 东京一本一道一二三区 | 中文毛片无遮挡高清免费 | 正在播放东北夫妻内射 | 久久久国产精品无码免费专区 | 亚洲成a人一区二区三区 | 清纯唯美经典一区二区 | 日韩亚洲欧美中文高清在线 | 夜夜夜高潮夜夜爽夜夜爰爰 | 亚洲乱码国产乱码精品精 | 日韩精品乱码av一区二区 | 大屁股大乳丰满人妻 | 亚洲精品成a人在线观看 | 精品久久久久久人妻无码中文字幕 | 中文字幕无码乱人伦 | 丰满肥臀大屁股熟妇激情视频 | 亚洲爆乳大丰满无码专区 | 亚洲精品成a人在线观看 | 国产内射老熟女aaaa | 色诱久久久久综合网ywww | 荫蒂添的好舒服视频囗交 | 无码精品人妻一区二区三区av | 精品偷拍一区二区三区在线看 | 在线精品国产一区二区三区 | aa片在线观看视频在线播放 | 少妇久久久久久人妻无码 | 中文字幕人妻丝袜二区 | 精品国产一区二区三区四区在线看 | 亚洲精品久久久久久久久久久 | 俺去俺来也在线www色官网 | 日本精品高清一区二区 | 中文字幕无码免费久久99 | 国产午夜福利亚洲第一 | 正在播放东北夫妻内射 | 午夜男女很黄的视频 | 九一九色国产 | 午夜福利一区二区三区在线观看 | 久久久久se色偷偷亚洲精品av | 欧美国产日韩亚洲中文 | 乱人伦人妻中文字幕无码 | 国产麻豆精品一区二区三区v视界 | 天堂久久天堂av色综合 | 色综合久久久无码中文字幕 | 国内精品一区二区三区不卡 | 亚洲精品欧美二区三区中文字幕 | 18禁止看的免费污网站 | 国产乱人无码伦av在线a | 欧美丰满少妇xxxx性 | 日韩精品一区二区av在线 | 国产精品99爱免费视频 | 国产精品久久久一区二区三区 | 午夜理论片yy44880影院 | 日本一卡二卡不卡视频查询 | 极品嫩模高潮叫床 | 国产精品-区区久久久狼 | 欧美肥老太牲交大战 | 国产网红无码精品视频 | 未满小14洗澡无码视频网站 | 欧美大屁股xxxxhd黑色 | 成人精品天堂一区二区三区 | 国产熟妇高潮叫床视频播放 | 久久久久久a亚洲欧洲av冫 | 国产在线无码精品电影网 | 国产女主播喷水视频在线观看 | 秋霞特色aa大片 | 久久久久久九九精品久 | 一区二区三区乱码在线 | 欧洲 | 午夜精品一区二区三区在线观看 | 国产午夜亚洲精品不卡 | 欧美丰满熟妇xxxx性ppx人交 | 乱中年女人伦av三区 | 欧美人与禽猛交狂配 | 又大又硬又爽免费视频 | √8天堂资源地址中文在线 | 亚洲国精产品一二二线 | 玩弄少妇高潮ⅹxxxyw | 亚洲成av人影院在线观看 | 国产明星裸体无码xxxx视频 | 国产精品亚洲五月天高清 | 理论片87福利理论电影 | 秋霞成人午夜鲁丝一区二区三区 | 成人女人看片免费视频放人 | 妺妺窝人体色www在线小说 | 国精产品一品二品国精品69xx | 精品乱码久久久久久久 | 亚洲欧美日韩国产精品一区二区 | 中文字幕av日韩精品一区二区 | 国产福利视频一区二区 | 人人澡人人透人人爽 | 强伦人妻一区二区三区视频18 | 强辱丰满人妻hd中文字幕 | 国产香蕉尹人视频在线 | 久久精品成人欧美大片 | 国产美女精品一区二区三区 | av小次郎收藏 | 影音先锋中文字幕无码 | 天天摸天天透天天添 | 国产电影无码午夜在线播放 | 亚洲一区二区三区无码久久 | 国产福利视频一区二区 | 国内精品九九久久久精品 | 国产 浪潮av性色四虎 | 亚洲熟女一区二区三区 | 狂野欧美性猛xxxx乱大交 | 色一情一乱一伦一视频免费看 | 中文字幕久久久久人妻 | 中文字幕久久久久人妻 | 麻豆国产丝袜白领秘书在线观看 | 精品夜夜澡人妻无码av蜜桃 | 老熟妇乱子伦牲交视频 | 亚洲理论电影在线观看 | 亚洲精品国产精品乱码不卡 | 97资源共享在线视频 | 亚洲综合另类小说色区 | 好屌草这里只有精品 | 国产亚洲美女精品久久久2020 | 婷婷综合久久中文字幕蜜桃三电影 | 夜精品a片一区二区三区无码白浆 | 天天摸天天碰天天添 | 亚洲熟妇色xxxxx亚洲 | 精品国产一区二区三区四区 | 色欲av亚洲一区无码少妇 | 日本精品少妇一区二区三区 | 国产一精品一av一免费 | 国产真实乱对白精彩久久 | 131美女爱做视频 | 亚洲国产精品久久久天堂 | 亚洲午夜久久久影院 | 久久亚洲中文字幕无码 | 午夜性刺激在线视频免费 | 欧美怡红院免费全部视频 | 久久久国产精品无码免费专区 | а天堂中文在线官网 | 白嫩日本少妇做爰 | 亚洲国产欧美日韩精品一区二区三区 | 漂亮人妻洗澡被公强 日日躁 | 亚洲自偷自拍另类第1页 | 中文字幕色婷婷在线视频 | 精品国产乱码久久久久乱码 | 色老头在线一区二区三区 | 四虎国产精品一区二区 | 日本va欧美va欧美va精品 | 国精品人妻无码一区二区三区蜜柚 | 少妇被黑人到高潮喷出白浆 | 少妇太爽了在线观看 | 天堂亚洲免费视频 | 久久精品国产一区二区三区 | 精品国产av色一区二区深夜久久 | 兔费看少妇性l交大片免费 | 天天摸天天碰天天添 | 精品国偷自产在线 | 精品国产成人一区二区三区 | 久久国产精品_国产精品 | 久久精品成人欧美大片 | 狠狠色色综合网站 | 2020最新国产自产精品 | 青春草在线视频免费观看 | 国产又粗又硬又大爽黄老大爷视 | 国产av一区二区三区最新精品 | 国产超碰人人爽人人做人人添 | 最近免费中文字幕中文高清百度 | 中文字幕乱码人妻二区三区 | 久久午夜无码鲁丝片秋霞 | 国产香蕉97碰碰久久人人 | 日本欧美一区二区三区乱码 | 999久久久国产精品消防器材 | 久久久久亚洲精品男人的天堂 | 国产在线aaa片一区二区99 | 中文字幕人妻丝袜二区 | 中文无码伦av中文字幕 | 美女毛片一区二区三区四区 | 成人片黄网站色大片免费观看 | 中文字幕人妻无码一区二区三区 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产香蕉尹人综合在线观看 | 日日噜噜噜噜夜夜爽亚洲精品 | 牲欲强的熟妇农村老妇女 | 玩弄少妇高潮ⅹxxxyw | 国产精品久免费的黄网站 | 黑人巨大精品欧美一区二区 | 亚洲最大成人网站 | 精品久久久中文字幕人妻 | 中文字幕无码热在线视频 | 性欧美大战久久久久久久 | 国产农村妇女高潮大叫 | 强开小婷嫩苞又嫩又紧视频 | 大肉大捧一进一出视频出来呀 | 国产人成高清在线视频99最全资源 | 精品无人区无码乱码毛片国产 | 国产无套粉嫩白浆在线 | 国产精品内射视频免费 | 性色欲情网站iwww九文堂 | 樱花草在线社区www | 久久午夜无码鲁丝片 | 高中生自慰www网站 | 亚洲中文字幕久久无码 | 精品aⅴ一区二区三区 | 精品久久久无码人妻字幂 | 国产精品久久久久久久9999 | 中文无码成人免费视频在线观看 | 最近免费中文字幕中文高清百度 | 特大黑人娇小亚洲女 | 日日摸天天摸爽爽狠狠97 | 久久人人爽人人人人片 | 免费无码的av片在线观看 | 亚洲一区二区三区国产精华液 | 国产乡下妇女做爰 | 粉嫩少妇内射浓精videos | 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲综合无码久久精品综合 | 亚洲日韩av一区二区三区四区 | 亚洲色欲色欲天天天www | 国产精品无码永久免费888 | 成人欧美一区二区三区黑人 | 中文字幕无码日韩欧毛 | 成在人线av无码免观看麻豆 | 伦伦影院午夜理论片 | 丝袜美腿亚洲一区二区 | 高潮毛片无遮挡高清免费视频 | 午夜丰满少妇性开放视频 | 99久久无码一区人妻 | 少妇被粗大的猛进出69影院 | 国产特级毛片aaaaaaa高清 | 成人三级无码视频在线观看 | 国产熟妇另类久久久久 | 成人欧美一区二区三区黑人 | 亚洲精品久久久久久久久久久 | 精品一二三区久久aaa片 | 国产香蕉97碰碰久久人人 | 亚洲精品国偷拍自产在线麻豆 | 国产亚洲视频中文字幕97精品 | 麻豆成人精品国产免费 | 在线 国产 欧美 亚洲 天堂 | 任你躁在线精品免费 | 国产午夜手机精彩视频 | 精品亚洲韩国一区二区三区 | 无码播放一区二区三区 | 搡女人真爽免费视频大全 | 又紧又大又爽精品一区二区 | 在线亚洲高清揄拍自拍一品区 | 中国女人内谢69xxxxxa片 | аⅴ资源天堂资源库在线 | 精品成在人线av无码免费看 | 久久精品99久久香蕉国产色戒 | 国产精品无码永久免费888 | 在线a亚洲视频播放在线观看 | 99精品久久毛片a片 | 少妇激情av一区二区 | 亚洲熟妇色xxxxx欧美老妇y | 国产在线aaa片一区二区99 | 熟妇人妻激情偷爽文 | 在线精品亚洲一区二区 | 久久精品一区二区三区四区 | 亚洲a无码综合a国产av中文 | 久久精品国产一区二区三区肥胖 | 小鲜肉自慰网站xnxx | 日韩精品无码一本二本三本色 | 波多野42部无码喷潮在线 | 女人被男人躁得好爽免费视频 | 国产xxx69麻豆国语对白 | 任你躁国产自任一区二区三区 | 少妇性l交大片欧洲热妇乱xxx | 妺妺窝人体色www在线小说 | 国语自产偷拍精品视频偷 | 国产成人无码av在线影院 | 日本一区二区三区免费高清 | 午夜精品久久久内射近拍高清 | 无码成人精品区在线观看 | 欧美35页视频在线观看 | 精品夜夜澡人妻无码av蜜桃 | 国产电影无码午夜在线播放 | 国产亚洲视频中文字幕97精品 | 日日麻批免费40分钟无码 | 荫蒂添的好舒服视频囗交 | 99久久精品日本一区二区免费 | 国产亚洲精品久久久久久大师 | 国产乱码精品一品二品 | 俄罗斯老熟妇色xxxx | 强伦人妻一区二区三区视频18 | 欧美大屁股xxxxhd黑色 | 少妇性l交大片欧洲热妇乱xxx | 人妻少妇精品无码专区二区 | 男女超爽视频免费播放 | 成人精品一区二区三区中文字幕 | 久久综合九色综合97网 | 综合激情五月综合激情五月激情1 | 无码纯肉视频在线观看 | 亚洲欧美日韩成人高清在线一区 | 国产午夜精品一区二区三区嫩草 | 乱码av麻豆丝袜熟女系列 | 在线欧美精品一区二区三区 | 99久久婷婷国产综合精品青草免费 | 色五月五月丁香亚洲综合网 | 亚洲日韩中文字幕在线播放 | 国产精品无码久久av | 欧美老人巨大xxxx做受 | 色欲久久久天天天综合网精品 | 亚洲综合无码久久精品综合 | 狠狠色欧美亚洲狠狠色www | 人人超人人超碰超国产 | 无码国内精品人妻少妇 | 18禁黄网站男男禁片免费观看 | 国产精品人妻一区二区三区四 | 丰满少妇高潮惨叫视频 | 欧美xxxxx精品 | 四虎国产精品免费久久 | 最近中文2019字幕第二页 | 97se亚洲精品一区 | 国产精品人妻一区二区三区四 | 人人妻人人澡人人爽欧美一区九九 | 中文字幕无线码免费人妻 | 国产精品沙发午睡系列 | 欧美熟妇另类久久久久久多毛 | 国产猛烈高潮尖叫视频免费 | 东京热无码av男人的天堂 | 激情五月综合色婷婷一区二区 | 亚洲s码欧洲m码国产av | 无码国模国产在线观看 | 亚洲s色大片在线观看 | 中文字幕色婷婷在线视频 | 国产极品美女高潮无套在线观看 | 中文字幕+乱码+中文字幕一区 | 国产精品亚洲专区无码不卡 | 性生交片免费无码看人 | 午夜男女很黄的视频 | 久久99精品国产麻豆 | 欧洲精品码一区二区三区免费看 | 天天做天天爱天天爽综合网 | 久久久久亚洲精品中文字幕 | 国产人妻精品午夜福利免费 | 中文无码成人免费视频在线观看 | 亚洲人成影院在线无码按摩店 | 成人片黄网站色大片免费观看 | 日韩精品久久久肉伦网站 | 搡女人真爽免费视频大全 | 久久综合狠狠综合久久综合88 | 欧美人与牲动交xxxx | 正在播放老肥熟妇露脸 | 国产乱人偷精品人妻a片 | 精品国产一区二区三区av 性色 | 国产精品怡红院永久免费 | 国产午夜亚洲精品不卡下载 | 国产成人一区二区三区别 | 精品久久8x国产免费观看 | 亚洲精品无码国产 | 午夜性刺激在线视频免费 | 特黄特色大片免费播放器图片 | 久久99精品国产.久久久久 | 东京一本一道一二三区 | 性色欲网站人妻丰满中文久久不卡 | 日本一区二区更新不卡 | 日韩人妻无码一区二区三区久久99 | 中文字幕乱妇无码av在线 | 中文字幕乱码人妻二区三区 | 国产av人人夜夜澡人人爽麻豆 | 性欧美牲交xxxxx视频 | 国产suv精品一区二区五 | 日本饥渴人妻欲求不满 | 无码av中文字幕免费放 | 国产高清不卡无码视频 | 国产av一区二区精品久久凹凸 | 牲欲强的熟妇农村老妇女 | 亚洲综合精品香蕉久久网 | 日韩精品成人一区二区三区 | 国产97在线 | 亚洲 | 少妇一晚三次一区二区三区 | 久久久国产一区二区三区 | 国产激情无码一区二区 | 5858s亚洲色大成网站www | 18精品久久久无码午夜福利 | 亚洲国产精品一区二区美利坚 | 久久精品国产99久久6动漫 | а天堂中文在线官网 | 无码福利日韩神码福利片 | 精品人妻av区 | 天下第一社区视频www日本 | 无码吃奶揉捏奶头高潮视频 | 国产成人无码区免费内射一片色欲 | 成在人线av无码免费 | 欧美高清在线精品一区 | 亚洲va欧美va天堂v国产综合 | 少妇一晚三次一区二区三区 | 蜜臀aⅴ国产精品久久久国产老师 | 最近的中文字幕在线看视频 | 红桃av一区二区三区在线无码av | 啦啦啦www在线观看免费视频 | 成人亚洲精品久久久久软件 | 特黄特色大片免费播放器图片 | 精品少妇爆乳无码av无码专区 | 丁香啪啪综合成人亚洲 | 男女性色大片免费网站 | 色情久久久av熟女人妻网站 | 久久久久久av无码免费看大片 | 奇米影视7777久久精品 | 国产麻豆精品一区二区三区v视界 | 亚洲最大成人网站 | 亚洲国精产品一二二线 | 国产成人精品必看 | 欧美激情一区二区三区成人 | 亚洲另类伦春色综合小说 | 久久久中文字幕日本无吗 | 十八禁真人啪啪免费网站 | 人人妻人人藻人人爽欧美一区 | 久9re热视频这里只有精品 | 少妇久久久久久人妻无码 | 日本又色又爽又黄的a片18禁 | 久久精品国产99久久6动漫 | 国产无套粉嫩白浆在线 | 成人av无码一区二区三区 | 性生交片免费无码看人 | 国产舌乚八伦偷品w中 | 成人女人看片免费视频放人 | av小次郎收藏 | 无码人妻久久一区二区三区不卡 | 成年美女黄网站色大免费全看 | 国产明星裸体无码xxxx视频 | 无码吃奶揉捏奶头高潮视频 | 动漫av网站免费观看 | 一本色道久久综合狠狠躁 | 国产亚洲欧美在线专区 | 亚洲啪av永久无码精品放毛片 | 色婷婷欧美在线播放内射 | 人人爽人人爽人人片av亚洲 | 综合激情五月综合激情五月激情1 | 国产精品人人妻人人爽 | 欧美xxxxx精品 | 99精品久久毛片a片 | 麻豆精品国产精华精华液好用吗 | 老熟女重囗味hdxx69 | 久久国产精品_国产精品 | 国产色视频一区二区三区 | 久久久久免费精品国产 | 大地资源网第二页免费观看 | 久久精品国产日本波多野结衣 | 亚洲精品午夜国产va久久成人 | 午夜丰满少妇性开放视频 | 无码人妻出轨黑人中文字幕 | 风流少妇按摩来高潮 | 人妻与老人中文字幕 | 久久国产自偷自偷免费一区调 | 午夜丰满少妇性开放视频 | 好男人社区资源 | 精品国产一区二区三区四区在线看 | 爱做久久久久久 | 亚洲熟妇自偷自拍另类 | 97精品国产97久久久久久免费 | 黑人巨大精品欧美一区二区 | 精品国产一区二区三区av 性色 | 国产精品嫩草久久久久 | 又黄又爽又色的视频 | 午夜精品久久久内射近拍高清 | 久久久精品欧美一区二区免费 | 精品一区二区三区波多野结衣 | 久久久久人妻一区精品色欧美 | 亚洲成av人综合在线观看 | 国产精品va在线播放 | 国产特级毛片aaaaaaa高清 | 国产精品久久久久久亚洲影视内衣 | 男人和女人高潮免费网站 | 成人亚洲精品久久久久 | 成人欧美一区二区三区黑人 | 欧美精品国产综合久久 | 欧美兽交xxxx×视频 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 大屁股大乳丰满人妻 | 欧美日韩精品 | 99久久精品国产一区二区蜜芽 | 偷窥村妇洗澡毛毛多 | 国产精品第一区揄拍无码 | 荫蒂被男人添的好舒服爽免费视频 | 国产又粗又硬又大爽黄老大爷视 | 亚洲精品国产第一综合99久久 | 98国产精品综合一区二区三区 | 正在播放东北夫妻内射 | 麻豆av传媒蜜桃天美传媒 | 99在线 | 亚洲 | 蜜臀av无码人妻精品 | 日日天干夜夜狠狠爱 | 日韩精品一区二区av在线 | 亚洲精品久久久久久一区二区 | 国产另类ts人妖一区二区 | 成人免费视频视频在线观看 免费 | 成人av无码一区二区三区 | 伊人久久大香线蕉av一区二区 | 日本乱人伦片中文三区 | 99精品无人区乱码1区2区3区 | 国产亚洲美女精品久久久2020 | 人人澡人人妻人人爽人人蜜桃 | 丰满人妻一区二区三区免费视频 | 一本久久伊人热热精品中文字幕 | 欧美成人高清在线播放 | 国产免费观看黄av片 | 久久精品人妻少妇一区二区三区 | 漂亮人妻洗澡被公强 日日躁 | 日韩欧美群交p片內射中文 | 全黄性性激高免费视频 | 免费网站看v片在线18禁无码 | 天天av天天av天天透 | 在线观看免费人成视频 | 伦伦影院午夜理论片 | 国产亚洲欧美在线专区 | 国产电影无码午夜在线播放 | 暴力强奷在线播放无码 | 免费人成在线视频无码 | 成人欧美一区二区三区黑人 | 亚洲欧美色中文字幕在线 | 丰满人妻翻云覆雨呻吟视频 | 国产精品久久久久久亚洲毛片 | 国产偷抇久久精品a片69 | 国产亚洲美女精品久久久2020 | 无码人妻丰满熟妇区毛片18 | 久久99精品国产麻豆 | 午夜精品一区二区三区在线观看 | 亚洲综合在线一区二区三区 | 日本肉体xxxx裸交 | 成人影院yy111111在线观看 | 亚洲成av人片在线观看无码不卡 | 中文字幕av日韩精品一区二区 | 亚洲国产精品无码一区二区三区 | 久久综合九色综合97网 | 亚洲成av人在线观看网址 | 99精品久久毛片a片 | 久久无码中文字幕免费影院蜜桃 | 美女毛片一区二区三区四区 | 亚洲一区二区三区在线观看网站 | 2020久久香蕉国产线看观看 | 国产超碰人人爽人人做人人添 | 国产美女极度色诱视频www | 色噜噜亚洲男人的天堂 | 天天躁夜夜躁狠狠是什么心态 | 久久www免费人成人片 | 久久精品国产一区二区三区 | 中文精品久久久久人妻不卡 | 国产又爽又黄又刺激的视频 | 欧洲极品少妇 | 丰满人妻精品国产99aⅴ | 性生交片免费无码看人 | 精品一区二区三区波多野结衣 | 欧美日韩综合一区二区三区 | 大乳丰满人妻中文字幕日本 | 久久综合网欧美色妞网 | 午夜理论片yy44880影院 | 亚洲人成影院在线无码按摩店 | 国产成人精品三级麻豆 | 水蜜桃色314在线观看 | 亚洲s码欧洲m码国产av | 国产综合久久久久鬼色 | 5858s亚洲色大成网站www | 亚洲国产精品一区二区美利坚 | 久久久久人妻一区精品色欧美 | 国产极品美女高潮无套在线观看 | 国产精品自产拍在线观看 | 久久综合色之久久综合 | 久久久无码中文字幕久... | 夜精品a片一区二区三区无码白浆 | 亚洲一区二区三区偷拍女厕 | aa片在线观看视频在线播放 | aa片在线观看视频在线播放 | 国产又粗又硬又大爽黄老大爷视 | 亚洲熟妇自偷自拍另类 | 国产精品第一区揄拍无码 | 国精品人妻无码一区二区三区蜜柚 | 99久久婷婷国产综合精品青草免费 | 国产成人精品视频ⅴa片软件竹菊 | 欧美怡红院免费全部视频 | 131美女爱做视频 | 国产成人无码av在线影院 | 日本肉体xxxx裸交 | 久久99精品久久久久久动态图 | 久久国语露脸国产精品电影 | 精品久久久无码人妻字幂 | 亚洲精品国偷拍自产在线观看蜜桃 | 久青草影院在线观看国产 | 丰满妇女强制高潮18xxxx | 在线成人www免费观看视频 | 精品无码一区二区三区爱欲 | 麻豆成人精品国产免费 | 天天av天天av天天透 | 日韩精品乱码av一区二区 | 精品久久8x国产免费观看 | 对白脏话肉麻粗话av | 无码毛片视频一区二区本码 | 亚洲精品成人av在线 | 亚洲无人区一区二区三区 | 国产无套粉嫩白浆在线 | 国内精品人妻无码久久久影院蜜桃 | 欧美性生交活xxxxxdddd | 免费观看的无遮挡av | 久久精品99久久香蕉国产色戒 | 国产97在线 | 亚洲 | 亚洲国产精华液网站w | 国产亚洲日韩欧美另类第八页 | 青草青草久热国产精品 | 日产精品高潮呻吟av久久 | 日本一区二区更新不卡 | 国产一精品一av一免费 | 波多野结衣av一区二区全免费观看 | 亚洲精品午夜国产va久久成人 | 中文字幕av无码一区二区三区电影 | 亚洲区小说区激情区图片区 | 亚洲中文字幕成人无码 | 美女黄网站人色视频免费国产 | 久久精品国产精品国产精品污 | 性生交大片免费看女人按摩摩 | 亚洲日本va中文字幕 | 狠狠噜狠狠狠狠丁香五月 | 丰满人妻翻云覆雨呻吟视频 | 97色伦图片97综合影院 | 久久无码专区国产精品s | 欧美三级不卡在线观看 | 国产舌乚八伦偷品w中 | 国产成人无码av片在线观看不卡 | 日韩亚洲欧美中文高清在线 | 一本久道久久综合狠狠爱 | 亚洲人成网站免费播放 | 无码av岛国片在线播放 | 亚洲大尺度无码无码专区 | 精品国产福利一区二区 | 欧美人妻一区二区三区 | 日产精品99久久久久久 | 精品无码成人片一区二区98 | 婷婷综合久久中文字幕蜜桃三电影 | 国产精品久久精品三级 | 亚洲欧洲日本综合aⅴ在线 | 超碰97人人做人人爱少妇 | 国产亚洲tv在线观看 | 国产sm调教视频在线观看 | 亚洲综合无码一区二区三区 | 色综合久久久无码中文字幕 | 一本精品99久久精品77 | 亚洲а∨天堂久久精品2021 | 少妇的肉体aa片免费 | 俺去俺来也www色官网 | 国产亚洲精品久久久久久久 | 亚洲精品美女久久久久久久 | 一本大道伊人av久久综合 | 久精品国产欧美亚洲色aⅴ大片 | 欧美肥老太牲交大战 | ass日本丰满熟妇pics | 亚洲乱码日产精品bd | 无码乱肉视频免费大全合集 | 久久久久久亚洲精品a片成人 | 蜜桃视频插满18在线观看 | 强伦人妻一区二区三区视频18 | 又色又爽又黄的美女裸体网站 | 久久这里只有精品视频9 | 国産精品久久久久久久 | 日日橹狠狠爱欧美视频 | 国产三级精品三级男人的天堂 | 国产乱人无码伦av在线a | 天天躁日日躁狠狠躁免费麻豆 | 中文字幕色婷婷在线视频 | 欧美第一黄网免费网站 | 亚洲成a人片在线观看日本 | 亚洲国产精品毛片av不卡在线 | 免费播放一区二区三区 | 日本欧美一区二区三区乱码 | 特级做a爰片毛片免费69 | 天堂久久天堂av色综合 | 精品人妻中文字幕有码在线 | 亚洲一区二区三区 | 无码播放一区二区三区 | 又大又黄又粗又爽的免费视频 | 久久人人爽人人爽人人片av高清 | 亚洲一区二区三区四区 | 亚洲熟熟妇xxxx | 久9re热视频这里只有精品 | 国产乱人伦av在线无码 | 亚洲精品国偷拍自产在线观看蜜桃 | 欧美一区二区三区视频在线观看 | 精品国产福利一区二区 | 啦啦啦www在线观看免费视频 | 久久久久久a亚洲欧洲av冫 | 无码乱肉视频免费大全合集 | 岛国片人妻三上悠亚 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 久久久精品欧美一区二区免费 | 内射老妇bbwx0c0ck | 日本一区二区三区免费高清 | 亚洲午夜福利在线观看 | 熟妇人妻激情偷爽文 | 久久精品国产一区二区三区 | 国产一区二区不卡老阿姨 | 精品人妻人人做人人爽夜夜爽 | 成 人影片 免费观看 | 无码国产激情在线观看 | 欧美一区二区三区视频在线观看 | 亚洲日本一区二区三区在线 | 日韩人妻少妇一区二区三区 | 久久精品人妻少妇一区二区三区 | 精品人妻av区 | 夜夜高潮次次欢爽av女 | 亚洲综合色区中文字幕 | 小泽玛莉亚一区二区视频在线 | 7777奇米四色成人眼影 | 亚洲の无码国产の无码步美 | 无码人妻av免费一区二区三区 | 亚洲国产欧美在线成人 | 巨爆乳无码视频在线观看 | 大胆欧美熟妇xx | 亚洲中文字幕无码中字 | 精品国产青草久久久久福利 | 国产精品美女久久久久av爽李琼 | 日本一卡二卡不卡视频查询 | 俺去俺来也www色官网 | 国产精品免费大片 | 国产精品美女久久久久av爽李琼 | 日本精品人妻无码免费大全 | 国产亚洲精品久久久久久 | 极品尤物被啪到呻吟喷水 | 99久久精品无码一区二区毛片 | 欧美亚洲国产一区二区三区 | 国产在线无码精品电影网 | 亚洲国产欧美日韩精品一区二区三区 | 久久综合久久自在自线精品自 | 俄罗斯老熟妇色xxxx | 亚洲午夜无码久久 | 日韩无码专区 | 疯狂三人交性欧美 | 国产精品无码久久av | 国产农村乱对白刺激视频 | 十八禁视频网站在线观看 | 野狼第一精品社区 | 午夜福利试看120秒体验区 | 国产精品久久福利网站 | 一本精品99久久精品77 | 美女黄网站人色视频免费国产 | 中文精品久久久久人妻不卡 | 中国大陆精品视频xxxx | 成人一在线视频日韩国产 | 午夜精品久久久久久久 | 女人色极品影院 | 中文字幕无码av波多野吉衣 | 午夜男女很黄的视频 | 亚洲综合另类小说色区 | 国产精品无码一区二区桃花视频 | 日本精品久久久久中文字幕 | 中文字幕av日韩精品一区二区 | 狂野欧美激情性xxxx | 老子影院午夜精品无码 | 亚洲狠狠色丁香婷婷综合 | 色欲av亚洲一区无码少妇 | 亚洲色偷偷偷综合网 | 精品久久综合1区2区3区激情 | 亚洲一区二区三区国产精华液 | 性开放的女人aaa片 | 无码纯肉视频在线观看 | 国产69精品久久久久app下载 | 国产成人精品久久亚洲高清不卡 | 精品人妻中文字幕有码在线 | 国产成人综合美国十次 | 精品人妻中文字幕有码在线 | 极品尤物被啪到呻吟喷水 | 亚洲精品www久久久 | 一本大道久久东京热无码av | 国产成人无码午夜视频在线观看 | 欧美人与禽zoz0性伦交 | 内射后入在线观看一区 | 国产亚洲精品久久久久久大师 | 丰满少妇女裸体bbw | 2020最新国产自产精品 | 亚洲色偷偷男人的天堂 | 在线观看国产午夜福利片 | 欧美怡红院免费全部视频 | 中文亚洲成a人片在线观看 | 久久www免费人成人片 | 亚洲一区二区三区偷拍女厕 | 国色天香社区在线视频 | 狂野欧美性猛交免费视频 | 国内老熟妇对白xxxxhd | 免费观看激色视频网站 | 成人无码影片精品久久久 | 成人av无码一区二区三区 | 精品国产青草久久久久福利 | 丰满少妇弄高潮了www | 台湾无码一区二区 | 免费无码的av片在线观看 | 日本va欧美va欧美va精品 | 欧美日韩一区二区三区自拍 | 久久综合色之久久综合 | a在线观看免费网站大全 | 久久综合给久久狠狠97色 | 久久久久成人精品免费播放动漫 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 99国产欧美久久久精品 | 日本va欧美va欧美va精品 | 日产国产精品亚洲系列 | 玩弄中年熟妇正在播放 | 日产精品99久久久久久 | 亚洲小说春色综合另类 | 国产乱子伦视频在线播放 | 男女性色大片免费网站 | 亚洲日韩中文字幕在线播放 | 熟妇女人妻丰满少妇中文字幕 | 国产特级毛片aaaaaa高潮流水 | 亚洲 欧美 激情 小说 另类 | 中文无码成人免费视频在线观看 | 波多野42部无码喷潮在线 | 亚洲精品美女久久久久久久 | 久久精品人人做人人综合试看 | 性欧美牲交在线视频 | 麻豆蜜桃av蜜臀av色欲av | 乌克兰少妇性做爰 | 国产激情精品一区二区三区 | 欧美日本免费一区二区三区 | 久久久久免费看成人影片 | 精品久久久无码中文字幕 | 婷婷六月久久综合丁香 | 国产超级va在线观看视频 | 久久精品国产大片免费观看 | 国产在线精品一区二区三区直播 | 国产亚洲欧美日韩亚洲中文色 | 欧美亚洲日韩国产人成在线播放 | 国产av无码专区亚洲awww | 波多野结衣av一区二区全免费观看 | 亚洲精品国偷拍自产在线麻豆 | 国产精品欧美成人 | 亚洲一区二区三区香蕉 | 中文字幕人成乱码熟女app | 噜噜噜亚洲色成人网站 | 久久zyz资源站无码中文动漫 | 欧美乱妇无乱码大黄a片 | 亚洲国产午夜精品理论片 | 国产精品第一国产精品 | 亚洲中文字幕无码中字 | 少妇一晚三次一区二区三区 | 国产香蕉97碰碰久久人人 | 无码精品人妻一区二区三区av | 成人无码精品1区2区3区免费看 | 亚洲精品综合一区二区三区在线 | 日韩精品久久久肉伦网站 | 亚洲欧美精品aaaaaa片 | 永久免费观看国产裸体美女 | 亚洲爆乳无码专区 | 人妻少妇精品无码专区动漫 | 免费观看又污又黄的网站 | a片在线免费观看 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产精品久久久久9999小说 | 综合激情五月综合激情五月激情1 | 99精品国产综合久久久久五月天 | 欧美freesex黑人又粗又大 | 中文字幕人妻无码一区二区三区 | 99久久人妻精品免费一区 | 国产亚洲日韩欧美另类第八页 | 无码国产色欲xxxxx视频 | 精品欧美一区二区三区久久久 | 国产农村妇女高潮大叫 | 中文字幕乱码亚洲无线三区 | 大乳丰满人妻中文字幕日本 | 国产亚洲精品久久久久久国模美 | 日本精品少妇一区二区三区 | 日日天干夜夜狠狠爱 | 又黄又爽又色的视频 | 亚洲熟妇色xxxxx亚洲 | 中文无码精品a∨在线观看不卡 | 人人妻人人澡人人爽欧美一区九九 | 午夜理论片yy44880影院 | 欧美xxxxx精品 | 免费无码午夜福利片69 | 成年美女黄网站色大免费视频 | 亚无码乱人伦一区二区 | 麻豆精品国产精华精华液好用吗 | 欧洲熟妇精品视频 | 亚洲成熟女人毛毛耸耸多 | 色情久久久av熟女人妻网站 | 六月丁香婷婷色狠狠久久 | 久久久久久久久888 | 久久综合九色综合欧美狠狠 | 又紧又大又爽精品一区二区 | 国产热a欧美热a在线视频 | 欧美兽交xxxx×视频 | 色综合久久久无码网中文 | 国产真实伦对白全集 | 噜噜噜亚洲色成人网站 | 国产精品美女久久久久av爽李琼 | 无码人妻丰满熟妇区五十路百度 | 欧美丰满熟妇xxxx性ppx人交 | 久久久无码中文字幕久... | 久久精品成人欧美大片 | 2019午夜福利不卡片在线 | 亚洲一区二区三区在线观看网站 | 双乳奶水饱满少妇呻吟 | 婷婷综合久久中文字幕蜜桃三电影 | 免费人成在线视频无码 | 亚洲高清偷拍一区二区三区 | 男人扒开女人内裤强吻桶进去 | 牲欲强的熟妇农村老妇女视频 | 亚洲日本va午夜在线电影 | 国产情侣作爱视频免费观看 | 亚洲日本va午夜在线电影 | 日韩av无码一区二区三区不卡 | 久久人人爽人人人人片 | 亚洲狠狠色丁香婷婷综合 | 亚洲成av人片在线观看无码不卡 | 伊人久久大香线蕉亚洲 | 中文字幕 人妻熟女 | 又黄又爽又色的视频 | 久久综合香蕉国产蜜臀av | 亚洲精品成a人在线观看 | 天天av天天av天天透 | 欧美精品免费观看二区 | 国产激情无码一区二区 | 亚洲精品欧美二区三区中文字幕 | 国产suv精品一区二区五 | 色综合久久中文娱乐网 | 欧美 日韩 人妻 高清 中文 | 无码帝国www无码专区色综合 | 水蜜桃亚洲一二三四在线 | 人妻体内射精一区二区三四 | 日欧一片内射va在线影院 | 亚洲乱码国产乱码精品精 | 久久亚洲日韩精品一区二区三区 | 国产精品爱久久久久久久 | 一本色道久久综合狠狠躁 | 久久www免费人成人片 | 无套内射视频囯产 | 无码吃奶揉捏奶头高潮视频 | 一本大道久久东京热无码av | 青青草原综合久久大伊人精品 | 国产午夜手机精彩视频 | 成人精品视频一区二区三区尤物 | 欧美性生交活xxxxxdddd | 国产99久久精品一区二区 | 狠狠色丁香久久婷婷综合五月 | 久久精品国产一区二区三区肥胖 | 亚洲成av人在线观看网址 | 丰满少妇人妻久久久久久 | 精品国产青草久久久久福利 | 漂亮人妻洗澡被公强 日日躁 | 一本久道久久综合婷婷五月 | 久久99国产综合精品 | 婷婷丁香六月激情综合啪 | 久久精品国产大片免费观看 | 亚洲综合无码久久精品综合 | 亚洲中文字幕在线观看 | 欧美精品无码一区二区三区 | 自拍偷自拍亚洲精品被多人伦好爽 | 丰满妇女强制高潮18xxxx | 国产suv精品一区二区五 | 色一情一乱一伦一区二区三欧美 | 亚洲精品一区二区三区大桥未久 | 国产亲子乱弄免费视频 | 久久综合色之久久综合 | 久久精品人人做人人综合试看 | 人人妻在人人 | 色诱久久久久综合网ywww | 免费观看又污又黄的网站 | 欧美黑人性暴力猛交喷水 | 欧美激情一区二区三区成人 | 日韩精品无码一本二本三本色 | 国产精品久久久久久久影院 | 色婷婷欧美在线播放内射 | 亚洲 欧美 激情 小说 另类 | 午夜肉伦伦影院 | 亚洲理论电影在线观看 | 欧美成人免费全部网站 | 中文字幕乱码亚洲无线三区 | 88国产精品欧美一区二区三区 | 国产99久久精品一区二区 | 国产特级毛片aaaaaa高潮流水 | 亚洲综合另类小说色区 | 水蜜桃亚洲一二三四在线 | 爆乳一区二区三区无码 | 久久99精品国产.久久久久 | a片免费视频在线观看 | 欧美丰满熟妇xxxx性ppx人交 | 欧美性生交活xxxxxdddd | 少妇高潮一区二区三区99 | 欧美 丝袜 自拍 制服 另类 | 99久久亚洲精品无码毛片 | 亚洲精品中文字幕久久久久 | 亚洲日韩乱码中文无码蜜桃臀网站 | 男女超爽视频免费播放 | 无码一区二区三区在线 | 亚洲精品久久久久中文第一幕 | 久久97精品久久久久久久不卡 | 国模大胆一区二区三区 | av小次郎收藏 | 日本乱人伦片中文三区 | 67194成是人免费无码 | 一本久久伊人热热精品中文字幕 | 久久亚洲精品中文字幕无男同 | 无码任你躁久久久久久久 | av无码不卡在线观看免费 | 国产 浪潮av性色四虎 | 精品国精品国产自在久国产87 | 日日碰狠狠躁久久躁蜜桃 | 精品熟女少妇av免费观看 | 中文字幕av无码一区二区三区电影 | 欧美人与善在线com | 国产人妻精品午夜福利免费 | 性欧美牲交xxxxx视频 | 欧美午夜特黄aaaaaa片 | 又紧又大又爽精品一区二区 | 亚洲国产精华液网站w | 国产人妻精品一区二区三区不卡 | 久久天天躁狠狠躁夜夜免费观看 | 夜先锋av资源网站 | 在线亚洲高清揄拍自拍一品区 | 中文字幕无码免费久久9一区9 | 乱人伦人妻中文字幕无码久久网 | 国产精品.xx视频.xxtv | 疯狂三人交性欧美 | 国内少妇偷人精品视频 | 精品乱子伦一区二区三区 | 精品成在人线av无码免费看 | 四虎4hu永久免费 | 国产激情一区二区三区 | 国产另类ts人妖一区二区 | 国产又爽又猛又粗的视频a片 | 99riav国产精品视频 | 波多野结衣乳巨码无在线观看 | 亚洲综合在线一区二区三区 | 国产莉萝无码av在线播放 | 亚洲熟妇色xxxxx欧美老妇y | 丰满少妇熟乱xxxxx视频 | 性欧美牲交xxxxx视频 | 四虎影视成人永久免费观看视频 | 美女张开腿让人桶 | 人人妻人人澡人人爽欧美一区九九 | 欧美日韩色另类综合 | 国产精品久久精品三级 | 亚洲一区二区三区四区 | 成人精品视频一区二区 | 精品厕所偷拍各类美女tp嘘嘘 | 国产精品久久久一区二区三区 | 亚洲精品综合五月久久小说 | 中文字幕人成乱码熟女app | 亚洲欧美日韩国产精品一区二区 | 久久久精品欧美一区二区免费 | 国产免费久久精品国产传媒 | 国产区女主播在线观看 | 亚洲精品中文字幕乱码 | 国产精品资源一区二区 | 欧美国产日韩亚洲中文 | 国产精品丝袜黑色高跟鞋 | 午夜时刻免费入口 | 国产午夜亚洲精品不卡 | 2019午夜福利不卡片在线 | 国产97色在线 | 免 | 一个人看的www免费视频在线观看 | 性色欲情网站iwww九文堂 | 久久精品国产99久久6动漫 | ass日本丰满熟妇pics | 日本熟妇大屁股人妻 | 亚洲人成无码网www | 无人区乱码一区二区三区 | 久久午夜夜伦鲁鲁片无码免费 | 久久精品女人的天堂av | 中文亚洲成a人片在线观看 | 麻豆精品国产精华精华液好用吗 | 无码国产激情在线观看 | 国产高清av在线播放 | 午夜性刺激在线视频免费 | 日本一区二区三区免费高清 | 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲一区二区三区在线观看网站 | 国产精品99久久精品爆乳 | 九一九色国产 | 荡女精品导航 | 国产成人精品无码播放 | 亚洲人成网站免费播放 | 俄罗斯老熟妇色xxxx | 国产精品久久久久久久9999 | 国产av人人夜夜澡人人爽麻豆 | 国产精品人人妻人人爽 | 欧美35页视频在线观看 | 极品嫩模高潮叫床 | 亚洲欧洲日本综合aⅴ在线 | 久久aⅴ免费观看 | 噜噜噜亚洲色成人网站 | 性欧美大战久久久久久久 | 久久亚洲精品成人无码 | 亚洲国产av精品一区二区蜜芽 | 久热国产vs视频在线观看 | 国内少妇偷人精品视频 | 国产精品久久久久久亚洲毛片 | 偷窥日本少妇撒尿chinese | 无码人妻精品一区二区三区下载 | 亚洲中文字幕无码一久久区 | 久久久久久国产精品无码下载 | 4hu四虎永久在线观看 | 久久久久99精品成人片 | 亚洲精品国偷拍自产在线观看蜜桃 | 强奷人妻日本中文字幕 | 日本一卡2卡3卡四卡精品网站 | 99久久久无码国产aaa精品 | 男人的天堂av网站 | 欧美熟妇另类久久久久久不卡 | 色一情一乱一伦一视频免费看 | 欧美老熟妇乱xxxxx | 宝宝好涨水快流出来免费视频 | 国产香蕉97碰碰久久人人 | 久久久久久九九精品久 | 欧美激情一区二区三区成人 | 国产亚洲精品精品国产亚洲综合 | 无码人妻少妇伦在线电影 | 日日天日日夜日日摸 | 成人性做爰aaa片免费看 | 精品乱子伦一区二区三区 | 亚洲成av人影院在线观看 | 成人综合网亚洲伊人 | 无遮挡国产高潮视频免费观看 | av香港经典三级级 在线 | 亚无码乱人伦一区二区 | 人妻无码αv中文字幕久久琪琪布 | 国精产品一区二区三区 | 久久99精品国产麻豆蜜芽 | 激情国产av做激情国产爱 | 天堂а√在线地址中文在线 | 亚洲国产高清在线观看视频 | 97久久精品无码一区二区 | 久久综合狠狠综合久久综合88 | 亚洲日本va午夜在线电影 | 性色欲网站人妻丰满中文久久不卡 | 国产麻豆精品精东影业av网站 | 97精品国产97久久久久久免费 | 日日摸夜夜摸狠狠摸婷婷 | 97人妻精品一区二区三区 | 精品乱码久久久久久久 | 九九在线中文字幕无码 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲国产综合无码一区 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 国内老熟妇对白xxxxhd | 免费观看激色视频网站 | 丰满肥臀大屁股熟妇激情视频 | 极品嫩模高潮叫床 | 欧美肥老太牲交大战 | 色一情一乱一伦一视频免费看 | 亚洲 欧美 激情 小说 另类 | 男人扒开女人内裤强吻桶进去 | 中文字幕无码乱人伦 | 国产偷国产偷精品高清尤物 | 国产超碰人人爽人人做人人添 | 中文字幕日产无线码一区 | 婷婷五月综合缴情在线视频 | 日本大香伊一区二区三区 | 亚洲 欧美 激情 小说 另类 | 人妻夜夜爽天天爽三区 | 国产精品永久免费视频 | 伊人久久大香线蕉av一区二区 | 国产精品毛片一区二区 | 日韩 欧美 动漫 国产 制服 | 国产凸凹视频一区二区 | 亚洲自偷精品视频自拍 | 色婷婷综合激情综在线播放 | 女人被男人躁得好爽免费视频 | 精品国产乱码久久久久乱码 | 国产人妖乱国产精品人妖 | 日韩精品一区二区av在线 | 亚洲中文字幕av在天堂 | 2020久久香蕉国产线看观看 | 国产特级毛片aaaaaaa高清 | 亚洲精品国产精品乱码视色 | 精品 日韩 国产 欧美 视频 | 蜜臀aⅴ国产精品久久久国产老师 | 国产性生大片免费观看性 | 亚洲国产一区二区三区在线观看 | 丁香花在线影院观看在线播放 | 三上悠亚人妻中文字幕在线 | 国产在线无码精品电影网 | 日韩精品乱码av一区二区 | 性做久久久久久久久 | 好爽又高潮了毛片免费下载 | 美女张开腿让人桶 | 国产精品igao视频网 | aⅴ亚洲 日韩 色 图网站 播放 | 免费看男女做好爽好硬视频 | 日韩欧美成人免费观看 | 国产精品亚洲а∨无码播放麻豆 | 无码精品人妻一区二区三区av | 波多野结衣高清一区二区三区 | 久久成人a毛片免费观看网站 | 午夜福利试看120秒体验区 | 欧美精品无码一区二区三区 | 在教室伦流澡到高潮hnp视频 | 欧美人与牲动交xxxx | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 伊在人天堂亚洲香蕉精品区 | 国产亚洲美女精品久久久2020 | 国产舌乚八伦偷品w中 | 无码成人精品区在线观看 | 动漫av一区二区在线观看 | 久久久久免费精品国产 | 色婷婷综合中文久久一本 | 最近的中文字幕在线看视频 | ass日本丰满熟妇pics | 欧美第一黄网免费网站 | 欧美大屁股xxxxhd黑色 | 乌克兰少妇xxxx做受 | 久久 国产 尿 小便 嘘嘘 | 亚洲精品国偷拍自产在线麻豆 | 任你躁在线精品免费 | 啦啦啦www在线观看免费视频 | 成人性做爰aaa片免费看不忠 | 国产香蕉尹人综合在线观看 | 亚洲欧美日韩成人高清在线一区 | 青青草原综合久久大伊人精品 | 国产精品久久久久久亚洲影视内衣 | 欧美黑人巨大xxxxx | 国产特级毛片aaaaaaa高清 | 久久99精品久久久久婷婷 | 欧美黑人巨大xxxxx | 色偷偷人人澡人人爽人人模 | 亚洲国产精品久久久天堂 | а√资源新版在线天堂 | 精品国产一区二区三区四区在线看 | 呦交小u女精品视频 | 人人超人人超碰超国产 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 又粗又大又硬又长又爽 | 国产凸凹视频一区二区 | 欧美 丝袜 自拍 制服 另类 | 大胆欧美熟妇xx | 无码精品人妻一区二区三区av | 久久 国产 尿 小便 嘘嘘 | av小次郎收藏 | 亚洲中文字幕无码中文字在线 | 亚洲色欲久久久综合网东京热 | 久久久国产精品无码免费专区 | 国产精品美女久久久 | 亚洲午夜福利在线观看 | 桃花色综合影院 | 樱花草在线播放免费中文 | 中文字幕+乱码+中文字幕一区 | av无码久久久久不卡免费网站 | 伊人久久大香线焦av综合影院 | 人人澡人人透人人爽 | 中文字幕人妻丝袜二区 | 精品国产一区av天美传媒 | 国产成人无码av一区二区 | 国产av一区二区三区最新精品 | 亚洲va欧美va天堂v国产综合 |