LWN:linker已经无法在32位架构上完美工作了

手把手教你配置MCAL中的CAN模块:从基础参数到实战避坑指南 本文提供了一份详尽的MCAL CAN模块配置指南,涵盖从基础参数设置到实战避坑的全过程。文章深入解析了CAN控制器核心参数、硬件对象配置、数据流处理及常见问题排查,并结合源码分析,帮助嵌入式开发者构建稳定高效的CAN通信链路,是汽车电子领域通信开发的实用参考。 阅读详情
640
点击上方蓝色“Linux News搬运工”关注我们~

Linker limitations on 32-bit architectures

August 27, 2019

This article was contributed by Alexander E. Patrakov


程序要能运行,必须得先被编译出来。大家越来越认识到现代软件消耗的运行资源要比以前的软件大的多,有时甚至要求用户必须得升级计算机硬件。其实与此同时,编译过程中也需要占用更多资源了,所以负责编译发行Linux发行版的管理者就需要投资购买更快的CPU、更多内存。不过在32位系统架构中,对虚拟内存空间有限制,所以现在这些发行版在针对那些架构编译软件包的时候就碰到了各种问题。


如果只用32位地址,那么进程就只能访问不超过4GB内存空间。在某些体系架构上甚至能访问的内存空间更加小,例如MIPS如果不带EVA硬件(Enhanced Virtual Addressing)的话,就必须得把高2GB的虚拟空间专用于kernel和supervisor mode。这样在需要把编译目标文件链接生成比较大的程序或者library的时候,链接器ld有时候需要超过2GB的内存空间,就会失败。


Building on 32-bit machines


这类问题是最近由Aurelien Jarno在一封发往多个Debian mailing list的邮件里面提出的。当然他并不是第一个碰到问题的人,此前在2012年在Gentoo forum就有一个关于webkit-gtk的帖子在抱怨了。我们来看一下这个例子,此外其他很多软件包也会有类似问题(Jarno提到firefox, Glasgow Haskell Compiler, Rust,和一些科学计算软件),就是进行32位编译的时候报错说虚拟地址空间不够。


在编译webkit-gitk的时候,首先会把C++源代码文件都分好组,拼接在一起,生成的文件被称为“unified sources”。先做这个步骤的好处是能减少编译时间。可以看WebKit开发者Michael Catanzaro的博客文章来详细了解:https://blogs.gnome.org/mcatanzaro/2018/02/17/on-compiling-webkit-now-twice-as-fast/

有意思的是,此前就有人建议采用这种方法,不过当时的目标是减少link阶段内存需求。


Unified source会用g++来编译生成目标代码文件,g++知道该调用哪个编译器(cc1plus)或者汇编器(as)。此阶段中最耗内存的程序是cc1plus,通常会消耗~500-800MB的RAM,在处理有些特别复杂的文件时可能会超过1.5GB。因此在只有32位物理地址空间的系统上,想要并行编译处理webkit-gtk从而加上-j2甚至-j3参数很有可能就会出错。换句话说,在真正的32位系统上,因为内存不够,我们甚至可能无法充分利用多进程的并行处理。不过好在无论是32位的x86还是MIPS,都有相应的CPU架构扩展(extension)来允许系统整体(注意这里不是针对某个单独进程)能使用超过4GB的物理内存。


Debian, Fedora,以及其他很多发行版(不过不包括Gentoo)都会在编译C/C++源文件的时候生成调试信息。这样在程序crash生成core dump文件的时候可以利用这些调试信息来分析出错原因,因为它们可以明确指出出错指令对应了源代码的哪一行,以及查看各个局部变量和全局变量在内存中的位置,怎么解析程序里面的各种数据结构。假如使用了-g编译器参数来生成调试信息,最终生成的目标文件可能会从几KB到10MB不等。例如WebDriverService.cpp.o就占用了2.1MB的磁盘空间,如果去除掉调试信息的话,就只需要208KB就够了。也就是说,这个文件里有90%的空间都是存放调试信息的。


编译器生成这些目标文件之后,会调用ld来把这些文件链接在一起生成最终可执行程序或者函数库。这个过程会把目标文件里的代码、数据、调试信息等都装进一个ELF文件里,并且修正互相引用的地址。在最终链接生成libwebkit2gtk-4.0.so.37的时候,会一下子把3GB的目标文件传递给ld。如果x86带有PAE(Physical Address Extension物理地址扩展)的话应该不会出错,不过也很临界了。我们可以在LDFLAGS里使用-Wl,--stats参数生成报告如下:

    ld.gold: total space allocated by malloc: 626630656 bytes
   total bytes mapped for read: 3050048838
   output file size: 1727812432 bytes

把前两行的数值加起来就看出为ld.gold总共分配了3.6GB的空间。这里大家肯定会对资源占用很有疑问。首先,这些内存(或者地址空间)都用来做什么了?其次,ld是否能再少用一点内存?


其实binutils里面实现了两个ld,分别是ld.bfd(旧版本,不过目前仍然是缺省版本)和ld.gold(新版本)。缺省来说这两个ld都会使用mmap()来把目标文件读进来作为输入。也就是说ld针对每一个目标文件会映射到它自己的一段虚拟地址空间上去,这样所有针对这段地址空间的内存操作都会被kernel通过page fault机制来重定向到文件操作。这种编程模式非常方便,理论上来说也会减少物理内存的占用,因为kernel不用被迫长期占用这段物理内存,而是可以在需要的时候自行把这段缓存了目标文件部分内容的内存空间释放出来做其他用途,并且今后ld需要读这部分目标文件数据的时候又可以自动再次从文件读到物理内存来。这种方案的缺点就是必须要确保有足够的虚拟内存空间足够覆盖所有输入输出文件,否则mmap()操作就会失败。


ld.bfd和ld.gold两者都提供了命令行参数来帮助调整保留内存,不过其实只是有时候有用:

    $ ld.bfd --help
     --no-keep-memory            Use less memory and more disk I/O
     --reduce-memory-overheads   Reduce memory overheads, possibly taking much longer
     --hash-size=<NUMBER>        Set default hash table size close to <NUMBER>
   $ ld.gold --help
     --no-keep-files-mapped      Release mapped files after each pass
     --no-map-whole-files        Map only relevant file parts to memory (default)
     --no-mmap-output-file       Do not map the output file for writing

当发行版维护者看到32位系统上出现编译错误的时候,如果用了上述参数中的某一项能解决问题,那么就会尽快提交一个patch给upstream来确保编译这个应用程序或库文件的时候缺省使用正确的参数。webkit-gtk的编译问题通常就是这么解决的。换句话说,所有容易解决的问题已经都解决了(all the low-hanging fruit is already collected,学个地道的英语说法——译者)。


对用户来说,比起没有安装包可用来说,能拿到一个不带调试信息的安装包,其实就已经很满意了。所以,发布者就被迫要把调试信息压缩一下,或者减少一些调试信息,甚至极端情况需要彻底拿掉调试信息。在Debian里面还是会有一些安装包在某些体系架构上是无法安装的,因为它们编译时会由于虚拟内存不足而导致编译失败。Jarno的结论是:“我们是时候要停止小修小补了,需要找一个真正的解决方案”。


Cross-compiling


有嵌入式系统开发经验的读者可能会问,为什么Debian会需要在计算能力很弱、资源有限的32位系统上编译安装包?不应该在更强大的amd64服务器上采用交叉编译(cross-compile)来生成安装包吗?确实,Yocto Project和Buildroot就是这么做的,他们就没有在哪怕一个体系架构上碰到编译带完整调试信息的webkit-gtk安装包的问题。不过,交叉编译就意味着无法执行所编译好的代码。有些安装包本来需要通过编译、运行一些小测试代码来检测系统配置,在交叉编译环境下就不能这么做了,所以只能完全依赖外部给出的配置信息,hard-code的信息,甚至做一些假设(通常都是按照悲观的情况做假设)。此外,维护者也就不能在编译过程中运行相应的test suite来做测试了。对Debian发布团队来说这些限制完全无法接受,所以他们就总是要求要进行本地编译,不能做交叉编译。相应的,虽然可以在QEMU这种模拟器里运行测试,但这个方案也是无法接受的,因为模拟器本身可能还会有各种问题。


Jarno建议利用Debian当前的"multiarch"支持能力。这是一个机制能同时安装针对多种架构的安装包。例如,一个系统上如果在运行amd64 kernel,那么i386和amd64的安装包都会被安装上去,所以这两种架构的程序都可以运行。同样的,32位和64位MIPS架构也做了同样的事情。这样一来,我们就可以生成运行在64位系统上、但是会生成32位程序的交叉编译器了。在gcc上这个很容易,只要创建一个wrapper来加上-m32开关就好。不过gcc并不是唯一的编译器,还有Haskell, Rust, OCaml等gcc等支持的语言,他们也需要按这个规则来提供编译器。


假如按照这个方案来走,那么如何得到所有这些编译器呢?也就是说,如果一个安装包在编译阶段需要占用非常非常多的内存,那么是应该用交叉编译生成,还是应该直接缺省提供呢?还有一个困难是关于RISC-V架构的:它的64位CPU并没有实现32位的指令,所以编译出来的32位程序没法保证能够执行。对Arm处理器来说也有类似的问题,有的arm64硬件上并没有实现32位指令。不过,这个阻力并不大,毕竟Debian还不支持32位的RISC-V系统,并且现在常用的arm64硬件还是支持32位指令的,可以直接拿来作为编译服务器。所以Ivo De Decker (Debian发布团队的一员)表示在这个方案可行之后,可以重新评估改变现行的编译策略。


此外,Sam Hartman(目前的Debian Project Leader)也表明,他并不觉得在32位系统上运行编译工具(包括编译器和链接器)是个好主意。当然,这个观点跟发布团队的观点并不一致,并且需要完成精确测量编译时间的测试报告。还有人提到一个解决方案就是利用distcc,不过最后讨论下来这个方案行不通,因为distcc的链接阶段仍然是本地完成的。


Luke Kenneth Casson Leighton也提出了对生态方面的担忧,因为这样就相当于是要迫使一些仍然能完美使用的硬件被淘汰进垃圾场了,仅仅因为编译工具里面使用了很浪费资源的算法。在Leighton看来,必须让编译工具这边修正行为,需要能支持比系统可用的虚拟内存空间大的多的文件,其实十几年前它本来就能做到这一点。


就目前来说,32位系统仍然用途广泛,也能运行通用操作系统。只有很少数的特别大的安装包会受到这个编译时资源不足问题的影响。不过终究有一天,我们会走到Hartman说的这一步:“如果没人做这件事,我们会失去所有32位架构”,至少对Debian是如此。


全文完

LWN文章遵循CC BY-SA 4.0许可协议。

极度欢迎将文章分享到朋友圈 
热烈欢迎转载以及基于现有协议修改再创作~


长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~


640?wx_fmt=jpeg

Grafana企业版vs开源版:从安装到插件管理的完整对比实测(含离线部署技巧) 本文深入对比Grafana企业版与开源版在安装流程、插件管理和功能限制等方面的差异,特别针对离线部署场景提供实用技巧。通过实测数据源支持、权限管理等核心功能,帮助企业用户做出明智选择,同时详细介绍离线安装和插件签名验证等关键操作。 阅读详情

相关推荐

stm32H743基于CubeMX配置为双ADC多通道DMA规则采样

stm32H743的ADC支持的最大频率为36MHz,有相关资料上说是可以超频,具体技术细节不多讨论。 需求: 使用stm32H743的ADC采集5路ovrc

xtqbp的博客 4361

LD说明文档--2.LD命令行命令翻译

国内的Ld链接器的翻译有点过时了,且有点错误,我重新翻译了一下找到的最新ld命令说明,如果有疑问以英文原版为主,如果有错误欢迎指正

yyww322的博客 1万+

CTFshow-CRYPTO(持续更新)

密码学签到 }wohs.ftc{galf 将字符串逆序即可 letters = '}wohs.ftc{galf' a = list(letters) a.reverse() for letters in a: print(letters,end='') crypto2 打开浏览器的控制台,复制粘贴回车即可得到flag crypto3 这一题同上 crypto4 如图填写即可,一开始e填写的是17,一直回答错误,后来经过群内大佬提醒软件的e是十六进制的,17转十六进制就是0x11 cr

i_kei的博客 1万+

Linux命令:ld

Linux命令:ld

深度安全实验室 1570

银河麒麟编译libjpeg库并配置qt环境

银河麒麟下编译libjpeg库并配置qt环境验证

小米的修行之路 1011

【AutoSAR CAN】04 - 如何使用Davinci Configurator Pro工具配置CAN的波特率

改参数为Tx Arbitration start delay value ,可用于延迟仲裁过程的起始点,用来补偿CAN收发器及线路的传输延迟,以优化传输性能。有关详细信息,请参阅硬件手册。该参数指定采样点模式,即选择多少个采样点的数量,如果选择了每比特三个样本选项,则该点标记第三个样本的位置;我们要配置CAN的波特率,其实就是要弄明白 CAN 控制器的位时序即可,具体的理论部分和EB的配置部门可参考文章《该参数表示传播延迟有多少个时间单位Tq,即上文中的Propagation delay/PROGSEG。.

2601

ld - GNU链接器(Linux手册页)下

  -Bdynamic -dy -call_shared 链接动态库。这仅对支持共享库的平台有意义。此选项通常是此类平台上的默认选项。此选项的不同变体是为了与各种系统兼容。您可以在命令行上多次使用此选项:它会影响库搜索后面的-l选项。 -Bgroup 在动态部分的“DT_FLAGS_1”条目中设置“DF_1_GROUP”标志。这会导致运行时链接程序处理此对象中的查找,并且只能在组内执行...

wogezheerne的博客 1040

文末含资料链接和视频讲解!YOLOv8+RepVGG+QueryDet小目标检测终极指南:从理论到实战,突破遥感图像检测难题

QueryDet(Query Detection)机制代表了目标检测领域的一个重要范式转变。传统的目标检测方法基于anchor或anchor-free的密集预测,需要为图像中的每个可能位置生成预测。而QueryDet采用了稀疏查询的方式,通过少量的可学习查询向量来直接预测目标。 这种设计灵感来源于Transformer架构中的注意力机制。在自然语言处理中,Transformer通过query-key-value机制实现了高效的序列建模。QueryDet将这一思想引入到目标检测中,将检测问题转化为查询匹配问

FJN110的博客 384

Hexagon Binutils GNU 手册(12)

Hexagon Binutils GNU 手册(12)3.2.2 Linker options(续3.2.2)3.2.2 Linker options(完结) 3.2.2 Linker options(续3.2.2) –dynamic-list file 指定一个动态列表文件的名称,该文件包含将由链接器处理的符号列表。 这个选项用于创建包含全局符号的共享库,这些符号的引用不能与共享库内的定义绑定。它也被用来创建动态链接的可执行文件,指定一个符号列表添加到可执行文件的符号表中。 动态列表文件的内容与版本节点的

weixin_38498942的博客 1094

C++笔记之emplace_back(),push_back()性能比较i++ 、 ++i

操作是否需要临时对象/拷贝性能需要(构造临时对象)较慢不需要(直接构造)较快i++需要(保存旧值)对于内置类型无影响,但对于自定义类型(如迭代器、大对象)会有拷贝开销++i不需要相对更快(尤其是自定义类型)都存在"是否需要额外的临时对象/拷贝"这一性能差异点和++i都是更高效的版本(避免临时对象/拷贝)和i++都可能产生额外的临时对象(前者构造临时对象,后者保存旧值)对于内置类型(如int),i++和++i性能几乎没有差异(编译器会优化);但对于自定义类型(尤其是迭代器等重量级对象),

小勇博客 95

如何在Ubuntu 22.04系统上安装CUDA 12.9

本文提供Ubuntu22.04系统上安装CUDA12.9的简明指南:1)确认已安装适配575驱动;2)清理旧版本后安装必需依赖库;3)通过deb包方式添加英伟达源并安装CUDA12.9工具包;4)配置环境变量;5)通过nvcc-V和nvidia-smi命令验证安装。文中包含常见问题解决方法及多显卡使用说明,全程约需10分钟完成安装。

2501_93651177的博客 1480

ld 和参数说明

本文档介绍GNU连接器ld的2.14版本. 本文档在GNU自由文档许可证下发行.在"GNU自由文档许可证"一章中有关于本许可证的一份拷贝. 概述 ‘ld’把一定量的目标文件跟档案文件连接起来,并重定位它们的数据,连接符号引用.一般,在编译一个程序 时,最后一步就是运行’ld’. 'ld’能接受连接命令语言文件,这是一种用AT&amp;T的连接编辑命令语言的超集写成的文件,用来在连接的整个 过程中提...

wdjjwb的专栏 1万+

分享一个我自用的 Python 消息发送模块,支持邮件、钉钉、企业微信

🔥 分享一个我自用的 Python 消息发送模块,支持邮件、钉钉、企业微信

XiaoqiangClub的博客 477

objdump&&ld

$(OUT)/bootblock: bootloader/bootasm.S bootloader/bootmain.c @mkdir -p $(OUT) $(CC) -fno-builtin -fno-pic -m32 -nostdinc -fno-stack-protector -Iinclude \ -Os -o $(OUT)/bootmain.o -c bootloader/bootmain.c $(CC) -fno-builtin -fno-pic -m32 -nostdinc -Iar

老鹰不捉小鸡 604

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

linux下的ld命令(1)

使用ld 本文档介绍GNU连接器ld的2.14版本. 本文档在GNU自由文档许可证下发行.在"GNU自由文档许可证"一章中有关于本许可证的一份拷贝. 概述 'ld'把一定量的目标文件跟档案文件连接起来,并重定位它们的数据,连接符号引用.一般,在编译一个程序 时,最后一步就是运行'ld'. 'ld'能接受连接命令语言文件,这是一种用AT&T的连接编辑命

cosmoslhf的专栏 3万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

汇编总结-第一部分_2_linux下汇编的相关工具

一个汇编程序员至少应该有下面这些工具: 1.汇编器 2.连接器 3.调试器 汇编器自然不用说,就是将汇编代码转换成目标代码的程序.注意是目标代码,windows平台上的可能会理解成最终的二进制代码,原因其实就是你们所用的IDE真的是给你们做了太多隐藏的工作.. 连接器就是将目标代码连接起来的工具.从而组成可执行文件.   汇编语言程序主要由3部分组成, 1.操作码助记符 2.数据

Coding Bad 1121

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

GCC编译优化指南

GCC编译优化指南作者:金步国版权声明本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布。任何人都可以自由使用、转载、复制和再分发,但必须保留作者署名,亦不得对声明中的任何条款作任何形式的修改,也不得附加任何其它条件。您可以自由链接、下载、传播此文档,但前提是必须保证全文完整转载,包括完整的版权信息和作译者声明。其他作品本文作者十分愿意与他人共

Bekars涡轮增压的Blog ^_^ 4077

arm-linux-androideabi——选项说明

http://www.fx114.net/qa-59-85000.aspx root@Ubuntu32:/home/zhangbin/android/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin# ls arm-linux-androideabi-addr2line   arm-

张同光 (Tongguang Zhang):Hello everyone ! 6181

gcc编译部分编译选项

我只写出一些我没有在文档中查到的,网上也搜索不出来什么明确的资料。正确性实在不敢保证。 https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/Option-Summary.html#Option-Summary 这是文档。 使用gcc命令显示的帮助信息 用法:gcc [选项] 文件... 选项: -pass-exit-codes

JabamiYu的博客 3万+

binutils几个重要工具使用方法总结

文章目录binutils软件包addr2linearldnmobjcopyobjdumpsizestringsstrip binutils软件包 工具 说明 addr2line 把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出在给出的地址上是哪个文件以及行号 ar 建立、修改、提取归档文件。归档文件是包含多个文件内容的一个大文件,其结构保证了可以恢复原始文件内容 as 主要用来编译GNU C编译器gcc输出的汇编文件,产生

qq_24601427的博客 2181

gcc的中文版使用说明和选项

使用gcc -v --help可以列出gcc的所有可选项 用法:gcc [选项] 文件... 选项: -pass-exit-codes 在某一阶段退出时返回最高的错误码 --help 显示此帮助说明 --target-help 显示目标机器特定的命令行选项 --help={common|optimizers

云守护的专栏 1万+

LWN:《BPF Performance Tools》介绍!

关注了就能看到更多这么棒的文章哦~A look at "BPF Performance Tools"ByJake EdgeFebruary 26, 2020原文来自:h...

Linux News搬运工 5618

Linux系统下运行jar文件,提示:No main manifest attribute, in XXX.jar

在Linux系统下执行java -jar XXX.jar com.HelloWorld往往会提示:No main manifest attribute, in XXX.jar 原因如下: 正常情况下,java打包成jar包需要在MANIFEST.MF中指定Main-Class项以便运行java -jar XXX.jar时找到对应的主类。因为-jar的含义就是后面跟的ja

nudt北极星的专栏 7万+

linux 全局搜索_每天一个 Linux 命令(64): ld 命令

(给Linux爱好者加星标,提升Linux技能)转自:恋猫大鲤鱼blog.youkuaiyun.com/k346k346/article/details/890886521.命令简介ld 命令是二进制工具集 GNU Binutils 的一员,是 GNU 链接器,用于将目标文件与库链接为可执行文件或库文件。2.命令格式ld [OPTIONS] OBJFILES3.选项说明ld 命令支持众多链接选项,但...

weixin_31999597的博客 957

常用jar包用途

jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现、查找和实现可插入式接口,提供一些一般类实例化、单件的生命周期管理的常用方法. jaxrpc.jar Axis运行所需要的组件包 saaj.jar 创建到端点的点到点连接的方法、创建并处理SOAP消息和附件的方法,以及接收和处理SOAP...

liu3098651的博客 555

LWN: 2019年LWN年终总结!

关注了就能看到更多这么棒的文章哦~A year-end wrap-up from LWNByJonathan CorbetDecember 18, 2019原文来自:https://l...

Linux News搬运工 1853
上一篇: 2019年,Greg怎样使用mutt(修订版 附视频)
下一篇: LWN:旧金山开源投票系统的现状
LinuxNews搬运工
博客等级 码龄7年 438粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值