Task: get and convert function address. The meaning is implied as follows:

We have a function

void func() {}; // ΠΈΠΌΠ΅Π΅ΠΌ адрСс 0x500000, ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ constexpr size_t inc_pointer = to_size_t(&func) + 5; // (*) 

Where to_size_t is a macro / constexpr function that converts the address of the function into a number at the compilation stage. The implementation may be as follows:

 #define to_size_t(x) (size_t)(x) // C-style каст #define to_size_t(x) reinterpret_cast<size_t>(x) // C++-style каст 

Why I did not write the cast immediately be clear below.

The problem is that the construction (*) turns into the following code

 mov eax, 0x500000 // 0x500000 == адрСс Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ func add eax, 5 ... 

I want to ensure that the code is

 mov eax, 0x500005 ... 

Attempt 1

Π‘ast 's did not lead to anything good, the result is higher


Attempt 2

 template <class T> union converter { T _func; size_t _pointer; constexpr converter(T func) : _func(func) {}; }; #define to_size_t(x) converter<decltype(x)>{x}._pointer #define identity(x) converter<decltype(x)>{x}._value 

To check constexpr 'a, I use the following functions:

 template <size_t N> void print_it() { std::cout << N << std::endl; } 

The catch is that constexpr union doesn't want to work the way I need

 print_it<identity(1)>(); // ΠΎΠΊ, компилируСтся (ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ полю _value) print_it<to_size_t(1)>(); // error C2975: 'N': invalid template argument for 'print_it', expected compile-time constant expression 

I will listen to your ideas.


PS And the following code generally crashes the studio (2015)

 template <class T> constexpr T identity_constexpr(T value) { return value; } print<identity_constexpr<1>>(); // fatal error C1001: An internal error has occurred in the compiler. 

UPDATE

The answer has been received, apparently the problem will have to be solved by replacing the constructions in an appropriate way already after compilation in the finished executable file.

  • 2
    I think that the address where the function will be placed is determined by the linker and is not known at the time of compilation. Therefore, the compiler cannot calculate it the way you want it. - KoVadim
  • If not a secret - why ? - Harry
  • in the sense of "why"? - KoVadim
  • @KoVadim if I understood correctly, then the code is first converted to mov eax, offset func , and then the address is substituted? If so, then everything is logical and my task has no solution. - int3
  • Yes, at the compilation stage the addresses are not known. At the linking stage, addresses already exist. - KoVadim

2 answers 2

Every time a program, generally speaking, is loaded into a different place in the memory - how can we talk about the address at the compilation level?

The maximum that can (theoretically!) Be obtained, and then at the layout level, is the relative offset of addresses.

  • Well, that's not true :) You can make a variable with a pointer to a function. Or are we talking about different things? - int3
  • 2
    @ int3 And what will happen in this variable? And when? Try it - get something like EXTRN hren_gde:PROC and mov DWORD PTR _p$[ebp], OFFSET hren_gde . And when will this OFFSET be calculated? When compiling ... - Harry
  • if we talk about physical memory (that is, at the level of microcircuits), then @Harry is certainly right. But at the level of virtual addresses, the linker usually puts the correct addresses. The fact that at the level of compilation of the address is not known does not mean that they are not at the level of linking (layout). - KoVadim
  • at the time of linking, the relative (relative to the address of the binary download) address of the function is determined. when loading a binary into memory, the loader sets up the addresses of the function calls and then they become defined. here we are talking about virtual addresses, but physical addresses in general can change during the program execution. - vasily-vm

Purely for the sake of assumptions: try to stuff the functions in different sections, and here sections set the addresses and size through the linker script. Boundaries can be declared external and constexpr , thereby providing access to the necessary information at the compilation stage. Maybe even get something out.