| mzimmers (516) | |||||
|
Hi - I have been given a line of code that I know works, but I want to understand it better. Here's a snippet:
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:
(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". Thanks for any clarification. | |||||
|
|
|||||
| Cubbi (1572) | |||
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.
online demo: http://ideone.com/PwbgfX 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))(); | |||
|
Last edited on
|
|||
| mzimmers (516) | |
|
Hey, Cubbi - 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? Thanks. | |
|
|
|
| Cubbi (1572) | |||
|
As long as the value at addr+4 is indeed the address of an address of a function, there's no problem with this. To make it really easy to understand, I would have written maybe
| |||
|
|
|||
| mzimmers (516) | |||
No, the addr+4 should point to the start of a function. My interpretation of:((void(*)(void))(*((int*)(addr+4))))();Is that it's casting addr+4 to an int pointer, then casting that to a function pointer, and invoking it. No? EDIT: I may have gotten that wrong. Here's the entire code passage:
So maybe it is a pointer to a pointer of sorts. | |||
|
Last edited on
|
|||
| Cubbi (1572) | ||
|
no, it's cast, dereference, cast, function call. Edit: right, I should have said the value OF addr+4 is the address of an address of a function. The value AT addr+4 is indeed the address of a function.
| ||
|
Last edited on
|
||
| mzimmers (516) | |
|
Right...so how is that not a pointer to a function? 1. addr is cast to a pointer 2. addr is then dereferenced 3. what addr points to then becomes cast to a pointer to a void function 4. that pointer is then called So, how is the value addr not simply an address to be branched to? | |
|
|
|
| Cubbi (1572) | |
| the value *(addr+4) is the address to be branched to. The value addr+4 is the address of that address. | |
|
|
|
| mzimmers (516) | |
|
OK, then, I must not understand how the VTOR works. (No big surprise there.) I'll review it tomorrow and make my change accordingly. Thanks for the help. | |
|
|
|