- 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/
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 5 年前。 Improve
在 C# 静态方法中是否有一种方法可以引用定义该方法的类型? 在实例方法中,您可以通过以下方式确定类型: public void Foo() { Type type = this.GetTyp
WPF:静态、动态资源以及资源词典 静态资源与动态资源 我们常常会使用样式或者控件模板放在Window.Resources中,比如这样: 静态资源与动态资源使用如下: <Window
任何人都知道如何在共享/静态函数中动态加载控件?该函数本身位于 mustinherit/abstract 类中。 (这是 VB 中的 ASP.NET 项目)我想做这样的事情: VB: Publ
在我看来,静态/强类型编程语言最宝贵的一点是它有助于重构:如果/当您更改任何 API,那么编译器会告诉您该更改破坏了什么。 我可以想象用运行时/弱类型语言编写代码......但我无法想象没有编译器的帮
正如我的名字所暗示的,我是一名 .NET 开发人员,但我对 Java 的兴趣越来越大,并且我有兴趣学习更多其他语言,因为这有助于我学习更多关于编程的知识。 无论如何,我的问题是:不带参数/不使用状态的
我在java中使用WireMock来 stub POST请求。该请求返回一个存储在我本地的 json 正文文件。 stub 看起来像这样: wireMockServer.stubFor(get(url
Python 是否有类构造函数的机制,即每当首次引用类时(而不是创建该对象的实例时)调用的函数?我知道其他一些语言中也存在这种情况,但我还没有在 Python 中遇到过。 基本上,我想初始化该函数中的
Python 是否有类构造函数的机制,即每当首次引用类时(而不是创建该对象的实例时)调用的函数?我知道其他一些语言中也存在这种情况,但我还没有在 Python 中遇到过。 基本上,我想初始化该函数中的
这个问题已经有答案了: What is the difference between dynamic and static polymorphism in Java? (14 个回答) 已关闭 4 年
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: Static initializer in Java 我想知道这个静态的东西(抱歉,这是我第一次遇到这个)对一个类有
如果c++应用程序是按以下方式组织的 //file1.cpp static Y sgObj = X::getInitObject(0); //declared in file scope //fil
我有一个抽象类(AvergedDataRecord),我需要进一步抽象(DataRecord),这样我就可以将它扩展到原始类和一个新的具体类(SummedDataRecord),并且我在获取某些方法时
我正在尝试制作一个字符串枚举。这是我到目前为止所得到的, private class TypedEnum : IEnumerable { public IEnumerator GetEnume
我选修了一门名为“安全代码”的类(class),在下一个作业中,我们应该对一些 C 文件和 JavaEE Web 项目进行静态/动态分析。 我检查了“源监视器”并在 C 文件上运行它,但是(除非我不知
我有两个类,一个是登录类,一个是用户类。在 loggedIn 类中,我想显示我在用户登录时所做的共享首选项。 loginPrefs = getSharedPreferences("loginprefe
我在同一个 Activity 中有两个静态 fragment ,在“fragmentA”中我有一个自定义列表,当一个项目被点击时必须在“fragmentB”中出现一个细节,细节只在我改变屏幕方向时出现
在 Java 中是未修改方法变量,缺少final,每次都重新初始化限定符 静态方法 实例方法 如果 1. 或 2.(或两者)的答案是 final 限定符允许 Java 执行优化并存储方法变量只有一次?
我有两个类相互交互。第一个是中心的,如下: public class Datenbank { double winkelPanel = 0; double groessePanel = 0; doub
我有一个 mysql 数据库,它连接基于 Web 的 php 应用程序和 FoxPro 应用程序(是的,foxpro)。在之前的“开发人员”被解雇后开始处理这个问题。 无论如何,我熟悉 AES_Enc
我是一名优秀的程序员,十分优秀!