2015-10-17 50 views
1

我試圖使用Linux中的LDT(局部描述符表)CS寄存器。我爲新代碼段設置了一個LDT條目LDT [0]。然後我嘗試用ljmp更新%CS。我找到ljmp指令後CS更新%,但隨後它只是一個printf功能後改回原來%CS值。所以我想知道libc修改%CS寄存器,但我不知道如何發生這種情況,我怎樣才能使用我自己指定的LDT?的libc如何修改Linux中

下面是代碼:

// allocate and setup an LDT entry 
struct user_desc *def_seg = (struct user_desc *)malloc(sizeof(struct user_desc)); 
def_seg->entry_number = 0x0; 
def_seg->base_addr = 0x0; 
def_seg->limit = 0xfffff; 
... ... 
ret = modify_ldt(1, (void *)def_seg, sizeof(struct user_desc)); 

asm("movl %%cs, %0":"=r"(val)::); // get and print the %cs value 
printf("val(cs) 0x%x\n", val);  // val(cs) 0x73 

// load the LDT into %cs, since x86 does not 
// allow us to explicitly modify the %cs register 
asm("ljmp $0x7, $reload_cs\n\t" 
    "reload_cs:\n\t"); 

asm("movl %%cs, %0":"=r"(val)::); // get and print the %cs value 
printf("val(cs) 0x%x\n", val);  // val(cs) 0x7 
asm("movl %%cs, %0":"=r"(val)::); // after a printf. get and print the %cs value again. 
printf("val(cs) 0x%x\n", val);  // val(cs) 0x73 

我使用自己分配的LDT只是想測試一些86分段功能的小型研究項目。

我的工作是i386機器與Ubuntu 14.04(內核版本4.1.9)。這只是一個試圖利用某些分段功能的小型研究項目。

+1

你爲什麼要這麼做?什麼是用例?在哪個處理器和OS架構上? –

+0

@BasileStarynkevitch:我正在使用Ubuntu 14.04(內核版本4.1.9)的i386機器。這只是一個試圖利用某些分段功能的小型研究項目。 – xiaogw

回答

4

的Linux/x86-64的真的不使用段寄存器,期待線程本地存儲(他們是由內核,不僅是可能的libc管理)。它主要是設置它們的內核。有關詳細信息,請閱讀Linux x86-64 ABI(或適用於32位x86的Linux ia32 ABI);請參閱其他參考文獻here 32位和here 64位)。

瞭解更多關於syscalls(2) & execve(2) & set_thread_area(2) & modify_ldt(2)

我猜創建線程可能會設置一些段寄存器(見clone(2) ......)。研究的您C standard library(這是free software),例如所述NPTL部分的源代碼GNU libcMUSL libc

你可能不應該和不能(不使用modify_ldt(2)變化段寄存器在Linux中32位的x86用戶代碼。恕我直言,他們一直只在上個世紀,16位MSDOS有用...閱讀wikipage x86 memory segmentation

恕我直言目前的處理器不能有效地處理段寄存器的變化。 請勿在代碼中使用段寄存器(超出其預定義用法)。段寄存器是上個世紀(或者是16位模式的BIOS)。

+0

感謝您的回覆。我要讀ABI和這些鏈接。它看起來像C庫在進入libc時設置了分段寄存器(特別是%cs),並在離開libc時將這些seg寄存器恢復爲默認的USER_SEG。順便說一句,我使用i386硬件。 – xiaogw

+1

我不認爲'libc'正在設置CS和其他段寄存器。它是設置它們的內核。 –

+0

是的。我想你可能是對的。也許內核設置它們。 :)保護模式段寄存器仍在x86中使用。例如,Linux內核在GS指定的段中存儲per-cpu數據。代碼段中的其他一些有趣功能可能仍然有用。 – xiaogw