Skip to content

Instantly share code, notes, and snippets.

@parttimenerd
Created March 19, 2019 14:00
Show Gist options
  • Save parttimenerd/96338488821ede74dae7f445e14e876b to your computer and use it in GitHub Desktop.
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/)
// 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;
}
};
// 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();
}
#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;
}
#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