Каков реальный адрес `% fs: 0xfffffffffffffff8`? - PullRequest
4 голосов
/ 19 марта 2020

Я хочу отследить goid go программ, использующих ebpf.

После прочтения некоторых постов и блогов я знаю, что %fs:0xfffffffffffffff8 указывает на структуру g go и mov %fs:0xfffffffffffffff8,%rcx инструкция всегда появляется в начале функции go.

Принимая main.main в качестве примера:

func main() {
 177341   458330:   64 48 8b 0c 25 f8 ff    mov    %fs:0xfffffffffffffff8,%rcx
 177342   458337:   ff ff
 177343   458339:   48 3b 61 10             cmp    0x10(%rcx),%rsp
 177344   45833d:   76 1a                   jbe    458359 <main.main+0x29>
 177345   45833f:   48 83 ec 08             sub    $0x8,%rsp
 177346   458343:   48 89 2c 24             mov    %rbp,(%rsp)
 177347   458347:   48 8d 2c 24             lea    (%rsp),%rbp
 177348     myFunc()
 177349   45834b:   e8 10 00 00 00          callq  458360 <main.myFunc>
 177350 }

Я также знаю, что информация о goid хранится в g структура go. Значение регистра fs можно получить с помощью аргумента ctx функции ebpf.

Но я не знаю, каков реальный адрес %fs:0xfffffffffffffff8, потому что я новичок в ассемблере. Кто-нибудь может дать мне несколько советов?

Если значение регистра fs было 0x88, каково значение %fs:0xfffffffffffffff8?

1 Ответ

6 голосов
/ 19 марта 2020

Это отрицательное число, так что это одно слово перед базой FS. Вам необходим базовый адрес FS, который равен , а не значению селектора в регистре сегмента FS, которое можно увидеть с помощью отладчика.

Возможно, ваш процесс совершил системный вызов, чтобы попросить ОС установите его или, возможно, использовали инструкцию wrfsbase в некоторых точках в системах, которые ее поддерживают.

Обратите внимание, что по крайней мере за пределами Go, Linux обычно использует FS для потока локальное хранилище.

(Я не уверен, что стандартный способ на самом деле найти базу FS; это, очевидно, зависит от ОС, чтобы сделать это в пользовательском пространстве, где rdmsr недоступен; FS и База GS выставляется как MSR, поэтому ОС используют вместо фактического изменения записи GDT или LDT. rdfsbase должно быть включено ядром, установив бит в CR4 на процессорах которые поддерживают расширение ISA FSGSBASE, поэтому вы не можете рассчитывать на это.)

@ MargaretBloom предполагает, что пользовательское пространство может вызвать ошибку неверной страницы; большинство ОС сообщают о сбойном виртуальном адресе обратно в пространство пользователя. Например, в Linux SIGSEGV имеет адрес. (Или SIGBUS, если он был неканоническим, IIR C. То есть не в младших или старших 47 битах виртуального адресного пространства, а в «дыре», где адрес не является расширением знака младших 48. )

Таким образом, вы хотите установить обработчики сигналов для этих сигналов и попробовать загрузку со смещением, которое (с 0 основанием) будет в середине пространства ядра, или что-то в этом роде. Если по какой-либо причине это не является ошибкой, увеличьте виртуальный адрес на 1 ТБ или что-то в al oop. Обычно MMIO не отображается в виртуальном адресном пространстве пользовательского пространства, поэтому побочных эффектов для простого чтения нет.

...