Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to execute code from the stack in standard C?

The following code doesn't work as intended but hopefully illustrates my attempt:

long foo (int a, int b) {
  return a + b;
}

void call_foo_from_stack (void) {
  /* reserve space on the stack to store foo's code */
  char code[sizeof(*foo)];

  /* have a pointer to the beginning of the code */
  long (*fooptr)(int, int) = (long (*)(int, int)) code;

  /* copy foo's code to the stack */
  memcpy(code, foo, sizeof(*foo));

  /* execute foo from the stack */
  fooptr(3, 5);
}

Obviously, sizeof(*foo) doesn't return the size of the code of the foo() function.

I am aware that executing the stack is restricted on some CPUs (or at least if a restriction flag is set). Apart from GCC's nested functions that can eventually be stored on the stack, is there a way to do that in standard C?

like image 959
Blagovest Buyukliev Avatar asked Sep 20 '10 21:09

Blagovest Buyukliev


People also ask

How code is executed in stack?

Execution stack, also known as “calling stack” in other programming languages, is a stack with a LIFO (Last in, First out) structure, which is used to store all the execution context created during the code execution.

Does C require a stack?

No, it does not. Let's cover the heap first, that's easy. An implementation that does not provide a heap of any sort just needs to return NULL whenever you try to call malloc (or any other memory allocation function).

Is it possible to execute some code before main function starts executing?

Executing code before main() Bookmark this question. Show activity on this post. In object-oriented languages (C++) you can execute code before main() by using a global object or a class static object and have their constructors run the code you want.

Is code on the stack?

Stack has nothing to do with code. Only local variables and parameters live on the stack.


1 Answers

A valid use case for this kind of thing is an embedded system that is generally running out of FLASH memory, but is required to be able to reprogram itself in the field. To do this, a portion of the code must run from some other memory device (in my case the FLASH device itself could not erase and program one page while allowing reads from any other page, but there are devices that can do that), and there was enough RAM in the system to hold both the flash writer and the new application image to be written.

We wrote the necessary FLASH programming function in C, but used #pragma directives to have it placed in a distinct .text segment from the rest of the code. In linker control file, we had the linker define global symbols for the start and end of that segment, and had it located at a base address in the RAM, while placing the generated code in a load region that was located in the FLASH along with the initialization data for the .data segment and the pure read-only .rodata segment; the base address in the FLASH was computed and defined as a global symbol as well.

At run time, when the application update feature was exercised, we read the new application image into its buffer (and did all the sanity checks that should be done to make sure it actually was an application image for this device). We then copied the update kernel out of its dormant location in FLASH to its linked location in RAM (using the global symbols defined by the linker), then called it just like any other function. We didn't have to do anything special at the call site (not even a function pointer) because as far as the linker was concerned it was located in RAM the whole time. The fact that during normal operation that particular piece of RAM had a very different purpose was not important to the linker.

That said, all of the machinery that made this possible is either outside the scope of the standard, or solidly implementation defined behavior. The standard doesn't care how code gets loaded into memory before it is executed. It just says that the system can execute code.

like image 92
RBerteig Avatar answered Oct 17 '22 08:10

RBerteig