Некоторые ответы здесь и статья о внедрении кода , на которую вы ссылались в своем ответе, охватывают фрагменты того, что я считаю оптимальным gdb
-ориентированным решением, но ни один из них не сводит все это вместе и не охватывает все точки. Кодовое выражение решения немного длинное, поэтому вот краткое изложение важных шагов:
dlopen()
в подчиненном процессе для связи в общей библиотеке, содержащей введенный код. В статье, которую вы связали с автором, вместо этого загрузили перемещаемый объектный файл и связали его вручную с подчиненным. Это, откровенно говоря, безумие - перемещаемые объекты не являются «готовыми к работе» и включают перемещения даже для внутренних ссылок. А ручная компоновка утомительна и подвержена ошибкам - гораздо проще позволить реальной работе динамического компоновщика во время выполнения. Это, в первую очередь, означает вовлечение в процесс libdl
, но для этого есть много вариантов. dlsym
, могут обойти GOT и обеспечить прямой доступ к интересующей функции. Единственный способ быть уверенным в перехвате всех вызовов определенной функции - это переписать начальные инструкции кода этой функции в памяти, чтобы создать «обходной» путь, перенаправляющий выполнение на вашу внедренную функцию. gdb
появилась возможность писать новые команды на Python. Эта поддержка может быть использована для реализации решения «под ключ» для внедрения и обхода кода в / в подчиненном процессе. Вот пример. У меня есть такие же исполняемые файлы a
и b
, как и раньше, и inject2.so
, созданный из следующего кода:
#include
#include
int (*rand__)(void) = NULL;
int
rand(void)
{
int result = rand__();
printf("rand invoked! result = %d\n", result);
return result % 47;
}
Затем я могу поместить свою команду Python detour
в detour.py
и иметь следующий сеанс gdb
:
(gdb) source detour.py (gdb) exec-file a (gdb) set follow-fork-mode child (gdb) catch exec Catchpoint 1 (exec) (gdb) run Starting program: /home/llasram/ws/detour/a a: 1933263113 a: 831502921 [New process 8500] b: 918844931 process 8500 is executing new program: /home/llasram/ws/detour/b [Switching to process 8500] Catchpoint 1 (exec'd /home/llasram/ws/detour/b), 0x00007ffff7ddfaf0 in _start () from /lib64/ld-linux-x86-64.so.2 (gdb) break main Breakpoint 2 at 0x4005d0: file b.c, line 7. (gdb) cont Continuing. Breakpoint 2, main (argc=1, argv=0x7fffffffdd68) at b.c:7 7 { (gdb) detour libc.so.6:rand inject2.so:rand inject2.so:rand__ (gdb) cont Continuing. rand invoked! result = 392103444 b: 22 Program exited normally.
В дочернем процессе я создаю обходной путь от функции rand()
в libc.so.6
к функции rand()
в inject2.so
и сохраняю указатель на батут для оригинала rand()
в переменной rand__
из inject2.so
. И, как и ожидалось, введенный код вызывает оригинал, отображает полный результат и возвращает этот результат по модулю 47.
Из-за длины, я просто ссылаюсь на pastie, содержащий код моей команды detour
. Это довольно поверхностная реализация (особенно с точки зрения создания батута), но она должна хорошо работать в большом проценте случаев. Я протестировал его с gdb
7.2 (последняя выпущенная версия) в Linux с 32-битными и 64-битными исполняемыми файлами. Я не проверял это на OS X, но любые различия должны быть относительно незначительными.
Посмотрите, подходит ли вам следующий синтаксис:
// WeekEnd enumeration
enum WeekEnd
{
Sunday = 1,
Saturday = 7
};
// String support for WeekEnd
Begin_Enum_String( WeekEnd )
{
Enum_String( Sunday );
Enum_String( Saturday );
}
End_Enum_String;
// Convert from WeekEnd to string
const std::string &str = EnumString<WeekEnd>::From( Saturday );
// str should now be "Saturday"
// Convert from string to WeekEnd
WeekEnd w;
EnumString<WeekEnd>::To( w, "Sunday" );
// w should now be Sunday
Если да, то можете прочитать эту статью:
http: // www.gamedev.net/reference/snippets/features/cppstringizing/[1286 visible
Мне несколько раз требовалась эта функциональность для отладки/анализа кода от других.
Для этого я написал скрипт Perl, который генерирует класс с несколькими перегруженными toString
методов. Каждый метод toString
принимает Enum
в качестве аргумента и возвращает const char*
.
Конечно, скрипт не анализирует C++ для самих обименов, а использует ctags для генерации таблицы символов.
Скрипт Perl находится здесь: http://heinitz-it.de/download/enum2string/enum2string.pl.html