Jim*_*eck 7 linux legacy gcc cross-compiling virtual-memory
我们正在使用基于gcc 2.6.0的遗留编译器来交叉编译我们仍在使用的旧嵌入式处理器(是的,它自1994年以来一直在使用!).为这款芯片做gcc端口的工程师早就开始了.虽然我们可以从网络上的某个地方恢复gcc 2.6.0源代码,但这个芯片的更改集已经在公司历史的大厅中消失了.直到最近,由于编译器仍然运行并生成可行的可执行文件,我们一直糊涂,但是从Linux内核2.6.25(以及2.6.26)开始,它失败并显示消息gcc: virtual memory exhausted
......即使在没有参数的情况下运行或仅运行-v
.我已经使用2.6.24内核重新启动了我的开发系统(从2.6.26开始)并且编译器再次工作(使用2.6.25重启不会).
我们有一个系统,我们保留在2.6.24只是为了为这个芯片做构建,但是感觉有点暴露,以防linux世界转移到我们不能再重建一个将运行的系统的程度编译器(即我们的2.6.24系统死机,我们无法在新系统上安装和运行2.6.24,因为某些软件部分不再可用).
有没有人有任何想法,我们可以做一些更现代的安装,以使这个遗留的编译器运行?
编辑:
回答一些评论......
遗憾的是,这是我们芯片特有的源代码更改丢失了.这种损失发生在两个主要的公司重组和几个系统管理员(其中一些确实留下了一团糟).我们现在使用配置控制,但这对于这个问题来说太晚关闭了谷仓门.
使用VM是一个好主意,也可能是我们最终要做的.谢谢你的想法.
最后,我尝试了strace作为ephemient建议,发现最后一次系统调用是brk(),它在新系统(2.6.26内核)上返回错误并在旧系统(2.6.24内核)上返回成功.这表明我真的用完了虚拟内存,除了tcsh"limit"在旧系统和新系统上返回相同的值,而/ proc/meminfo显示新系统有更多的内存和更多的交换空间.也许这是一个碎片问题或程序加载的地方?
我做了一些进一步的研究,并在内核2.6.25中添加了"brk randomization",但是CONFIG_COMPAT_BRK
默认情况下会启用(禁用brk随机化).
编辑:
好的,更多信息:它看起来真的像brk随机化是罪魁祸首,传统的gcc正在调用brk()来改变数据段的结束并且现在失败,导致传统的gcc报告"虚拟内存耗尽".有一些记录的方法可以禁用brk随机化:
sudo echo 0 > /proc/sys/kernel/randomize_va_space
sudo sysctl -w kernel.randomize_va_space=0
用setarch i386 -R tcsh
(或"-R -L")开始一个新的shell
我已经尝试了它们,它们确实有效,因为brk()返回值与没有它们(并且在内核2.6.25和2.6.26上都试过)不同(并且总是相同),但是brk()仍然失败,所以传统的gcc仍然失败:-(.
此外,我已经设置vm.legacy_va_layout=1
并vm.overcommit_memory=2
没有改变,我已经与重新启动vm.legacy_va_layout=1
,并kernel.randomize_va_space=0
保存在/etc/sysctl.conf中的设置.仍然没有变化.
编辑:
使用kernel.randomize_va_space=0
内核2.6.26(2.6.25和)在以下brk的结果()通过所报告的呼叫strace legacy-gcc
:
brk(0x80556d4) = 0x8056000
这表明brk()失败了,但看起来它失败了,因为数据段已经超出了请求的范围.使用objdump,我可以看到数据段应该以0x805518c结束,而失败的brk()表示数据段当前以0x8056000结束:
Sections: Idx Name Size VMA LMA File off Algn 0 .interp 00000013 080480d4 080480d4 000000d4 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .hash 000001a0 080480e8 080480e8 000000e8 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .dynsym 00000410 08048288 08048288 00000288 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .dynstr 0000020e 08048698 08048698 00000698 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .rel.bss 00000038 080488a8 080488a8 000008a8 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .rel.plt 00000158 080488e0 080488e0 000008e0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .init 00000008 08048a40 08048a40 00000a40 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 7 .plt 000002c0 08048a48 08048a48 00000a48 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 8 .text 000086cc 08048d10 08048d10 00000d10 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 9 .fini 00000008 080513e0 080513e0 000093e0 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 10 .rodata 000027d0 080513e8 080513e8 000093e8 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 11 .data 000005d4 08054bb8 08054bb8 0000bbb8 2**2 CONTENTS, ALLOC, LOAD, DATA 12 .ctors 00000008 0805518c 0805518c 0000c18c 2**2 CONTENTS, ALLOC, LOAD, DATA 13 .dtors 00000008 08055194 08055194 0000c194 2**2 CONTENTS, ALLOC, LOAD, DATA 14 .got 000000b8 0805519c 0805519c 0000c19c 2**2 CONTENTS, ALLOC, LOAD, DATA 15 .dynamic 00000088 08055254 08055254 0000c254 2**2 CONTENTS, ALLOC, LOAD, DATA 16 .bss 000003b8 080552dc 080552dc 0000c2dc 2**3 ALLOC 17 .note 00000064 00000000 00000000 0000c2dc 2**0 CONTENTS, READONLY 18 .comment 00000062 00000000 00000000 0000c340 2**0 CONTENTS, READONLY SYMBOL TABLE: no symbols
编辑:
回应ephemient的评论如下:"将GCC视为没有来源的二进制文件非常奇怪"!
因此,使用strace,objdump,gdb以及我对386汇编程序和体系结构的有限理解,我已将问题追溯到遗留代码中的第一个malloc调用.传统的gcc调用malloc,它返回NULL,导致stderr上的"虚拟内存耗尽"消息.这个malloc在libc.so.5中,它多次调用getenv并最终调用brk()...我想增加堆...失败了.
从这个我可以推测,问题不仅仅是brk随机化,或者我还没有完全禁用brk随机化,尽管randomize_va_space = 0和legacy_va_layout = 1 sysctl设置.
小智 12
将linux +旧gcc安装到虚拟机上.
你有这个自定义编译器的来源吗?如果你可以恢复2.6.0基线(这应该相对容易),那么差异和补丁应该恢复你的变更集.
然后,我建议使用该更改集来构建针对最新gcc的新版本.然后将其置于配置控制之下.
对不起,不要吼叫.这是我30年来大部分时间都在说同样的话.