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

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? 漫談兼容內(nèi)核之八:elf映像的裝入(一).txt

?? 漫談系統(tǒng)內(nèi)核內(nèi)幕 收集得很辛苦 呵呵 大家快下在吧
?? TXT
?? 第 1 頁 / 共 3 頁
字號:
漫談兼容內(nèi)核之八:ELF映像的裝入(一)

[align=center][b][size=4]漫談兼容內(nèi)核之八:ELF映像的裝入(一)[/size][/b][/align]

[align=center]毛德操[/align]

    上一篇漫談中介紹了Wine的二進制映像裝入和啟動,現(xiàn)在我們來看看ELF映像的裝入和啟動。
    一般而言,應(yīng)用軟件的編程不可能是“一竿子到底”、所有的代碼都自己寫的,程序員不可避免地、也許是不自覺地、都會使用一些現(xiàn)成的程序庫。對于C語言的編程,至少C程序庫是一定會用到的。從編譯/連接和運行的角度看,應(yīng)用程序和庫程序的連接有兩種方法。一種是固定的、靜態(tài)的連接,就是把需要用到的庫函數(shù)的目標(二進制)代碼從程序庫中抽取出來,連接進應(yīng)用軟件的目標映像中,或者甚至干脆把整個程序庫都連接進應(yīng)用軟件的映像中。這里所謂的連接包括兩方面的操作,一是把庫函數(shù)的目標代碼“定位”在應(yīng)用軟件目標映像中的某個位置上。由于不同應(yīng)用軟件本身的大小和結(jié)構(gòu)都可能不同,庫函數(shù)在目標映像中的位置是無法預(yù)先確定的。為此,程序庫中的代碼必須是可以浮動的,即“與位置無關(guān)”的,在編譯時必須加上-fPIC選項,這里PIC是“Position-Independent Code”的縮寫。一旦一個庫函數(shù)在映像中的位置確定以后,就要使應(yīng)用軟件中所有對此函數(shù)的調(diào)用都指向這個函數(shù)。早期的軟件都采用這種靜態(tài)的連接方法,好處是連接的過程只發(fā)生在編譯/連接階段,而且用到的技術(shù)也比較簡單。但是也有缺點,那就是具體庫函數(shù)的代碼往往重復(fù)出現(xiàn)在許多應(yīng)用軟件的目標映像中,從而造成運行時的資源浪費。另一方面,這也不利于軟件的發(fā)展,因為即使某個程序庫有了更新更好的版本,已經(jīng)與老版本靜態(tài)連接的應(yīng)用軟件也享受不到好處,而重新連接往往又不現(xiàn)實。再說,這也不利于將程序庫作為商品獨立發(fā)展的前景。于是就發(fā)展起了第二種連接方法,那就是動態(tài)連接。所謂動態(tài)連接,是指庫函數(shù)的代碼并不進入應(yīng)用軟件的目標映像,應(yīng)用軟件在編譯/連接階段并不完成跟庫函數(shù)的連接;而是把函數(shù)庫的映像也交給用戶,到啟動應(yīng)用軟件目標映像運行時才把程序庫的映像也裝入用戶空間(并加以定位)、再完成應(yīng)用軟件與庫函數(shù)的連接。說到程序庫,最基本、最重要的當(dāng)然是C語言庫、即libc或glibc。
    這樣,就有了兩種不同的ELF格式映像。一種是靜態(tài)連接的,在裝入/啟動其運行時無需裝入函數(shù)庫映像、也無需進行動態(tài)連接。另一種是動態(tài)連接的,需要在裝入/啟動其運行時同時裝入函數(shù)庫映像并進行動態(tài)連接。顯然,Linux內(nèi)核應(yīng)該既支持靜態(tài)連接的ELF映像、也支持動態(tài)連接的ELF映像。進一步的分析表明:裝入/啟動ELF映像必需由內(nèi)核完成,而動態(tài)連接的實現(xiàn)則既可以在內(nèi)核中完成,也可在用戶空間完成。因此,GNU把對于動態(tài)連接ELF映像的支持作了分工:把ELF映像的裝入/啟動放在Linux內(nèi)核中;而把動態(tài)連接的實現(xiàn)放在用戶空間,并為此提供一個稱為“解釋器”的工具軟件,而解釋器的裝入/啟動也由內(nèi)核負責(zé)。
大家知道,在Linux系統(tǒng)中,目標映像的裝入/啟動是由系統(tǒng)調(diào)用execve()完成的,但是可以在Linux內(nèi)核上運行的二進制映像有a.out和ELF兩種。由于篇幅的關(guān)系,在“情景分析”一書中對于二進制映像只講了a.out格式映像的裝入/啟動,而沒有講ELF格式映像的裝入/啟動。這是因為如果講了ELF映像就不可避免地要講到動態(tài)連接、講到“解釋器”,那樣一來篇幅就大了。從對于裝入/啟動可執(zhí)行映像的過程的一般了解而言,光講a.out也許就夠了;可是考慮到ELF映像(以及Windows軟件的PE映像)對于兼容內(nèi)核開發(fā)的重要意義,還是有必要補上這一課。
    本文先介紹裝入/啟動一個ELF映像時發(fā)生于Linux內(nèi)核中的操作,下一篇漫談則介紹發(fā)生于用戶空間的操作、即“解釋器”對于共享庫的操作。

1.系統(tǒng)空間的操作

    內(nèi)核中實際執(zhí)行execv()或execve()系統(tǒng)調(diào)用的程序是do_execve(),這個函數(shù)先打開目標映像文件,并從目標文件的頭部(從第一個字節(jié)開始)讀入若干(128)字節(jié),然后調(diào)用另一個函數(shù)search_binary_handler(),在那里面讓各種可執(zhí)行程序的處理程序前來認領(lǐng)和處理。內(nèi)核所支持的每種可執(zhí)行程序都有個struct linux_binfmt數(shù)據(jù)結(jié)構(gòu),通過向內(nèi)核登記掛入一個隊列。而search_binary_handler(),則掃描這個隊列,讓各個數(shù)據(jù)結(jié)構(gòu)所提供的處理程序、即各種映像格式、逐一前來認領(lǐng)。如果某個格式的處理程序發(fā)現(xiàn)特征相符而,便執(zhí)行該格式映像的裝入和啟動。
    我們從ELF格式映像的linux_binfmt數(shù)據(jù)結(jié)構(gòu)開始:

[code]#define load_elf_binary load_elf32_binary

static struct linux_binfmt elf_format = {
  .module  = THIS_MODULE,
  .load_binary = load_elf_binary,
  .load_shlib = load_elf_library,
  .core_dump = elf_core_dump,
  .min_coredump = ELF_EXEC_PAGESIZE
};[/code]
    這個數(shù)據(jù)結(jié)構(gòu)表明:ELF格式的二進制映像的認領(lǐng)、裝入和啟動是由load_elf_binary()完成的。而“共享庫”、即動態(tài)連接庫映像的裝入則由load_elf_library()完成。實際上共享庫的映像也是二進制的,但是一般說“二進制”映像是指帶有main()函數(shù)的、可以獨立運行并構(gòu)成一個進程主體的可執(zhí)行程序的二進制映像。另一方面,盡管裝入/啟動二進制映像的過程中蘊含了共享庫的裝入(否則無法運行),但是在此過程中卻并沒有調(diào)用load_elf_library(),而是通過別的函數(shù)進行,這個函數(shù)只是在sys_uselib()、即系統(tǒng)調(diào)用uselib()中通過函數(shù)指針load_shlib受到調(diào)用。所以,load_elf_library()所處理的是應(yīng)用軟件在運行時對于共享庫的動態(tài)裝入,而不是啟動進程時的靜態(tài)裝入。
    下面我們就來看load_elf_binary()代碼,這個函數(shù)在fs/binfmt_elf.c中。由于篇幅的關(guān)系,本文只能以近似于偽代碼的形式列出經(jīng)過簡化整理的代碼(下同),有需要或興趣的讀者不妨結(jié)合源文件中的原始代碼閱讀。由于load_elf_binary()是個比較大的函數(shù),我們分段閱讀。

[code][sys_execve() > do_execve() > search_binary_handler() > load_elf_binary()]

static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
. . . . . .
struct {
  struct elfhdr elf_ex;
  struct elfhdr interp_elf_ex;
    struct exec interp_ex;
} *loc;

loc = kmalloc(sizeof(*loc), GFP_KERNEL);
. . . . . .

/* Get the exec-header */
loc->elf_ex = *((struct elfhdr *) bprm->buf);

. . . . . .
/* First of all, some simple consistency checks */
if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
  goto out;           //比對四個字符,必須是0x7f、‘E’、‘L’、和‘F’。

if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN)
  goto out;           //映像類型必須是ET_EXEC或ET_DYN。
if (!elf_check_arch(&loc->elf_ex))
  goto out;           //機器(CPU)類型必須相符。
. . . . . .[/code]
    首先是認領(lǐng)。ELF映像文件的頭部應(yīng)該是個struct elfhdr數(shù)據(jù)結(jié)構(gòu),對于32位映像這實際上是struct elf32_hdr數(shù)據(jù)結(jié)構(gòu)、即Elf32_Ehdr,其定義如下所示:

[code]#define elfhdr  elf32_hdr

typedef struct elf32_hdr{
  unsigned char e_ident[EI_NIDENT];  // EI_NIDENT = 16
  Elf32_Half  e_type;      // 即unsigned shout
  Elf32_Half  e_machine;     // 即 unsigned int
  Elf32_Word  e_version;
  Elf32_Addr  e_entry;  /* Entry point */
  Elf32_Off  e_phoff;
  Elf32_Off  e_shoff;
  Elf32_Word  e_flags;
  Elf32_Half  e_ehsize;
  Elf32_Half  e_phentsize;
  Elf32_Half  e_phnum;
  Elf32_Half  e_shentsize;
  Elf32_Half  e_shnum;
  Elf32_Half  e_shstrndx;
} Elf32_Ehdr;[/code]
    這個數(shù)據(jù)結(jié)構(gòu)的前16個字節(jié)是ELF映像的標志e_ident[ ],其中開頭的4個字節(jié)就是所謂“Magic Number”,應(yīng)該是“\177ELF”。除這4個字符比對相符以外,還要看映像的類型是否ET_EXEC和ET_DYN之一;前者表示可執(zhí)行映像,后者表示共享庫(此外還有ET_REL和ET_CORE,分別表示浮動地址模塊和dump映像)。同時,映像所適用的CPU類型(如x86或PPC)也須相符。如果這些條件都滿足,就算認領(lǐng)成功,下面就是進一步的處理了。進一步的處理當(dāng)然需要更多的信息,在Elf32_Ehdr中提供了兩個指針,或者說兩個(文件內(nèi)的)位移量,即e_phoff和e_shoff。如果非0的話,前者指向“程序頭(Program Header)”數(shù)組的起點;后者指向“區(qū)段頭(Section Header)”數(shù)組的起點。兩個數(shù)組的大小(元素的個數(shù))分別由e_phnum和e_shnum提供,而每個數(shù)組元素(表項)的大小由e_phentsize和e_shentsize提供。至于e_ehsize,則是映像頭部本身的大小。還有個值得特別說明的成分是e_entry,那就是該映像的程序入口,一般是_start()的起點。
    人們常常提到二進制代碼映像中有所謂“程序段”“數(shù)據(jù)段”等等,那都屬于映像中的“區(qū)段”即“Section”。但是區(qū)段的種類遠遠不止這些而有很多,例如“符號表”就是一個區(qū)段,再如用于動態(tài)連接的信息、用于Debug的信息等等,都屬于不同的區(qū)段。而區(qū)段頭數(shù)組、或曰區(qū)段頭表,則為映像中的每一個區(qū)段都提供一個描述性的數(shù)據(jù)結(jié)構(gòu)。
    而程序頭數(shù)組或曰程序頭表中的每一個表項,則是對一個“部(Segment)”的描述。一個部可以包含若干個區(qū)段,也可以只是一個簡單的數(shù)據(jù)結(jié)構(gòu)。整個ELF映像就是由文件頭、區(qū)段頭表、程序頭表、一定數(shù)量的區(qū)段、以及一定數(shù)量的部構(gòu)成。而ELF映像的裝入/啟動過程,則就是在各種頭部信息的指引下將某些部或區(qū)段裝入一個進程的用戶空間,并為其運行做好準備(例如裝入所需的共享庫),最后(在目標進程首次受調(diào)度運行時)讓CPU進入其程序入口的過程。讀者將會看到,這個過程很可能是嵌套的,因為在裝入一個映像的過程中很可能需要裝入另一個或另幾個別的映像。
    我們繼續(xù)往下看:

[code][sys_execve() > do_execve() > search_binary_handler() > load_elf_binary()]

/* Now read in all of the header information */
. . . . . .
size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
retval = -ENOMEM;
elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
if (!elf_phdata)
  goto out;

retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size);
. . . . . .
files = current->files;  /* Refcounted so ok */
. . . . . .
retval = get_unused_fd();
. . . . . .
get_file(bprm->file);
fd_install(elf_exec_fileno = retval, bprm->file);

elf_ppnt = elf_phdata;
elf_bss = 0;
elf_brk = 0;

start_code = ~0UL;
end_code = 0;
start_data = 0;
end_data = 0;[/code]
    這里通過kernel_read()讀入的是目標映像的整個程序頭表,這是一個struct elf_phdr、實際上是struct elf32_phdr結(jié)構(gòu)數(shù)組。這種數(shù)據(jù)結(jié)構(gòu)的定義為:

[code]typedef struct elf32_phdr{
  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;[/code]
    這里的p_type表示部的類型。
    同時,這里還為已打開的目標映像文件在當(dāng)前進程的打開文件表中另外分配一個表項,類似于執(zhí)行了一次dup(),目的在于為目標文件維持兩個不同的上下文,以便從不同的位置上讀出。
    接著是對elf_bss 、elf_brk、start_code、end_code等等變量的初始化。這些變量分別紀錄著當(dāng)前(到此刻為止)目標映像的bss段、代碼段、數(shù)據(jù)段、以及動態(tài)分配“堆” 在用戶空間的位置。除start_code的初始值為0xffffffff外,其余均為0。隨著映像內(nèi)容的裝入,這些變量也會逐步得到調(diào)整,讀者不妨自己留意這些變量在整個過程中的變化。
    讀入了程序頭表,并對start_code等變量進行初始化以后,下面的第一步就是在程序頭表中尋找“解釋器”部、并加以處理的過程。

[code][sys_execve() > do_execve() > search_binary_handler() > load_elf_binary()]

for (i = 0; i < loc->elf_ex.e_phnum; i++) {
  if (elf_ppnt->p_type == PT_INTERP) {
   . . . . . .
   retval = -ENOMEM;
   elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, GFP_KERNEL);
   . . . . . .
   retval = kernel_read(bprm->file, elf_ppnt->p_offset,
elf_interpreter, elf_ppnt->p_filesz);
   . . . . . .
   interpreter = open_exec(elf_interpreter);
   retval = PTR_ERR(interpreter);
   if (IS_ERR(interpreter))
    goto out_free_interp;
   retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
   . . . . . .
   /* Get the exec headers */
   loc->interp_ex = *((struct exec *) bprm->buf);
   loc->interp_elf_ex = *((struct elfhdr *) bprm->buf);
   break;
  }
  elf_ppnt++;
}[/code]
    顯然,這個for循環(huán)的目的僅在于尋找和處理目標映像的“解釋器”部。ELF格式的二進制映像在裝入和啟動的過程中需要得到一個工具軟件的協(xié)助,其主要的目的在于為目標映像建立起跟共享庫的動態(tài)連接。這個工具稱為“解釋器”。一個ELF映像在裝入時需要用什么解釋器是在編譯/連接是就決定好了的,這信息就保存在映像的“解釋器”部中。“解釋器”部的類型為PT_INTERP,找到后就根據(jù)其位置p_offset和大小p_filesz把整個“解釋器”部讀入緩沖區(qū)。整個“解釋器”部實際上只是一個字符串,即解釋器的文件名,例如“/lib/ld-linux.so.2”。有了解釋器的文件名以后,就通過open_exec()打開這個文件,再通過kernel_read()讀入其開頭128個字節(jié),這就是映像的頭部。早期的解釋器映像是a.out格式的,現(xiàn)在已經(jīng)都是ELF格式的了,/lib/ld-linux.so.2就是個ELF映像。
    下面是對解釋器映像頭部的處理,首先要確認其為ELF格式還是a.out格式。

[code][sys_execve() > do_execve() > search_binary_handler() > load_elf_binary()]

. . . . . .
/* Some simple consistency checks for the interpreter */
if (elf_interpreter) {
  interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;

  /* Now figure out which format our binary is */
  if ((N_MAGIC(loc->interp_ex) != OMAGIC) &&
      (N_MAGIC(loc->interp_ex) != ZMAGIC) &&
      (N_MAGIC(loc->interp_ex) != QMAGIC))
   interpreter_type = INTERPRETER_ELF;

  if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
   interpreter_type &= ~INTERPRETER_ELF;
  . . . . . .
} else {
  . . . . . .
}

/* OK, we are done with that, now set up the arg stuff,
    and then start this sucker up */[/code]
    至此,我們已為目標映像和解釋器映像的裝入作好了準備。可以讓當(dāng)前進程(線程)與其父進程分道揚鑣,轉(zhuǎn)化成真正意義上的進程,走自己的路了。

[code][sys_execve() > do_execve() > search_binary_handler() > load_elf_binary()]

/* Flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
  . . . . . .
/* OK, This is the point of no return */
current->mm->start_data = 0;
current->mm->end_data = 0;
current->mm->end_code = 0;
current->mm->mmap = NULL;
current->flags &= ~PF_FORKNOEXEC;
current->mm->def_flags = def_flags;
. . . . . .
/* Do this so that we can load the interpreter, if need be.  We will
    change some of these later */
retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack);
. . . . . .[/code]
    可想而知,flush_old_exec()把當(dāng)前進程用戶空間的頁面都釋放了。這么一來,當(dāng)前進程的用戶空間是“一片白茫茫大地真干凈”,什么也沒有了,原有的物理頁面映射都已釋放。
    現(xiàn)在要來重建用戶空間的映射了。一個新的映像要能運行,用戶空間堆棧是必須的,所以首先要把用戶空間的一個虛擬地址區(qū)間劃出來用于堆棧。進一步,當(dāng)CPU進入新映像的程序入口時,堆棧上應(yīng)該有argc、argv[]、envc、envp[]等參數(shù)。這些參數(shù)來自老的程序,需要通過堆棧把它們傳遞給新的映像。實際上,argv[]和envp[]中是一些字符串指針,光把指針傳給新映像,而不把相應(yīng)的字符串傳遞給新映像,那是毫無意義的。為此,在進入search_binary_handler()、從而進入load_elf_binary()之前,do_execve()已經(jīng)為這些字符串分配了若干頁面,并通過copy_strings()從用戶空間把這些字符串拷貝到了這些頁面中。現(xiàn)在則要把這些頁面再映射回用戶空間(當(dāng)然是在不同的地址上),這就是這里setup_arg_pages()要做的事。這些頁面映射的地址是在用戶空間堆棧的最頂部。對于x86處理器,用戶空間堆棧是從3GB邊界開始向下伸展的,首先就是存放著這些字符串的頁面,再往下才是真正意義上的用戶空間堆棧。而argc、argv[]這些參數(shù),則就在這真正意義上的用戶空間堆棧上。
    下面就可以裝入新映像了。所謂“裝入”,實際上就是將映像的(部分)內(nèi)容映射到用戶(虛擬地址)空間的某些區(qū)間中去。在MMU的swap機制的作用下,這個過程甚至并不需要真的把映像的內(nèi)容讀入物理頁面,而把實際的讀入留待將來的缺頁中斷。
    首先裝入的是目標映像本身。

[code][sys_execve() > do_execve() > search_binary_handler() > load_elf_binary()]

  /* Now we do a little grungy work by mmaping the ELF image into
       the correct location in memory.  At this point, we assume that

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
在线视频一区二区三| 国产精品理论片在线观看| 精品免费日韩av| 一区在线中文字幕| 秋霞影院一区二区| 不卡一区二区中文字幕| 91精品国产91久久久久久最新毛片 | 中文字幕成人网| 天天av天天翘天天综合网| 成年人网站91| 日本一区二区三区久久久久久久久不| 亚洲福利一二三区| 成年人午夜久久久| 精品国产电影一区二区| 天天做天天摸天天爽国产一区| aaa亚洲精品一二三区| 久久伊人蜜桃av一区二区| 午夜精品久久久久| 日本久久一区二区三区| 中文子幕无线码一区tr| 国产美女精品在线| 日韩精品自拍偷拍| 视频一区欧美精品| 精品视频999| 亚洲一区二区精品久久av| 成人永久免费视频| 国产日韩欧美在线一区| 国产乱色国产精品免费视频| 日韩欧美123| 日韩精品欧美成人高清一区二区| 在线日韩国产精品| 最新日韩在线视频| 成人免费看黄yyy456| 国产三级久久久| 粉嫩av亚洲一区二区图片| 国产亚洲精品超碰| 高清beeg欧美| 国产亚洲自拍一区| 国产成人av一区二区| 国产精品久久久久一区二区三区 | 国产精品理论片| 精品日韩av一区二区| 天天爽夜夜爽夜夜爽精品视频| 91高清视频在线| 亚洲一区日韩精品中文字幕| 欧美熟乱第一页| 亚洲一区二区视频| 88在线观看91蜜桃国自产| 三级亚洲高清视频| 欧美电影免费观看高清完整版在线| 美美哒免费高清在线观看视频一区二区| 91精品国产综合久久香蕉麻豆| 美女在线观看视频一区二区| 国产欧美在线观看一区| 99久久精品免费精品国产| 亚洲一区在线免费观看| 欧美一区二区三区四区五区 | 久久久精品黄色| av网站一区二区三区| 一区二区三区在线观看网站| 精品视频在线视频| 久久国产尿小便嘘嘘尿| 国产精品美女久久久久久久网站| 欧美亚洲一区二区在线观看| 蜜臂av日日欢夜夜爽一区| 中文字幕精品在线不卡| 欧洲另类一二三四区| 久久99国产精品成人| 国产精品全国免费观看高清 | 成人美女在线视频| 一区二区三区精品久久久| 911精品产国品一二三产区| 极品少妇xxxx精品少妇偷拍| 国产精品不卡一区二区三区| 日韩一级免费一区| www.色精品| 久草在线在线精品观看| 亚洲欧洲www| 精品日韩一区二区| 色婷婷国产精品久久包臀| 九色综合国产一区二区三区| 亚洲理论在线观看| 精品国产百合女同互慰| 色婷婷精品大视频在线蜜桃视频| 精品写真视频在线观看 | 99国产精品国产精品毛片| 美日韩一级片在线观看| 亚洲美女在线一区| 久久精子c满五个校花| 欧美日韩一区二区三区视频| 成人一级黄色片| 久久成人精品无人区| 夜夜夜精品看看| 国产精品久久久久影院亚瑟 | 精品久久久久久亚洲综合网 | 日韩一区二区三区视频| 色狠狠一区二区| 成人国产一区二区三区精品| 九九热在线视频观看这里只有精品| 亚洲免费观看在线视频| 国产色91在线| 欧美精品一区二| 日韩一区二区三区在线| 欧美三区在线视频| 91官网在线免费观看| 99精品视频一区| 成人在线视频一区二区| 精品系列免费在线观看| 美女国产一区二区| 日本欧美久久久久免费播放网| 一个色综合网站| 亚洲精品视频免费看| 最好看的中文字幕久久| 中文字幕在线观看一区| 国产精品久线观看视频| 中文字幕巨乱亚洲| 国产精品久久久久国产精品日日| 国产无人区一区二区三区| 精品成人私密视频| 精品久久久久av影院 | 国产丝袜美腿一区二区三区| 国产网站一区二区三区| 欧美精品一区二区三区蜜桃视频 | 欧美日韩不卡一区| 欧美怡红院视频| 欧美三级电影在线观看| 欧美国产一区二区| 精品国产一区二区三区久久影院 | 欧美日韩国产免费| 欧美日本国产一区| 日韩一区二区精品葵司在线| 日韩欧美一级二级三级久久久| 欧美精品一区二区久久婷婷| 国产日韩欧美一区二区三区乱码| 中文字幕va一区二区三区| 最好看的中文字幕久久| 亚洲午夜精品一区二区三区他趣| 肉肉av福利一精品导航| 日本成人在线看| 国产精品456| 91蝌蚪porny| 欧美肥胖老妇做爰| 精品福利在线导航| 国产精品久久久久7777按摩 | 亚洲美女淫视频| 婷婷丁香久久五月婷婷| 激情综合五月婷婷| jlzzjlzz欧美大全| 欧美喷水一区二区| 亚洲精品一区在线观看| 中文字幕一区二区三中文字幕| 亚洲成人激情自拍| 激情文学综合丁香| 91蜜桃传媒精品久久久一区二区| 欧美精三区欧美精三区| 久久精品日韩一区二区三区| 亚洲资源在线观看| 国产一区二区久久| 欧美亚洲一区二区在线| 精品国产不卡一区二区三区| 亚洲欧美日韩人成在线播放| 久久精品国产免费| 一本久久精品一区二区| 精品国产91久久久久久久妲己| 亚洲三级免费电影| 美女网站视频久久| 一本久久a久久免费精品不卡| 精品卡一卡二卡三卡四在线| 亚洲综合丝袜美腿| 国产一本一道久久香蕉| 欧美日韩精品一区二区三区四区| 国产三级欧美三级| 成人一区二区三区视频| 欧美大片日本大片免费观看| 夜夜亚洲天天久久| av中文字幕在线不卡| 久久综合久久鬼色| 亚欧色一区w666天堂| 94色蜜桃网一区二区三区| 国产亚洲综合色| 激情小说欧美图片| 7777女厕盗摄久久久| 亚洲卡通欧美制服中文| 成人免费黄色在线| 精品国产一区二区三区久久久蜜月| 亚洲成人综合视频| 91麻豆6部合集magnet| 欧美韩日一区二区三区四区| 麻豆成人久久精品二区三区小说| 欧美久久久久久久久| 亚洲欧美电影院| 99精品久久只有精品| 国产欧美一区二区三区沐欲| 国产乱码精品一区二区三区av | 日韩电影一区二区三区| 色偷偷久久一区二区三区| 中文字幕在线不卡一区| 国产盗摄一区二区| 久久午夜色播影院免费高清| 国产美女在线观看一区|