首先要考虑上下文
我目前正在开发一个模块化(嵌入式)微型操作系统,该微型操作系统具有驱动程序,端口,分区和其他表示为结构的对象,并具有不同的“操作”结构,其中包含指向您所称呼其方法的指针。没什么好看的。
我有宏和链接描述文件位,以使给定类型的所有对象(例如,所有驱动程序),尽管它们的定义分散在源文件中,却以数组的形式放置在闪存中,但是一种使链接器(我与GNU GCC / LD一起工作)可以垃圾收集那些未在代码中明确引用的对象的方法。
但是,经过几年的完善和增强了系统的灵活性,我发现对于中小型微控制器来说,它过于贪婪。 (我可能只使用32位体系结构,没有什么太小的。)您可能会说我很值得期待,但是我想走得更远,做得更好,目前,我怀疑LD将允许我这样做。 / p>
我想得到的是代码未使用的方法/函数也被垃圾回收了。当前情况并非如此,因为它们全部由拥有它们的对象的指针结构引用。我想避免使用宏配置开关,而应用程序开发人员则必须经过几层代码才能确定当前使用的功能以及可以安全禁用的功能。我真的非常希望链接程序的垃圾回收使我能够自动完成所有过程。
首先,我想我可以将每个方法的结构划分为各个部分,以便所有端口的“ probe”方法最终都位于名为.struct_probe的部分中,并且包装的port_probe()函数可以引用零-该函数内部的length对象,以便仅当port_probe()函数在某处被调用时,所有端口的探针引用才被链接。
但是我错了,对于链接器来说,“输入节”是他的垃圾回收解决方案(因为到此为止,里面没有更多的对齐信息,因此无法利用符号来-和传入对象-通过对包含部分的内部进行重新排序并缩小来删除),不是仅由部分名称标识,而是由部分名称和标识。因此,如果我实现了我想要的目的,那么我的方法都不会链接到最终的可执行文件中,我会很敬酒。
那是我目前的位置,坦率地说,我很茫然。我想知道也许有人在这里有一个更好的主意,要么让每个方法“向后引用”包装函数,要么让其他对象依次被该函数引用并采用所有方法,或者如标题所述,以某种方式分组这些方法/部分(请不要在一个文件中收集所有代码),以便引用一个方法意味着将它们全部链接起来。
我对所有永恒的感激就在这里。 ;)
答案 0 :(得分:0)
由于我花了一些时间记录和试验以下线索,所以即使没有成功,我也想在这里揭露我发现的内容。
ELF有一个称为“组部分”的功能,该功能用于定义部分组或部分组,例如,如果该组的一个成员部分是活动的(因此已链接),则全部是。
我希望这是我的问题的答案。 TL; DR:并非如此,因为分组节旨在对模块内的节进行分组。实际上,当前定义的唯一组类型是COMDAT组,从定义上讲,它们是与其他模块中定义的具有相同名称的组排斥的。
至少可以说很少有关于该功能及其实现的文档。当前,可以在here上找到该标准对组节的定义。
GCC没有提供一种操作节组的结构(或任何种类的节标志/属性)。 GNU汇编器的文档指定了如何影响到here组的节。
我在任何GNU文档中都没有发现有关LD对组节的处理。不过,其中提到了here和here。
作为奖励,我发现了一种使用GCC在C代码中指定节属性(包括分组)的方法。这是一个肮脏的技巧,因此到您阅读本文时,它可能不再起作用。
显然,当你写
int bar __attribute__((section("<name>")));
GCC会将引号之间的内容盲目地加起来,以便在汇编输出中使用:
.section <name>,"aw"
(如果名称与一些预定义模式之一匹配,则实际标志可能会有所不同。)
从那里开始,全部都是代码注入问题。如果你写
int bar __attribute__((section("<name>,\"awG\",%probbits,<group> //")));
你得到
.section <name>,"awG",%progbits,<group> //"aw"
,工作完成。如果您想知道为什么仅在单独的内联汇编语句中对部分进行特征描述还不够,如果这样做,您会得到一个空的分组部分和一个填充的具有相同名称的单独部分,这在链接时不会起作用。所以。
答案 1 :(得分:0)
这并不是令人满意的,但是由于缺少更好的方法,这就是我追求的目标:
从链接器的角度来看,似乎必须有效地合并多个编译单元中的节的唯一方法是,首先将结果对象链接到一个大对象中,然后使用该大对象而不是小对象链接最终程序。那些。在小对象中具有相同名称的部分将合并到大对象中。
这有点脏,但也有一些缺点,例如可能出于垃圾收集目的合并一些您不想使用的部分,并隐藏每个部分来自哪个文件(尽管信息保留在调试部分),例如,如果您想在最终的ELF中拆分主要部分(.text,.data,.bss ...),以便能够看到哪个文件对闪存和RAM的使用有贡献,例如。