2011-07-07 17 views
23

Trên kiến ​​trúc x86-64, hai thanh ghi có mục đích đặc biệt: FS và GS. Trong linux 2.6. *, Thanh ghi FS dường như được sử dụng để lưu trữ thông tin luồng-cục bộ.Các thanh ghi fs/gs được sử dụng trong Linux AMD64 như thế nào?

  • Điều đó có đúng không?
  • Điều gì được lưu trữ tại fs: 0? Có cấu trúc C nào mô tả nội dung này không?
  • Sau đó sử dụng GS là gì?

Trả lời

28

Trong x86-64 có 3 TLS entries, hai trong số họ accesible qua FS and GS, FS được sử dụng trong nội bộ của glibc (trong IA32 rõ ràng FS is used by Wine and GS by glibc).

Glibc làm cho điểm nhập TLS của nó thành struct pthread có chứa một số cấu trúc nội bộ cho luồng. Glibc thường đề cập đến một biến số struct pthreadpd, có lẽ là cho mô tả pthread.

Trên x86-64, struct pthread bắt đầu bằng tcbhead_t (điều này tùy thuộc vào kiến ​​trúc, xem các macro TLS_DTV_AT_TPTLS_TCB_AT_TP). Tiêu đề khối điều khiển chủ đề này, AFAIU, chứa một số trường cần thiết ngay cả khi có một chuỗi đơn. DTV là Vector chủ đề động và chứa các con trỏ tới các khối TLS cho các DSO được tải qua dlopen(). Trước hoặc sau TCB có một khối TLS tĩnh cho các thực thi và các DSO được liên kết tại thời gian tải (của chương trình). TCB và DTV được giải thích khá rõ trong Ulrich Drepper's TLS document (tìm các sơ đồ trong chương 3).

+1

FS được sử dụng bởi win32 trên x86 để trỏ vào thông tin chuỗi cửa sổ - rượu chỉ phù hợp với điều đó. –

10

Để thực sự trả lời câu hỏi fs:0 của bạn: x86_64 ABI yêu cầu rằng fs:0 chứa địa chỉ "được trỏ tới" bởi chính số fs. Tức là, fs:-4 tải giá trị được lưu trữ tại fs:0 - 4. Tính năng này là cần thiết bởi vì bạn không thể dễ dàng lấy địa chỉ được trỏ đến bởi fs mà không cần phải trải qua mã hạt nhân. Có địa chỉ được lưu trữ tại fs:0 do đó làm cho việc lưu trữ cục bộ luồng hiệu quả hơn nhiều.

Bạn có thể thấy điều này trong hành động khi bạn lấy địa chỉ của một biến địa phương chủ đề:

static __thread int test = 0; 

int *f(void) { 
    return &test; 
} 

int g(void) { 
    return test; 
} 

biên dịch để

f: 
    movq %fs:0, %rax 
    leaq -4(%rax), %rax 
    retq 

g: 
    movl %fs:-4, %eax 
    retq 

i686 cũng làm như vậy nhưng với %gs. Trên aarch64, điều này là không cần thiết vì địa chỉ có thể được đọc từ chính bản thân tls.

Các vấn đề liên quan