传统的gcc编译器问题 [英] legacy gcc compiler issues

查看:214
本文介绍了传统的gcc编译器问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用基于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在新系统上安装和运行,因为一些软件部分不再可用)。



有没有人有任何想法,我们可以做一个更现代的安装,让这个遗留编译器运行?



编辑



回答一些评论...



很遗憾,它是特定于我们的芯片丢失了。这种损失发生在两家主要的公司reorgs和几个系统管理员(其中一些真正留下了混乱)。我们现在使用配置控制,但是这对于这个问题来说太晚了。



使用虚拟机是一个好主意,可能是我们结束做起来。

最后,我试着用ephemient建议的strace,发现最后一个系统调用是brk(),它在新系统上返回一个错误(2.6 .26内核),并在旧系统(2.6.24内核)上返回成功。这表明我真的用完了虚拟内存,除了tcshlimit在旧系统和新系统上返回相同的值,而/ proc / meminfo显示新系统的内存稍多,交换空间也多一点。也许这是一个碎片化的问题或程序被加载的问题?



我做了一些进一步的研究,在内核2.6.25中添加了brk随机化,但是 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 < code $ <$ b $ li

    开始一个新的shell> setarch i386 -R tcsh (或 - 我已经尝试过他们,他们似乎有一个效果,因为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
    会导致以下的brk()调用被 strace legacy报告-GCC $ b $ p
    $(0x80556d4)= 0x8056000



    这表明brk()失败,但它看起来像失败了,因为数据段已经超出请求的范围。使用objdump,我可以看到数据段应该在0x805518c处结束,而失败的brk()表示数据段当前在0x8056000结束:

     
    部分:
    Idx名称大小VMA LMA文件关闭
    0 .interp 00000013 080480d4 080480d4 000000d4 2 ** 0
    目录,ALLOC,LOAD,READONLY,DATA
    1 .hash 000001a0 080480e8 080480e8 000000e8 2 ** 2
    目录,ALLOC,LOAD,READONLY,DATA
    2 .dynsym 00000410 08048288 08048288 00000288 2 ** 2
    目录,ALLOC,LOAD,READONLY,DATA
    3 .dynstr 0000020e 08048698 08048698 00000698 2 ** 0
    目录,ALLOC,LOAD,READONLY,DATA
    4.rel.bss 00000038 080488a8 080488a8 000008a8 2 ** 2
    目录, ALLOC,LOAD,READONLY,DATA
    5 .rel.plt 00000158 080488e0 080488e0 000008e0 2 ** 2
    CONTENT S,ALLOC,LOAD,READONLY,DATA
    6 .init 00000008 08048a40 08048a40 00000a40 2 ** 4
    目录,ALLOC,LOAD,READONLY,CODE
    7 .plt 000002c0 08048a48 08048a48 00000a48 2 * * 2
    目录,ALLOC,LOAD,READONLY,CODE
    8 .text 000086cc 08048d10 08048d10 00000d10 2 ** 4
    目录,ALLOC,LOAD,READONLY,CODE
    9 .fini 00000008 080513e0 080513e0 000093e0 2 ** 4
    目录,ALLOC,LOAD,READONLY,CODE
    10 .rodata 000027d0 080513e8 080513e8 000093e8 2 ** 0
    目录,ALLOC,LOAD,READONLY,DATA
    11 .data 000005d4 08054bb8 08054bb8 0000bbb8 2 ** 2
    CONTENTS,ALLOC,LOAD,DATA
    12.ctors 00000008 0805518c 0805518c 0000c18c 2 ** 2
    目录,ALLOC,LOAD, DATA
    13 .dtors 00000008 08055194 08055194 0000c194 2 ** 2
    目录,ALLOC,LOAD,DATA
    14 .got 000000b8 0805519c 0805519c 0000c19c 2 ** 2
    目录,ALLOC,LOAD,DATA
    15。动态00000088 08055254 08055254 0000c254 2 ** 2
    目录,ALLOC,LOAD,DATA
    16 .bss 000003b8 080552dc 080552dc 0000c2dc 2 ** 3
    ALLOC
    17 .note 00000064 00000000 00000000 0000c2dc 2 ** 0
    目录, READONLY
    18 .comment 00000062 00000000 00000000 0000c340 2 ** 0
    CONTENTS,READONLY
    符号表:
    无符号

    编辑

    回覆ephemient的评论如下: !

    因此,使用strace,objdump,gdb和我对386汇编器和体系结构的有限理解,我已经将问题追溯到遗留代码中的第一个malloc调用。传统的gcc调用malloc,它返回NULL,导致stderr上的虚拟内存耗尽消息。这个malloc在libc.so.5中,它调用getenv
    a一堆次,最后调用brk()...我想增加堆......失败。



    从这里我只能推测出问题不仅仅是brk随机化,或者我还没有完全禁用brk随机化,尽管randomize_va_space = 0和legacy_va_layout = 1 sysctl设置。

    解决方案

    将linux +旧版gcc安装到虚拟机上。

    We are using a legacy compiler, based on gcc 2.6.0, to cross compile for an old imbedded processor we are still using (yes, it is still in use since 1994!). The engineer that did the gcc port for this chip has long since moved on. Although we might be able to recover the gcc 2.6.0 source from somewhere on the web, the change set for this chip has disappeared in the halls of corporate history. We have muddled along until recently as the compiler still ran and produced workable executables, but as of linux kernel 2.6.25 (and also 2.6.26) it fails with the message gcc: virtual memory exhausted... even when run with no parameters or with only -v. I have rebooted my development system (from 2.6.26) using the 2.6.24 kernel and the compiler works again (rebooting with 2.6.25 does not).

    We have one system that we are keeping at 2.6.24 just for the purpose of doing builds for this chip, but are feeling a bit exposed in case the linux world moves on to the point that we cannot any longer rebuild a system that will run the compiler (i.e. our 2.6.24 system dies and we cannot get 2.6.24 to install and run on a new system because some of the software parts are no longer available).

    Does anyone have any ideas for what we might be able to do to a more modern installation to get this legacy compiler to run?

    Edit:

    To answer some of the comments...

    Sadly it is the source code changes that are specific to our chip that are lost. This loss occurred over two major company reorgs and several sysadmins (a couple of which really left a mess). We now use configuration control, but that is closing the barn door too late for this problem.

    The use of a VM is a good idea, and may be what we end up doing. Thank you for that idea.

    Finally, I tried strace as ephemient suggested and found that the last system call was brk() which returned an error on the new system (2.6.26 kernel) and returned success on the old system (2.6.24 kernel). This would indicate that I really am running out of virtual memory, except that tcsh "limit" returns the same values on old and new systems, and /proc/meminfo shows the new systems has slightly more memory and quite a bit more swap space. Maybe it is a problem of fragmentation or where the program is being loaded?

    I did some further research and "brk randomization" was added in kernel 2.6.25, however CONFIG_COMPAT_BRK is supposedly enabled by default (which disables brk randomization).

    Edit:

    OK, more info: It really looks like brk randomization is the culprit, the legacy gcc is calling brk() to change the end of the data segment and that now fails, causing the legacy gcc to report "virtual memory exhausted". There are a few documented ways to disable brk randomization:

    • sudo echo 0 > /proc/sys/kernel/randomize_va_space

    • sudo sysctl -w kernel.randomize_va_space=0

    • starting a new shell with setarch i386 -R tcsh (or "-R -L")

    I have tried them and they do seem to have an effect in that the brk() return value is different (and always the same) than without them (tried on both kernel 2.6.25 and 2.6.26), but the brk() still fails so the legacy gcc still fails :-(.

    In addition I have set vm.legacy_va_layout=1 and vm.overcommit_memory=2 with no change, and I have rebooted with the vm.legacy_va_layout=1 and kernel.randomize_va_space=0 settings saved in /etc/sysctl.conf. Still no change.

    Edit:

    Using kernel.randomize_va_space=0 on kernel 2.6.26 (and 2.6.25) results in the following brk() call being reported by strace legacy-gcc:

    brk(0x80556d4) = 0x8056000

    This indicates the brk() failed, but it looks like it failed because the the data segment already ends beyond what was requested. Using objdump, I can see the data segment should end at 0x805518c whereas the failed brk() indicates that the data segment currently ends at 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
    

    Edit:

    To echo ephemient's comment below: "So strange to treat GCC as a binary without source"!

    So, using strace, objdump, gdb and my limited understanding of 386 assembler and architecture I have traced the problem to the 1st malloc call in the legacy code. The legacy gcc calls malloc, which returns NULL, which results in the "virtual memory exhausted" message on stderr. This malloc is in libc.so.5, and it calls getenv a bunch of times and ends up calling brk()... I guess to increase the heap... which fails.

    From this I can only surmise that the problem is more than brk randomization, or I have not fully disabled brk randomization, despite the randomize_va_space=0 and legacy_va_layout=1 sysctl settings.

    解决方案

    Install linux + the old gcc onto a virtual machine.

    这篇关于传统的gcc编译器问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆