zhuowei / MCPELauncher

Source code for BlockLauncher, a launcher that patches Minecraft for Android
Apache License 2.0
670 stars 193 forks source link

How to generate header for MCPE? #1482

Open XsJIONG opened 5 years ago

XsJIONG commented 5 years ago

I'm using MC 1.1.0.55, and I cannot find the header files(e.g. Block.h, Item.h) for my version. I downloaded IDA in order to disassembly libminecraftpe.so, but I soon find that it's hard to guess the size of a struct and the meaning of a variable. I wish you to write a complete wiki about the way to generate header files for any version of MCPE! P.S. Since I am a Chinese, there may be some grammar mistakes in my comment.

zedman2000 commented 5 years ago

What are you trying to accomplish. Unless something has changed since the last time I used this, you do not need the headers. Just write the .JS file and continue on haing fun!

XsJIONG commented 5 years ago

To be honest, I'm going to create a MCPE Launcher myself, so it's hard for me to publish this launcher without any API. I really need the header files to create API, but I just can't find the way. As you know, since I was a Chinese, I can't visit Google and some other specific websites, so I can hardly find some document about this. I need some help!

zedman2000 commented 5 years ago

I don't think anyone is going to write a wiki for you. You'll have to figure it out.

XsJIONG commented 5 years ago

OK, I'll try my best to do it.

cntlb commented 5 years ago

You will do a lot of work to build headers for any version of MCPE. 开始说人话!

  1. 熟悉 c语言编写的库中接口和头文件中函数声明的关系.
    
    .text:000026B8 ; void android_main(android_app *state)
    .text:000026B8                 EXPORT android_main
看到这个应该知道这是一个用c编写的接口, 于是需要了解 extern "C"何时使用
2. 熟悉 c++语言编写的库中接口和头文件中函数声明的关系.
.text:00002C3C ; int Util::add(int a, int b)
.text:00002C3C                 EXPORT _ZN4Util3addEii
看到这个应该知道这是一个用c++编写的接口, 根据c++的特性 int add(int, int)属于一个叫做`Util`的类或者namespace
3. 熟悉GNU符号改编机制
  理论上2中的函数我们不能确定返回值(这个返回值是IDA判断出来的, 基本上可以用), 万一返回值是IDA内置库中不支持的呢(比如返回Item结构体),怎么办? 由GNU符号改编机制可以将导出符号(_ZN4Util3addEii)转换为声明:  void Util::add(int, int), 返回值根据实际情况通过反汇编代码判断出来(static? return int? return struct? virtual function? R0=this?)

4. 熟悉函数调用及参数的传递
    对于c来说比较容易, 因为没有面向对象的多态设计需求, 因此在arm汇编上R0-R3分别是前4个参数, 后面的通过函数栈传递. 但如果返回的是结构体, 那么R0便是返回结构地址, 真正的参数是R1-R3! 这个适用于C++. 对于c++比较麻烦, 如果是普通函数汇编后R0是this指针, 如果是静态函数R0是第一个参数或者返回结构地址, 也需要根据汇编代码进行判断.

5. vtable
    面向对象的最大特性恐怕是多态了(mcpe用c++编写的), 为了实现c++多态采用了virtual table技术, 简单来讲
        class Object{virtual void f();}
    会将函数f存储在Object的vtable中动态调用, 只要有virtual函数就会为Object单独创建一个`void** vtable`在其开始的4字节(`sizeof(void**)`), vtable+2之后取值便是每个虚函数的地址了. IDA中形如:

.data.rel.ro:006B29C8 ; `vtable for'Entity .data.rel.ro:006B29C8 _ZTV6Entity DCB 0 ; DATA XREF: Entity::~Entity()+Co .data.rel.ro:006B29C8 ; Entity::Entity(BlockSource &)+24o ... .data.rel.ro:006B29C9 DCB 0 .data.rel.ro:006B29CA DCB 0 .data.rel.ro:006B29CB DCB 0 .data.rel.ro:006B29CC DCB 0 .data.rel.ro:006B29CD DCB 0 .data.rel.ro:006B29CE DCB 0 .data.rel.ro:006B29CF DCB 0 .data.rel.ro:006B29D0 DCD _ZN6EntityD2Ev+1 .data.rel.ro:006B29D4 DCD _ZN6EntityD0Ev+1 .data.rel.ro:006B29D8 DCD _ZN6Entity9_postInitEv+1 .data.rel.ro:006B29DC DCD _ZN6Entity5resetEv+1 .data.rel.ro:006B29E0 DCD _ZN6Entity18getOwnerEntityTypeEv+1 .data.rel.ro:006B29E4 DCD _ZN6Entity6removeEv+1 .data.rel.ro:006B29E8 DCD _ZN6Entity6setPosERK4Vec3+1 .data.rel.ro:006B29EC DCD _ZNK6Entity6getPosEv+1


6. 暂时说这么多吧
   路漫漫其修远兮, 与尔上下而求索. [PocketHeaderBuilder](https://github.com/cntlb/PocketHeaderBuilder.git), [demangler](https://demangler.com/)