Why the setjmp and longjmp I wrote can not work?

Discussion in 'C Programming' started by Zheng Da, Nov 6, 2005.

  1. Zheng Da

    Zheng Da Guest

    I wrote a simple one as follow:

    typedef struct __myjmp_buf
    {
    int efp;
    int epc;
    }myjmp_buf;

    int mysetjmp(myjmp_buf env)
    {
    int reval=0;
    __asm__("movl %%ebp,%0":"=r"(env[0].efp));
    __asm__("movl $1f,%0\n\t"
    "1:"
    :"=r"(env[0].epc));
    return reval;
    }

    void mylongjmp(myjmp_buf env , int val)
    {
    __asm__("movl %1,-4(%0)\n\t"
    "movl %0,%%ebp\n\t"
    "jmp %2"
    ::"r"(env[0].efp),
    "r"(val),
    "r"(env[0].epc));
    }

    myjmp_buf buf;

    int test()
    {
    int i=0;
    i++;
    mylongjmp(buf , 1);
    return 0;
    }

    int main()
    {
    if(mysetjmp(buf))
    {
    printf("return success\n");
    }
    printf("pc:%x,fp:%x\n" , buf[0].epc , buf[0].efp);
    printf("main address:%x\n" , main);
    test();
    exit(0);
    }

    When the computer execute jmp %2, and gives me a segment fault.
    Why the address I save is a invalid address?
    By the way, I want to find the codes of setjmp and longjmp in glibc,
    but can not get it, and waht I find does not seem to be what I want.
    How to find the codes of setjmp and longjmp which can run under Linux
    and x86?
    Thank you
     
    Zheng Da, Nov 6, 2005
    #1
    1. Advertising

  2. Zheng Da

    Michael Mair Guest

    Zheng Da wrote:
    > I wrote a simple one as follow:
    >

    <snip>
    Sorry, your code does not compile; you forgot to
    #include <stdio.h>
    and you use the non-standard __asm__() function.

    > When the computer execute jmp %2, and gives me a segment fault.
    > Why the address I save is a invalid address?
    > By the way, I want to find the codes of setjmp and longjmp in glibc,
    > but can not get it, and waht I find does not seem to be what I want.
    > How to find the codes of setjmp and longjmp which can run under Linux
    > and x86?


    Please provide a minimal compiling example in standard
    C or repost your request in a newsgroup where your
    platform/operating system/compiler-combination is on-topic.

    Information about setjmp/longjmp() can be found below.


    Cheers
    Michael

    PS: The following is only a quote from the standard.

    As for setjmp()/longjmp():

    7.13 Nonlocal jumps <setjmp.h>

    1 The header <setjmp.h> defines the macro setjmp, and declares one
    function and one type, for bypassing the normal function call and
    return discipline.207)
    ,---
    | 207) These functions are useful for dealing with unusual conditions
    | encountered in a low-level function of a program.
    `---

    2 The type declared is
    jmp_buf
    which is an array type suitable for holding the information needed to
    restore a calling environment. The environment of a call to the setjmp
    macro consists of information sufficient for a call to the longjmp
    function to return execution to the correct block and invocation of that
    block, were it called recursively. It does not include the state of the
    floating-point status flags, of open files, or of any other component of
    the abstract machine.

    3 It is unspecified whether setjmp is a macro or an identifier declared
    with external linkage. If a macro definition is suppressed in order to
    access an actual function, or a program defines an external identifier
    with the name setjmp, the behavior is undefined.

    7.13.1 Save calling environment
    7.13.1.1 The setjmp macro

    Synopsis
    1
    #include <setjmp.h>
    int setjmp(jmp_buf env);

    Description
    2 The setjmp macro saves its calling environment in its jmp_buf argument
    for later use by the longjmp function.

    Returns
    3 If the return is from a direct invocation, the setjmp macro returns
    the value zero. If the return is from a call to the longjmp function,
    the setjmp macro returns a nonzero value.

    Environmental limits
    4 An invocation of the setjmp macro shall appear only in one of the
    following contexts:
    — the entire controlling expression of a selection or iteration
    statement;
    — one operand of a relational or equality operator with the other
    operand an integer constant expression, with the resulting expression
    being the entire controlling expression of a selection or iteration
    statement;
    — the operand of a unary ! operator with the resulting expression being
    the entire controlling expression of a selection or iteration
    statement; or
    — the entire expression of an expression statement (possibly cast to
    void).

    5 If the invocation appears in any other context, the behavior is undefined.

    7.13.2 Restore calling environment
    7.13.2.1 The longjmp function

    Synopsis
    1
    #include <setjmp.h>
    void longjmp(jmp_buf env, int val);

    Description
    2 The longjmp function restores the environment saved by the most recent
    invocation of the setjmp macro in the same invocation of the program
    with the corresponding jmp_buf argument. If there has been no such
    invocation, or if the function containing the invocation of the setjmp
    macro has terminated execution208) in the interim, or if the invocation
    of the setjmp macro was within the scope of an identifier with variably
    modified type and execution has left that scope in the interim, the
    behavior is undefined.
    ,---
    | 208) For example, by executing a return statement or because another
    | longjmp call has caused a transfer to a setjmp invocation in a
    | function earlier in the set of nested calls.
    `---

    3 All accessible objects have values, and all other components of the
    abstract machine209) have state, as of the time the longjmp function was
    called, except that the values of objects of automatic storage duration
    that are local to the function containing the invocation of the
    corresponding setjmp macro that do not have volatile-qualified type
    and have been changed between the setjmp invocation and longjmp call are
    indeterminate.
    ,---
    | 209) This includes, but is not limited to, the floating-point status
    | flags and the state of open files.
    `---

    Returns
    4 After longjmp is completed, program execution continues as if the
    corresponding invocation of the setjmp macro had just returned the value
    specified by val. The longjmp function cannot cause the setjmp macro to
    return the value 0; if val is 0, the setjmp macro returns the value 1.

    5 EXAMPLE
    The longjmp function that returns control back to the point of the
    setjmp invocation might cause memory associated with a variable length
    array object to be squandered.

    #include <setjmp.h>
    jmp_buf buf;
    void g(int n);
    void h(int n);
    int n = 6;

    void f(void)
    {
    int x[n]; // valid: f is not terminated
    setjmp(buf);
    g(n);
    }

    void g(int n)
    {
    int a[n]; // a may remain allocated
    h(n);
    }

    void h(int n)
    {
    int b[n]; // b may remain allocated
    longjmp(buf, 2); // might cause memory loss
    }

    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Nov 6, 2005
    #2
    1. Advertising

  3. Zheng Da

    Zheng Da Guest

    Thank you for advice and information you provided.
    I compile the program in Fedora core1 which runs in x86, and the
    version of gcc is 3.3.2.
    By the way, the program has been a minimal compiling example, and there
    is no error to compile it in my system but a warning "indirect jmp
    without '*' "
    But I do not know what the warning mean.
     
    Zheng Da, Nov 6, 2005
    #3
  4. "Zheng Da" <> writes:
    > Thank you for advice and information you provided.
    > I compile the program in Fedora core1 which runs in x86, and the
    > version of gcc is 3.3.2.
    > By the way, the program has been a minimal compiling example, and there
    > is no error to compile it in my system but a warning "indirect jmp
    > without '*' "
    > But I do not know what the warning mean.


    Please don't assume your readers can see the article to which you're
    replying. You need to provide some context so each article can be
    read on its own. Google makes it unnecessarily difficult to do this
    properly, but there is a workaround:

    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.

    We don't know what the warning means either, because it doesn't refer
    to anything in standard C. "__asm__" is not part of the C standard;
    it's apparently a gcc extension.

    You might try gnu.gcc.help.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 6, 2005
    #4
  5. Zheng Da

    Zheng Da Guest

    Keith Thompson wrote:
    > "Zheng Da" <> writes:
    > > Thank you for advice and information you provided.
    > > I compile the program in Fedora core1 which runs in x86, and the
    > > version of gcc is 3.3.2.
    > > By the way, the program has been a minimal compiling example, and there
    > > is no error to compile it in my system but a warning "indirect jmp
    > > without '*' "
    > > But I do not know what the warning mean.

    >
    > Please don't assume your readers can see the article to which you're
    > replying. You need to provide some context so each article can be
    > read on its own. Google makes it unnecessarily difficult to do this
    > properly, but there is a workaround:
    >
    > If you want to post a followup via groups.google.com, don't use
    > the broken "Reply" link at the bottom of the article. Click on
    > "show options" at the top of the article, then click on the
    > "Reply" at the bottom of the article headers.
    >
    > We don't know what the warning means either, because it doesn't refer
    > to anything in standard C. "__asm__" is not part of the C standard;
    > it's apparently a gcc extension.
    >
    > You might try gnu.gcc.help.
    >
    > --
    > Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    > San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    > We must do something. This is something. Therefore, we must do this.


    First, I am sorry. I did know it made so much trouble when I click
    "Reply" link at the bottom of the article in google newsgroup.
    I think I should redescribe the problem I met.
    I wrote a program as follow:
    #include <stdio.h>

    typedef struct __myjmp_buf
    {
    int efp;
    int epc;
    }myjmp_buf;

    int mysetjmp(myjmp_buf env)
    {
    int reval=0;
    __asm__("movl %%ebp,%0":"=r"(env[0].efp));
    __asm__("movl $1f,%0\n\t"
    "1:"
    :"=r"(env[0].epc));
    return reval;
    }

    void mylongjmp(myjmp_buf env , int val)
    {
    __asm__("movl %1,-4(%0)\n\t"
    "movl %0,%%ebp\n\t"
    "jmp %2"
    ::"r"(env[0].efp),
    "r"(val),
    "r"(env[0].epc));
    }

    myjmp_buf buf;

    int test()
    {
    int i=0;
    i++;
    mylongjmp(buf , 1);
    return 0;
    }

    int main()
    {
    if(mysetjmp(buf))
    {
    printf("return success\n");
    }
    printf("pc:%x,fp:%x\n" , buf[0].epc , buf[0].efp);
    printf("main address:%x\n" , main);
    test();
    exit(0);
    }
    When the computer execute jmp %2, and gives me a segment fault.
    I do not know why the address I save is a invalid address, and wonder
    to know what should I do if I want that mysetjmp and mylongjmp can work
    like setjmp and longjmp.
    My platform is x86, the system I use is Fedora core1, and I compile the
    program with gcc.
     
    Zheng Da, Nov 6, 2005
    #5
  6. Zheng Da

    Flash Gordon Guest

    Zheng Da wrote:

    <snip>

    > First, I am sorry. I did know it made so much trouble when I click
    > "Reply" link at the bottom of the article in google newsgroup.


    Please send a complaint to Google about the problems their interface
    causes you and others.

    Also, you don't need to quote everything, snip out the bits you are not
    replying too.

    <snip>

    > void mylongjmp(myjmp_buf env , int val)
    > {
    > __asm__("movl %1,-4(%0)\n\t"
    > "movl %0,%%ebp\n\t"
    > "jmp %2"
    > ::"r"(env[0].efp),
    > "r"(val),
    > "r"(env[0].epc));
    > }


    <snip>

    > When the computer execute jmp %2, and gives me a segment fault.


    <snip>

    I'm sure I've seen posts telling you that __asm__ is not on topic here
    because it is a system specific extension and we don't deal with those.
    Please ask about your problem in a GNU or Linux group, or possibly an
    x86 group since this is x86 assembler.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Nov 6, 2005
    #6
  7. Zheng Da

    Zheng Da Guest


    > I'm sure I've seen posts telling you that __asm__ is not on topic here
    > because it is a system specific extension and we don't deal with those.
    > Please ask about your problem in a GNU or Linux group, or possibly an
    > x86 group since this is x86 assembler.


    OK. Thank you all the same
     
    Zheng Da, Nov 6, 2005
    #7
  8. Zheng Da

    jacob navia Guest

    Zheng Da wrote:
    > I wrote a simple one as follow:
    >
    > typedef struct __myjmp_buf
    > {
    > int efp;
    > int epc;
    > }myjmp_buf;
    >
    > int mysetjmp(myjmp_buf env)
    > {
    > int reval=0;
    > __asm__("movl %%ebp,%0":"=r"(env[0].efp));
    > __asm__("movl $1f,%0\n\t"
    > "1:"
    > :"=r"(env[0].epc));
    > return reval;
    > }
    >
    > void mylongjmp(myjmp_buf env , int val)
    > {
    > __asm__("movl %1,-4(%0)\n\t"
    > "movl %0,%%ebp\n\t"
    > "jmp %2"
    > ::"r"(env[0].efp),
    > "r"(val),
    > "r"(env[0].epc));
    > }
    >
    > myjmp_buf buf;
    >
    > int test()
    > {
    > int i=0;
    > i++;
    > mylongjmp(buf , 1);
    > return 0;
    > }
    >
    > int main()
    > {
    > if(mysetjmp(buf))
    > {
    > printf("return success\n");
    > }
    > printf("pc:%x,fp:%x\n" , buf[0].epc , buf[0].efp);
    > printf("main address:%x\n" , main);
    > test();
    > exit(0);
    > }
    >
    > When the computer execute jmp %2, and gives me a segment fault.
    > Why the address I save is a invalid address?
    > By the way, I want to find the codes of setjmp and longjmp in glibc,
    > but can not get it, and waht I find does not seem to be what I want.
    > How to find the codes of setjmp and longjmp which can run under Linux
    > and x86?
    > Thank you
    >

    1)
    Your program will not compile
    In the function "mysetjump" you declare "env" as a structure
    "myjmp_buf" but you access it as an array.

    2) You are passing the structure myjump_buf by value to the
    function mysetjmp, so any changes or assignments done to that
    structure are destroyed when the function returns. You are working
    in a COPY of the structure

    3) Do not use the embedded assembler of gcc. It is utterly
    incomprehensible. Write setjmp like this:

    mov 0x4(%esp,1),%edx ;save address of buffer in edx
    mov (%esp,1),%ecx ;save return address in ecx
    mov %ebx,0xc(%edx) ; save ebx
    mov %esi,0x10(%edx) ; save esi
    mov %edi,0x14(%edx) ; save edi
    mov %ecx,0x8(%edx) ; save return address
    mov %eax,0x1c(%edx) ; save eax
    mov %ebp,0x4(%edx) ; save ebp
    mov %esp,%eax ; save esp+4
    add $0x4,%eax
    mov %eax,(%edx) ; at the bottom of the buffer
    xor %eax,%eax ; return zero
    ret

    I leave you the long jump routine as an exercise for the reader :)
     
    jacob navia, Nov 7, 2005
    #8
  9. In article <>,
    "Zheng Da" <> wrote:

    > void mylongjmp(myjmp_buf env , int val)
    > {
    > __asm__("movl %1,-4(%0)\n\t"
    > "movl %0,%%ebp\n\t"
    > "jmp %2"
    > ::"r"(env[0].efp),
    > "r"(val),
    > "r"(env[0].epc));
    > }
    >


    To be honest, implementing setjmp and longjmp is one of the things that
    you shouldn't even try if you have to ask people how to do it.
     
    Christian Bau, Nov 7, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. someone
    Replies:
    5
    Views:
    3,548
    SM Ryan
    May 1, 2004
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,226
    Smokey Grindel
    Dec 2, 2006
  3. Replies:
    3
    Views:
    428
    Fred Kleinschmidt
    Feb 23, 2007
  4. c
    Replies:
    43
    Views:
    1,579
    Richard
    Dec 15, 2007
  5. jacob navia

    The stack and longjmp/setjmp

    jacob navia, Mar 4, 2008, in forum: C Programming
    Replies:
    34
    Views:
    1,494
    David Thompson
    Mar 31, 2008
Loading...

Share This Page