programing

gcc 옵션 -fomit-frame-pointer를 이해하려고 합니다.

prostudy 2022. 6. 27. 21:10
반응형

gcc 옵션 -fomit-frame-pointer를 이해하려고 합니다.

나는 구글에게 그 의미를 알려달라고 부탁했다.gcc선택-fomit-frame-pointer다음 문장으로 리다이렉트 됩니다.

- 프레임 프레임 표시

프레임 포인터는 필요 없는 기능을 위해 레지스터에 보관하지 마십시오.이렇게 하면 프레임 포인터를 저장, 설정 및 복원하라는 명령이 필요하지 않습니다. 또한 많은 기능에서 추가 레지스터를 사용할 수 있습니다.또, 일부의 머신에서는 디버깅을 할 수 없게 됩니다.

각 기능에 대해 알고 있는 바와 같이 프로세스 메모리의 스택에 활성화 레코드가 생성되어 모든 로컬 변수와 추가 정보가 유지됩니다.이 프레임 포인터가 함수의 활성화 레코드의 주소를 의미하기를 바랍니다.

이 경우 프레임 포인터를 레지스터에 보관할 필요가 없는 함수의 종류는 무엇입니까?이 정보를 얻으면 (가능하다면) 그것을 바탕으로 새로운 함수를 설계하려고 합니다.프레임 포인터가 레지스터에 보관되어 있지 않으면 바이너리 명령어가 생략되기 때문입니다.이것에 의해, 기능이 많은 애플리케이션의 퍼포먼스가 현저하게 향상됩니다.

대부분의 작은 기능에는 프레임 포인터가 필요하지 않습니다.큰 기능에는 프레임 포인터가 필요할 수 있습니다.

이는 컴파일러가 스택의 사용 방법과 스택 상의 사물(로컬 변수, 현재 함수에 전달된 인수 및 호출될 함수에 대한 준비)을 얼마나 잘 추적하느냐에 관한 것입니다.프레임 포인터를 필요로 하는 함수와 필요로 하지 않는 함수를 특징짓는 것은 쉽지 않다고 생각합니다(기술적으로는 NO 함수는 프레임 포인터를 가질 필요가 없습니다.컴파일러가 다른 코드의 복잡성을 줄일 필요가 있다고 판단되는 경우입니다).

코드화 전략의 일환으로 "프레임 포인터가 없는 함수"를 시도해서는 안 된다고 생각합니다.말씀 드렸듯이 단순한 함수에는 필요하지 않으므로 사용하세요.-fomit-frame-pointer레지스터 할당자가 사용할 수 있는 레지스터가 1개 더 있고, 입력 및 기능에 대한 명령어가 1-3개 저장됩니다.만약 당신의 함수에 프레임 포인터가 필요하다면, 컴파일러는 그것이 프레임 포인터를 사용하지 않는 것보다 더 좋은 선택이라고 판단하기 때문입니다.프레임 포인터 없이 기능하는 것이 목적이 아니라 정확하고 빠르게 동작하는 코드를 갖는 것이 목표입니다.

"프레임 포인터가 없는" 것이 더 나은 성능을 제공할 수 있지만, 특히 x86-64에서는 큰 향상을 가져올 수 없습니다. x86-64에서는 이미 16개의 레지스터가 있습니다.32비트 x86에서는 8개의 레지스터밖에 없기 때문에, 그 중 하나가 스택 포인터이며, 프레임 포인터로서 다른 하나를 차지하는 것은 레지스터 공간의 25%를 차지한다.그것을 12.5%로 변경하는 것은 상당한 개선이다.물론 64비트용 컴파일도 많은 도움이 됩니다.

이것은, 인텔 플랫폼의 BP/EBP/RBP 레지스터에 관한 것입니다.이 레지스터는 디폴트로 스택세그먼트가 됩니다(스택세그먼트에 액세스하기 위해서 특별한 프리픽스는 필요 없습니다).

EBP는 스택 내에서 데이터 구조, 변수 및 동적으로 할당된 작업 공간에 액세스하기 위한 최적의 레지스터 선택입니다.EBP는 현재 TOS가 아닌 스택 상의 고정 포인트를 기준으로 스택 상의 요소에 액세스하기 위해 자주 사용됩니다.통상, 현재의 순서로 확립된 현재의 스택프레임의 베이스 주소를 식별합니다.오프셋 계산에서 EBP가 베이스 레지스터로 사용되는 경우, 오프셋은 현재 스택 세그먼트(즉, SS에 의해 현재 선택된 세그먼트)에서 자동으로 계산됩니다.SS를 명시적으로 지정할 필요가 없기 때문에 이러한 경우 명령 부호화가 더 효율적입니다.EBP 는, 다른 세그먼트 레지스터를 개입시켜 주소 지정 가능한 세그먼트에 인덱스를 붙이기 위해서도 사용할 수 있습니다.

( 출처 - http://css.csail.mit.edu/6.858/2017/readings/i386/s02_03.htm )

대부분의 32비트 플랫폼, 데이터 세그먼트 및 스택세그먼트는 동일하기 때문에 스택과의 EBP/RBP 관련성은 문제가 되지 않습니다.64비트 플랫폼에서도 마찬가지입니다.2003년에 AMD에 의해 도입된 x86-64 아키텍처에서는 64비트 모드에서의 세그먼트화 지원이 대폭 중단되었습니다.세그먼트 레지스터의 4개(CS, SS, DS 및 ES)는 강제로 0으로 설정됩니다.이러한 x86 32비트 및 64비트 플랫폼의 상황은 기본적으로 메모리에 액세스하는 프로세서 명령에서 프리픽스 없이 EBP/RBP 레지스터를 사용할 수 있음을 의미합니다.

따라서 당신이 쓴 컴파일러 옵션을 사용하면 BP/EBP/RBP를 로컬 변수 보유 등의 다른 수단으로 사용할 수 있습니다.

"프레임 포인터를 저장, 설정 및 복원하는 지침을 회피합니다"는 각 함수의 입력에 다음 코드를 사용하지 않는 것을 의미합니다.

push ebp
mov ebp, esp

또는enter인텔(R) 80286 및 80386 프로세서에서 매우 유용한 명령어입니다.

또한 함수가 반환되기 전에 다음 코드가 사용됩니다.

mov esp, ebp
pop ebp 

또는leave설명.

디버깅 툴은 스택 데이터를 스캔하여 이러한 푸시된 EBP 레지스터 데이터를 사용하여 찾을 수 있습니다.call sites즉, 함수 및 인수의 이름을 계층적으로 호출된 순서대로 표시합니다.

프로그래머는 스택 프레임에 대해 폭넓은 관점에서가 아니라 좁은 의미에서 (1개의 함수 호출을 처리하고 반환 주소, 인수 및 로컬 변수를 유지하는 스택 내의 단일 엔티티라는 것) 질문이 있을 수 있습니다.stack frames는 컴파일러 옵션의 컨텍스트에 기재되어 있습니다.컴파일러의 관점에서 스택프레임은 스택에 앵커를 푸시하는 루틴의 엔트리 코드와 출구 코드일 뿐이며 디버깅 및 예외 처리에도 사용할 수 있습니다.디버깅 툴은 스택 데이터를 스캔하여 이러한 앵커를 백트레이싱에 사용할 수 있습니다.call sites즉, 계층적으로 호출된 것과 동일한 순서로 함수의 이름을 표시합니다.

컴파일러가 이 코드를 생성할지 여부를 제어할 수 있기 때문에 프로그래머가 스택프레임을 컴파일러 옵션과 관련하여 이해하는 것이 중요합니다.

경우에 따라서는 컴파일러에 의해 스택프레임(루틴의 엔트리 코드와 종료 코드)이 생략되어 편리한 베이스 포인터(BP/ESP/RSP)가 아닌 스택 포인터(SP/ESP/RSP)를 통해 변수에 직접 액세스 할 수 있습니다.컴파일러가 일부 함수에 대해 스택프레임을 생략하는 조건은 다를 수 있습니다.예를 들어 (1) 함수는 리프 함수(즉, 다른 함수를 호출하지 않는 엔드 엔티티), (2) 예외는 사용되지 않습니다. (3) 스택에서 발신 파라미터를 사용하여 루틴을 호출하지 않으며 (4) 함수는 파라미터를 가지지 않습니다.

스택 프레임(루틴의 엔트리 코드와 종료 코드)을 생략하면, 코드를 보다 작게 해 고속으로 할 수 있습니다.그러나 스택의 데이터를 역추적하여 프로그래머에게 표시하는 디버거의 능력에도 부정적인 영향을 미칠 수 있습니다.컴파일러가 스택프레임의 엔트리 코드와 종료 코드를 부여하기 위해 어떤 조건이 충족되어야 하는지를 결정하는 컴파일러 옵션입니다.예를 들어, 컴파일러는 (a)항상, (b)절대, (c)필요할 때 (조건 지정) 함수에 이러한 입력 및 종료 코드를 추가하는 옵션을 가질 수 있습니다.

일반에서 특수성으로의 회귀:-fomit-frame-pointerGCC 컴파일러 옵션은 루틴의 엔트리 코드와 종료 코드 양쪽에서 승리할 수 있으며 추가 레지스터가 있는 경우(이 경우 디폴트 자체 또는 다른 옵션에 의해 이미 켜져 있지 않은 경우, 당신은 이미 EBP/RBP 레지스터를 사용하는 이득을 얻고 있으며 명시적으로 지정하면 추가 이득을 얻을 수 없습니다.이 옵션이 이미 암묵적으로 켜져 있는 경우 이 옵션을 입력합니다).다만, 16비트 및 32비트 모드에서는, AX와 같이 BP 레지스터의 8비트 부분에의 액세스를 제공하는 기능은 없습니다(AL 및 AH).

이 옵션은 컴파일러가 EBP를 최적화의 범용 레지스터로 사용할 수 있도록 하는 것 외에 스택프레임의 종료 코드와 엔트리 코드를 생성하는 것도 방지하므로 디버깅이 복잡해집니다.그 때문에, GCC 문서에서는, 이 옵션을 유효하게 하면 디버깅이 불가능하게 되는 것을 명시적으로 기술하고 있습니다(보통 굵은 글씨로 강조하지 않습니다.기계대에 대해 불평하다.

또한 디버깅 또는 최적화와 관련된 다른 컴파일러 옵션이 암시적으로 다음 명령을 실행할 수 있습니다.-fomit-frame-pointer[ON] 또는 [OFF]옵션을 선택합니다.

gcc.gnu.org에서 다른 옵션이 어떤 영향을 미치는지에 대한 공식 정보를 찾을 수 없었습니다.-fomit-frame-pointer x86 플랫폼의 경우 https://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Optimize-Options.html에는 다음 내용만 기재되어 있습니다.

-O는 디버깅을 방해하지 않는 머신에서도 -fomit-frame-pointer를 활성화합니다.

따라서 문서 그 자체로는 그 여부가 명확하지 않습니다.-fomit-frame-pointerx86 플랫폼에서 단일 '-O' 옵션으로 컴파일만 하면 켜집니다.이것은 경험적으로 테스트될 수 있지만, 이 경우 GCC 개발자는 이 옵션의 동작을 예고 없이 변경하지 않기로 약속하지 않습니다.

그러나 Peter Cordes는 코멘트에서 디폴트 설정에 차이가 있음을 지적했습니다.-fomit-frame-pointerx86-16 플랫폼과 x86-32/64 플랫폼 간의 상호 접속이 가능합니다.

이 옵션–-fomit-frame-pointer GCC뿐만 아니라 인텔 C++ 컴파일러 15.0과도 관련이 있습니다.

인텔 컴파일러의 경우 이 옵션에는 에일리어스가 있습니다./Oy.

Here is what Intel wrote about it:

These options determine whether EBP is used as a general-purpose register in optimizations. Options -fomit-frame-pointer and /Oy allow this use. Options -fno-omit-frame-pointer and /Oy- disallow it.

Some debuggers expect EBP to be used as a stack frame pointer, and cannot produce a stack back-trace unless this is so. The -fno-omit-frame-pointer and /Oy- options direct the compiler to generate code that maintains and uses EBP as a stack frame pointer for all functions so that a debugger can still produce a stack back-trace without doing the following:

For -fno-omit-frame-pointer: turning off optimizations with -O0 For /Oy-: turning off /O1, /O2, or /O3 optimizations The -fno-omit-frame-pointer option is set when you specify option -O0 or the -g option. The -fomit-frame-pointer option is set when you specify option -O1, -O2, or -O3.

The /Oy option is set when you specify the /O1, /O2, or /O3 option. Option /Oy- is set when you specify the /Od option.

Using the -fno-omit-frame-pointer or /Oy- option reduces the number of available general-purpose registers by 1 and can result in slightly less efficient code.

NOTE For Linux* systems: There is currently an issue with GCC 3.2 exception handling. Therefore, the Intel compiler ignores this option when GCC 3.2 is installed for C++ and exception handling is turned on (the default).

Please be aware that the above quote is only relevant for the Intel C++ 15 compiler, not to GCC.

I haven't come across the term "activation record" before, but I would assume it reffers to what is normally called a "stack frame". That is the area on the stack used by the current function.

The frame pointer is a register that holds the address of the current function's stack frame. If a frame pointer is used then on entering the function the old frame pointer is saved to the stack and the frame pointer is set to the stack pointer. On leaving the function the old frame pointer is restored.

Most normal functions don't need a frame pointer for their own operation. The compiler can keep track of the stack pointer offset on all codepaths through the function and generate local variable accesses accordingly.

프레임 포인터는 디버깅 및 예외 처리에 중요한 경우가 있습니다.그러나 대부분의 경우 프레임 포인터가 없는 기능을 지원하도록 설계된 최신 디버깅 및 예외 처리 형식이 점점 더 드물어지고 있습니다.

현재 프레임 포인터가 필요한 주요 시간은 함수가 alloca 또는 가변 길이 배열을 사용하는 경우입니다.이 경우 스택 포인터의 값은 스태틱하게 추적할 수 없습니다.

언급URL : https://stackoverflow.com/questions/14666665/trying-to-understand-gcc-option-fomit-frame-pointer

반응형