I have been given a line of code that I know works, but I want to understand it better. Here's a snippet:
1 2 3 4 5 6
int addr; // assume addr gets a value (actually an address)
This code is used in a simple bootloader, and passes control of the program pointed to by addr.
I'd like to break this into bite-size pieces perhaps like this:
1 2 3
pApp = (void *) addr + 4;
(I can't test this currently, as I don't have access to the development hardware.) It compiles successfully, but...will it work? I'm particularly interested in whether the pointer arithmetic will be OK with the "+ 4".
This would only work on a platform where a value of type int is capable of holding a value of a pointer to data. I am going to replace your int with uintptr_t because otherwise it won't work on my system. If you don't have uintptr_t, size_t works on many platforms too.
std::cout << "foo\n";
void(*fptr)() = f; // assuming C++, where f(void) and f() are the same
void(**fptrptr)() = &fptr;
std::uintptr_t addr = reinterpret_cast<std::uintptr_t>(fptrptr);
addr -= 4;
(void(*)(void)) // cast to function pointer the following value
*( // obtain the value pointed to by the following pointer
(std::uintptr_t*)( // cast to intptr_t pointer
addr+4 // add 4 to the memory address (a uintptr_t value)
)(); // invoke the function pointer
in short, your addr is the numeric value of a pointer to a pointer to a function, minus 4.
PS: Actually, this line would be more logical if you cast addr+4 to a pointer to pointer to function (since you're going to dereference it and invoke the result as a pointer to function anyway): (*(void(**)(void))(addr+4))(); or, in C++, (*reinterpret_cast<void(**)()>(addr+4))();
I should have mentioned that portability is really a non-issue for this passage of code. It's going onto an ARM device and some of the code I left out is hard-coded values to set up the stack and VTOR for the code that this branches to.
Regarding the "+ 4," I'm pretty sure this is to skip over the first four bytes of the image file (probably contains a checksum or something).
So, while your example is definitely worth studying for my education, I want to keep the code in this bootloader to something I can readily understand. Other than your proviso about int being the correct size for a pointer, can you see any showstoppers in my implementation?