Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about relocations and static local variables #17

Closed
ddovod opened this issue Jan 12, 2019 · 4 comments
Closed

Question about relocations and static local variables #17

ddovod opened this issue Jan 12, 2019 · 4 comments

Comments

@ddovod
Copy link

ddovod commented Jan 12, 2019

Hi.
Suppose we have this StaticVar.cpp file:

#include <cstdio>

static int localStaticVar = 10;

void printAndIncrement()
{
    printf("%d", localStaticVar++);
}

We're calling printAndIncrement each frame. We want to reload this file for some reason. We're expecting to get this output:

10
11
12
13
CODE RELOAD
14
15
...

On linux we cannot use relocation data from the StaticVar.cpp.o because such a relocations are 32-bit (probably compiler takes into account the "locality" of localStaticVar relative to printAndIncrement), and in general we cannot insert the address of old localStaticVar into the new version of printAndIncrement. How blink deal with such cases?
Thank you!

@suVrik
Copy link
Contributor

suVrik commented Jan 12, 2019

Hello! Take a look at #12

There's code that successfully finds local static variable usages in reloaded object file (it's mentioned in #12), but currently this code changes such usages for incorrect addresses.

@ddovod
Copy link
Author

ddovod commented Jan 12, 2019

Hey! Thank you, I've read that issue, but my question is more about this.
Suppose we have a GetAndIncrement.cpp file:

static int localStaticVariable = 0;

int getAndIncrement()
{
    return localStaticVariable++;
}

If we compile it to the object file, we will have smth like this:
getandincrement
Take a look at mov instruction at 0x08000044. Second operand is the address of the localStaticVariable which will be filled by the linker when relocations (on linux it is R_X86_64_32S) will be applied.
Then we're touching this file, recompiling, linking it into .dll, loading and fixing the address of the localStaticVariable in the .dll in a way where new getAndIncrement function will use old version of localStaticVariable, exactly what you're talking about in #12.
The problem here is second operand of mov instruction is relative 32-bit address of localStaticVariable, but since this variable lives in the executable and getAndIncrement function lives in the .dll, probably the distance between them in the memory will be way more than a 32-bit number.
So the question is - is there any guarantee on windows that second operand of mov instruction in this case is 64-bit address?

@crosire
Copy link
Owner

crosire commented Jan 12, 2019

blink handles this by allocating the memory region for the new object file sections as close as possible to the existing code in memory. This way the relative offset should still fit into a 32-bit value. Windows has APIs to allocate memory at a specific virtual address which allow this:

static uint8_t *find_free_memory_region(uint8_t *address, size_t size)
const auto module_base = static_cast<BYTE *>(VirtualAlloc(find_free_memory_region(_image_base, allocated_module_size), allocated_module_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE));

@ddovod
Copy link
Author

ddovod commented Jan 12, 2019

I see, thank you very much!

@ddovod ddovod closed this as completed Jan 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants