Как определить значения, сохраненные в стеке? - PullRequest
6 голосов
/ 06 апреля 2010

Я провожу некоторые эксперименты и хотел бы иметь возможность видеть, что сохраняется в стеке во время системного вызова (сохраненное состояние процесса пользовательской земли). Согласно 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, для проверки содержимого стека в ядре? Я не очень широко использую отладку и не уверен, как отлаживать код внутри ядра. Буду признателен за любую оказанную помощь.

Ответы [ 3 ]

5 голосов
/ 10 апреля 2010

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

struct pt_regs *regs = task_pt_regs(current);

4 голосов
/ 06 апреля 2010

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

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

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

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

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

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

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

Возможно, это не решит вашу проблему, но это путь. Для справки отметьте , , , и , .

.
0 голосов
/ 06 апреля 2010

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

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

...