为什么 Android dex 文件会有 64K 引用限制 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
StonyGround
V2EX    Android

为什么 Android dex 文件会有 64K 引用限制

  •  
  •   StonyGround 2022-04-25 10:33:39 +08:00 13093 次点击
    这是一个创建于 1333 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天在研究 linux lds 文件的时候,看到一篇博客,如下所写:

    许多脚本是相当的简单的. 可能的最简单的脚本只含有一个命令: 'SECTIONS'. 你可以使用'SECTIONS'来描述输出文件的内存布局. 'SECTIONS'是一个功很强大的命令. 这里这们会描述一个很简单的使用. 让我们假设你的程序只有代码节, 初始化过的数据节, 和未初始化过的数据节. 这些会存在于'.text','.data'和'.bss'节, 另外, 让我们进一 步假设在你的输入文件中只有这些节. 对于这个例子, 我们说代码应当被载入到地址'0x10000'处, 而数据应当从 0x8000000 处开始. 下面是一个实现 这个功能的脚本: SECTIONS { . = 0x10000; .text : { *(.text) } . = 0x8000000; .data : { *(.data) } .bss : { *(.bss) } } 你使用关键字'SECTIONS'写了这个 SECTIONS 命令, 后面跟有一串放在花括号中的符号赋值和输出节描述的内容. 上例中, 在'SECTIONS'命令中的第一行是对一个特殊的符号'.'赋值, 这是一个定位计数器. 如果你没有以其 它的方式指定输出节的地址(其他方式在后面会描述), 那地址值就会被设为定位计数器的现有值. 定位计数器 然后被加上输出节的尺寸. 在'SECTIONS'命令的开始处, 定位计数器拥有值'0'. 第二行定义一个输出节,'.text'. 冒号是语法需要,现在可以被忽略. 节名后面的花括号中,你列出所有应当被 放入到这个输出节中的输入节的名字. '*'是一个通配符,匹配任何文件名. 表达式'*(.text)'意思是所有的输 入文件中的'.text'输入节. 因为当输出节'.text'定义的时候, 定位计数器的值是'0x10000',连接器会把输出文件中的'.text'节的地址设 为'0x10000'. 余下的内容定义了输出文件中的'.data'节和'.bss'节. 连接器会把'.data'输出节放到地址'0x8000000'处. 连接 器放好'.data'输出节之后, 定位计数器的值是'0x8000000'加上'.data'输出节的长度. 得到的结果是连接器会 把'.bss'输出节放到紧接'.data'节后面的位置. 连接器会通过在必要时增加定位计数器的值来保证每一个输出节具有它所需的对齐. 在这个例子中, 为'.text' 和'.data'节指定的地址会满足对齐约束, 但是连接器可能会 需要在'.data'和'.bss'节之间创建一个小的缺口. 就这样,这是一个简单但完整的连接脚本. 

    0x10000 正是 64*1024 ,不禁想到 Android 的 64K 引用限制,好奇为什么都是这个值,还是业界标准如此?

    6 条回复    2022-04-25 19:52:16 +08:00
    o02VFqu3gZnZfX8n
        1
    o02VFqu3gZnZfX8n  
       2022-04-25 11:19:56 +08:00   1
    maokabc
        2
    maokabc  
       2022-04-25 12:16:56 +08:00 via Android
    没这么复杂,就是谷歌设计 dex 格式时没考虑到。.class 索引是 u2 那是别人只是单文件,这么用没问题,它.dex 也跟着这样,然后很快就有问题了。dalivk 字节码很多指令只有 u2 的索引,所以那些常量池只能在 u2 范围内。
    StonyGround
        3
    StonyGround  
    OP
       2022-04-25 16:44:05 +08:00
    @DaVinci42 找到了,https://source.android.com/devices/tech/dalvik/dalvik-bytecode 里面有一段这么写的:
    “在实践中,一个方法需要 16 个以上的寄存器不太常见,而需要 8 个以上的寄存器却相当普遍,因此很多指令仅限于寻址前 16 个寄存器。在合理的可能情况下,指令允许引用最多前 256 个寄存器。此外,某些指令还具有允许更多寄存器的变体,包括可寻址 v0 - v65535 范围内的寄存器的一对 catch-all move 指令。如果指令变体不能用于寻址所需的寄存器,寄存器内容会(在运算前)从原始寄存器移动到低位寄存器和 /或(在运算后)从低位结果寄存器移动到高位寄存器。”
    StonyGround
        4
    StonyGround  
    OP
       2022-04-25 16:45:21 +08:00
    @DaVinci42 所以,大概就是 2 楼说的,只是因为没考虑到?
    StonyGround
        5
    StonyGround  
    OP
       2022-04-25 16:47:29 +08:00
    @maokabc 感谢!是否是像 3 楼写的那样呢
    maokabc
        6
    maokabc  
       2022-04-25 19:52:16 +08:00 via Android
    @StonyGround 和寄存器这个关系不大,比如 const-class vAA, type@BBBB ,type@BBBB 就是索引到类型常量池,这个只在 u2 范围内,如果一个 dex 包含的 class 太多那么类型常量池可能超过 0xffff ,这时就出现了 64k 问题。实际还有更多的指令都是 u2 索引,像 invoke 系列指令的 method ref 也只能在 u2 范围内。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5585 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 48ms UTC 06:31 PVG 14:31 LAX 22:31 JFK 01:31
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86