18

I want the program to jump to a specific address in memory and continue execution from that address. I thought about using goto but I don't have a label rather just an address in memory.

There is no need to worry about return back from the jump address.

edit: using GCC compiler

7
  • maybe this might help you stackoverflow.com/questions/61341/… Commented Nov 16, 2011 at 20:16
  • 2
    this is wildly platform dependent ; which OS / compiler are you using ? Commented Nov 16, 2011 at 20:16
  • 4
    Are you writing some sort of exploit? Commented Nov 16, 2011 at 20:17
  • 2
    C or C++? And why do you want to do this? Commented Nov 16, 2011 at 20:32
  • Do you understand that if you do this (either with an inline assembly jump instruction, or a function pointer bodge), then any variables will not necessarily keep their values across the jump? A variable might be cached in one register at the point you jump from, and a different register in the point you jump to, and that's assuming the two points are even in the same function. So if the destination address is code written in C, it's almost guaranteed not to work. Commented Nov 17, 2011 at 0:58

8 Answers 8

35

Inline assembly might be the easiest and most "elegant" solution, although doing this is highly unusual, unless you are writing a debugger or some specialized introspective system.

Another option might be to declare a pointer to a void function (void (*foo)(void)), then set the pointer to contain your address, and then invoke it:

void (*foo)(void) = (void (*)())0x12345678;
foo();

There will be things pushed on the stack since the compiler thinks you are doing a subroutine call, but since you don't care about returning, this might work.

Sign up to request clarification or add additional context in comments.

4 Comments

I tested it with my setup, using gcc and with nucleus, was writing a minimal bootloader, and it works.....
Some compilers may evaluate the memory address (0x12345678 in this case) as an int, and complain when you try to set the function pointer's value to it. You should explicitly cast the memory address: void (*foo)(void) = (void (*)())0x12345678;.
Anyway to make it literally emit a jump instruction instead of a call? Eg trick it into jumping to a label that is an address not within the current function?
Clang seems to hard error with "Indirect goto in function with no address-of-label expressions" now. Is there any solution?
29

gcc has an extension that allows jumping to an arbitrary address:

void *ptr = (void *)0x1234567;  // a random memory address
goto *ptr;                      // jump there -- probably crash

This is pretty much the same as using a function pointer that you set to a fixed value, but it will actually use a jump instruction rather than a call instruction (so the stack won't be modified)

3 Comments

Note that this really is gcc specific. Clang does not allow this.
clang 12 (and possibly earlier) supports this.
A recent update to Atmel Studio broke this line that had been working for a decade... asm("jmp " STR(FLASH_ACTIVE_IMAGE_START_ADDRESS) ); ...but replaced with syntax above works. Thanks!
13
#include <stdio.h>
#include <stdlib.h>

void go(unsigned int addr) {
  (&addr)[-1] = addr;
}

int sub() {
  static int i;
  if(i++ < 10) printf("Hello %d\n", i);
  else exit(0);
  go((unsigned int)sub);
}

int main() {
  sub();
}

Of course, this invokes undefined behavior, is platform-dependent, assumes that code addresses are the same size as int, etc, etc.

2 Comments

This is genius. I was looking into using C as a language backend and needed to know how to jump to arbitrary addresses. Then I found this.
I can vouch that this trick mostly works, as long as the destination function has no arguments and you don't try to return a value. I changed it to be void* instead of unsigned int and that worked for me. But as a general solution to replace x86 jmp inline asm, doesn't work well enough.
5

It should look something like this:

unsigned long address=0x80; 

void (*func_ptr)(void) = (void (*)(void))address;
func_ptr();

However, it is not a very safe operation, jumping to some unknown address will probably result in a crash!

1 Comment

You also have to take the problem of virtual addresses into consideration when running programs on an OS.
2

Since the question has a C++ tag, here's an example of a C++ call to a function with a signature like main()--int main(int argc, char* argv[]):

int main(int argc, char* argv[])
{
    auto funcAddr = 0x12345678; //or use &main...
    auto result = reinterpret_cast<int (*)(int, char**)>(funcAddr)(argc, argv);
}

Comments

1

Do you have control of the code at the address that you intend to jump to? Is this C or C++?

I hesitantly suggest setjmp() / longjmp() if you're using C and can run setjmp() where you need to jump back to. That being said, you've got to be VERY careful with these.

As for C++, see the following discussion about longjmp() shortcutting exception handling and destructors destructors. This would make me even more hesitant to suggest it's use in C++.

C++: Safe to use longjmp and setjmp?

2 Comments

I think setjmp() and longjmp() are ment for non-standard stack unwinding aka. simulating exception handling in C.
Exception handling is a major use for them, yes. That being said, depending on what the code in question looks like, it would be possible to use a longjmp() to jump to a known point in the code without worrying about the address provided that a setjmp() call can be run at that point.
1

This is what I am using for my bootstrap loader(MSP430AFE253,Compiler = gcc,CodeCompeserStudio);

#define API_RESET_VECT 0xFBFE
#define JUMP_TO_APP()  {((void (*)()) (*(uint16_t*)API_RESET_VECT)) ();}

Comments

0

I Propos this code:

asm(
"LDR R0,=0x0a0000\n\t" /* Or 0x0a0000 for the base Addr. */
"LDR R0, [R0, #4]\n\t" /* Vector+4 for PC */
"BX R0"
);

1 Comment

Anyway to get the address from the C code into the inline ASM?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.