- Working code for runtime Vtable alteration (MS-Windows, Linux) - 19 Updates
- [Jesus Loves You] Tag for filtering - 6 Updates
Frederick Gotham <cauldwell.thomas@gmail.com>: Jun 11 07:00AM -0700 I started a thread here three days ago about altering the VTable of a class at runtime: https://groups.google.com/forum/#!topic/comp.lang.c++/q_QY4zNnLJ4 That thread has over a hundred posts now going in various directions so I've created this new thread to specifically look at the following sample program. Note that I'm editing the VTable for the class, rather than altering the pointer-to-Vtable which exists inside any given object. First of all, here's a sample program for printing incrementing numbers to the screen: #include <chrono> // milliseconds #include <thread> // this_thread::sleep_for #include <iostream> using std::cout; using std::cin; using std::endl; struct NumberPrinter { long unsigned i; virtual void Print(void) = 0; }; struct DecimalNumberPrinter : NumberPrinter { void Print(void) { cout << std::dec << i++ << endl; } }; struct HexadecimalNumberPrinter : NumberPrinter { void Print(void) { cout << "0x" << std::hex << i++ << endl; } }; auto main(void) -> int { NumberPrinter *p; cout << "Enter 1 for Decimal, or 2 for Hexadecimal: " << std::flush; unsigned choice; cin >> choice; if ( 2 == choice ) p = new HexadecimalNumberPrinter; else p = new DecimalNumberPrinter;https://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible p->i = 0; for ( ; /* ever */ ; ) { p->Print(); std::this_thread::sleep_for(std::chrono::milliseconds(100u)); } } And so next I want to add code to the loop in 'main' to simulate the firing of an interrupt (which then synchronously calls the function Interrupt_Routine and then hands control back to main). The following code compiles and runs properly on Linux using the GNU compiler, and also on MS-Windows using the Visual C++ compiler. I _do_ have an understanding of how different compilers handle pointers to methods, as explained here: https://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible However I _don't_ fully understand how and why I was able to get the code to work for MS-Visual (for instance I don't know why it worked when I added the magic number 88 to the address). So if anyone can look further into this with me and help me understand then I'd greatly appreciate it! On the website, "rextester.com", this code works properly for GNU and VC++. It fails for 'clang' because the two method pointers are equal in value (I got this same behaviour on VC++ and had to work around it as you can see). When you run this program, if you select (1) for decimal, then it should print 5 numbers in decimal format, the it will switch to hexadecimal for the next 5, and then switch back to decimal. It will keep alternating like that for every 5 iterations. extern bool Check_For_Interrupt(void); // Defined below main extern void Interrupt_Routine(void); // Defined below main #include <chrono> // milliseconds #include <thread> // this_thread::sleep_for #include <iostream> using std::cout; using std::cin; using std::endl; struct NumberPrinter { long unsigned i; virtual void Print(void) = 0; }; struct DecimalNumberPrinter : NumberPrinter { void Print(void) { cout << std::dec << i++ << endl; } }; struct HexadecimalNumberPrinter : NumberPrinter { void Print(void) { cout << "0x" << std::hex << i++ << endl; } }; auto main(void) -> int { NumberPrinter *p; cout << "Enter 1 for Decimal, or 2 for Hexadecimal: " << std::flush; unsigned choice; cin >> choice; if ( 2 == choice ) p = new HexadecimalNumberPrinter; else p = new DecimalNumberPrinter; p->i = 0; for ( ; /* ever */ ; ) { p->Print(); std::this_thread::sleep_for(std::chrono::milliseconds(100u)); if ( Check_For_Interrupt() ) Interrupt_Routine(); } } bool Check_For_Interrupt(void) { // Interrupt after every 5 iterations static unsigned i = 0u; if ( i++ > 3u ) { i = 0u; return true; } return false; } struct VTable { void (*funcptr[1u])(void); }; #include <cstdint> // uintptr_t, uint32_t, uint64_t #ifdef _WIN32 extern "C" int VirtualProtect( uint64_t lpAddress, uint64_t dwSize, uint32_t flNewProtect, uint32_t *lpflOldProtect ); struct SYSTEM_INFO { char stuff[4]; uint32_t dwPageSize; char more_stuff[128]; }; extern "C" void GetSystemInfo( uint64_t lpSystemInfo ); #else extern "C" uint32_t sysconf(int32_t name); extern "C" int32_t mprotect(uint64_t addr, uint64_t len, int32_t prot);
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment