Как получить адрес возврата функции внутри функции?

Я хочу напечатать возвращаемое значение в моем трассере, есть два вопроса

  1. Как получить обратный адрес?
  2. Возвращаемая позиция обновляется до ИЛИ после ~ Tracer ()?

Здесь нужен текст, чтобы Stackoverflow форматировал код:

struct Tracer
{
int* _retval;
~Tracer()
{ printf("return value is %d", *_retval); }
};int foo()
{
Tracer __tracter = { __Question_1_how_to_get_return_address_here__ };

if(cond) {
return 0;
} else {
return 99;
}

//Question-2:
// return postion is updated before OR after ~Tracer() called ???
}

3

Решение

Вы не можете переносить или надежно сделать это в C ++. Возвращаемое значение может находиться в памяти или в регистре и может быть или не быть косвенным в разных случаях.

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

Одним из возможных способов является сделать ваш Tracer шаблон, который принимает ссылку на переменную возвращаемого значения (при необходимости) и печатает тот до разрушения.

Также обратите внимание, что идентификаторы с __ (двойное подчеркивание) зарезервированы для реализации.

3

Другие решения

Я нашел несколько подсказок для Вопроса-1, сейчас проверяю код Vc

Для gcc, __builtin_return_address
http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html

Для Visual C ++ _ReturnAddress

3

Ваш вопрос довольно запутанный, вы взаимозаменяемо используете термины «адрес» и «значение», которые не являются взаимозаменяемыми.

Возвращаемое значение — это то, что функция выдает, в x86 (_64), которое приходит в виде значения 4/8 байтов в E / RAX, или EDX: EAX, или XMM0 и т. Д., Вы можете прочитать об этом больше Вот.

Адрес возврата, с другой стороны, это то, на что указывает E / RSP при совершении вызова (то есть на вершине стека), и содержит адрес, на который функция «переходит» назад, когда это сделано (что по определению называется возвращение).

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

Для значения и при условии, что вы делаете это внутренне, просто подключите функцию к функции с таким же определением, и как только она вернется, вы получите свой результат.

Что касается адреса, это немного сложнее, потому что вам придется пойти немного ниже и, возможно, сделать несколько asm shenanigains, я действительно понятия не имею, что именно вы ищете, но я сделал небольшую «заглушку», если вы будете , чтобы предоставить вызываемому указатель возврата.

Вот:

 void __declspec(noinline) __declspec(naked) __stdcall _replaceFirstArgWithRetPtrAndJump_() {
__asm {                   //let's call the function we jump to "callee", and the function that called us "caller"push ebp             //save ebp, ESP IS NOW -4
mov ebp, [esp + 4]  //save return address
mov eax, [esp + 8] //get callee's address (which is the first param) - eax is volatile so iz fine
mov[esp + 8], ebp //put the return address where the callee's address was (to the callee, it will be the caller)
pop ebp          //restore ebp
jmp eax         //jump to callee
}   }
#define CallFunc_RetPtr(Function, ...) ((decltype(&Function))_replaceFirstArgWithRetPtrAndJump_)(Function, __VA_ARGS__)

unsigned __declspec(noinline) __stdcall printCaller(void* caller, unsigned param1, unsigned param2) {
printf("I'm printCaller, Called By %p; Param1: %u, Param2: %u\n", caller, param1, param2);
return 20;
}

void __declspec(noinline) doshit() {
printf("us: %p\nFunction we're calling: %p\n", doshit, printCaller);
CallFunc_RetPtr(printCaller, 69, 420);
}

Теперь, конечно, вы могли бы и, возможно, должны использовать _ReturnAddress () или любые другие встроенные функции компилятора, но если это недоступно (что должно быть действительно редким сценарием в зависимости от вашей работы), и вы знаете свой ASM, эта концепция должна работать для любой архитектуры, поскольку набор команд может быть разным, все они следуют одному и тому же дизайну счетчика программ.

Я написал это больше, потому что я искал ответ на этот вопрос довольно давно для определенной цели, и я не мог найти хороший, потому что большинство людей просто говорят: «Блин, это не возможно, не переносимо или что-то в этом роде», и Я чувствую, что это помогло бы.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector