HusseinAl-haj Ответов: 2

Можем ли мы прочитать счетчик программ другого потока?


предположим, что у нас есть программа с одним потоком, и мы надеемся захватить значение счетчика программ (PC), когда происходит предопределенное прерывание (например, прерывание таймера).
Это кажется простым, как вы знаете, мы просто пишем определенный ассемблерный код, используя специальное ключевое слово " _ _ asm__", и помещаем значение в верхнюю часть стека после сдвига на 4 байта.
А как насчет многопоточных программ ?
Как мы можем получить значения всех потоков из другого потока, который выполняется в том же процессе? (Кажется крайне невероятным получать значения из потока, который работает на отдельном ядре в многоядерных процессорах).
(в многопоточных программах каждый поток имеет свой стек и регистры тоже).

-------------------------------------

I would  implement a saboteur thread.
in order to perform fault injection in the target multi-threaded program, the model of fault is SEU (single error upset) which means that an arbitrary bit in the program counter register modified randomly (bit-flip) causing to violate the right program sequence. therefore, control flow error (CFE)  occurs.
Since our target program is a multi-threaded program, we have to perform fault injection on all threads' PC. This is the task of saboteur tread. It should be able  to obtain threads' PC to perform fault injection.
assume we have this code,
main ()
{
foo
}

void foo()
{
__asm__{
pop "%eax"
pop "%ebx" // now ebx holds porgram counter value (for main thread)
// her code injection like  00000111 XOR ebx for example
push ...
push ...
};
}

If our program was a multithreaded program.
is it means that we have more than one stack? 
when OS perform context switching, it means that the stack and registers of the thread that was running moved to some place in the memory. Does this mean that if we want to get the values of the program counter for those threads, we find them in memory? where? and is it possible during run-time?




любая помощь, я Вам благодарен.

Что я уже пробовал:

используя _ _ asm__, мы можем получить значение PC основного потока.

2 Ответов

Рейтинг:
20

OriginalGriff

АФАИК, нет.
Проблема в том, что вы не знаете, когда работает ваш поток, не говоря уже о том, какой другой поток работает одновременно. А в современных процессорах это действительно может быть "одновременно" - несколько ядер означают несколько одновременных потоков, и каждое ядро может легко запускать свой поток исключительно из кэша, так что...ваше прерывание будет работать только на одном ядре, и вы понятия не имеете, какой поток работает на другом(ах).
Даже в однопоточном приложении у вас нет гарантии, что ядро, на котором выполняется прерывание, является тем же ядром, что и ваше приложение!
А если поток застопорился, он находится в памяти (или даже выгружается на диск) вместе со своими регистрами - и у вас, вероятно, не будет доступа к этой памяти, даже если вы знаете, где она находится, потому что она находится вне "вашего" адресного пространства.


HusseinAl-haj

Я бы реализовал саботажную нить.
для того чтобы выполнить инъекцию ошибок в целевую многопоточную программу, моделью ошибки является SEU (single error disset), что означает, что произвольный бит в регистре счетчика программы изменяется случайным образом (bit-flip), вызывая нарушение правильной последовательности программ. поэтому возникает ошибка потока управления (CFE).
Поскольку наша целевая программа является многопоточной, мы должны выполнить инъекцию ошибок на ПК всех потоков. Это задача диверсанта Трэда. Он должен быть в состоянии получить ПК потоков для выполнения инъекции неисправностей.
предположим, у нас есть этот код,
главный ()
{
foo
}

пустота фу()
{
__ассемблер__{
поп "в регистре %EAX"
pop "%ebx" / / теперь ebx содержит значение счетчика porgram (для основного потока)
// ее инъекция кода, например 00000111 XOR ebx
толкать...
толкать...
};
}

Если бы наша программа была многопоточной.
значит ли это, что у нас есть более одного стека?
когда ОС Выполняет переключение контекста, это означает, что стек и регистры запущенного потока перемещаются в какое-то место в памяти. Означает ли это, что если мы хотим получить значения счетчика программы для этих потоков, мы находим их в памяти? - куда? и возможно ли это во время выполнения?
большое спасибо.

Рейтинг:
0

Dave Kreskowiak

Получить контекст можно, но устанавливать его в запущенном потоке не рекомендуется, так как поведение непредсказуемо.

Видеть Функция GetThreadContext (Windows)[^].

Это единственный намек, который вы получите, и это все, что я могу сказать. Я больше не буду помогать в этом. Вы находитесь на свой собственный с этой точки зрения.