博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GDB中打印ART基础类
阅读量:6957 次
发布时间:2019-06-27

本文共 9669 字,大约阅读时间需要 32 分钟。

【art::mirror::String】

(gdb) p /x  *('art::mirror::String' *)0x71237d00$89 = {  ...  count_ = 0x11,   hash_code_ = 0x6c3617af,   value_ = 0x71237d10,   ...}

其中count_是字符串长度,value_是字符串buffer,buffeer里的内容是Unicode字符串:

(gdb) x /17hc 0x71237d100x71237d10:	97 'a'	110 'n'	100 'd'	114 'r'	111 'o'	105 'i'	100 'd'	46 '.'0x71237d20:	118 'v'	105 'i'	101 'e'	119 'w'	46 '.'	86 'V'	105 'i'	101 'e'0x71237d30:	119 'w'

因此,这个String类对象是"android.view.View"

对应脚本及用法如下:

define art_print_string  set $local_string = ('art::mirror::String' *) $arg0  set $string_length  = (int) $local_string->count_  set $declaringstr = (char*)($local_string->value_)  set $logcal_index = (int) 0  set $string_length = (int) 2*$string_length  while $logcal_index < $string_length    printf "%c", *($declaringstr + $logcal_index)    set $logcal_index = $logcal_index + 2  endend(gdb) art_print_string 0x71237d00android.view.View

 

【art::mirror::Class】

(gdb) p /x  *('art::mirror::Class' *)0x70eac5e0$90 = {  ...  dex_cache_ = {    
> = { reference_ = 0x70dac310 },
}, ... name_ = {
> = { reference_ = 0x71237d00 },
}, ... dex_type_idx_ = 0x61f, ... }}

这里分两种,如果类被Resolve过,则就可以直接通过art::mirror::String类的name_字段获取类名

否则就得从dex_file_中读取,而dex_file_的地址保存在dex_cache_中:

(gdb) p /x *('art::mirror::DexCache' *)0x70dac310$97 = {  ...  dex_file_ = 0x7f9ba7b780,   resolved_fields_ = 0x71a80078,   resolved_methods_ = 0x719c8b78,   ...}

 

dex_file_的结构如下:

(gdb) p /x  *('art::DexFile' *)0x7f9ba7b280$98 = {  begin_ = 0x72ffa3cc,   size_ = 0x7fdf88,   ...  header_ = 0x72ffa3cc,   string_ids_ = 0x72ffa43c,   type_ids_ = 0x73046ab4,   field_ids_ = 0x7306afe0,   method_ids_ = 0x730b24c8,   proto_ids_ = 0x7304c7a0,   class_defs_ = 0x7311d350,   oat_dex_file_ = 0x7f9ba2f200,   ...}

根据dex_file_中的type_ids_指针和class中的dex_type_idx_,找到该类的TypeId

(gdb) p /x *(('art::DexFile::TypeId' *)0x73046ab4+0x61f)$101 = {  descriptor_idx_ = 0x3741}

这个descriptor_idx_就是类名字符串的StringId在string_ids_中的偏移:

(gdb) p *(('art::DexFile::StringId' *)0x72ffa43c+0x3741)$102 = {  string_data_off_ = 0x52f79d}

最终得到的string_data_off_就是类名字符串真正存放的地址:dex_file_(base = 0x73ffa3cc)中的相对偏移。

因此,最终的字符串的地址是:

(gdb) p /x 0x72ffa3cc+0x52f79d$103 = 0x73529b69

这个地址存放的是Leb128类型的字符串,对于长度小于128的字符串,它的长度放在buffer的第一个位置,后面存放的就是字符串的ASCII码:

(gdb) x /b 0x73529b690x73529b69:	0x13 (gdb) x /s 0x73529b69+10x73529b6a:	"Landroid/view/View;"

对应脚本及用法如下:

define art_print_class  set $myclass = ('art::mirror::Class' *)$arg0  set $classstring = ('art::mirror::String' *)($myclass->name_.reference_)  if $classstring != 0    art_print_string $classstring  else    set $dexfile = ('art::DexFile' *) (('art::mirror::DexCache' *)$myclass->dex_cache_.reference_)->dex_file_    set $dextypeidx = (int) $myclass->dex_type_idx_    set $descriptoridx = (int) ($dexfile->type_ids_ + $dextypeidx)->descriptor_idx_    set $classnameptr = (char*) ($dexfile->string_ids_[$descriptoridx].string_data_off_ + $dexfile->begin_ + 1)    art_print_cstring $classnameptr  endenddefine art_print_cstring  set $buffer = (char*)$arg0  if *$buffer == 'L'    set $buffer = $buffer + 1    while *$buffer != ';'      if *$buffer == 0        loop_break      end      if *$buffer == '\/'        printf "."      else        printf "%c", *$buffer      end        set $buffer = $buffer + 1    end  else    printf "%s", $buffer  endend(gdb) art_print_class 0x70eac5e0android.view.View

 

【art::mirror::Object】

(gdb) p /x *('art::mirror::Object' *)0x1354a5e0$114 = {  static kVTableLength = 0xb,   static hash_code_seed = {    
> = {
> = {
> = { __a_ = 0xf2e119b1 },
},
},
}, klass_ = {
> = { reference_ = 0x70eac5e0 },
}, monitor_ = 0x0}

对于Object来说,只需要打印所属类名就可以了。

对应脚本及用法如下:

define art_print_object   set $curclass = ('art::mirror::Class' *)((('art::mirror::Object' *)$arg0)->klass_.reference_)   art_printn_class $curclassend(gdb) art_print_object 0x1354a5e0android.view.View

 

【art::ArtMethod】

(gdb) p /x *('art::ArtMethod' *)0x7144b280$115 = {  declaring_class_ = {    root_ = {      
> = { reference_ = 0x70eac5e0 },
} }, access_flags_ = 0x90001, dex_code_item_offset_ = 0x1d5968, dex_method_index_ = 0x307a, method_index_ = 0xa, hotness_count_ = 0x0, ptr_sized_fields_ = { dex_cache_resolved_methods_ = 0x719c8b7800000000, dex_cache_resolved_types_ = 0x719c2e8800000000, entry_point_from_jni_ = 0x0, entry_point_from_quick_compiled_code_ = 0x75f568b400000000 }}

打印方法名分三部分:

1、方法所属类

2、方法名

3、参数及返回值

 

方法所属类这个可以简单的打印ArtMethod的declaring_class_即可

(gdb) art_print_class 0x70eac5e0android.view.View

可以通过declaring_class_找到DexCache,进而找到DexFile。

通过ArtMethod中的dex_method_index和DexFile中的method_ids_,找到该方法对应的MethodId:

(gdb) p /x  *('art::DexFile' *)0x7f9ba7b280$98 = {  begin_ = 0x72ffa3cc,   size_ = 0x7fdf88,   ...  header_ = 0x72ffa3cc,   string_ids_ = 0x72ffa43c,   type_ids_ = 0x73046ab4,   field_ids_ = 0x7306afe0,   method_ids_ = 0x730b24c8,   proto_ids_ = 0x7304c7a0,   class_defs_ = 0x7311d350,   oat_dex_file_ = 0x7f9ba2f200,   ...}(gdb) p /x *(('art::DexFile::MethodId' *)0x730b24c8+0x307a)$117 = {  class_idx_ = 0x61f,   proto_idx_ = 0x155e,   name_idx_ = 0x9f2}

其中MethodId中的

class_idx_是方法所属类的TypeId的索引值,通过前面的分析可知,0x61f对应的就是android.view.View。

proto_idx_是方法原型的索引,通过这个索引可在DexFile中的proto_ids_中查找该方法对应的原型。

name_idx_是方法名在字符串池中的偏移。

 

先看看方法名:

(gdb) x /8c (('art::DexFile::StringId' *)0x72ffa43c+0x9f2).string_data_off_ + 0x72ffa3cc0x734e212c:	6 '\006'	60 '<'	105 'i'	110 'n'	105 'i'	116 't'	62 '>'	0 '\000'

方法名是长度为6的字符串"<init>",也就是android.view.View类的构造函数。

 

再看看方法的原型:

(gdb) p /x *(('art::DexFile::ProtoId' *)0x7304c7a0+0x155e)$120 = {  shorty_idx_ = 0x764b,   return_type_idx_ = 0x1588,   pad_ = 0x0,   parameters_off_ = 0x4c51b4}

return_type_idx_是方法的返回值在DexFile的TypeId(0x73046ab4)数组里的偏移。

(gdb)  p /x *(('art::DexFile::TypeId' *)0x73046ab4+0x1588)$121 = {  descriptor_idx_ = 0x745a}(gdb) x /8c (('art::DexFile::StringId' *)0x72ffa43c+0x745a).string_data_off_ + 0x72ffa3cc0x735a4fb9:	1 '\001'	86 'V'	0 '\000'	16 '\020'	86 'V'	49 '1'	95 '_'	80 'P'

返回值类型是长度为1的字符串"V"

 

parameters_off_(0x4c51b4)是参数列表距dexfile起始位置(0x72ffa3cc)的的偏移:

(gdb) p /x * ('art::DexFile::TypeList' *)(0x72ffa3cc+0x4c51b4)$122 = {  size_ = 0x3,   list_ = {
{ type_idx_ = 0x9b }}}

该函数有3个参数,每个参数的在TypeId中的偏移为:

(gdb) p /x  (('art::DexFile::TypeList' *)(0x72ffa3cc+0x4c51b4))->list_[0]$124 = {  type_idx_ = 0x9b}(gdb) p /x  (('art::DexFile::TypeList' *)(0x72ffa3cc+0x4c51b4))->list_[1]$125 = {  type_idx_ = 0x48a}(gdb) p /x  (('art::DexFile::TypeList' *)(0x72ffa3cc+0x4c51b4))->list_[2]$126 = {  type_idx_ = 0x4}

三个参数descriptor_idx_及字符串为:

(gdb)  p /x (('art::DexFile::TypeId' *)0x73046ab4+0x9b).descriptor_idx_$130 = 0x3149(gdb)  p /x (('art::DexFile::TypeId' *)0x73046ab4+0x48a).descriptor_idx_$131 = 0x356d(gdb)  p /x (('art::DexFile::TypeId' *)0x73046ab4+0x4).descriptor_idx_$132 = 0x27cc(gdb) x /26c (('art::DexFile::StringId' *)0x72ffa43c+0x3149).string_data_off_ + 0x72ffa3cc0x7351ac73:	25 '\031'	76 'L'	97 'a'	110 'n'	100 'd'	114 'r'	111 'o'	105 'i'0x7351ac7b:	100 'd'	47 '/'	99 'c'	111 'o'	110 'n'	116 't'	101 'e'	110 'n'0x7351ac83:	116 't'	47 '/'	67 'C'	111 'o'	110 'n'	116 't'	101 'e'	120 'x'0x7351ac8b:	116 't'	59 ';'(gdb)  x /28c (('art::DexFile::StringId' *)0x72ffa43c+0x356d).string_data_off_ + 0x72ffa3cc0x735253f4:	27 '\033'	76 'L'	97 'a'	110 'n'	100 'd'	114 'r'	111 'o'	105 'i'0x735253fc:	100 'd'	47 '/'	117 'u'	116 't'	105 'i'	108 'l'	47 '/'	65 'A'0x73525404:	116 't'	116 't'	114 'r'	105 'i'	98 'b'	117 'u'	116 't'	101 'e'0x7352540c:	83 'S'	101 'e'	116 't'	59 ';'(gdb) x /2c (('art::DexFile::StringId' *)0x72ffa43c+0x27cc).string_data_off_ + 0x72ffa3cc0x7350ed6e:	1 '\001'	73 'I'

 

分别是

长度为25的"Landroid/context/Context;"

长度为27的"Landroid/util/AttributeSet;"

长度为1的"I"

 

将上诉内容用脚本实现:

define art_get_method_name_by_method_id  set $methodid = ('art::ArtMethod' *)$arg0  set $declaringclass = ('art::mirror::Class' *) $methodid->declaring_class_.root_.reference_  set $dexfile = ('art::DexFile' *) (('art::mirror::DexCache' *) $declaringclass->dex_cache_.reference_)->dex_file_  art_print_class $declaringclass  set $methodidx = (int) $methodid->dex_method_index_  set $methodnameidx = (int) $dexfile->method_ids_[$methodidx]->name_idx_  set $methodstr = (char*) ($dexfile->string_ids_[$methodnameidx].string_data_off_ + $dexfile->begin_ + 1)  printf ".%s ", $methodstr  set $protoid = ('art::DexFile::ProtoId' *)$dexfile->proto_ids_ + $dexfile->method_ids_[$methodidx]->proto_idx_  printf "\"("  if $protoid->parameters_off_ != 0    set $typelist = ('art::DexFile::TypeList' *)($dexfile->begin_ + $protoid->parameters_off_)    set $typelistsize = (int)$typelist->size_    set $typelistitems = (unsigned short *) ($typelist->list_)    set $logcal_index = (int) 0    while $logcal_index < $typelistsize      set $descriptoridx = (int) ($dexfile->type_ids_ + *($typelistitems +$logcal_index))->descriptor_idx_      set $paramstr = (char*) ($dexfile->string_ids_[$descriptoridx].string_data_off_ + $dexfile->begin_ + 1)      printf "%s", $paramstr      set $logcal_index = $logcal_index + 1    end  end  printf ")"  set $descriptoridx = (int) ($dexfile->type_ids_ + $protoid->return_type_idx_)->descriptor_idx_  set $returnstr = (char*) ($dexfile->string_ids_[$descriptoridx].string_data_off_ + $dexfile->begin_ + 1)  printf "%s\"\n", $returnstrend

用法如下:

(gdb) art_get_method_name_by_method_id 0x7144b280android.view.View.
"(Landroid/content/Context;Landroid/util/AttributeSet;I)V"

 

转载于:https://www.cnblogs.com/YYPapa/p/6858787.html

你可能感兴趣的文章
模拟返回的后台数据实现统计图
查看>>
《Linux命令行与shell脚本编程大全》第二十六章 一些有意思的脚本
查看>>
设置文字旋转角度
查看>>
Spring_DI_XML_02
查看>>
uCos-III移植到STM32F10x
查看>>
openssl编译使用
查看>>
不学无数——SpringBoot入门V
查看>>
Android Pie 引入 Keystore 新特性,安全防护再升级
查看>>
前端性能优化之 Composite
查看>>
一文看懂混淆代码——Java Decompiled过程和代码阅读
查看>>
React 16.8.6 发布,构建用户界面的 JavaScript 库
查看>>
Behavior-2
查看>>
TypeScript 发布 3.4 首个 RC 预览版
查看>>
ES6(Symbol)
查看>>
华丽转身再获新生?体验大陆集团深耕自动驾驶生态圈的最新技术与产品
查看>>
代码查看神器--Editplus
查看>>
Prometheus vs. Graphite:时序数据监控工具选择
查看>>
Flask入门的第一个项目
查看>>
MikroTik RouterOS旧版本下载地址收集
查看>>
嵌入式软件开发工程师谈软件架构的设计
查看>>