472,805 Members | 911 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,805 software developers and data experts.

Why the setjmp and longjmp I wrote can not work?

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

Nov 15 '05 #1
8 2340
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.
Nov 15 '05 #2
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.

Nov 15 '05 #3
"Zheng Da" <zh*********@gmail.com> 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) ks***@mib.org <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.
Nov 15 '05 #4

Keith Thompson wrote:
"Zheng Da" <zh*********@gmail.com> 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) ks***@mib.org <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.

Nov 15 '05 #5
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.
Nov 15 '05 #6
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

Nov 15 '05 #7
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 :-)

Nov 15 '05 #8
In article <11**********************@f14g2000cwb.googlegroups .com>,
"Zheng Da" <zh*********@gmail.com> 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.
Nov 15 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Thomas Baruchel | last post by:
Hi, wondering about: func1: setjmp() ; func2(); func2: {FILE *f; f = fopen(); func3(); fclose(f)} func3 : if() longjmp; else return; Note that FILE *fis a local variable in func2.
6
by: someone | last post by:
I have *thought* that setjmp/longjmp() should take a pointer to jmp_buf. And the calling function should hold the actual struct data. But ... I trid on both Win32 and Linux, it seems that...
12
by: Michael B Allen | last post by:
Should setjmp/longjmp really be used in a fast mundane ANSI C piece of code? Or is it frowned apon like goto? I have a need but I don't want to use something that is costly, isn't supported...
4
by: Jrferguson | last post by:
I have a C program that I am trying to port to a Motorola 68k based system. It makes use of setjmp and longjmp which are not supported by my C compiler. I understand the general principle behind...
5
by: candy | last post by:
hi all, Consider the following C code: void funct(){ }
20
by: JS | last post by:
When setjmp is called how can the if statement evaluate to true or false when setjmp only returns 0 or non-zero? struct pcb { void *(*start_routine) (void *); void *arg; jmp_buf state; int...
15
by: rover8898 | last post by:
Hello all, I used setjmp() in a recent of program of mine (it is not completed, so I have not the chance to test it out yet). I am not very profocient in C coding as are some of my co-workers....
4
by: nicho | last post by:
Could some knowledgable soul tell me if the following setjmp/longjmp structure will work from a logical standpoint ? The problem is that bar() needs to suspend processing and return control to...
5
by: Spiros Bousbouras | last post by:
In the following assume that a is int and env is of type jmp_buf a = setjmp(env) ; Is it legal ? It looks reasonable but it seems to violate what is mentioned under "Environmental limits" of...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: kcodez | last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: lllomh | last post by:
How does React native implement an English player?
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.