문제

우리는 여전히 사용하고 있는 오래된 내장 프로세서에 대한 크로스 컴파일을 위해 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를 시도했고 마지막 시스템 호출이 새 시스템(2.6.26 커널)에서는 오류를 반환하고 이전 시스템(2.6.24 커널)에서는 성공을 반환한 brk()라는 것을 발견했습니다.이는 tcsh "limit"가 이전 시스템과 새 시스템에서 동일한 값을 반환하고 /proc/meminfo에서 새 시스템이 약간 더 많은 메모리와 상당히 더 많은 스왑 공간을 가지고 있음을 보여주는 점을 제외하면 실제로 가상 메모리가 부족하다는 것을 나타냅니다.어쩌면 조각화 문제이거나 프로그램이 로드되는 위치 때문일까요?

좀 더 자세히 조사한 결과 "brk 무작위화"가 커널 2.6.25에 추가되었습니다. 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")

나는 그것들을 시도했고 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는 NULL을 반환하는 malloc을 호출하여 stderr에 "가상 메모리 소진" 메시지가 표시됩니다.이 malloc은 libc.so.5에 있으며, getenv를 여러 번 부르고 brk ()에게 전화하게됩니다.힙을 늘리는거 같은데...실패합니다.

이것으로부터 나는 문제가 brk 무작위화 이상의 것이라고 추측할 수 있습니다. 또는 randomize_va_space=0 및 Legacy_va_layout=1 sysctl 설정에도 불구하고 brk 무작위화를 완전히 비활성화하지 않았습니다.

도움이 되었습니까?

해결책

Linux + 기존 GCC를 가상 시스템에 설치하십시오.

다른 팁

당신은 있습니다 출처 이 사용자 지정 컴파일러를 위해? 2.6.0 기준선을 복구 할 수 있다면 (그리고 비교적 쉬워야 함) Diff와 Patch는 변경 세트를 복구해야합니다.

그런 다음 권장하는 것은 해당 변경 세트를 사용하여 최신 GCC에 대해 새 버전을 구축하는 것입니다. 그런 다음 구성 제어에 넣습니다.

죄송합니다. 외치는 것을 의미하지 않습니다. 나는 단지 30 년 동안 같은 말을 해왔다.

할 수 있나요 strace 그만큼 gcc-2.6.0 실행 가능?독서와 같은 일을 하고 있을지도 모릅니다 /proc/$$/maps, 출력이 사소한 방식으로 변경되면 혼란스러워집니다.비슷한 문제가 있었습니다. 최근에 알아차린 2.6.28과 2.6.29 사이.

그렇다면 해킹할 수 있다 /usr/src/linux/fs/proc/task_mmu.c 또는 그 무렵 이전 출력을 복원하거나 일부 설정을 설정합니다. $LD_PRELOAD 속이기 위해 gcc 다른 파일을 읽습니다.

편집하다

당신이 언급한 이후로 brk...

CONFIG_COMPAT_BRK 기본값으로 설정 kernel.randomize_va_space=1 대신에 2, 그러나 이는 여전히 힙(brk).

다음과 같은 경우 문제가 해결되는지 확인하세요. echo 0 > /proc/sys/kernel/randomize_va_space 또는 sysctl kernel.randomize_va_space=0 (동등한).

그렇다면 추가하세요. kernel.randomize_va_space = 0 에게 /etc/sysctl.conf 또는 추가 norandmaps 커널 명령줄(동등)로 이동하고 다시 행복해집니다.

나는 만났다 이것 그리고 당신의 문제에 대해 생각했습니다. 이진을 사용하여 ELF 형식으로 이동하는 방법을 찾을 수 있습니까? 또는 관련이 없을 수도 있지만 ObjDump를 사용하면 더 많은 정보를 제공 할 수 있습니다.

프로세스 메모리 맵을 볼 수 있습니까?

그래서 뭔가 해결을 해봤는데...완전한 해결책은 아니지만 레거시 gcc에서 겪었던 원래 문제를 해결했습니다.

.plt(프로시저 연결 테이블)의 모든 libc 호출에 중단점을 설정하면 malloc(libc.so.5에서)이 getenv()를 호출하여 다음을 얻는 것을 볼 수 있습니다.

    MALLOC_TRIM_THRESHOLD_
    MALLOC_TOP_PAD_
    MALLOC_MMAP_THRESHOLD_
    MALLOC_MMAP_MAX_
    MALLOC_CHECK_

그래서 웹서핑해서 이런걸 발견했어요 이것 조언한 것

    setenv MALLOC_TOP_PAD_ 536870912

그러면 레거시 gcc가 작동합니다!!!!

하지만 홈 프리는 아니고 실패하기 전에 빌드의 링크까지 올라갔으므로 우리가 가지고 있는 레거시 nld에 대해 추가 작업이 진행되고 있습니다. :-( 다음과 같이 보고됩니다.

    Virtual memory exceeded in `new'

/etc/sysctl.conf에는 다음이 있습니다.

    kernel.randomize_va_space=0
    vm.legacy_va_layout=1

다음과 같은 경우에도 여전히 동일하게 작동합니다.

    kernel.randomize_va_space=1
    vm.legacy_va_layout=0

하지만 그렇지 않다면

kernel.randomize_va_space=2

공유 라이브러리 종속성을 확인하려면 "ldd"를 사용하라는 제안이 있었습니다.레거시 gcc에는 libc5 만 필요하지만 레거시 NLD에는 libg ++ .so.27 , libstdc ++ .so.27 , libm.so.5 가 필요하며 libg ++ .so.27 (libg ++ 27-altdev ??) libc5-compat은 어떻습니까?

그래서 제가 말했듯이 아직 집에 무료가 아닙니다 ...점점 가까워지세요.아마도 nld 문제에 대한 새로운 질문을 게시할 것입니다.

편집하다:

원래는 해당 레거시 링커에 여전히 문제가 있기 때문에 이 답변을 "수락"하지 않으려고 했지만 적어도 이 질문에 대한 최종성을 얻기 위해 해당 입장을 다시 생각하고 있습니다.

감사합니다:

  • vm 사용을 제안한 an0nym0usc0ward(궁극적으로 승인된 답변이 될 수 있음)
  • strace 사용을 제안하고 stackoverflow 사용에 도움을 주는 표현
  • objdump 사용을 제안하는 shodanex

편집하다

다음은 제가 배운 마지막 내용입니다. 다른 방법으로는 완전히 해결할 수 없으므로(적어도 이에 대해 할당된 시간 동안) 이제 VM 솔루션을 수락하겠습니다.

최신 커널에는 libc5를 사용할 수 있도록 하는 CONFIG_COMPAT_BRK 빌드 플래그가 있으므로 아마도 이 플래그를 사용하여 새 커널을 빌드하면 문제가 해결될 것입니다. (그리고 커널 src를 살펴보면 그렇게 될 것 같지만 그렇게 했기 때문에 확신할 수는 없습니다. 모든 경로를 따르지는 않습니다).(커널 빌드 시간이 아닌) 런타임에 libc5 사용을 허용하는 또 다른 문서화된 방법도 있습니다.sudo sysctl -w kernel.randomize_va_space=0.그러나 이것은 완전한 작업을 수행하지 않고 일부 (대부분?) libc5 앱은 여전히 중단됩니다.우리의 레거시 컴파일러와 링커.이는 최신 커널과 이전 커널 간의 정렬 가정이 다르기 때문인 것 같습니다.bss의 끝을 페이지 경계까지 가져오기 위해 더 큰 bss 섹션이 있다고 생각하도록 링커 바이너리를 패치했습니다. 이는 sysctl var kernel.randomize_va_space=0일 때 최신 커널에서 작동합니다.중요한 바이너리 실행 파일을 맹목적으로 패치하고 있고, 최신 커널에서 패치된 링커를 실행하면 이전 커널에서 실행되는 원래 링커와 비트가 동일한 출력이 생성되기 때문에 이것은 나에게 만족스러운 솔루션이 아닙니다. 다른 링커 입력(예:링크되는 프로그램을 변경하면) 역시 동일한 결과를 생성합니다.

시스템이 죽으면 다시 설치할 수있는 디스크 이미지를 만들 수 없습니까? 아니면 VM을 만들까요?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top