Я работаю над проектом, в котором мне нужно, чтобы работающая программа выполняла функцию по требованию.Для этого я использую ptrace.Я знаю, что это возможно, потому что GDB делает это.
Сейчас я использую адаптированную версию кода, найденного на: https://github.com/eklitzke/ptrace-call-userspace Эта программа показывает, как вызвать fprintf в целевой программе.
Программа, с которой я сталкиваюсьпоявляется, когда вызываемая функция использует nanosleep ().Если nanosleep () вызывается в то время как внутри функции, вызываемой трассировщиком, трассировка падает с SIGSEGV, но только после завершения сна.Если функция вызывается нормально самой трассировкой, все работает правильно.
Я пришел к выводу, что проблема связана с тем, как вызывается функция, возможно, что-то связанное со стеком трассировки или ее значениями регистров.Я уже проверил, что при входе в функцию, например, стек выравнивается по 16 байтам.
Код трассировщика присутствует в github выше (разница - вызываемая функция, и я также удалил аргументы)
Код для трассировки - простой фиктивный процесс, который печатает его PID каждую секунду.
Код вызываемой функции:
#include <stdio.h>
#include <time.h>
void hello()
{
struct timespec tim1;
tim1.tv_sec = 1;
tim1.tv_nsec = 0;
struct timespec tim2;
nanosleep(&tim1, &tim2);
puts("Hello World!!!");
}
В случае сбоя отслеживаемой программы обратная трассировка выглядит следующим образом:
#0 0xfffffffffffffff7 in ?? ()
#1 0x00007effb0e6e6e0 in hello () at hello.c:10
#2 0x00007effb195c005 in ?? ()
#3 0x00007effb1435cc4 in __sleep (seconds=0) at ../sysdeps/unix/sysv/linux/sleep.c:137
#4 0x00000000004005de in main ()
Значения регистра для сброшенногоcore:
rax 0xfffffffffffffff7 -9
rbx 0x7ffc858a0e40 140722548903488
rcx 0x7effb1435e12 139636655742482
rdx 0x7ffc858a0df8 140722548903416
rsi 0x7ffc858a0df8 140722548903416
rdi 0x7ffc858a0e08 140722548903432
rbp 0x7ffc858a0e18 0x7ffc858a0e18
rsp 0x7ffc858a0df0 0x7ffc858a0df0
r8 0xffffffffffffffff -1
r9 0x0 0
r10 0x7ffc858a0860 140722548901984
r11 0x246 582
r12 0x7ffc858a0ec0 140722548903616
r13 0x7ffc858a1100 140722548904192
r14 0x0 0
r15 0x0 0
rip 0xfffffffffffffff7 0xfffffffffffffff7
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
Вывод трассировщика:
./call_hello -p 17611
their %rip 0x7effb1435e10
allocated memory at 0x7effb195c000
executing jump to mmap region
successfully jumped to mmap area
their lib 0x7effb0e6e000
their func 0x7effb0e6e000
Adding rel32 to new_text[0]Adding func_delta to new_text[1-4]Adding TRAP to new_text[5]inserting code/data into the mmap area at 0x7effb195c000
setting the registers of the remote process
continuing execution
PTRACE_CONT unexpectedly got status Unknown signal 2943
Если я уберу вызов nanosleep, все будет работать как положено - «Hello World !!!»печатается.Как я уже говорил ранее, ошибка сегментации возникает только после запрошенного спящего режима в течение 1 секунды.Я не знаю, как nanosleep заставляет указатель инструкции держать 0xfffffffffffffff7
.Любые предложения или идеи о том, что я должен изучить, чтобы решить эту проблему?Заранее спасибо!
Я тестирую это на CentOS Linux версии 7.6.1810.