17

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

Sam
  • 4,727
  • 9
  • 23
  • 17
  • maybe this might help you http://stackoverflow.com/questions/61341/is-there-a-way-to-insert-assembly-code-into-c – 0x90 Nov 16 '11 at 20:16
  • 2
    this is wildly platform dependent ; which OS / compiler are you using ? – rotoglup Nov 16 '11 at 20:16
  • 4
    Are you writing some sort of exploit? – Kerrek SB Nov 16 '11 at 20:17
  • 2
    C or C++? And why do you want to do this? – David Heffernan Nov 16 '11 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. – Steve Jessop Nov 17 '11 at 00:58
  • Don't forget to accept answers that you like. – Randall Cook Nov 22 '11 at 18:52
  • One place I have seen this used is in custom bootloader code for a microprocessor. Once the bootloader has initialized all the necessary configuration registers, execution can jump to the hard-coded location of a payload or baremetal program. – thomas.cloud Aug 15 '23 at 18:30

8 Answers8

34

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.

Randall Cook
  • 6,728
  • 6
  • 33
  • 68
  • I tested it with my setup, using gcc and with nucleus, was writing a minimal bootloader, and it works..... – fazkan Jan 05 '16 at 13:23
  • 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;`. – Tyrel Kostyk Feb 13 '20 at 20:10
  • 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? – rollsch Jun 29 '23 at 05:52
23

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)

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Note that this really is gcc specific. Clang does not allow this. – martinhans Nov 29 '13 at 09:13
  • 3
    clang 12 (and possibly earlier) supports this. – Allison Aug 24 '20 at 05:04
  • 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! – bigjosh May 09 '21 at 07:56
11
#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.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • 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. – kirbyfan64sos Nov 23 '14 at 20:48
  • 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. – Chris Dolan Jun 02 '15 at 14:09
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!

Andro
  • 2,232
  • 1
  • 27
  • 40
  • You also have to take the problem of virtual addresses into consideration when running programs on an OS. – Andro Jun 14 '13 at 13:17
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);
}
U007D
  • 5,772
  • 2
  • 38
  • 44
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)) ();}
İlkerK
  • 76
  • 4
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?

Community
  • 1
  • 1
Taylor Price
  • 622
  • 1
  • 8
  • 21
  • I think setjmp() and longjmp() are ment for non-standard stack unwinding aka. simulating exception handling in C. – Andro Jun 13 '13 at 21:45
  • 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. – Taylor Price Jun 14 '13 at 22:03
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"
);
Tay2510
  • 5,748
  • 7
  • 39
  • 58
Bahman
  • 1