- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我现在有一个第三方提供的c静态库(用arm-gcc编译的)。我不可能(让第三方)重新编译库。
在调查库内容时,我发现 gcc 选项 -ffunction-sections 和 -fdata-sections 没有用于编译库。但这对于减少项目的二进制大小非常有帮助。
编译完成:(ARM 嵌入式处理器的 GNU 工具)4.8.4 20140526(发布)[ARM/embedded-4_8-branch 修订版 211358]。
有没有什么方法可以将每个数据和每个函数放到它们自己单独的部分中,以便为该库启用函数级链接,而无需重新编译代码?
我想到了这种可能的做法:
这行得通吗,或者您有其他建议,最好只使用 arm-gcc 提供的工具吗?
最佳答案
我知道这已经过时了,但我也遇到了这个问题,我想我会提供我的发现。
TL;DR:这是可能的,但非常困难。您不能简单地将符号移动到它们自己的部分中。搬迁会给您带来麻烦。
当编译器生成机器代码时,如果提供或不提供 -ffunction-sections
和 -fdata-sections
标志,它将生成略有不同的指令。这是由于编译器能够做出符号所在位置的假设。这些假设会根据提供的标志而变化。
这最好用例子来说明。采用以下非常简单的代码片段:
int a, b;
int getAPlusB()
{
return a + b;
}
下面是arm-none-eabi-objdump -xdr test.o
的结果:
arm-none-eabi-gcc -c -Os -mthumb -mcpu=cortexm3 -mlittle-endian -o test.o test.c
:
SYMBOL TABLE:
00000000 g F .text 0000000c getAPlusB
00000004 g O .bss 00000004 b
00000000 g O .bss 00000004 a
Disassembly of section .text:
00000024 <getAPlusB>:
24: 4b01 ldr r3, [pc, #4] ; (2c <getAPlusB+0x8>)
26: cb09 ldmia r3, {r0, r3}
28: 4418 add r0, r3
2a: 4770 bx lr
2c: 00000000 .word 0x00000000
2c: R_ARM_ABS32 .bss
arm-none-eabi-gcc -c -Os -ffunction-sections -fdata-sections\
:
-mthumb -mcpu=cortexm3 -mlittle-endian -o test.o test.c
SYMBOL TABLE:
00000000 g F .text.getAPlusB 00000014 getAPlusB
00000000 g O .bss.b 00000004 b
00000000 g O .bss.a 00000004 a
Disassembly of section .text.getAPlusB:
00000000 <getAPlusB>:
0: 4b02 ldr r3, [pc, #8] ; (c <getAPlusB+0xc>)
2: 6818 ldr r0, [r3, #0]
4: 4b02 ldr r3, [pc, #8] ; (10 <getAPlusB+0x10>)
6: 681b ldr r3, [r3, #0]
8: 4418 add r0, r3
a: 4770 bx lr
...
c: R_ARM_ABS32 .bss.a
10: R_ARM_ABS32 .bss.b
区别很微妙,但很重要。启用标志的代码执行两个单独的加载,而禁用的代码执行单个“多次加载”。启用的代码执行此操作是因为它知道这两个符号都包含在同一部分中,并按特定顺序排列。使用启用的代码,情况并非如此。这些符号位于两个不同的部分,虽然它们很可能会保持顺序和接近度,但不能保证。更重要的是,如果两个部分都未被引用,链接器可能会决定一个部分未被使用,并将其删除。
另一个例子:
int a, b;
int getB()
{
return b;
}
以及生成的代码。首先没有标志:
SYMBOL TABLE:
00000000 g F .text 0000000c getB
00000004 g O .bss 00000004 b
00000000 g O .bss 00000004 a
Disassembly of section .text:
00000018 <getB>:
18: 4b01 ldr r3, [pc, #4] ; (20 <getB+0x8>)
1a: 6858 ldr r0, [r3, #4]
1c: 4770 bx lr
1e: bf00 nop
20: 00000000 .word 0x00000000
20: R_ARM_ABS32 .bss
还有旗帜:
SYMBOL TABLE:
00000000 g F .text.getB 00000014 getB
00000000 g O .bss.b 00000004 b
00000000 g O .bss.a 00000004 a
Disassembly of section .text.getB:
00000000 <getB>:
0: 4b01 ldr r3, [pc, #4] ; (8 <getB+0x8>)
2: 6818 ldr r0, [r3, #0]
4: 4770 bx lr
6: bf00 nop
8: 00000000 .word 0x00000000
8: R_ARM_ABS32 .bss.b
在这种情况下,差异更加微妙。启用的代码加载偏移量为 0,而禁用的代码使用 4。由于禁用的代码引用该部分的开头,因此它需要偏移到 b
的位置。然而,启用的代码引用仅包含 b
的部分,因此不需要偏移量。如果我们将其拆分并仅更改重定位,则新代码将包含对 a
所在部分的引用,但不包含 b
。这同样会导致链接器对错误的部分进行垃圾回收。
这只是我在查看此问题时遇到的两种情况,可能还有更多。
生成功能上等同于使用 -ffunction-sections
和 -fdata-sections
标志编译的代码的有效目标文件将需要解析机器指令以查找这些和任何其他可能出现的搬迁问题。这不是一项容易完成的任务。
关于c - 第三方C静态库: Add -ffunction-sections -fdata-sections,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31426182/
我正在实现一个显示在对话框中的 FileUploader。相关代码: function onAddExcelData() { var that = this; if(this.fixe
我现在有一个第三方提供的c静态库(用arm-gcc编译的)。我不可能(让第三方)重新编译库。 在调查库内容时,我发现 gcc 选项 -ffunction-sections 和 -fdata-secti
我想在编译时从代码中删除未使用的函数。然后我写一些代码(main.c): #include const char *get1(); int main() { puts( get1() );
GCC 页面中针对功能部分和数据部分选项的以下内容: -ffunction-sections -fdata-sections Place each function or data item into
我想知道为什么 GCC 编译器标志 -ffunction-sections 和链接器标志 --gc-sections 没有消除不必要的响应。我的最终可执行文件中未引用的符号/函数代码。为什么它没有按预
我是一名优秀的程序员,十分优秀!