2017-01-14 2 views
1

Я только что прочитал о поддержке префиксов сегментов% fs и% gs на платформах Intel в GCC. Было упомянуто, что «То, как вы получаете указатели на основе% gs или управляете значением самого% gs, выходит за рамки gcc;»__seg_fs на GCC. Можно ли эмулировать его только в программе?

Я ищу способ, когда я вручную могу установить значение% fs (я на IA32, RH Linux) и работать с ним. Когда я просто устанавливаю% fs =% ds, тест ниже работает нормально, и это ожидается. Но я не могу изменить тест, чтобы иметь другое значение% fs и не получить ошибку сегментации. Я начинаю думать, что изменение значения% fs - это не единственное, что нужно сделать. Поэтому я ищу совет, как сделать часть памяти, адресованную% fs, которая не равна DS.

#include <stddef.h> 

typedef char __seg_fs fs_ptr; 
fs_ptr p[] = {'h','e','l','l','o','\0'}; 

void fs_puts(fs_ptr *s) 
{ 
    char buf[100]; 

    buf[0] = s[0]; 
    buf[1] = s[1]; 
    buf[2] = s[2]; 
    buf[3] = '\0'; 

    puts(buf); 
} 

void __attribute__((constructor)) set_fs() 
{ 
    __asm__("mov %ds, %bx\n\t" 
      "add $0, %bx\n\t"  //<---- if fs=ds then the program executes as expected. If not $0 here, then segmentation fault happens.   
      "mov %bx, %fs\n\t"); 
} 

int main() 
{ 
    fs_puts(p); 

    return 0; 
}   

ответ

1

Я разговаривал с Armin, который реализован __seg_gs/__ seg_fs в НКУ (Спасибо Armin!). Так что в основном я не могу использовать эти ключевые слова для глобальных. Цель введения __seg_gs/fs заключалась в том, чтобы иметь возможность динамически распределять области памяти, которые являются нитями локальными. Мы не можем использовать __thread для указателя и выделять для него память, используя malloc. Но __seg_gs/fs представляет такую ​​возможность. Тест ниже как-то иллюстрирует это. Обратите внимание, что используется arch_prctl(). Он существует только как 64-разрядная версия. Также обратите внимание, что% fs используется для __thread на 64-битных и% gs является бесплатным.

#include <stddef.h> 
#include <string.h> 
#include <stdio.h> 
#include <asm/ldt.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <sys/prctl.h> 
#include <asm/prctl.h> 
#include <sys/syscall.h> 
#include <unistd.h> 

typedef __seg_gs char gs_str; 

void gs_puts(gs_str *ptr) 
{ 
    int i; 
    char buf[100]; 
    for(i = 0; i < 100; i++) 
     buf[i] = ptr[i]; 

    puts(buf); 
} 

int main() 
{ 
    int i; 
    void *buffer = malloc(100 * sizeof(char)); 

    arch_prctl(ARCH_SET_GS, buffer); 

    gs_str *gsobj = (gs_str *)0; 
    for (i = 0; i < 100; i++) 
     gsobj[i] = 'a';  /* in the %gs space */ 

    gs_puts(gsobj); 

    return 0; 
} 
Смежные вопросы