Created
March 19, 2019 14:00
-
-
Save parttimenerd/96338488821ede74dae7f445e14e876b to your computer and use it in GitHub Desktop.
Example code for my talk on object layouts in the C++ user group Karlsruhe (https://www.meetup.com/de-DE/C-User-Group-Karlsruhe/events/jphqdmyzgbnb/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// by Andreas Fried | |
#include <cstring> | |
#include <iostream> | |
#include <string> | |
class Animal { | |
protected: | |
const std::string name; | |
public: | |
Animal() : name("") { } | |
Animal(std::string name) : name(name) { } | |
virtual void make_a_noise() = 0; | |
}; | |
class Dog : public Animal { | |
public: | |
Dog() : Animal() { } | |
Dog(std::string name) : Animal(name) { } | |
virtual void make_a_noise() { | |
std::cout << name << ": Wuff!" << std::endl; | |
} | |
}; | |
class Cat : public Animal { | |
public: | |
Cat() : Animal() { } | |
Cat(std::string name) : Animal(name) { } | |
virtual void make_a_noise() { | |
std::cout << name << ": Miau!" << std::endl; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// by Andreas Fried | |
#include "animals.hpp" | |
template <class T> void become(void *obj) { | |
T tmp; | |
memcpy(obj, &tmp, sizeof(void*)); | |
} | |
int main() { | |
Animal *fiffi = new Dog("fiffi"); | |
fiffi->make_a_noise(); | |
become<Cat>(fiffi); | |
fiffi->make_a_noise(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <sys/mman.h> | |
class A { | |
public: | |
int tmp = 111; | |
virtual void print(){ | |
std::cout << "I belong to A" << std::endl; | |
} | |
}; | |
class B : public virtual A { | |
int tmp = 444; | |
}; | |
class NotA { | |
public: | |
virtual void not_print(){ | |
std::cout << "Who's A?" << std::endl; | |
} | |
}; | |
void make_writable(void* ptr){ | |
size_t * aligned_ptr = (size_t *) ((size_t) ptr &~(4096-1)); | |
mprotect(aligned_ptr, 8000, PROT_WRITE|PROT_EXEC|PROT_READ ); | |
} | |
template <typename T> | |
void change_name(T* obj, const std::string &name){ | |
void** vtbl = ((void***)obj)[0]; | |
void** type_info = (void**)vtbl[-1]; | |
make_writable(type_info); | |
char* str = (char*)new std::string(std::move(name)); | |
type_info[0] = (void*)str; | |
} | |
template <typename T1, typename T2> | |
void change_vbase_ptr(T1 *obj, T2 *other){ | |
void** vtbl = ((void***)obj)[0]; | |
size_t * aligned_vtbl = (size_t *) ((size_t) vtbl &~(4096-1)); | |
mprotect(aligned_vtbl, 1024, PROT_WRITE|PROT_EXEC|PROT_READ ); | |
((size_t*)vtbl)[-3] = (size_t)other - (size_t)obj; | |
} | |
void test_print(A *obj){ | |
obj->print(); | |
} | |
int main(){ | |
B *b = new B(); | |
test_print(b); | |
change_vbase_ptr(b, new NotA()); | |
test_print(b); | |
A a; | |
std::cout << typeid(a).name() << std::endl; | |
change_name(&a, "Hello World!"); | |
std::cout << typeid(a).name() << std::endl; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <utility> | |
#include <sys/mman.h> | |
#include <cstring> | |
void make_writable(void* ptr){ | |
size_t * aligned_ptr = (size_t *) ((size_t) ptr &~(4096-1)); | |
mprotect(aligned_ptr, 8000, PROT_WRITE|PROT_EXEC|PROT_READ ); | |
} | |
class A { | |
virtual void blub(){} | |
}; | |
template <typename T> | |
void change_name(T* obj, const std::string &name) { | |
void **vtbl = ((void ***) obj)[0]; | |
void **type_info = (void **) vtbl[-1]; | |
make_writable(type_info); | |
const char *str = (new std::string(name))->c_str(); | |
((char **) type_info)[1] = (char *) str; | |
} | |
int main(){ | |
A a; | |
std::cout << typeid(a).name() << std::endl; | |
change_name(&a, "Hello World!"); | |
std::cout << typeid(a).name() << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment