本文为看雪论坛优秀文章
看雪论坛作者ID:唱过阡陌
单继承
测试源码:
#define MAIN __attribute__((constructor))
#define NOINLINE __attribute__((__noinline__))
class BaseClass{
public:
int a,b;
BaseClass(int mA=1,int mB=2,int mC=3,int mD=4){
this->a = mA;
this->b = mB;
this->c = mC;
this->d = mD;
}
private:
int c;
protected:
int d;
};
class ChildClass: public BaseClass{
public:
int m,n;
ChildClass(int mM=5,int mN=6){
this->m = mM;
this->n = mN;
}
};
MAIN
void test0(){
auto* baseClass = new BaseClass();
LOGD("baseClass : %p sizeof: %d ",baseClass,sizeof(*baseClass));
auto* child1 = new ChildClass(10,20);
LOGD("child1 : %p sizeof: %d", child1, sizeof(*child1));
}
// 新增一个BaseNewClass,让ChildClass:BaseClass继承这两个Class
class BaseNewClass{
public:
int p,q;
BaseNewClass(int mP=10,int mQ=11){
this->p = mP;
this->q = mQ;
}
};
class ChildClass:BaseClass,BaseNewClass{
public:
int m,n;
ChildClass(int mM=5,int mN=6){
this->m = mM;
this->n = mN;
}
};
// LOG()日志
D/ZZZ: baseClass : 0xf216dd70 sizeof: 16
D/ZZZ: childClass : 0xea17e280 sizeof: 32
// 内存情况
[Pixel XL::XXX]-> seeHexA(0xea17e280,32)
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
ea17e280 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................
ea17e290 0a 00 00 00 0b 00 00 00 05 00 00 00 06 00 00 00 ................
// 测试源码
class BaseClass{
public:
int a,b;
BaseClass(int mA=1,int mB=2,int mC=3,int mD=4){
this->a = mA;
this->b = mB;
this->c = mC;
this->d = mD;
}
virtual void showLOG(){
LOGD("Called BaseClass showLOG");
}
virtual void showLOG1(){
LOGD("Called BaseClass showLOG1");
}
private:
int c;
protected:
int d;
};
class ChildClass:BaseClass{
public:
int m,n;
ChildClass(int mM=5,int mN=6){
this->m = mM;
this->n = mN;
}
virtual void showLOG(){
LOGD("Called ChildClass showLOG");
}
virtual void showLOG1(){
LOGD("Called ChildClass showLOG1");
}
virtual void showLOG2(){
LOGD("Called ChildClass showLOG2");
}
};
MAIN
void test0(){
auto* baseClass = new BaseClass();
LOGD("baseClass : %p sizeof: %d",baseClass,sizeof(*baseClass));
auto* childClass = new ChildClass();
LOGD("childClass : %p sizeof: %d",childClass,sizeof(*childClass));
}
// 日志
D/ZZZ: baseClass : 0xe75a7648 sizeof: 20
D/ZZZ: childClass : 0xe75d8d00 sizeof: 28
// 内存情况
[Pixel XL::XXX]-> seeHexA(0xe75a7648,20)
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
e75a7648 24 59 5f d2 01 00 00 00 02 00 00 00 03 00 00 00 $Y_.............
e75a7658 04 00 00 00 ....
[Pixel XL::XXX]-> seeHexA(0xe75d8d00,28)
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
e75d8d00 3c 59 5f d2 01 00 00 00 02 00 00 00 03 00 00 00 <Y_.............
e75d8d10 04 00 00 00 05 00 00 00 06 00 00 00 ............
//读取vptr指向的位置
[Pixel XL::XXX]-> seeHexA(ptr(0xe75a7648).readPointer(),0x20)
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
d25f5924 b1 fa 5a d2 c9 fa 5a d2 d4 60 5f d2 39 29 5f d2 ..Z...Z..`_.9)_.
d25f5934 00 00 00 00 48 59 5f d2 e1 fa 5a d2 f9 fa 5a d2 ....HY_...Z...Z.
[Pixel XL::XXX]-> Module.findBaseAddress("libdynamic.so")
"0xd2593000"
[Pixel XL::XXX]-> ptr(0xd25f5924).readPointer().sub(0xd2593000)
"0x1cab1"
[Pixel XL::XXX]-> ptr(0xd25f5928).readPointer().sub(0xd2593000)
"0x1cac9"
[Pixel XL::XXX]-> ptr(0xd25f592c).readPointer().sub(0xd2593000)
"0x630d4"
[Pixel XL::XXX]-> ptr(0xd25f5930).readPointer().sub(0xd2593000)
"0x5f939"
//
[Pixel XL::XXX]-> seeHexA(ptr(0xe75d8d00).readPointer(),0x20)
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
d25f593c e1 fa 5a d2 f9 fa 5a d2 11 fb 5a d2 30 61 5f d2 ..Z...Z...Z.0a_.
d25f594c 44 29 5f d2 00 00 00 00 01 00 00 00 2c 59 5f d2 D)_.........,Y_.
[Pixel XL::XXX]-> ptr(0xd25f593c).readPointer().sub(0xd2593000)
"0x1cae1"
[Pixel XL::XXX]-> ptr(0xd25f5940).readPointer().sub(0xd2593000)
"0x1caf9"
[Pixel XL::XXX]-> ptr(0xd25f5944).readPointer().sub(0xd2593000)
"0x1cb11"
[Pixel XL::XXX]-> ptr(0xd25f5948).readPointer().sub(0xd2593000)
"0x63130"
[Pixel XL::XXX]-> ptr(0xd25f594c).readPointer().sub(0xd2593000)
"0x5f944"
NOINLINE
void test1(ChildClass* cls){
cls->showLOG();
}
NOINLINE
void test2(ChildClass &cls){
cls.showLOG();
}
NOINLINE
void test3(ChildClass cls){
cls.showLOG1();
}
NOINLINE
ChildClass test4(ChildClass cls){
return cls;
}
MAIN
void test0(){
auto* baseClass = new BaseClass();
LOGD("baseClass : %p sizeof: %d typeid: %s",baseClass,sizeof(*baseClass),typeid(baseClass).name());
auto* child1 = new ChildClass(10,20);
LOGD("child1 : %p sizeof: %d typeid: %d", child1, sizeof(*child1), typeid(child1).hash_code());
auto* child2 = new ChildClass(*child1);
child2->showLOG();
test1(child2);
test2(*child2);
test3(*child2);
test4(*child2);
}
ChildClass(const ChildClass &child){
this->m = child.m;
this->n = 12;
LOGD("called ChildClass拷贝构造函数");
}
BaseClass* baseTmp = dynamic_cast<BaseClass*>(child1);
if (baseTmp!= nullptr){
baseTmp->showLOG1();
}
BaseClass* baseTmp1 = static_cast<BaseClass*>(child1);
if (baseTmp1!= nullptr){
baseTmp1->showLOG1();
}
ChildClass* baseTmp2 = dynamic_cast<ChildClass*>(baseTmp);
if (baseTmp2!= nullptr){
baseTmp2->showLOG1();
}
#define xASM(x) __asm __volatile__ (x)
using namespace std;
class testA{
private:
int tempInt0 = 123;
int tempInt1 = 321;
int tempInt2 = 110;
public:
testA(){
testFunction();
}
NOINLINE
void testFunction(){
[&]()-> void {
LOGD("testA anonymous_0 -> tempInt2:%d",this->tempInt2);
}();
[]()-> void {
xASM("MOV r4, r0":::"r4");
int** tmp = nullptr;
xASM("MOV %0, r4":"=r"(tmp)::);
LOGD("testA anonymous_1 -> tempInt0:%d",**(tmp + 0x1));
}();
[]()-> void {
xASM("MOV r4, r0":::"r4");
int tmp = 0;
xASM("LDR r4, [r4, #0x8]":::"r4");
xASM("LDR r4, [r4, #0x4]":::"r4");
xASM("MOV %0, r4":"=r"(tmp)::"r4");
LOGD("testA anonymous_2 -> tempInt1:%d",tmp);
}();
}
};
0x4*6 = 24(0x18) sp+0x4 sp+0x8 sp+0xc
NOINLINE
void testB(){
auto testNoCatch = [](int s) -> int {
LOGD("testB called lambda function : %d", ++s);
return s;
};
LOGD("testB testNoCatch ---> %p",*testNoCatch);
// using TypeFunc = int(*)(int);
auto testNoCatchNew = *testNoCatch;
testNoCatchNew(5);
testNoCatch(10);
}
类外 lambda 函数,*lambda 都会生产这样的一个跳转逻辑。
类内 lambda 函数不管有没有捕获参数都是直接理解为匿名类重载 () 运算符。
NOINLINE
void testC(){
int a = 10;
int* b = new int(11);
auto c = make_unique<int>(12);
auto* d = new float(13);
auto testNoCatch = [](int s,int t) -> void {
LOGD("testC called lambda function : %d", s+t);
};
auto testCatch = [=,&c,&d](int s) -> void {
LOGD("testC called lambda function : {%d} | {%d,%d,%d,%f}", ++s,a,*b,*c,*d);
};
// LOGD("testC testNoCatch typeid:%s | testCatch typeid:%s",typeid(testNoCatch).name(),typeid(testCatch).name());
LOGD("testC ------ ");
testNoCatch(3,4);
testCatch(2);
// &testCatch 拿到的是他准备好的参数在栈区的首地址
LOGD("testC &testCatch %p", &testCatch);
LOGD("testC &testNoCatch %p", &testNoCatch);
void* funcAddress = nullptr;
auto testCatchNew= [=,&c,&d,&funcAddress](int s) -> void {
// xASM("MOV %0, lr":"=r"(funcAddress)::);
// [&funcAddress]()-> void{
// if (funcAddress == nullptr) xASM("MOV %0, lr":"=r"(funcAddress)::);
// }();
LOGD("testC called lambda function : {%d} | {%d,%d,%d,%f}", ++s,a,*b,*c,*d);
};
testCatchNew(3);
LOGD(" %p ", funcAddress);
free(b);
}
class testClass {
public:
int a = 10;
int b = 11;
int c = 12;
int d = 13;
testClass(){
LOGD("testClass");
}
void callTest() {
LOGD("callTest");
}
};
NOINLINE
testClass getTestClass() {
auto tmp = testClass();
LOGD("getTestClass %p %d",&tmp,tmp.c);
return tmp;
}
void testRetClass() {
testClass tt = getTestClass();
LOGD("testRetClass b -> %d",tt.d);
}
它的上一层是一个 plt 跳转。
使用模板对应生成了多个实现方法。
看雪ID:唱过阡陌
https://bbs.pediy.com/user-home-868525.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!