在上一篇中介绍了field_ids的解析,那么接下来就要学习method_ids的解析。
1. method_ids结构在android的aosp源码中,method_ids的结构如下:
aosp源码位置:art/libdexfile/dex/dex_file.h
// Raw method_id_item.
struct MethodId {
dex::TypeIndex class_idx_; // index into type_ids_ array for defining class
uint16_t proto_idx_; // index into proto_ids_ array for method prototype
dex::StringIndex name_idx_; // index into string_ids_ array for method name
private:
DISALLOW_COPY_AND_ASSIGN(MethodId);
};
StringIndex
class StringIndex {
public:
uint32_t index_;
....
....
};
TypeIndex
class TypeIndex {
public:
uint16_t index_;
....
....
};
从method的结构可以看出以下几点:
- dex::TypeIndex class_idx_: 无符号int类型,占2个字节。类型索引列表的索引/下标,表示的是方法所在的类
- uint16_t proto_idx_:无符号int类型,占2个字节。原型索引列表的索引/下标,表示的是方法的原型(签名)
- dex::StringIndex name_idx_:无符号int类型,占4个字节。字符串索引列表的索引/下标,表示的是方法的名称
private static ListtoParseDexMethodIds(RandomAccessFile raf) { try { List methodIdList = new ArrayList<>(); //获取到方法索引列表的文件偏移量 int method_ids_off = mDexHeader.getMethod_ids_off(); //获取到方法索引列表的大小 int method_ids_size = mDexHeader.getMethod_ids_size(); //偏移到方法索引列表位置 raf.seek(method_ids_off); for (int i = 0; i < method_ids_size; i++) { //获取 这个字段所在的类的类名,类名idx在类型索引列表中 int class_idx = NumConversion.byteToInt(readData(raf, 2), false); //获取 这个字段的原型(方法签名),原型idx在原型索引列表中 int proto_idx = NumConversion.byteToInt(readData(raf,2),false); //获取 这个字段的方法名称,方法名称idx在字符串索引列表中 int name_idx = NumConversion.byteToInt(readData(raf,4),false); //打印数据 //获取方法名称 StringId name_string_id = mStringIds.get(name_idx); String name_string = new String(name_string_id.getData()); //获取类 TypeId class_type_id = mTypeIds.get(class_idx); StringId class_type_string_id = mStringIds.get(class_type_id.getTypeDescriptorIdx()); String class_type_string = new String(class_type_string_id.getData()); //获取返回值类型 ProtoId proto_id = mProtyIds.get(proto_idx); TypeId return_type_id = mTypeIds.get(proto_id.getReturnIdx()); StringId return_type_string_id = mStringIds.get(return_type_id.getTypeDescriptorIdx()); String return_type_string = new String(return_type_string_id.getData()); //获取方法参数列表 StringBuilder sb = new StringBuilder("("); for (int j=0;j int parame_idx = proto_id.getParameterIdxs()[j]; TypeId parame_type_id = mTypeIds.get(parame_idx); StringId parame_string_id = mStringIds.get(parame_type_id.getTypeDescriptorIdx()); sb.append(new String(parame_string_id.getData())); if (j == proto_id.getParameter_size()-1) { sb.append(")"); }else if (proto_id.getParameter_size() != 1) { sb.append(", "); } } if (proto_id.getParameter_size() == 0) sb.append(")"); //创建实体类 MethodId methodId = new MethodId(); methodId.setClass_idx(class_idx); methodId.setProto_idx(proto_idx); methodId.setName_idx(name_idx); methodIdList.add(methodId); System.out.println(i+" 在 " + class_type_string + "类中, 方法:" +return_type_string+" "+name_string+sb.toString()); } return methodIdList; }catch (Exception e) { e.printStackTrace(); } return null; } public static byte[] readData(RandomAccessFile raf,int limit) { byte[] buff = new byte[limit]; try { raf.read(buff); } catch (IOException e) { e.printStackTrace(); } return buff; }
实体类MethodId
public class MethodId {
private int class_idx;
private int proto_idx;
private int name_idx;
public int getClass_idx() {
return class_idx;
}
public void setClass_idx(int class_idx) {
this.class_idx = class_idx;
}
public int getProto_idx() {
return proto_idx;
}
public void setProto_idx(int proto_idx) {
this.proto_idx = proto_idx;
}
public int getName_idx() {
return name_idx;
}
public void setName_idx(int name_idx) {
this.name_idx = name_idx;
}
}
工具类NumConversion
public class NumConversion {
public static int byteToInt(byte[] bytes,boolean isBigEndian) {
if (bytes.length <=0 || bytes.length > 4) return -1;
int result = 0;
for (int i=0;i
int b ;
if(isBigEndian){
b = (bytes[i] & 0xFF) << (8*(bytes.length-1-i));
}else {
b = (bytes[i] & 0xFF) << (8*i);
}
result = result | b;
}
return result;
}
}
asjhan for Android reverse



