nora
nora

Reputation: 57

skipping functions in return sequence of callers

In a sequence of function calls, such as

                main() --> A() --> B()-->C();

when a called function finishes, it normally returns to the calling function, e.g. C() returns to B(), which returns to A(), etc.

i'm wondering if it is also possible to return directly to an earlier function in the calling sequence so C() return to main() and skip B() and A()

if it is possible how can i do it ? and can you explain how it work and when it used in reality.

this is my code

#include <stdio.h>
int A(void);
int B(void);
void main(void )
{
    A();
}

int A()
{ 
    printf("enter A()\n");
    B();
    printf("exit A()\n");
}

int B()
{
    printf("enter B()\n");
    printf("exit B()\n");
}

and i want to skip return to function A() from B() so that the printf("exit A()\n"); will not execute and give me this result:

enter A()                                                                                                                  
enter B()                                                                                                                  
exit B() 

Upvotes: 3

Views: 564

Answers (1)

zerocool
zerocool

Reputation: 3502

before everything check out @PeterCordes is answers the question in more than a way

okey let's start :

this type of stuff can be done using something known as long jump so your code after editing will look like this :

#include <stdio.h>
#include <setjmp.h>//c standard library header
jmp_buf env; // for saving longjmp environment
main()
{
    int r, a=100;
    printf("call setjmp to save environment\n");
    if ((r=setjmp(env)) == 0){
        A();
        printf("normal return\n");
    }
    else
        printf("back to main() via long jump, r=%d a=%d\n", r, a);
}
int A()
{ 
    printf("enter A()\n");
    B();
    printf("exit A()\n");
}
int B()
{
    printf("enter B()\n");
    printf("long jump? (y|n) ");
    if (getchar()=='y')
    longjmp(env, 1234);
    printf("exit B()\n");
}

let's understand what just happened

In the above program, setjmp() saves the current execution environment in a jmp_buf structure and returns 0.

The program proceeds to call A(), which calls B().

While in the function B(), if the user chooses not to return by long jump, the functions will show the normal return sequence.

If the user chooses to return by longjmp(env,1234), execution will return to the last saved environment with a nonzero value.

In this case, it causes B() to return to main() directly, bypassing A().

The principle of long jump is very simple. When a function finishes, it returns by the

(caller_EIP, caller_EBP) in the current stack frame, If we replace (caller_EIP, caller_EBP) with

(saved_EIP, saved_EBP) of an earlier function in the calling sequence, execution would return to that function directly.

In addition to the (saved_EIP, saved_EBP), setjmp() may also save CPU’s general registers and the original ESP, so that longjmp() can restore the complete environment of the returned function.

Long jump can be used to abort a function in a calling sequence, causing execution to resume from a known environment saved earlier.

Although rarely used in user mode programs, it is a common technique in systems programming.

For example, it may be used in a signal catcher to bypass a user mode function that caused an exception or trap error.

you can check this is also good

Upvotes: 3

Related Questions