Как решить, что значения экономили на стеке?

Я делаю некоторое экспериментирование и хотел бы смочь видеть то, что сохраняется на стеке во время системного вызова (сохраненное состояние процесса пространства пользователя). Согласно http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S это показывает, что различные значения регистров сохраняются при тех конкретных смещениях к указателю вершины стека. Вот код, который я пытался использовать для исследования то, что сохраняется на стеке (это находится в пользовательском системном вызове, который я создал):

asm("movl 0x1C(%esp), %ecx");
asm("movl %%ecx, %0" : "=r" (value));

где значение является неподписанным долго.

С прямо сейчас, это значение не то, что ожидается (оно показывает, что 0 сохраняется для пользовательского значения ds).

Я правильно получаю доступ к смещению указателя вершины стека?

Другая возможность могла бы быть, я мог использовать отладчик, такой как GDB для исследования содержания стека в то время как в ядре? У меня нет большого широкого применения с отладкой, и не уверено в том, как отладить код в ядре. Любая справка очень ценится.

6
задан starblue 6 April 2010 в 18:31
поделиться

3 ответа

Встроенная сборка сложнее, чем кажется. Попытка кратко осветить проблемы, связанные с GCC:

  1. Если он изменяет регистры процессора, необходимо поместить эти регистры в список затирающих устройств. Важно отметить, что список clobber должен содержать ВСЕ регистры, которые вы изменили напрямую (прочтите явно ) или косвенно (прочтите неявно );
  2. Для подкрепления (1), условные и математические операции также изменяют регистры, более известные как флаги состояния (ноль, перенос, переполнение и т. Д.), Поэтому вы должны сообщить об этом, добавив «cc» в список clobber;
  3. Добавьте «память» , если он изменяет различные (читаемые случайным образом) позиции памяти;
  4. Добавьте ключевое слово volatile , если оно изменяет память, которая не упоминается во вводе / выводе arguments;

Тогда ваш код станет:

asm("movl 0x1C(%%esp), %0;"
    : "=r" (value)
    : /* no inputs :) */
    /* no modified registers */
);

Выходной аргумент не обязательно должен быть в списке clobber, потому что GCC уже знает, что он будет изменен.

В качестве альтернативы, поскольку все, что вам нужно, это значение регистра ESP, вы можете избежать всей этой боли:

register int esp asm("esp");
esp += 0x1C;

Это может не решить вашу проблему, но это правильный путь. Для справки проверьте это , this и this .

4
ответ дан 10 December 2019 в 02:45
поделиться

Имейте в виду, что код x86_64 часто передает значения в регистрах (поскольку их так много), поэтому в стеке ничего не будет. Проверьте промежуточный выход gcc ( -S IIRC) и найдите в сборке push .

Я не знаком с отладкой кода ядра, но gdb определенно лучше проверять стек в интерактивном режиме.

0
ответ дан 10 December 2019 в 02:45
поделиться

Нет необходимости во встроенной сборке. Сохраненное состояние, которое entry_32.S помещает в стек для системного вызова, оформлено как struct pt_regs , и вы можете получить указатель на нее следующим образом (вам потребуется include и / или прямо или косвенно):

struct pt_regs * regs = task_pt_regs (current);

5
ответ дан 10 December 2019 в 02:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: