RHEL 8에서 C 및 C++ 애플리케이션 개발
개발자 워크스테이션 설정 및 Red Hat Enterprise Linux 8에서 C 및 C++ 애플리케이션 개발 및 디버깅
초록
Red Hat 문서에 관한 피드백 제공
문서에 대한 피드백에 감사드립니다. 어떻게 개선할 수 있는지 알려주십시오.
Jira를 통해 피드백 제출 (등록 필요)
- Jira 웹 사이트에 로그인합니다.
- 상단 탐색 모음에서 생성 을 클릭합니다.
- Summary (요약) 필드에 설명 제목을 입력합니다.
- Description (설명) 필드에 개선을 위한 제안을 입력합니다. 문서의 관련 부분에 대한 링크를 포함합니다.
- 대화 상자 하단에서 생성 을 클릭합니다.
1장. 개발 워크스테이션 설정
Red Hat Enterprise Linux 8은 사용자 지정 애플리케이션 개발을 지원합니다. 개발자가 이를 수행할 수 있도록 하려면 필요한 툴과 유틸리티를 사용하여 시스템을 설정해야 합니다. 이 장에서는 개발 및 설치할 항목의 가장 일반적인 사용 사례를 나열합니다.
1.1. 사전 요구 사항
- 시스템은 그래픽 환경을 포함한 설치되고 가입되어야 합니다.
1.2. 디버그 및 소스 리포지토리 활성화
Red Hat Enterprise Linux의 표준 설치는 디버그 및 소스 리포지토리를 활성화하지 않습니다. 이러한 리포지토리에는 시스템 구성 요소를 디버그하고 해당 성능을 측정하는 데 필요한 정보가 포함되어 있습니다.
절차
소스 및 디버깅 정보 패키지 채널을 활성화합니다.
# subscription-manager repos --enable rhel-8-for-$(uname -i)-baseos-debug-rpms # subscription-manager repos --enable rhel-8-for-$(uname -i)-baseos-source-rpms # subscription-manager repos --enable rhel-8-for-$(uname -i)-appstream-debug-rpms # subscription-manager repos --enable rhel-8-for-$(uname -i)-appstream-source-rpms
$(uname -i)
부분은 시스템 아키텍처와 일치하는 값으로 자동 교체됩니다.아키텍처 이름 값 64비트 Intel 및 AMD
x86_64
64비트 ARM
aarch64
IBM POWER
ppc64le
64-bit IBM Z
s390x
1.3. 애플리케이션 버전을 관리하기 위한 설정
효과적인 버전 제어는 모든 다중 개발자 프로젝트에 필수적입니다. Red Hat Enterprise Linux는 분산 버전 제어 시스템인 Git과 함께 제공됩니다.
절차
git 패키지를 설치합니다.
# yum install git
선택 사항: Git 커밋과 연결된 전체 이름 및 이메일 주소를 설정합니다.
$
git config --global user.name "Full Name"
$git config --global user.email "email@example.com"
Full Name (전체 이름)과 실제 이름 및 이메일 주소로 바꿉니다.
선택 사항: Git에서 시작한 기본 텍스트 편집기를 변경하려면
core.editor 구성 옵션의 값을 설정합니다.
$
git config --global core.editor command
선택한 텍스트 편집기 를 시작하는 데 사용할 명령으로 명령을 바꿉니다.
추가 리소스
Git 및 튜토리얼용 Linux 도움말 페이지:
$ man git $ man gittutorial $ man gittutorial-2
대부분의 Git 명령에는 고유한 도움말 페이지가 있습니다. 예를 들어 git-commit(1) 을 참조하십시오.
1.4. C 및 C++를 사용한 애플리케이션 개발 구축
Red Hat Enterprise Linux에는 C 및 C++ 애플리케이션 개발을 위한 툴이 포함되어 있습니다.
사전 요구 사항
- 디버그 및 소스 리포지토리를 활성화해야 합니다.
절차
GCC( GNU 컴파일러 컬렉션), GDB(GNU Debugger) 및 기타 개발 툴을 포함한 개발 도구 패키지 그룹을 설치합니다.
# yum group install "Development Tools"
clang
컴파일러 및lldb
디버거를 포함하여 LLVM 기반 툴체인을 설치합니다.# yum install llvm-toolset
선택 사항: Fortran 종속성의 경우 GNU Fortran 컴파일러를 설치합니다.
# yum install gcc-gfortran
1.5. 애플리케이션 디버깅으로 설정
Red Hat Enterprise Linux는 여러 디버깅 및 계측 툴을 제공하여 내부 애플리케이션 동작을 분석하고 문제를 해결합니다.
사전 요구 사항
- 디버그 및 소스 리포지토리를 활성화해야 합니다.
절차
디버깅에 유용한 툴을 설치합니다.
# yum install gdb valgrind systemtap ltrace strace
debuginfo -install 툴을 사용하려면 yum-utils 패키지를 설치합니다
.# yum install yum-utils
환경을 설정하기 위해 SystemTap 도우미 스크립트를 실행합니다.
# stap-prep
stap-prep 은 현재 실행 중인 커널과 관련된 패키지를 설치합니다. 이 패키지는 실제로 설치된 커널과 같지 않을 수 있습니다. stap-prep 이 올바른 kernel-debuginfo 및 kernel -headers 패키지를 설치하도록 하려면
uname -r
명령을 사용하여 현재 커널 버전을 재확인하고 필요한 경우 시스템을 재부팅합니다.-
SELinux 정책에서
관련 애플리케이션을 정상적으로 실행할 수 있을 뿐 아니라 디버깅 상황도 실행할 수 있는지 확인합니다. 자세한 내용은 SELinux 사용을 참조하십시오.
추가 리소스
1.6. 애플리케이션 성능 측정을 위해 설정
Red Hat Enterprise Linux에는 개발자가 애플리케이션 성능 손실의 원인을 파악하는 데 도움이 되는 여러 애플리케이션이 포함되어 있습니다.
사전 요구 사항
- 디버그 및 소스 리포지토리를 활성화해야 합니다.
절차
성능 측정 도구를 설치합니다.
# yum install perf papi pcp-zeroconf valgrind strace sysstat systemtap
환경을 설정하기 위해 SystemTap 도우미 스크립트를 실행합니다.
# stap-prep
stap-prep 은 현재 실행 중인 커널과 관련된 패키지를 설치합니다. 이 패키지는 실제로 설치된 커널과 같지 않을 수 있습니다. stap-prep 이 올바른 kernel-debuginfo 및 kernel -headers 패키지를 설치하도록 하려면
uname -r
명령을 사용하여 현재 커널 버전을 재확인하고 필요한 경우 시스템을 재부팅합니다.PCP(Performance Co-Pilot) 컬렉터 서비스를 활성화하고 시작합니다.
# systemctl enable pmcd && systemctl start pmcd
2장. C 또는 C++ 애플리케이션 생성
2.1. GCC를 사용하여 코드 빌드
소스 코드를 실행 코드로 변환해야 하는 상황에 대해 알아봅니다.
2.1.1. 코드 양식의 관계
사전 요구 사항
- 컴파일 및 연결의 개념 이해
가능한 코드 양식
C 및 C++ 언어는 다음 세 가지 형식을 지원합니다.
C 또는 C++ 언어로 작성된 소스 코드는 일반 텍스트 파일로 제공됩니다.
일반적으로 파일은
.c,.
cc,.
cpp,.
h,.
hpp,.
i,.
inc
등의 확장 프로그램을 사용합니다. 지원되는 확장 기능 및 해석의 전체 목록은 gcc 도움말 페이지를 참조하십시오.$ man gcc
컴파일러 로 소스 코드를 컴파일 하여 생성된 개체 코드입니다. 이는 중간 형식입니다.
오브젝트 코드 파일은
.o
확장자를 사용합니다.개체 코드를 링커 와 연결하여 만든 실행 코드.
Linux 애플리케이션 실행 파일은 파일 이름 확장자를 사용하지 않습니다. 공유 오브젝트(library) 실행 파일은
.so
파일 이름 확장자를 사용합니다.
정적 연결을 위한 라이브러리 아카이브 파일도 존재합니다. 이것은 .a
파일 이름 확장을 사용하는 오브젝트 코드의 변형입니다. 정적 연결은 권장되지 않습니다. 2.2.2절. “정적 및 동적 연결”을 참조하십시오.
GCC에서 코드 양식 처리
소스 코드에서 실행 가능한 코드를 생성하는 작업은 두 단계로 수행되며 서로 다른 애플리케이션 또는 도구가 필요합니다. GCC는 컴파일러와 링커 모두에 대한 지능형 드라이버로 사용할 수 있습니다. 이렇게 하면 필수 작업(컴파일링 및 연결)에 단일 gcc
명령을 사용할 수 있습니다. GCC는 작업 및 해당 시퀀스를 자동으로 선택합니다.
- 소스 파일은 오브젝트 파일로 컴파일됩니다.
- 오브젝트 파일과 라이브러리가 연결되어 있습니다(이전 컴파일된 소스 포함).
단일 단계에서 컴파일, 연결 또는 컴파일 및 연결을 모두 수행할 수 있도록 GCC를 실행할 수 있습니다.It is possible to run GCC so that it performs only compiling, only linking, or both compiling and linking in a single step. 입력 유형과 요청된 출력 유형에 따라 결정됩니다.
대규모 프로젝트에는 각 작업에 대해 일반적으로 GCC를 별도로 실행하는 빌드 시스템이 필요하므로 GCC가 두 가지 개별 작업으로 항상 컴파일하고 연결하는 것이 좋습니다.
2.1.2. 개체 코드로 소스 파일 컴파일
소스 파일에서 개체 코드 파일을 즉시 생성하고 실행 파일이 아닌 경우 GCC는 출력으로 개체 코드 파일만 생성하도록 지시해야 합니다. 이 작업은 대규모 프로젝트에 대한 빌드 프로세스의 기본 작업을 나타냅니다.
사전 요구 사항
- C 또는 C++ 소스 코드 파일
- 시스템에 GCC가 설치됨
절차
- 소스 코드 파일이 포함된 디렉터리로 변경합니다.
c
옵션을
사용하여gcc
를 실행합니다.$ gcc -c source.c another_source.c
개체 파일은 원본 소스 코드 파일을 반영하는 파일 이름을 사용하여 생성됩니다
. source.c
는source.o
가 됩니다.참고C++ 소스 코드로
gcc
명령을g++로 교체하여 C++
표준 라이브러리 종속성을 편리하게 처리하십시오.
2.1.3. GCC를 사용하여 C 및 C++ 애플리케이션 디버깅 활성화
디버깅 정보는 크기 때문에 기본적으로 실행 파일에 포함되지 않습니다. C 및 C++ 애플리케이션을 디버깅할 수 있도록 하려면 컴파일러에 이를 명시적으로 지시해야 합니다.
코드를 컴파일하고 연결할 때 GCC 를 사용하여 디버깅 정보를 생성할 수 있도록 하려면 -g
옵션을 사용합니다.
$ gcc ... -g ...
-
컴파일러 및 링커에 의해 수행되는 최적화는 원래 소스 코드와 관련되기 어려운 실행 코드를 초래할 수 있습니다. 변수가 최적화되고, 스크롤되지 않고, 작업이 주변에 병합될 수 있습니다. 이는 디버깅에 부정적인 영향을 미칩니다. 디버깅 환경을 개선하려면
-Og
옵션으로 최적화를 설정하는 것이 좋습니다. 그러나 최적화 수준을 변경하면 실행 코드가 변경되며 일부 버그 제거를 포함하여 실제 동작을 변경할 수 있습니다. -
디버그 정보에 매크로 정의를 포함하려면 g 대신
-g
3 -
f
compare-debug
GCC 옵션은 디버그 정보와 디버그 정보 없이 GCC에서 컴파일한 코드를 테스트합니다. 결과 두 바이너리 파일이 동일한 경우 테스트가 통과합니다. 이 테스트를 사용하면 디버깅 옵션의 영향을 받지 않으므로 디버그 코드에 숨겨진 버그가 없습니다. fcompare-debug
옵션을 사용하면 컴파일 시간이 크게 증가합니다. 이 옵션에 대한 자세한 내용은 GCC 도움말 페이지를 참조하십시오.
추가 리소스
- 3.1절. “디버깅 정보를 사용하여 디버깅 활성화”
- GCC(GNU 컴파일러 컬렉션) 사용 - 프로그램 디버깅 옵션
- GDB를 사용하여 디버깅 - 별도의 파일에 정보 디버깅 https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
GCC 도움말 페이지:
$ man gcc
2.1.4. GCC를 사용한 코드 최적화
단일 프로그램은 2개 이상의 머신 명령어로 변환될 수 있습니다. 컴파일 중 코드를 분석하는 데 더 많은 리소스를 할당하면 더 최적의 결과를 얻을 수 있습니다.
GCC를 사용하면 -O 수준옵션을
사용하여 최적화 수준을 설정할 수 있습니다. 이 옵션은 수준 대신 값 집합을 허용합니다.
level | 설명 |
---|---|
| 컴파일 속도에 최적화 - 코드 최적화(기본값) 없음. |
| 코드 실행 속도를 높이도록 최적화합니다(숫자가 클수록 속도가 증가). |
| 파일 크기에 최적화. |
|
레벨 |
| 디버깅 환경에 최적화. |
릴리스 빌드의 경우 최적화 옵션 -O2
를 사용합니다.
개발 중에 -Og
옵션은 일부 상황에서 프로그램 또는 라이브러리를 디버깅하는 데 유용합니다. 일부 버그 매니페스트는 특정 최적화 수준으로만 표시되므로 릴리스 최적화 수준으로 프로그램 또는 라이브러리를 테스트하십시오.
GCC는 개별 최적화를 가능하게 하는 다양한 옵션을 제공합니다. 자세한 내용은 다음 추가 리소스를 참조하십시오.
추가 리소스
- GNU 컴파일러 컬렉션 사용 - 제어 최적화 옵션
GCC의 Linux 도움말 페이지:
$ man gcc
2.1.5. GCC를 사용하여 코드 강화 옵션
컴파일러가 소스 코드를 개체 코드로 변환할 때 일반적으로 악용되는 상황을 방지하고 보안을 강화하기 위해 다양한 점검을 추가할 수 있습니다. 컴파일러 옵션 집합을 선택하면 소스 코드를 변경할 필요 없이 보다 안전한 프로그램과 라이브러리를 생성할 수 있습니다.
릴리스 버전 옵션
다음은 Red Hat Enterprise Linux를 대상으로 하는 개발자에게 최소 권장 옵션 목록입니다.
$ gcc ... -O2 -g -Wall -Wl,-z,now,-z,relro -fstack-protector-strong -fstack-clash-protection -D_FORTIFY_SOURCE=2 ...
-
프로그램의 경우
-fPIE
및-pie
Position Independent Executable 옵션을 추가합니다. -
동적으로 연결된 라이브러리의 경우 필수
-fPIC
(Position Independent Code) 옵션은 간접적으로 보안을 강화합니다.
개발 옵션
다음 옵션을 사용하여 개발 중에 보안 결함을 감지합니다. 릴리스 버전 옵션과 함께 다음 옵션을 사용합니다.
$ gcc ... -Walloc-zero -Walloca-larger-than -Wextra -Wformat-security -Wvla-larger-than ...
추가 리소스
- Defensive Coding 가이드
- GCC를 사용한 메모리 오류 감지 - Red Hat 개발자 블로그 게시
2.1.6. 실행 가능한 파일 생성을 위한 코드 연결
C 또는 C++ 애플리케이션을 빌드할 때의 마지막 단계는 연결입니다. 연결은 모든 개체 파일과 라이브러리를 실행 파일로 결합합니다.
사전 요구 사항
- 하나 이상의 오브젝트 파일
- gcc는 시스템에 설치되어 있어야 합니다.
절차
- 개체 코드 파일이 포함된 디렉터리로 변경합니다.
gcc
실행 :$ gcc ... objfile.o another_object.o ... -o executable-file
executable-file이라는 실행 가능한 파일은 제공된 오브젝트 파일 및 라이브러리에서 생성됩니다.
추가 라이브러리를 연결하려면 오브젝트 파일 목록 뒤에 필요한 옵션을 추가합니다. 자세한 내용은 2.2절. “GCC와 함께 라이브러리 사용”의 내용을 참조하십시오.
참고C++ 소스 코드로
gcc
명령을g++로 교체하여 C++
표준 라이브러리 종속성을 편리하게 처리하십시오.
2.1.7. 예제: GCC를 사용하여 C 프로그램 빌드(한 단계로 컴파일 및 연결)
이 예에서는 간단한 샘플 C 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서는 코드를 컴파일하고 연결하는 작업이 한 단계로 수행됩니다.
사전 요구 사항
- GCC 사용 방법을 알아야 합니다.
절차
hello-c
디렉터리를 생성하고 변경합니다.$ mkdir hello-c $ cd hello-c
다음 콘텐츠를 사용하여
hello.c
파일을 생성합니다.#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
GCC로 코드를 컴파일하고 연결합니다.
$ gcc hello.c -o helloworld
이렇게 하면 코드가 컴파일되고, 오브젝트 파일
hello.o
를 생성하고, 오브젝트 파일에서 실행 파일helloworld
를 연결합니다.결과 실행 파일을 실행합니다.
$ ./helloworld Hello, World!
2.1.8. 예제: GCC로 C 프로그램 빌드(두 단계로 컴파일 및 연결)
이 예에서는 간단한 샘플 C 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서는 코드를 컴파일하고 연결하는 방법은 두 가지입니다.
사전 요구 사항
- GCC 사용 방법을 알아야 합니다.
절차
hello-c
디렉터리를 생성하고 변경합니다.$ mkdir hello-c $ cd hello-c
다음 콘텐츠를 사용하여
hello.c
파일을 생성합니다.#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
GCC를 사용하여 코드를 컴파일하십시오.
$ gcc -c hello.c
오브젝트 파일
hello.o
가 생성됩니다.오브젝트 파일에서 실행 가능한 파일
helloworld
를 연결합니다.$ gcc hello.o -o helloworld
결과 실행 파일을 실행합니다.
$ ./helloworld Hello, World!
2.1.9. 예제: GCC로 C++ 프로그램 빌드(단일 단계로 컴파일 및 연결)
이 예에서는 샘플 최소 C++ 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서는 코드를 컴파일하고 연결하는 작업이 한 단계로 수행됩니다.
사전 요구 사항
-
gcc
와g++
의 차이점을 이해해야 합니다.
절차
hello-cpp
디렉터리를 생성하고 변경합니다.$ mkdir hello-cpp $ cd hello-cpp
다음 콘텐츠를 사용하여
hello.cpp
파일을 생성합니다.#include <iostream> int main() { std::cout << "Hello, World!\n"; return 0; }
코드를 컴파일하고
g++
로 연결 :$ g++ hello.cpp -o helloworld
이렇게 하면 코드가 컴파일되고, 오브젝트 파일
hello.o
를 생성하고, 오브젝트 파일에서 실행 파일helloworld
를 연결합니다.결과 실행 파일을 실행합니다.
$ ./helloworld Hello, World!
2.1.10. 예제: GCC로 C++ 프로그램 빌드(두 단계로 컴파일 및 연결)
이 예에서는 샘플 최소 C++ 프로그램을 빌드하는 정확한 단계를 보여줍니다.
이 예제에서는 코드를 컴파일하고 연결하는 방법은 두 가지입니다.
사전 요구 사항
-
gcc
와g++
의 차이점을 이해해야 합니다.
절차
hello-cpp
디렉터리를 생성하고 변경합니다.$ mkdir hello-cpp $ cd hello-cpp
다음 콘텐츠를 사용하여
hello.cpp
파일을 생성합니다.#include <iostream> int main() { std::cout << "Hello, World!\n"; return 0; }
g++
로 코드를 컴파일하십시오.$ g++ -c hello.cpp
오브젝트 파일
hello.o
가 생성됩니다.오브젝트 파일에서 실행 가능한 파일
helloworld
를 연결합니다.$ g++ hello.o -o helloworld
결과 실행 파일을 실행합니다.
$ ./helloworld Hello, World!
2.2. GCC와 함께 라이브러리 사용
코드에서 라이브러리 사용에 대해 알아봅니다.
2.2.1. 라이브러리 이름 지정 규칙
특수 파일 이름 규칙은 라이브러리에 사용됩니다. foo라는 라이브러리가 파일 lib foo.so 또는
로 존재할 것으로 예상됩니다. 이 규칙은 GCC의 입력 옵션을 연결하면 자동으로 이해되지만 출력 옵션에는 해당되지 않습니다.
libfoo .
a
라이브러리에 대해 연결할 때 라이브러리는
-l 옵션을 -l
foo:
로 사용하여 foo 이름으로만 지정할 수 있습니다.$ gcc ... -lfoo ...
-
라이브러리를 생성할 때 전체 파일 이름
libfoo.so
또는libfoo.a
를 지정해야 합니다.
추가 리소스
2.2.2. 정적 및 동적 연결
개발자는 완전히 컴파일된 언어로 애플리케이션을 빌드할 때 정적 또는 동적 연결을 사용할 수 있습니다. 특히 Red Hat Enterprise Linux에서 C 및 C++ 언어를 사용하는 컨텍스트에서 정적 연결과 동적 연결의 차이점을 이해하는 것이 중요합니다. 요약하자면, Red Hat은 Red Hat Enterprise Linux의 애플리케이션에서 정적 링크 사용을 권장하지 않습니다.
정적 및 동적 연결 비교
정적 연결은 라이브러리가 결과 실행 파일의 일부로 만듭니다. 동적 연결은 이러한 라이브러리를 별도의 파일로 유지합니다.
동적 및 정적 연결은 다음과 같은 여러 방법으로 비교할 수 있습니다.
- 리소스 사용
정적 연결로 더 많은 코드가 포함된 실행 파일이 더 커집니다. 라이브러리에서 제공하는 이 추가 코드는 시스템의 여러 프로그램에서 공유할 수 없으므로 런타임에 파일 시스템 사용과 메모리 사용량이 증가합니다. 정적으로 연결된 동일한 프로그램을 실행하는 여러 프로세스가 여전히 코드를 공유합니다.
반면, 정적 애플리케이션에는 더 적은 가동 시간 재배치가 필요하므로 시작 시간이 줄어들고RSS(개인 상주 설정 크기) 메모리가 줄어듭니다. 정적 연결을 위한 생성된 코드는 PoC(위치 종속 코드)에서 도입한 오버헤드로 인해 동적 연결보다 효율적일 수 있습니다.
- 보안
- ABI 호환성을 제공하는 동적으로 연결된 라이브러리는 이러한 라이브러리에 따라 실행 파일을 변경하지 않고 업데이트할 수 있습니다. 이는 Red Hat이 보안 업데이트를 제공하는 Red Hat Enterprise Linux의 일부로 Red Hat에서 제공하는 라이브러리에 특히 중요합니다. 이러한 라이브러리에 대한 정적 연결은 권장되지 않습니다.
- 호환성
정적 연결은 운영 체제에서 제공하는 라이브러리 버전과 관계없이 실행 파일을 제공하는 것으로 나타납니다. 그러나 대부분의 라이브러리는 다른 라이브러리에 의존합니다. 정적 연결을 사용하면 이 종속성이 유연해지므로 정방향 및 이전 버전과의 호환성이 모두 손실됩니다. 정적 연결은 실행 파일이 빌드된 시스템에서만 작동하도록 보장됩니다.
주의GNU C 라이브러리(glibc)에서 정적 라이브러리를 연결하는 애플리케이션은 여전히 glibc 가 동적 라이브러리로서 시스템에 존재해야 합니다. 또한 애플리케이션 실행 시 사용할 수 있는 glibc 의 동적 라이브러리 변형은 애플리케이션을 연결하는 동안 현재 버전과 약간 동일한 버전이어야 합니다. 따라서 정적 연결은 실행 파일이 빌드된 시스템에서만 작동할 수 있습니다.
- 지원 범위
- Red Hat에서 제공하는 대부분의 정적 라이브러리는 CodeReady Linux Builder 채널에 있으며 Red Hat에서 지원하지 않습니다.
- 기능
일부 라이브러리, 특히 GNU C 라이브러리(glibc)는 정적으로 연결될 때 축소된 기능을 제공합니다.
예를 들어, 정적으로 연결된 경우 glibc 는 스레드를 지원하지 않으며 동일한 프로그램에서
dlopen()
함수에 대한 호출 형식을 지원합니다.
나열된 단점으로 인해 특히 전체 애플리케이션 및 glibc 및 libstdc++ 라이브러리의 경우 정적 연결을 피할 수 있습니다.
정적 연결 케이스
다음과 같은 일부 경우 정적 연결이 합리적인 선택이 될 수 있습니다.
- 동적 연결에 사용할 수 없는 라이브러리 사용.
-
빈 chroot 환경 또는 컨테이너에서 코드를 실행하려면 완전히 정적 연결이 필요할 수 있습니다. 그러나 Red Hat에서는
glibc-static
패키지를 사용한 정적 연결은 지원되지 않습니다.
추가 리소스
2.2.3. GCC를 사용하여 라이브러리 사용
라이브러리는 프로그램에서 재사용할 수 있는 코드 패키지입니다. C 또는 C++ 라이브러리는 다음 두 부분으로 구성됩니다.
- 라이브러리 코드
- 헤더 파일
라이브러리를 사용하는 코드 컴파일
헤더 파일은 라이브러리의 인터페이스, 라이브러리에서 사용할 수 있는 함수 및 변수를 설명합니다. 헤더 파일의 정보는 코드를 컴파일하는 데 필요합니다.
일반적으로 라이브러리의 헤더 파일은 애플리케이션 코드와 다른 디렉터리에 저장됩니다. GCC에 헤더 파일이 있는 위치를 지정하려면 -I
옵션을 사용합니다.
$ gcc ... -Iinclude_path ...
include_path 를 헤더 파일 디렉터리의 실제 경로로 바꿉니다.
I
옵션을 여러 번 사용하여 헤더 파일로 여러 디렉터리를 추가할 수 있습니다. 헤더 파일을 찾을 때 이러한 디렉터리는 -I
옵션에 표시되는 순서대로 검색됩니다.
라이브러리를 사용하는 코드 연결
실행 파일을 연결할 때 애플리케이션의 개체 코드와 라이브러리의 바이너리 코드를 모두 사용할 수 있어야 합니다. 정적 및 동적 라이브러리의 코드는 다양한 형태로 제공됩니다.
-
정적 라이브러리는 아카이브 파일로 사용할 수 있습니다. 개체 파일의 그룹이 포함되어 있습니다. 아카이브 파일에는 파일 이름 확장명이 있습니다
.
-
동적 라이브러리는 공유 개체로 사용할 수 있습니다. 실행 파일의 형식입니다. 공유 오브젝트에는 파일 이름 확장명이 있습니다
.so
.
GCC에 라이브러리의 아카이브 또는 공유 오브젝트 파일을 지정하려면 -L
옵션을 사용합니다.
$ gcc ... -Llibrary_path -lfoo ...
library_path 를 라이브러리 디렉터리의 실제 경로로 바꿉니다.
L 옵션을 여러
번 사용하여 여러 디렉터리를 추가할 수 있습니다. 라이브러리를 찾을 때 이러한 디렉터리는 -L
옵션 순서로 검색됩니다.
옵션의 순서가 중요합니다. GCC는 이 라이브러리의 디렉토리를 모르는 한 foo 라이브러리와 연결할 수 없습니다. 따라서 라이브러리를 연결하는 데 -
옵션을 사용하여 라이브러리 디렉터리를 지정합니다.
l 옵션을 사용하기 전에 -
L
한 단계에서 라이브러리를 사용하는 코드 컴파일 및 연결
코드를 컴파일하고 하나의 gcc
명령에 연결할 수 있는 경우 한 번에 위에서 언급한 두 가지 상황에 대해 옵션을 사용합니다.
추가 리소스
- GNU Compiler Collection (GCC) 사용 - 디렉터리 검색 옵션
- GNU Compiler Collection (GCC) 사용 - 링크 옵션
2.2.4. GCC와 함께 정적 라이브러리 사용
정적 라이브러리는 오브젝트 파일을 포함하는 아카이브로 사용할 수 있습니다. 연결한 후 결과 실행 파일의 일부가 됩니다.
Red Hat은 보안상의 이유로 정적 링크 사용을 권장하지 않습니다. 2.2.2절. “정적 및 동적 연결”을 참조하십시오. 특히 Red Hat에서 제공하는 라이브러리에 대해 필요할 때만 정적 링크를 사용합니다.
사전 요구 사항
- GCC는 시스템에 설치되어 있어야 합니다.
- 정적 및 동적 연결을 이해해야 합니다.
- 유효한 프로그램을 구성하는 일련의 소스 또는 오브젝트 파일이 있으므로 일부 정적 라이브러리 foo 및 다른 라이브러리가 필요하지 않습니다.
-
foo 라이브러리는
libfoo.a
파일로 사용할 수 있으며 동적 연결에는libfoo.so
파일이 제공되지 않습니다.
Red Hat Enterprise Linux의 일부인 대부분의 라이브러리는 동적 연결에만 지원됩니다. 아래 단계는 동적 연결에 사용할 수 없는 라이브러리에서만 작동합니다. 2.2.2절. “정적 및 동적 연결”을 참조하십시오.
절차
소스 및 객체 파일에서 프로그램을 연결하려면 libfoo.a 파일로 찾을 수 있는 정적으로 연결된 라이브러리 foo 를 추가합니다.
- 코드가 포함된 디렉터리로 변경합니다.
foo 라이브러리의 헤더를 사용하여 프로그램 소스 파일을 컴파일합니다.
$ gcc ... -Iheader_path -c ...
header_path 를 foo 라이브러리의 헤더 파일이 포함된 디렉터리의 경로로 바꿉니다.
foo 라이브러리와 프로그램을 연결합니다.
$ gcc ... -Llibrary_path -lfoo ...
library_path 를
libfoo.a
파일이 포함된 디렉터리 경로로 바꿉니다.나중에 프로그램을 실행하려면 다음을 수행하십시오.
$ ./program
정적 링크와 관련된 -static
GCC 옵션은 모든 동적 연결을 금지합니다. 대신 -Wl,-Bstatic
및 -Wl,-Bdynamic
옵션을 사용하여 링커 동작을 보다 정확하게 제어합니다. 2.2.6절. “GCC를 사용하여 정적 및 동적 라이브러리 사용”을 참조하십시오.
2.2.5. GCC와 함께 동적 라이브러리 사용
동적 라이브러리는 연결 시간과 런타임 모두에 필요한 독립 실행형 실행 파일로 사용할 수 있습니다. 애플리케이션의 실행 파일과는 별개로 유지됩니다.
사전 요구 사항
- GCC는 시스템에 설치되어 있어야 합니다.
- 유효한 프로그램을 구성하는 소스 또는 오브젝트 파일 세트로, 일부 동적 라이브러리 foo 및 다른 라이브러리가 필요하지 않습니다.
- foo 라이브러리는 libfoo.so 파일로 사용할 수 있어야 합니다.
동적 라이브러리에 대해 프로그램 연결
동적 라이브러리 foo 에 대해 프로그램을 연결하려면 다음을 수행합니다.
$ gcc ... -Llibrary_path -lfoo ...
프로그램이 동적 라이브러리와 연결되어 있는 경우 결과 프로그램은 항상 런타임에 라이브러리를 로드해야 합니다. 라이브러리를 찾는 데는 두 가지 옵션이 있습니다.
-
실행 파일 자체에 저장된
rpath
값 사용 -
런타임 시
LD_LIBRARY_PATH
변수 사용
실행 가능한 파일에 저장된 rpath
값 사용
rpath
는 연결될 때 실행 파일의 일부로 저장되는 특수 값입니다. 나중에 프로그램이 실행 파일에서 로드되면 런타임 링커는 rpath
값을 사용하여 라이브러리 파일을 찾습니다.
GCC 와 연결하는 동안 경로 library_path를 rpath
로 저장합니다.
$ gcc ... -Llibrary_path -lfoo -Wl,-rpath=library_path ...
경로 library_path 는 libfoo.so 파일이 포함된 디렉터리를 가리켜야 합니다.
-Wl,-rpath=
옵션에 쉼표 뒤에 공백을 추가하지 마십시오.
프로그램을 나중에 실행하려면 다음을 수행합니다.
$ ./program
LD_LIBRARY_PATH 환경 변수 사용
프로그램의 실행 파일에 rpath
를 찾을 수 없는 경우 런타임 링커는 LD_LIBRARY_PATH
환경 변수를 사용합니다. 이 변수의 값은 각 프로그램에 대해 변경해야 합니다. 이 값은 공유 라이브러리 오브젝트가 있는 경로를 나타내야 합니다.
rpath
설정 없이 프로그램을 실행하려면 path library_path 에 라이브러리가 있음 :
$ export LD_LIBRARY_PATH=library_path:$LD_LIBRARY_PATH
$ ./program
rpath
값을 제외하면 유연성이 제공되지만, 프로그램을 실행할 때마다 LD_LIBRARY_PATH
변수를 설정해야 합니다.
라이브러리를 기본 디렉터리에 배치
런타임 링커 구성은 여러 디렉터리를 동적 라이브러리 파일의 기본 위치로 지정합니다. 이러한 기본 동작을 사용하려면 라이브러리를 적절한 디렉터리에 복사합니다.
동적 링커 동작에 대한 자세한 설명은 이 문서의 범위를 벗어납니다. 자세한 내용은 다음 리소스를 참조하십시오.
동적 링커의 Linux 도움말 페이지:
$ man ld.so
/etc/ld.so.conf
설정 파일의 내용:$ cat /etc/ld.so.conf
디렉터리가 포함된 추가 구성 없이 동적 링커에서 인식하는 라이브러리 보고서:
$ ldconfig -v
2.2.6. GCC를 사용하여 정적 및 동적 라이브러리 사용
경우에 따라 일부 라이브러리를 정적 및 일부 동적으로 연결해야 할 수도 있습니다. 이러한 상황은 몇 가지 도전 과제입니다.
사전 요구 사항
소개
GCC 는 동적 라이브러리와 정적 라이브러리를 모두 인식합니다. l foo
옵션이 나오면 gcc 는 먼저 foo 라이브러리의 동적으로 연결된 버전이 포함된 공유 오브젝트(a .so
파일)를 찾은 다음, 정적 버전의 라이브러리를 포함하는 아카이브 파일(.a
)을 찾습니다. 따라서 다음과 같은 상황이 발생할 수 있습니다.
- 공유 오브젝트만 발견되고 gcc 링크가 동적으로 제공됩니다.
- 아카이브만 발견되고 gcc 링크만 정적으로 연결됩니다.
- 공유 오브젝트와 아카이브가 모두 발견되며 gcc 는 공유 오브젝트에 대한 동적 연결을 선택합니다.
- 공유 개체와 아카이브를 모두 찾을 수 없으며 연결에 실패합니다.
이러한 규칙으로 인해 연결할 라이브러리의 정적 또는 동적 버전을 선택하는 가장 좋은 방법은 gcc 에서 해당 버전만 찾는 것입니다. 이 작업은 -L경로
옵션을 지정할 때 라이브러리 버전이 포함된 디렉터리를 사용하거나 종료하여 어느 정도까지 제어할 수 있습니다.
또한 동적 연결이 기본값이기 때문에 연결을 명시적으로 지정해야 하는 유일한 상황은 두 버전이 있는 라이브러리를 정적으로 연결해야 합니다. 두 가지 해결 방법이 있습니다.
-
l
옵션
대신 파일 경로로 정적 라이브러리 지정 -
옵션을 링크에 전달하려면
-Wl
옵션을 사용합니다.
파일을 기준으로 정적 라이브러리 지정
일반적으로 gcc 는 foo 라이브러리에 -l foo
옵션을 사용하여 연결하라는 지시를 받습니다. 대신 라이브러리를 포함하는 libfoo.a
파일의 전체 경로를 지정할 수 있습니다.
$ gcc ... path/to/libfoo.a ...
파일 확장자 에서
gcc 는 이것이 프로그램과 연결할 라이브러리임을 이해할 것입니다. 그러나 라이브러리 파일의 전체 경로를 지정하는 것은 덜 유연한 방법입니다.
W l 옵션
사용
gcc 옵션 -Wl
은 옵션을 기본 링커에 전달하는 특수 옵션입니다. 이 옵션의 구문은 다른 gcc 옵션과 다릅니다. w l
옵션 뒤에는 콤마로 구분된 링커 옵션 목록이 오는 반면, 다른 gcc 옵션에는 공백으로 구분된 옵션 목록이 필요합니다.
gcc 에서 사용하는 ld 링커는 이 옵션을 각각 정적으로 또는 동적으로 연결해야 하는지 여부를 지정하는
옵션을 제공합니다. B -Bstatic
및 -Bdynamicstatic
및 라이브러리를 링커에 통과한 후에는 기본 동적 연결 동작을 수동으로 복원해야 합니다. 이 경우 라이브러리가 -Bdynamic
옵션과 동적으로 연결되도록 수동으로 복원해야 합니다.
프로그램을 연결하려면 먼저 라이브러리를 정적으로 연결(libfirst.a
) 및 두 번째 동적으로 연결(libsecond.so
).
$ gcc ... -Wl,-Bstatic -lfirst -Wl,-Bdynamic -lsecond ...
gcc 는 기본 ld 이외의 링커를 사용하도록 구성할 수 있습니다.
추가 리소스
- GCC(GNU 컴파일러 컬렉션) 사용 - 연결 옵션 3.14 옵션
- binutils 2.27 - 2.1 명령줄 옵션설명서
2.3. GCC를 사용하여 라이브러리 만들기
라이브러리를 생성하는 단계와 Linux 운영 체제에서 라이브러리에 사용하는 필수 개념에 대해 알아봅니다.
2.3.1. 라이브러리 이름 지정 규칙
특수 파일 이름 규칙은 라이브러리에 사용됩니다. foo라는 라이브러리가 파일 lib foo.so 또는
로 존재할 것으로 예상됩니다. 이 규칙은 GCC의 입력 옵션을 연결하면 자동으로 이해되지만 출력 옵션에는 해당되지 않습니다.
libfoo .
a
라이브러리에 대해 연결할 때 라이브러리는
-l 옵션을 -l
foo:
로 사용하여 foo 이름으로만 지정할 수 있습니다.$ gcc ... -lfoo ...
-
라이브러리를 생성할 때 전체 파일 이름
libfoo.so
또는libfoo.a
를 지정해야 합니다.
추가 리소스
2.3.2. soname 메커니즘
동적으로 로드된 라이브러리(공유 오브젝트)는 soname 이라는 메커니즘을 사용하여 여러 호환 가능한 라이브러리 버전을 관리합니다.
사전 요구 사항
- 동적 연결 및 라이브러리를 이해해야 합니다.
- ABI 호환성이라는 개념을 이해해야 합니다.
- 라이브러리 이름 지정 규칙을 이해해야 합니다.
- 심볼릭 링크를 이해해야 합니다.
문제 도입
동적으로 로드된 라이브러리(공유 오브젝트)는 독립 실행 파일로 존재합니다. 이렇게 하면 라이브러리에 종속된 애플리케이션을 업데이트하지 않고 라이브러리를 업데이트할 수 있습니다. 그러나 이 개념에는 다음과 같은 문제가 발생합니다.
- 라이브러리의 실제 버전 식별
- 동일한 라이브러리의 여러 버전이 필요합니다.
- 여러 버전의 ABI 호환성 신호
soname 메커니즘
이 문제를 해결하기 위해 Linux는 soname이라는 메커니즘을 사용합니다.
foo
라이브러리 버전 X.Y 는 버전 번호에서 동일한 X 값을 가진 다른 버전과 ABI와 호환됩니다. 호환성을 유지하는 마이너 변경으로 숫자 Y 가 증가합니다. 호환성을 중단시키는 주요 변경 사항은 숫자 X 를 증가시킵니다.
실제 foo
라이브러리 버전 X.Y 는 libfoo.so.x.y
파일로 존재합니다. 라이브러리 파일 내에서 soname이 libfoo.so.x
값으로 기록되어 호환성을 나타냅니다.
애플리케이션이 빌드되면 링커에서 libfoo.so
파일을 검색하여 라이브러리를 찾습니다. 이 이름의 심볼릭 링크가 있어야 실제 라이브러리 파일을 가리키는 심볼릭 링크가 있어야 합니다. 그런 다음 링커는 라이브러리 파일에서 soname을 읽고 이를 애플리케이션 실행 파일에 기록합니다. 마지막으로 링커는 이름 또는 파일 이름이 아닌 soname을 사용하여 라이브러리에 대한 종속성을 선언하는 애플리케이션을 생성합니다.
런타임 동적 링커가 애플리케이션을 실행하기 전에 연결하면 애플리케이션 실행 파일에서 soname을 읽습니다. 이 soname은 libfoo.so.x
입니다. 이 이름의 심볼릭 링크가 있어야 실제 라이브러리 파일을 가리키는 심볼릭 링크가 있어야 합니다. 이렇게 하면 soname이 변경되지 않기 때문에 버전의 Y 구성 요소에 관계없이 라이브러리를 로드할 수 있습니다.
버전 번호의 Y 구성 요소는 단일 번호로만 제한되지 않습니다. 또한 일부 라이브러리는 해당 버전을 이름으로 인코딩합니다.
파일에서 soname 읽기
라이브러리 파일의 soname을 표시하려면 somelibrary
:
$ objdump -p somelibrary | grep SONAME
somelibrary 를 검사할 라이브러리의 실제 파일 이름으로 바꿉니다.
2.3.3. GCC를 사용하여 동적 라이브러리 생성
동적으로 연결된 라이브러리(공유 오브젝트)는 다음을 허용합니다.
- 코드 재사용을 통한 리소스
- 라이브러리 코드를 더 쉽게 업데이트할 수 있도록 함으로써 보안이 강화되었습니다.
다음 단계에 따라 소스에서 동적 라이브러리를 빌드하고 설치합니다.
사전 요구 사항
- soname 메커니즘을 이해해야 합니다.
- GCC는 시스템에 설치되어 있어야 합니다.
- 라이브러리에 대한 소스 코드가 있어야 합니다.
절차
- 라이브러리 소스를 사용하여 디렉터리로 변경합니다.
Position 독립적인 코드 옵션
-fPIC
를 사용하여 각 소스 파일을 개체 파일로 컴파일합니다.$ gcc ... -c -fPIC some_file.c ...
오브젝트 파일의 이름은 원본 소스 코드 파일과 동일하지만 해당 확장자는
.o
입니다.오브젝트 파일에서 공유 라이브러리를 연결합니다.
$ gcc -shared -o libfoo.so.x.y -Wl,-soname,libfoo.so.x some_file.o ...
사용된 주 버전 번호는 X 및 부 버전 번호 Y입니다.
libfoo.so.x.y
파일을 시스템의 동적 링커가 찾을 수 있는 적절한 위치에 복사합니다. Red Hat Enterprise Linux에서 라이브러리 디렉터리는/usr/lib64
입니다.# cp libfoo.so.x.y /usr/lib64
이 디렉터리의 파일을 조작하려면 루트 권한이 필요합니다.
soname 메커니즘에 대한 심볼릭 링크를 생성합니다.
# ln -s libfoo.so.x.y libfoo.so.x # ln -s libfoo.so.x libfoo.so
추가 리소스
- Linux 설명서 프로젝트 - 프로그램 라이브러리 HOWTO - 3. 라이브러리 공유
2.3.4. GCC 및 ar를 사용하여 정적 라이브러리 생성
오브젝트 파일을 특수 유형의 아카이브 파일로 변환하여 정적 연결을 위한 라이브러리를 만들 수 있습니다.
Red Hat은 보안상의 이유로 정적 링크 사용을 권장하지 않습니다. 특히 Red Hat에서 제공하는 라이브러리에 대해 필요할 때만 정적 링크를 사용합니다. 자세한 내용은 2.2.2절. “정적 및 동적 연결”를 참조하십시오.
사전 요구 사항
- GCC 및 binutils가 시스템에 설치되어 있어야 합니다.
- 정적 및 동적 연결을 이해해야 합니다.
- 라이브러리로 공유할 함수가 포함된 소스 파일을 사용할 수 있습니다.
절차
GCC를 사용하여 중간 개체 파일을 만듭니다.
$ gcc -c source_file.c ...
필요한 경우 소스 파일을 더 추가합니다. 결과 오브젝트 파일은 파일 이름을 공유하지만
.o
파일 이름 확장자를 사용합니다.binutils
패키지의ar
툴을 사용하여 오브젝트 파일을 정적 라이브러리(아카이브)로 전환합니다.$ ar rcs libfoo.a source_file.o ...
libfoo.a
파일이 생성됩니다.nm
명령을 사용하여 결과 아카이브를 검사합니다.$ nm libfoo.a
- 정적 라이브러리 파일을 적절한 디렉터리에 복사합니다.
라이브러리를 연결할 때 GCC는 라이브러리가 정적 연결을 위한 아카이브인
.a
파일 이름 확장자에서 자동으로 인식됩니다.$ gcc ... -lfoo ...
추가 리소스
ar(1) 의 Linux 도움말 페이지 :
$ man ar
2.4. Make를 사용하여 더 많은 코드 관리
GNU make 유틸리티는 일반적으로 축약된 make 에서 소스 파일에서 실행 파일 생성을 제어하는 도구입니다. 복잡한 프로그램의 어떤 부분이 변경되었으며 다시 컴파일해야 하는지 확인합니다. make 는 Makefiles라는 설정 파일을 사용하여 프로그램이 빌드되는 방식을 제어합니다.
2.4.1. GNU make
및 Makefile
개요
특정 프로젝트의 소스 파일에서 사용 가능한 양식(일반적으로 실행 파일)을 만들려면 몇 가지 필수 단계를 수행합니다. 작업 및 해당 시퀀스를 기록하여 나중에 반복할 수 있습니다.
Red Hat Enterprise Linux에는 이러한 목적을 위해 설계된 빌드 시스템인 GNU make
가 포함되어 있습니다.
사전 요구 사항
- 컴파일 및 연결의 개념 이해
GNU make
GNU make
는 빌드 프로세스를 설명하는 지침이 포함된 Makefiles를 읽습니다. Makefile에는 특정 조건(대상)을 충족하는 방법을 설명하는 특정 작업(메시피)을 설명하는 여러 규칙이 포함되어있습니다. 규칙은 다른 규칙에 따라 계층적으로 달라질 수 있습니다.
옵션 없이 make
를 실행하면 현재 디렉터리에서 Makefile을 찾아 기본 대상에 도달하려고 시도합니다. 실제 Makefile 파일 이름은 Makefile
,makefile
및 GNUmakefile
중 하나일 수 있습니다. 기본 대상은 Makefile 콘텐츠에서 결정됩니다.
Makefile 세부 정보
makefiles는 타겟 과 레시피로 구성된 변수 및 규칙을 정의하는 비교적 간단한 구문을 사용합니다. target은 규칙이 실행되는 경우 출력을 지정합니다. 레시피가 포함된 행은 TAB 문자로 시작해야 합니다.
일반적으로 Makefile에는 소스 파일을 컴파일하는 규칙, 결과 개체 파일을 연결하는 규칙 및 계층 구조의 맨 위 진입점 역할을 하는 대상이 포함됩니다.
단일 파일 hello.c
로 구성된 C 프로그램을 빌드하려면 다음 Makefile
을 고려해 보십시오.
all: hello hello: hello.o gcc hello.o -o hello hello.o: hello.c gcc -c hello.c -o hello.o
이 예에서는 대상에 도달하기 위해 hello
파일이 필요함
을 보여줍니다. hello를 얻으려면 hello
.o
(gcc로 링크됨 )
가 필요하며 hello.c
(gcc에 의해 컴파일됨 )
에서 생성됩니다.
target all
은 마침표(.)로 시작하지 않는 첫 번째 대상이기 때문에 기본 대상입니다. 인수 없이 make
를 실행하면 현재 디렉터리에 이 Makefile
이 포함된 경우 실행 중인 make
와 같습니다.
일반적인 Makefile
더 일반적인 Makefile에서는 단계를 일반화하기 위해 변수를 사용하고, 대상 "clean"을 추가합니다. - 소스 파일을 제외한 모든 항목을 제거합니다.
CC=gcc CFLAGS=-c -Wall SOURCE=hello.c OBJ=$(SOURCE:.c=.o) EXE=hello all: $(SOURCE) $(EXE) $(EXE): $(OBJ) $(CC) $(OBJ) -o $@ %.o: %.c $(CC) $(CFLAGS) $< -o $@ clean: rm -rf $(OBJ) $(EXE)
이러한 Makefile에 소스 파일을 추가하려면 SOURCE 변수가 정의된 행에만 추가하면 됩니다.
추가 리소스
- GNU make: 소개 - 2 Makefiles 소개
- 2.1절. “GCC를 사용하여 코드 빌드”
2.4.2. 예제: Makefile을 사용하여 C 프로그램 빌드
이 예제의 단계에 따라 Makefile을 사용하여 샘플 C 프로그램을 빌드합니다.
사전 요구 사항
절차
hellomake
디렉터리를 생성하고 이 디렉터리로 변경합니다.$ mkdir hellomake $ cd hellomake
다음 콘텐츠를 사용하여
hello.c
파일을 생성합니다.#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello, World!\n"); return 0; }
다음 콘텐츠를 사용하여
Makefile
파일을 생성합니다.CC=gcc CFLAGS=-c -Wall SOURCE=hello.c OBJ=$(SOURCE:.c=.o) EXE=hello all: $(SOURCE) $(EXE) $(EXE): $(OBJ) $(CC) $(OBJ) -o $@ %.o: %.c $(CC) $(CFLAGS) $< -o $@ clean: rm -rf $(OBJ) $(EXE)
중요Makefile 레시피 행은 탭 문자로 시작해야 합니다! 설명서에서 위의 텍스트를 복사하는 경우 cut-and-paste 프로세스는 탭 대신 공백을 붙여넣을 수 있습니다. 이 경우 문제를 수동으로 수정합니다.
make
: 실행$ make gcc -c -Wall hello.c -o hello.o gcc hello.o -o hello
그러면 실행 가능한 파일
hello
가 생성됩니다.실행 파일
hello
:$ ./hello Hello, World!
Makefile target
clean
을 실행하여 생성된 파일을 제거합니다.$ make clean rm -rf hello.o hello
2.4.3. Make
에 대한 문서 리소스
make
에 대한 자세한 내용은 아래 나열된 리소스를 참조하십시오.
설치된 문서
man
및info
툴을 사용하여 시스템에 설치된 도움말 페이지와 정보 페이지를 확인합니다.$ man make $ info make
온라인 문서
- Free Software Foundation에서 호스팅하는 GNU Make 설명서
2.5. RHEL 7 이후 툴체인의 변경
다음 섹션에서는 Red Hat Enterprise Linux 7에 설명된 구성 요소의 릴리스 이후 툴체인의 변경 사항을 나열합니다. Red Hat Enterprise Linux 8.0의 릴리스 노트 를 참조하십시오.
2.5.1. RHEL 8 GCC의 변경 사항
Red Hat Enterprise Linux 8에서 GCC 툴체인은 GCC 8.2 릴리스 시리즈를 기반으로 합니다. Red Hat Enterprise Linux 7 이후 주요 변경 사항은 다음과 같습니다.
- 별칭 분석, 벡터라이저 개선, 동일한 코드 접기, 절차 간 분석, 저장 최적화 패스 등의 다양한 일반적인 최적화가 추가되었습니다.
- Address Sanitizer가 개선되었습니다.
- 메모리 누수를 감지하기 위한 Leak Sanitizer가 추가되었습니다.
- 정의되지 않은 동작의 탐지를 위한 Undefined Behavior Sanitizer가 추가되었습니다.
- 이제 DWARF5 형식으로 디버그 정보를 생성할 수 있습니다. 이 기능은 실험적입니다.
- 소스 코드 적용 범위 분석 도구 GCOV가 다양한 개선 사항으로 확장되었습니다.
- OpenMP 4.5 사양에 대한 지원이 추가되었습니다. 또한 OpenMP 4.0 사양의 오프로드 기능은 이제 C, C++ 및 Fortran 컴파일러에서 지원됩니다.
- 가능한 특정 프로그래밍 오류를 정적 감지하기 위해 새로운 경고 및 개선된 진단이 추가되었습니다.
- 이제 소스 위치가 포인트 대신 범위로 추적되어 훨씬 더 풍부한 진단이 가능합니다. 컴파일러는 이제 "fix-it" 힌트를 제공하여 가능한 코드 수정 사항을 제안합니다. 대체 이름을 제공하고 오타를 쉽게 감지하기 위해 맞춤법 검사기가 추가되었습니다.
보안
GCC는 생성된 코드를 추가로 강화할 수 있도록 툴을 제공하도록 확장되었습니다.
자세한 내용은 2.5.2절. “RHEL 8 GCC의 보안 개선 사항” 의 내용을 참조하십시오.
아키텍처 및 프로세서 지원
아키텍처 및 프로세서 지원 개선 사항은 다음과 같습니다.
- Intel AVX-512 아키텍처, 많은 마이크로 아키텍처 및 Intel SGX(Software Guard Extensions)에 대한 여러 가지 새로운 아키텍처별 옵션이 추가되었습니다.
- 코드 생성은 64비트 ARM 아키텍처 LSE 확장, ARMv8.2-A 16비트 부동 소수점 확장(FPE) 및 ARMv8.2-A, ARMv8.3-A, ARMv8.4-A 아키텍처 버전을 대상으로 할 수 있습니다.
-
ARM 및 64비트 ARM 아키텍처에서
-march=native
옵션 처리가 수정되었습니다. - 64비트 IBM Z 아키텍처의 z13 및 z14 프로세서에 대한 지원이 추가되었습니다.
언어 및 표준
언어 및 표준과 관련된 주요 변경 사항은 다음과 같습니다.
- C 언어로 코드를 컴파일할 때 사용되는 기본 표준은 GNU 확장으로 C17로 변경되었습니다.
- C++ 언어로 코드를 컴파일할 때 사용되는 기본 표준은 GNU 확장과 함께 C++14로 변경되었습니다.
- C++ 런타임 라이브러리는 이제 C++11 및 C++14 표준을 지원합니다.
-
C++ 컴파일러는 이제 변수 템플릿과 같은 많은 새로운 기능을 사용하고, 비정적 데이터 멤버 초기화기, 확장된
constexpr
, 크기 조정된 거래 할당 함수, 일반 lambdas, 변수 길이 배열 및 숫자 구분 기호 등의 많은 새로운 기능을 통해 C++14 표준을 구현합니다. - C 언어 표준 C11에 대한 지원이 향상되었습니다. ISO C11 원자성, 일반 선택 및 스레드 로컬 스토리지를 사용할 수 있습니다.
-
새로운
__auto_type
GNU C 확장은 C 언어에서 C++11auto
키워드의 기능 하위 집합을 제공합니다. -
ISO/EC TS 18661-3:2015 표준에 지정된
_FloatN
및 _FloatNx -
C 언어로 코드를 컴파일할 때 사용되는 기본 표준은 GNU 확장으로 C17로 변경되었습니다. 이는
--std=gnu17
옵션을 사용하는 것과 동일한 효과가 있습니다. 이전에는 GNU 확장이 포함된 기본값은 C89였습니다. - GCC는 이제 C++17 언어 표준 및 C++20 표준의 특정 기능을 사용하여 코드를 실험적으로 컴파일할 수 있습니다.
- 이제 플랫폼 ABI에 필요한 대로 빈 클래스를 인수로 전달하면 Intel 64 및 AMD64 아키텍처 공간이 필요하지 않습니다. 삭제된 복사본만 있는 클래스를 전달하거나 반환합니다. 이제 생성자가 아닌 복사본 또는 이동 생성자가 있는 클래스와 동일한 호출 규칙을 사용합니다.
-
C++11
alignof
연산자가 반환한 값이 C_Alignof
연산자와 일치하도록 수정되었으며 최소 정렬을 반환합니다. 선호하는 정렬을 찾으려면 GNU 확장__alignof__
를 사용합니다. -
Fortran 언어 코드에 대한
libgfortran
라이브러리의 주요 버전이 5로 변경되었습니다. - Ada(GNAT), GCC Go 및 Objective C/C++ 언어에 대한 지원이 제거되었습니다. Go 코드 개발을 위해 Go Toolset을 사용합니다.
추가 리소스
2.5.2. RHEL 8 GCC의 보안 개선 사항
다음은 보안과 관련된 GCC 변경 사항이며 Red Hat Enterprise Linux 7.0 릴리스 이후 추가됩니다.
새 경고
이러한 경고 옵션이 추가되었습니다.
옵션 | 에 대한 경고 표시 |
---|---|
|
|
|
인증되지 않은 클래스 유형의 개체는 경고는 사용자 정의 생성자 또는 복사 할당 연산자를 우회하는 호출을 탐지하는 데 도움이 되며, 손상된 가상 테이블 포인터, const-qualified 형식 또는 참조의 데이터 구성원 또는 멤버 포인터를 감지하는 데 도움이 됩니다. 경고는 데이터 멤버에 대한 액세스 제어를 바이패스하는 호출도 탐지합니다. |
| 코드의 들여쓰기가 코드 블록 구조에 대한 잘못된 아이디어를 사람 리더에게 제공하는 위치를 배치합니다. |
|
할당할 메모리 양이 크기를 초과하는 메모리 할당 함수 호출. 두 매개 변수와 |
|
메모리 양이 0개인 메모리 할당 함수에 대한 호출입니다. 두 매개 변수와 |
|
all |
|
요청된 메모리가 크기보다 큰 |
| 지정된 크기를 초과하거나 바인딩이 충분히 제한될 수 없는 VLA(변수 길이 배열) 정의. |
|
포맷된 출력 함수의 |
|
포맷된 출력 함수의 스니프 제품군에 대한 호출 |
|
|
경고 개선
이러한 GCC 경고가 개선되었습니다.
-
인바운드 배열 인덱스 및 포인터 오프셋의 더 많은 인스턴스를 감지하도록
-Warray-bounds
옵션이 개선되었습니다. 예를 들어 유연한 배열 멤버 및 문자열 리터럴에 대한 음수 또는 과도한 인덱스가 감지됩니다. -
GCC 7에 도입된
-Wrestrict
옵션은 표준 메모리 및memcpy
및strcpy
와 같은 문자열 조작 기능에 대한 제한 정규화된 인수를 통해 개체에 대한 중복 액세스의 많은 인스턴스를 감지하도록 향상되었습니다. -
W
nonnull
옵션은 null 포인터를 비null 인수를 예상하는 함수에 전달하는 광범위한 사례를 감지하도록 향상되었습니다(null이 아닌 특성으로 결정됨
).
New UndefinedBehaviorSanitizer
UndefinedBehaviorSanitizer라는 정의되지 않은 동작을 감지하기 위한 새로운 런타임 제거 기능이 추가되었습니다. 다음 옵션은 참고할 수 있습니다.
옵션 | 검사 |
---|---|
| 부동 소수점 분할을 0으로 감지. |
| 부동 소수점 유형에서 정수 변환으로의 결과가 오버플로우되지 않는지 확인합니다. |
| 배열 바운드의 계측을 활성화하고 아웃 오브 바운드 액세스를 감지합니다. |
| 정렬 검사를 활성화하고 다양한 잘못 정렬된 개체를 감지합니다. |
| 개체 크기 검사를 활성화하고 다양한 인바운드 액세스를 감지합니다. |
| C++ 멤버 함수 호출, 멤버 액세스 및 기본 클래스에 대한 포인터 간 일부 변환을 확인할 수 있습니다. 또한 참조되는 오브젝트에 올바른 동적 유형이 없는 경우 탐지합니다. |
|
배열 범위를 엄격하게 검사할 수 있습니다. 이렇게 하면 |
| 일반 벡터를 사용하는 산술 연산에서도 산술 오버플로 진단. |
|
런타임 시 잘못된 인수를 |
|
포인터 래핑을 위해 저렴한 런타임 테스트를 수행합니다. |
AddressSanitizer의 새로운 옵션
이 옵션은 AddressSanitizer에 추가되었습니다.
옵션 | 검사 |
---|---|
| 다른 메모리 개체를 가리키는 포인터에 대해 경고합니다. |
| 다른 메모리 개체를 가리키는 포인터의 빼기에 대해 경고합니다. |
| 변수가 정의된 범위 뒤에 주소를 가져와 사용하는 변수를 삭제합니다. |
기타 바이저 및 계측
-
스택 공간이 정적 또는 동적으로 할당된 경우 프로브를 삽입하기 위해
-fstack-clash-protection
옵션이 추가되어 스택 오버플로를 안정적으로 감지하여 운영 체제에서 제공하는 스택 보호 페이지로 이동하는 공격 벡터가 완화되었습니다. -
새로운 옵션
-fcf-protection=[full|branch|return|none]
이 추가되어 코드 계측을 수행하고 제어 흐름 전송 명령의 대상 주소(예: 간접 함수 호출, 함수 반환, 간접 건너뛰)가 유효한지 확인하여 프로그램 보안이 향상되었습니다.
추가 리소스
위의 옵션에 제공되는 일부 값에 대한 자세한 내용과 설명은 gcc(1) 매뉴얼 페이지를 참조하십시오.
$ man gcc
2.5.3. RHEL 8 GCC의 호환성 혁신적인 변경 사항
std:: string 및 std::
list
에서 C++ ABI 변경
std::
list
libstdc++
라이브러리의 std::string
및 std::list
클래스의 ABI(Application Binary Interface)는 RHEL 7(GCC 4.8)과 RHEL 8(GCC 8) 간에 변경되어 C++11 표준을 준수합니다. libstdc++
라이브러리는 이전 ABI와 새 ABI를 모두 지원하지만, 일부 다른 C++ 시스템 라이브러리는 지원하지 않습니다. 따라서 이러한 라이브러리에 대해 동적으로 연결되는 애플리케이션을 다시 빌드해야 합니다. 이는 C++98을 포함한 모든 C++ 표준 모드에 영향을 미칩니다. 또한 이전 ABI가 시스템 라이브러리와의 호환성을 유지하기 위해 RHEL 7용 Red Hat Developer Toolset 컴파일러로 구축된 애플리케이션에도 영향을 미칩니다.
GCC는 더 이상 Ada, Go 및 Objective C/C++ 코드를 빌드하지 않습니다.
Ada(GNAT), GCC Go 및 Objective C/C++ 언어에서 코드 빌드 기능이 GCC 컴파일러에서 제거되었습니다.
Go 코드를 빌드하려면 대신 Go Toolset을 사용합니다.
3장. 애플리케이션 디버깅
디버깅 애플리케이션은 매우 광범위한 주제입니다. 이 부분은 개발자에게 여러 상황에서 디버깅을 위한 가장 일반적인 기술을 제공합니다.
3.1. 디버깅 정보를 사용하여 디버깅 활성화
애플리케이션과 라이브러리를 디버깅하려면 디버깅 정보가 필요합니다. 다음 섹션에서는 이 정보를 가져오는 방법에 대해 설명합니다.
3.1.1. 디버깅 정보
실행 코드를 디버깅하는 동안 두 가지 유형의 정보를 통해 프로그래머를 확장하고 바이너리 코드를 이해할 수 있습니다.
- 소스 코드 텍스트
- 소스 코드 텍스트가 바이너리 코드와 관련된 방법에 대한 설명
이러한 정보를 디버깅 정보라고 합니다.
Red Hat Enterprise Linux는 실행 바이너리, 공유 라이브러리 또는 debuginfo
파일에 ELF 형식을 사용합니다. 이러한 ELF 파일 내에 DWARF 형식은 디버그 정보를 유지하는 데 사용됩니다.
ELF 파일 내에 저장된 DWARF 정보를 표시하려면 readelf -w file
명령을 실행합니다.
STABS는 성능이 떨어지고 경우에 따라 UNIX와 함께 사용되는 이전 형식입니다. Red Hat에서는 사용하지 않는 것이 좋습니다. GCC 및 GDB는 STABS 생산 및 소비를 최상의 노력으로만 제공합니다. Valgrind 및 elfutils
와 같은 기타 도구는 STABS에서 작동하지 않습니다.
추가 리소스
3.1.2. GCC를 사용하여 C 및 C++ 애플리케이션 디버깅 활성화
디버깅 정보는 크기 때문에 기본적으로 실행 파일에 포함되지 않습니다. C 및 C++ 애플리케이션을 디버깅할 수 있도록 하려면 컴파일러에 이를 명시적으로 지시해야 합니다.
코드를 컴파일하고 연결할 때 GCC 를 사용하여 디버깅 정보를 생성할 수 있도록 하려면 -g
옵션을 사용합니다.
$ gcc ... -g ...
-
컴파일러 및 링커에 의해 수행되는 최적화는 원래 소스 코드와 관련되기 어려운 실행 코드를 초래할 수 있습니다. 변수가 최적화되고, 스크롤되지 않고, 작업이 주변에 병합될 수 있습니다. 이는 디버깅에 부정적인 영향을 미칩니다. 디버깅 환경을 개선하려면
-Og
옵션으로 최적화를 설정하는 것이 좋습니다. 그러나 최적화 수준을 변경하면 실행 코드가 변경되며 일부 버그 제거를 포함하여 실제 동작을 변경할 수 있습니다. -
디버그 정보에 매크로 정의를 포함하려면 g 대신
-g
3 -
f
compare-debug
GCC 옵션은 디버그 정보와 디버그 정보 없이 GCC에서 컴파일한 코드를 테스트합니다. 결과 두 바이너리 파일이 동일한 경우 테스트가 통과합니다. 이 테스트를 사용하면 디버깅 옵션의 영향을 받지 않으므로 디버그 코드에 숨겨진 버그가 없습니다. fcompare-debug
옵션을 사용하면 컴파일 시간이 크게 증가합니다. 이 옵션에 대한 자세한 내용은 GCC 도움말 페이지를 참조하십시오.
추가 리소스
- 3.1절. “디버깅 정보를 사용하여 디버깅 활성화”
- GCC(GNU 컴파일러 컬렉션) 사용 - 프로그램 디버깅 옵션
- GDB를 사용하여 디버깅 - 별도의 파일에 정보 디버깅 https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
GCC 도움말 페이지:
$ man gcc
3.1.3. debuginfo 및 debugsource 패키지
The debuginfo
및 debugsource
패키지에는 프로그램 및 라이브러리에 대한 디버깅 정보와 디버그 소스 코드가 포함되어 있습니다. Red Hat Enterprise Linux 리포지토리의 패키지에 설치된 애플리케이션 및 라이브러리의 경우 추가 채널에서 separate debuginfo
및 debugsource
패키지를 얻을 수 있습니다.
디버깅 정보 패키지 유형
디버깅에 사용할 수 있는 패키지 유형은 다음 두 가지입니다.
- debuginfo 패키지
-
debuginfo
패키지는 바이너리 코드 기능에 대해 사람이 읽을 수 있는 이름을 제공하는 데 필요한 디버깅 정보를 제공합니다. 이러한 패키지에는 DWARF 디버깅 정보가 포함된.debug
파일이 포함되어 있습니다. 이러한 파일은/usr/lib/debug
디렉토리에 설치됩니다. - 디버그 소스 패키지
-
debugsource
패키지에는 바이너리 코드를 컴파일하는 데 사용되는 소스 파일이 포함되어 있습니다. 각debuginfo
및debugsource
패키지가 설치되어 있으면 GDB 또는 LLDB와 같은 디버거가 바이너리 코드의 실행을 소스 코드와 관련시킬 수 있습니다. 소스 코드 파일은/usr/src/debug
디렉터리에 설치됩니다.
RHEL 7의 차이점
Red Hat Enterprise Linux 7에서 the debuginfo
패키지에는 두 가지 종류의 정보가 포함되어 있습니다. Red Hat Enterprise Linux 8은 debuginfo
패키지에서 별도의 디버그 소스 패키지로 디버깅하는 데 필요한 소스
코드 데이터를 분할합니다.
패키지 이름
A debuginfo
또는 debugsource
패키지는 동일한 이름, 버전, 릴리스 및 아키텍처가 있는 바이너리 패키지에만 유효한 디버깅 정보를 제공합니다.
-
바이너리 패키지:
packagename-version-release.architecture.rpm
-
debuginfo package:
packagename-debuginfo-version-release.architecture.rpm
-
debugsource package:
packagename-debugsource-version-release.architecture.rpm
3.1.4. GDB를 사용하여 애플리케이션 또는 라이브러리의 debuginfo 패키지 가져오기
코드를 디버깅하려면 디버깅 정보가 필요합니다. 패키지에서 설치된 코드의 경우 gDB(GNU Debugger)는 누락된 디버그 정보를 자동으로 인식하고 패키지 이름을 해결하며 패키지를 가져오는 방법에 대한 구체적인 조언을 제공합니다.
사전 요구 사항
- 디버그하려는 애플리케이션 또는 라이브러리는 시스템에 설치해야 합니다.
-
GDB 및
debuginfo-install
툴을 시스템에 설치해야 합니다. -
debuginfo
및debugsource
패키지를 제공하는 리포지토리는 시스템에서 구성하고 활성화해야 합니다. 자세한 내용은 디버그 및 소스 리포지토리 활성화 를 참조하십시오.
절차
디버그하려는 애플리케이션 또는 라이브러리에 연결된 GDB를 시작합니다. GDB는 누락된 디버깅 정보를 자동으로 인식하고 실행할 명령을 제안합니다.
$ gdb -q /bin/ls Reading symbols from /bin/ls...Reading symbols from .gnu_debugdata for /usr/bin/ls...(no debugging symbols found)...done. (no debugging symbols found)...done. Missing separate debuginfos, use: dnf debuginfo-install coreutils-8.30-6.el8.x86_64 (gdb)
exit GDB: q 를 입력하고 Enter 를 사용하여 확인합니다.
(gdb) q
GDB에서 제안하는 명령을 실행하여 required
debuginfo
패키지를 설치합니다.# dnf debuginfo-install coreutils-8.30-6.el8.x86_64
dnf
패키지 관리 도구는 변경 사항에 대한 요약을 제공하고 확인을 요청한 후 필요한 모든 파일을 확인, 다운로드 및 설치합니다.-
GDB가
debuginfo
패키지를 제안할 수 없는 경우 3.1.5절. “애플리케이션 또는 라이브러리에 대한 debuginfo 패키지 수동으로 가져오기” 에 설명된 절차를 따르십시오.
추가 리소스
- RHEL 시스템용 debuginfo 패키지를 다운로드하거나 설치하려면 어떻게 해야 합니까? - Red Hat Knowledgebase 솔루션
3.1.5. 애플리케이션 또는 라이브러리에 대한 debuginfo 패키지 수동으로 가져오기
실행 파일을 찾은 다음 이를 설치하는 패키지를 찾아 설치해야 하는 debuginfo
패키지를 수동으로 결정할 수 있습니다.
GDB를 사용하여 설치할 패키지를 결정하는 것이 좋습니다. GDB가 설치할 패키지를 제안할 수 없는 경우에만 이 수동 절차를 사용하십시오.
사전 요구 사항
- 애플리케이션 또는 라이브러리가 시스템에 설치되어 있어야 합니다.
- 애플리케이션 또는 라이브러리가 패키지에서 설치되었습니다.
-
debuginfo-install
툴은 시스템에서 사용할 수 있어야 합니다. -
debuginfo
패키지를 제공하는 채널은 시스템에서 구성하고 활성화해야 합니다.
절차
애플리케이션 또는 라이브러리의 실행 파일을 찾습니다.
애플리케이션 파일을 찾으려면
which
명령을 사용합니다.$ which less /usr/bin/less
locate
명령을 사용하여 라이브러리 파일을 찾습니다.$ locate libz | grep so /usr/lib64/libz.so.1 /usr/lib64/libz.so.1.2.11
원래의 디버깅에 오류 메시지를 디버깅하는 이유는 오류 메시지에 언급된 파일과 라이브러리의 추가 번호가 같은 결과를 선택하십시오. 확실하지 않은 경우 나머지 절차에 따라 라이브러리 파일 이름에 추가 번호가 포함되지 않은 결과를 표시하십시오.
참고locate
명령은mlocate
패키지에서 제공합니다. 설치하고 사용을 활성화하려면 다음을 수행합니다.# yum install mlocate # updatedb
파일을 제공한 패키지의 이름 및 버전을 검색합니다.
$ rpm -qf /usr/lib64/libz.so.1.2.7 zlib-1.2.11-10.el8.x86_64
출력은 이름에 설치된 패키지에 대한 세부 정보를 제공합니다 :epoch-version.release.아키텍처 형식입니다.
중요이 단계에서 결과가 생성되지 않으면 바이너리 파일이 제공된 패키지를 결정할 수 없습니다. 다음과 같은 몇 가지 사례가 있습니다.
- 파일은 현재 구성에서 패키지 관리 툴로 알 수 없는 패키지에서 설치됩니다.
-
파일은 로컬에서 다운로드되고 수동으로 설치된 패키지에서 설치됩니다. 이러한 경우 적합한
debuginfo
패키지를 자동으로 결정하는 것은 불가능합니다. - 패키지 관리 툴이 잘못 구성되어 있습니다.
-
파일은 어떤 패키지에서도 설치되지 않습니다. 이러한 경우 각
debuginfo
패키지가 존재하지 않습니다.
추가 단계는 이 문제를 해결하기 때문에 이 상황을 해결하거나 이 절차를 중단해야 합니다. 정확한 문제 해결 단계를 설명하는 것은 이 절차의 범위를 벗어납니다.
debuginfo
-install 유틸리티를 사용하여debuginfo
패키지를 설치합니다. 명령에서 이전 단계에서 결정한 패키지 이름과 기타 세부 정보를 사용합니다.# debuginfo-install zlib-1.2.11-10.el8.x86_64
추가 리소스
3.2. GDB를 사용하여 애플리케이션 내부 상태 검사
애플리케이션이 제대로 작동하지 않는 이유를 찾으려면 해당 실행을 제어하고 내부 상태를 디버거로 검사합니다. 이 섹션에서는 이 작업에 GNU Debugger(GDB)를 사용하는 방법을 설명합니다.
3.2.1. GNU 디버거(GDB)
Red Hat Enterprise Linux에는 명령줄 사용자 인터페이스를 통해 프로그램 내에서 발생하는 상황을 조사할 수 있는 GNU 디버거(GDB)가 포함되어 있습니다.
GDB 기능
단일 GDB 세션은 다음 유형의 프로그램을 디버깅할 수 있습니다.
- 멀티스레딩 및 forking 프로그램
- 여러 프로그램 한 번에
-
TCP/IP 네트워크 연결을
통해 연결된
원격 시스템 또는 컨테이너의 프로그램
디버깅 요구 사항
실행 가능한 코드를 디버깅하려면 GDB에서 해당 특정 코드에 대한 디버깅 정보가 필요합니다.
- 사용자가 개발한 프로그램의 경우 코드를 빌드하는 동안 디버깅 정보를 생성할 수 있습니다.
- 패키지에서 설치된 시스템 프로그램의 경우 debuginfo 패키지를 설치해야 합니다.
3.2.2. 프로세스에 GDB 연결
프로세스를 검사하려면 GDB를 프로세스에 연결해야 합니다.
사전 요구 사항
GDB로 프로그램 시작
프로그램이 프로세스로 실행되지 않으면 GDB로 시작합니다.
$ gdb program
program 을 파일 이름 또는 프로그램의 경로로 바꿉니다.
GDB는 프로그램의 실행을 시작하도록 설정합니다. run
명령으로 프로세스 실행을 시작하기 전에 중단점 및 the gdb
환경을 설정할 수 있습니다.
이미 실행 중인 프로세스에 GDB 연결
GDB를 프로세스로 이미 실행 중인 프로그램에 연결하려면 다음을 수행합니다.
ps
명령을 사용하여 PID(프로세스ID)를 찾습니다.$ ps -C program -o pid h pid
program 을 파일 이름 또는 프로그램의 경로로 바꿉니다.
이 프로세스에 GDB를 연결합니다.
$ gdb -p pid
ps
출력의 실제 프로세스 ID 번호로 pid 를 바꿉니다.
이미 실행 중인 GDB를 이미 실행 중인 프로세스에 연결
이미 실행 중인 GDB를 이미 실행 중인 프로그램에 연결하려면 다음을 수행합니다.
쉘
GDB 명령을 사용하여ps
명령을 실행하고 프로그램의 프로세스 ID(pid)를 찾습니다.(gdb) shell ps -C program -o pid h pid
program 을 파일 이름 또는 프로그램의 경로로 바꿉니다.
attach
명령을 사용하여 GDB를 프로그램에 연결합니다.(gdb) attach pid
ps
출력 의 실제 프로세스 ID 번호로 바꿉니다.
경우에 따라 GDB가 해당 실행 파일을 찾지 못할 수 있습니다. file
명령을 사용하여 경로를 지정합니다.
(gdb) file path/to/program
추가 리소스
- GDB - 2.1 GDB 호출
- GDB를 사용한 디버깅 - 4.7 Already 실행 프로세스 디버깅
3.2.3. GDB를 이용한 프로그램 코드 단계
GDB 디버거가 프로그램에 연결되면 여러 명령을 사용하여 프로그램의 실행을 제어할 수 있습니다.
사전 요구 사항
필요한 디버깅 정보를 사용할 수 있어야 합니다.
- 프로그램은 디버깅 정보로 컴파일 및 구축되거나
- 관련 debuginfo 패키지가 설치됨
- 디버깅하려면 GDB를 프로그램에 첨부해야 합니다.
코드를 단계별로 GDB 명령
R
(run)-
프로그램 실행을 시작합니다.
run
을 인수와 함께 실행하면 해당 인수가 프로그램이 정상적으로 시작된 것처럼 실행 파일에 전달됩니다. 일반적으로 사용자는 중단점을 설정한 후 이 명령을 실행합니다. start
-
프로그램의 실행을 시작하되, 프로그램의 메인 함수가 시작될 때 중지됩니다.
start
가 인수와 함께 실행되면 해당 인수는 프로그램이 정상적으로 시작된 것처럼 실행 파일에 전달됩니다.
c
(계속)현재 상태에서 프로그램을 계속 실행합니다. 프로그램 실행이 다음 중 하나가 true가 될 때까지 계속됩니다.
- 중단에 도달했습니다.
- 지정된 조건이 충족됩니다.
- 프로그램에 의해 신호가 수신됩니다.
- 오류가 발생합니다.
- 프로그램이 종료됩니다.
N
(next)현재 소스 파일의 다음 코드 줄에 도달할 때까지 현재 상태에서 프로그램을 계속 실행합니다. 프로그램 실행이 다음 중 하나가 true가 될 때까지 계속됩니다.
- 중단에 도달했습니다.
- 지정된 조건이 충족됩니다.
- 프로그램에 의해 신호가 수신됩니다.
- 오류가 발생합니다.
- 프로그램이 종료됩니다.
s
(단계)-
또한
step
명령은 현재 소스 파일의 각 코드 줄에서 실행을 중지합니다. 그러나 함수 호출이 포함된 소스 줄에서 현재 실행이 중지된 경우 GDB는 함수 호출 을 입력한 후 실행을 중지합니다(실행하는 대신). - 위치
까지
- 위치 옵션으로 지정한 코드 위치에 도달할 때까지 실행을 계속합니다.
Fini
(마지막)프로그램 실행을 재개하고 함수가 반환되면 중지됩니다. 프로그램 실행이 다음 중 하나가 true가 될 때까지 계속됩니다.
- 중단에 도달했습니다.
- 지정된 조건이 충족됩니다.
- 프로그램에 의해 신호가 수신됩니다.
- 오류가 발생합니다.
- 프로그램이 종료됩니다.
Q
(quit)- 실행을 종료하고 GDB를 종료합니다.
추가 리소스
- 3.2.5절. “GDB 중단점을 사용하여 정의된 코드 위치에서 실행 중지”
- GDB로 디버깅 - 프로그램 시작
- GDB를 사용한 디버깅 - 연속 및 단계
3.2.4. GDB를 사용하여 프로그램 내부 값 표시
프로그램의 내부 변수 값을 표시하는 것은 프로그램이 수행하는 작업을 이해하는 데 중요합니다. GDB는 내부 변수를 검사하는 데 사용할 수 있는 여러 명령을 제공합니다. 다음은 다음 명령 중 가장 유용합니다.
p
(인쇄)주어진 인수의 값을 표시합니다. 일반적으로 인수는 간단한 단일 값에서 구조까지 복잡한 변수의 이름입니다. 인수는 프로그램 변수 및 라이브러리 함수 또는 테스트 중인 프로그램에 정의된 함수 사용을 포함하여 현재 언어로 유효한 표현식일 수도 있습니다.
출력 명령을 사용하여 데이터 구조(예: 클래스, groups)의 사용자 지정 표시를 위해 GDB를 Python 또는 Guile 스크립트로 확장할
수
있습니다.BT(
backtrace)현재 실행 지점에 도달하는 데 사용되는 함수 호출 체인을 표시하거나 실행이 종료될 때까지 사용되는 함수 체인을 표시합니다. 이는 제거 원인과 같은 심각한 버그(예: 분할 오류)를 조사하는 데 유용합니다.
backtrace
명령에전체
옵션을 추가하면 로컬 변수도 표시됩니다.bt
및info 프레임 명령을 사용하여 표시된 데이터의 사용자 지정 디스플레이에 대해 프레임 필터 Python 스크립트를 사용하여 GDB를 확장할 수 있습니다
. 프레임 이라는 용어는 단일 함수 호출과 연관된 데이터를 나타냅니다.info
info
명령은 다양한 항목에 대한 정보를 제공하는 일반적인 명령입니다. 설명할 항목을 지정하는 옵션을 사용합니다.-
info args
명령은 현재 선택된 프레임인 함수 호출의 옵션을 표시합니다. -
info locals
명령은 현재 선택된 프레임에 로컬 변수를 표시합니다.
가능한 항목 목록은 GDB 세션에서 명령
도움말 정보를
실행하십시오.(gdb) help info
-
l
(list)-
프로그램이 중지된 소스 코드에서 행을 표시합니다. 이 명령은 프로그램 실행이 중지된 경우에만 사용할 수 있습니다. 반드시 내부 상태를 표시하는 명령은 아니지만,
list
를 사용하면 프로그램 실행의 다음 단계에서 내부 상태에 대한 변경이 어떻게 되는지 이해하는 데 도움이 됩니다.
추가 리소스
- GDB Python API - Red Hat Developers 블로그 항목
- GDB로 디버깅 - Pretty Printing
3.2.5. GDB 중단점을 사용하여 정의된 코드 위치에서 실행 중지
대개는 작은 코드 부분만 조사됩니다. 중단점은 GDB가 코드의 특정 위치에서 프로그램의 실행을 중지하도록 지시하는 마커입니다. 중단점은 소스 코드 행과 가장 일반적으로 연관됩니다. 이 경우 중단자를 배치하려면 소스 파일 및 행 번호를 지정해야 합니다.
중단을 배치하려면:
소스 코드 파일의 이름과 해당 파일의 행을 지정합니다.
(gdb) br file:line
파일이 없으면 현재 실행 지점에서 소스 파일의 이름이 사용됩니다.
(gdb) br line
또는 함수 이름을 사용하여 시작에 중단점을 둡니다.
(gdb) br function_name
작업에 대해 일정 횟수가 반복된 후 프로그램이 오류가 발생할 수 있습니다. 실행을 중단할 추가 조건을 지정하려면 다음을 수행합니다.
(gdb) br file:line if condition
C 또는 C++ 언어의 조건으로 조건을 바꿉니다. 파일과 행 의 의미는 위와 동일합니다.
모든 중단점 및 감시점의 상태를 검사 하려면 다음을 수행합니다.
(gdb) info br
정보 br
의 출력에 표시된 번호를 사용하여 중단점을 제거하려면 다음을 수행합니다.(gdb) delete number
지정된 위치에서 중단 항목을 제거하려면 다음을 수행합니다.
(gdb) clear file:line
추가 리소스
- GDB로 디버깅 - Breakpoints, Watchpoints, Catchpoints
3.2.6. GDB 감시 포인트를 사용하여 데이터 액세스 및 변경 시 실행을 중지합니다
대부분의 경우 특정 데이터가 변경되거나 액세스될 때까지 프로그램을 실행하도록 하는 것이 유리합니다. 다음 예제는 가장 일반적인 사용 사례입니다.
사전 요구 사항
- GDB이해
GDB에서 워치포인트 사용
Watchpoints는 GDB 가 프로그램의 실행을 중지하도록 지시하는 마커입니다. Watchpoints는 데이터와 연결되어 있습니다. 감시 지점을 배치하려면 변수, 여러 변수 또는 메모리 주소를 설명하는 식을 지정해야 합니다.
데이터 변경에 대한 감시 지점을 배치 하려면 다음을 실행합니다 (쓰기).
(gdb) watch expression
보고자 하는 내용을 설명하는 표현식 으로 표현식을 바꿉니다. 변수의 경우 표현식 은 변수 이름과 동일합니다.
데이터 액세스를 위한 감시 지점을 배치 하려면(읽기:).
(gdb) rwatch expression
데이터 액세스(읽기 및 쓰기) 에 대한 감시 지점을 배치 하려면 다음을 수행하십시오.
(gdb) awatch expression
모든 감시점 및 중단점의 상태를 검사 하려면 다음을 수행합니다.
(gdb) info br
감시 지점을 제거하려면 다음을 수행합니다.
(gdb) delete num
num 옵션을
info br
명령으로 보고된 번호로 바꿉니다.
추가 리소스
- 디버깅 with GDB - Watchpoints 설정
3.2.7. GDB를 사용하여 포크 또는 스레드 프로그램 디버깅
일부 프로그램은 포크 또는 스레드를 사용하여 병렬 코드 실행을 수행합니다. 여러 동시 실행 경로를 디버깅하려면 특별한 고려 사항이 필요합니다.
사전 요구 사항
- 프로세스 포크 및 스레드의 개념을 이해해야 합니다.
GDB를 사용하여 분기된 프로그램 디버깅
포크는 프로그램(상위)이 자체(자체)의 독립적인 사본을 만들 때 발생하는것입니다. 다음 설정과 명령을 사용하여 포크 발생 시 GDB가 수행하는 작업에 영향을 미칩니다.
follow-fork-mode
설정은 GDB가 포크 뒤의 상위 또는 하위 항목을 따르는지 여부를 제어합니다.follow-fork-mode 상위 설정
- 포크 후 상위 프로세스를 디버깅합니다. 이는 기본값입니다.
follow-fork-mode 하위 설정
- 포크 후에 하위 프로세스를 디버그합니다.
show follow-fork-mode
-
현재
follow-fork-mode
설정을 표시합니다.
설정된 detach-on-fork
설정은 GDB가 다른(후로) 프로세스를 계속 제어하거나 실행되도록 유지할지 여부를 제어합니다.detach-on-fork on 설정
-
뒤따르지 않는 프로세스(
follow-fork-mode
값에 따라)는 분리되며 독립적으로 실행됩니다. 이는 기본값입니다. detach-on-fork off 설정
-
GDB는 두 프로세스를 모두 제어합니다. 뒤에 오는 프로세스(
follow-fork-mode
값에 따라)는 정상적으로 디버그되지만 다른 프로세스는 일시 중지됩니다. show detach-on-fork
-
detach-on-fork
의 현재 설정을 표시합니다.
GDB를 사용하여 스레드 프로그램 디버깅
GDB는 개별 스레드를 디버그하고 독립적으로 조작 및 검사할 수 있습니다. GDB가 검사된 스레드만 중지하도록 하려면 명령 집합을 사용하지 않고 에서
target-async를 설정합니다.
이러한 명령을 .gdbinit
파일에 추가할 수 있습니다. 해당 기능이 켜진 후 GDB는 스레드 디버깅을 수행할 준비가 되었습니다.
GDB는 현재 스레드 의 개념을 사용합니다. 기본적으로 명령은 현재 스레드에만 적용됩니다.
정보 스레드
-
id
andgid
번호를 사용하여 현재 스레드를 나타내는 스레드 목록을 표시합니다. 스레드 ID
-
지정된
id
를 현재 스레드로 사용하여 스레드를 설정합니다. thread apply ids 명령
-
id로 나열된 모든 스레드에
명령 명령을
적용합니다.ids
옵션은 공백으로 구분된 스레드 ID 목록입니다. 특수 값all
이 모든 스레드에 명령을 적용합니다. 조건인 경우 위치 스레드 ID 중단
-
스레드 번호
ID
에 대해서만 특정조건이
있는 특정위치에서
중단점을 설정합니다. 조사 표현식 스레드 ID
-
스레드 번호
ID
에 대해서만식에
의해 정의된 감시 지점을 설정합니다. 명령&
-
명령
명령을
실행하고 gdb 프롬프트(gdb)
로 즉시 돌아가 백그라운드에서 코드 실행을 계속합니다. interrupt
- 백그라운드에서 실행을 중지합니다.
추가 리소스
- GDB를 사용한 디버깅 - 여러 스레드로 4.10 디버깅 프로그램
- GDB를 사용한 디버깅 - 4.11 Forks 디버깅
3.3. 애플리케이션 상호 작용 기록
실행 가능한 애플리케이션 코드는 운영 체제 및 공유 라이브러리의 코드와 상호 작용합니다. 이러한 상호 작용의 활동 로그를 기록하면 실제 애플리케이션 코드를 디버깅하지 않고도 애플리케이션의 동작에 충분한 통찰력을 제공할 수 있습니다. 또는 애플리케이션의 상호 작용을 분석하면 버그 매니페스트가 되는 조건을 파악하는 데 도움이 될 수 있습니다.
3.3.1. 애플리케이션 상호 작용을 기록하는 데 유용한 도구
Red Hat Enterprise Linux는 애플리케이션 상호 작용을 분석하기 위한 다양한 툴을 제공합니다.
- strace
strace
툴을 사용하면 애플리케이션에서 사용하는 시스템 호출(커널 함수)을 로깅할 수 있습니다.-
strace
는 매개 변수 및 결과를 기본 커널 코드에 대한 지식을 해석하므로strace
툴은 호출에 대한 자세한 출력을 제공할 수 있습니다. 숫자는 해당 상수 이름, 플래그 목록을 위해 확장된 비트 조합 플래그, 실제 문자열을 제공하기 위해 역참조되는 문자 배열 포인터로 변환됩니다. 최신 커널 기능에 대한 지원이 부족할 수 있습니다. - 추적된 호출을 필터링하여 캡처된 데이터 양을 줄일 수 있습니다.
-
strace
를 사용하는 경우 로그 필터를 설정하는 경우를 제외하고는 특정 설정이 필요하지 않습니다. -
strace
를 사용하여 애플리케이션 코드를 추적하면 애플리케이션의 실행이 상당히 느려집니다. 결과적으로strace
는 많은 프로덕션 배포에 적합하지 않습니다. 또는ltrace
또는 SystemTap 사용을 고려하십시오. -
Red Hat Developer Toolset에서 사용할 수 있는
strace
버전도 시스템 호출 조작을 수행할 수 있습니다. 이 기능은 디버깅에 유용합니다.
-
- ltrace
ltrace
툴을 사용하면 애플리케이션의 사용자 공간 호출을 공유 오브젝트(dynamic 라이브러리)에 기록할 수 있습니다.-
ltrace
툴을 사용하면 모든 라이브러리에 대한 호출을 추적할 수 있습니다. - 추적된 호출을 필터링하여 캡처된 데이터 양을 줄일 수 있습니다.
-
ltrace
를 사용하는 경우 로그 필터를 설정하는 경우를 제외하고 ltrace를 사용할 필요가 없습니다. -
ltrace
툴은 가볍고 빠르며 strace:strace
를 사용하여 커널 기능을 추적하는 대신glibc
와ltrace
와 같은 라이브러리에서 해당 인터페이스를 추적할 수 있습니다.
-
ltrace
는strace
와 같은 알려진 호출 세트를 처리하지 않기 때문에 라이브러리 함수에 전달되는 값을 설명하려고 시도하지 않습니다.ltrace
출력에는 원시 번호 및 포인터만 포함되어 있습니다.ltrace
출력을 해석하려면 출력에 있는 라이브러리의 실제 인터페이스 선언을 확인해야 합니다.
참고Red Hat Enterprise Linux 8에서 알려진 문제는
ltrace
가 시스템 실행 파일을 추적하지 못하도록 합니다. 이 제한은 사용자가 빌드한 실행 파일에 적용되지 않습니다.-
- SystemTap
SystemTap은 Linux 시스템에서 실행 중인 프로세스 및 커널 활동을 조사하기 위한 계측 플랫폼입니다. SystemTap은 사용자 지정 이벤트 핸들러를 프로그래밍하는 데 자체 스크립팅 언어를 사용합니다.
-
strace 및
를 사용하는 것과 비교했을 때 로깅을 스크립팅하면 초기 설정 단계에서 더 많은 작업을 수행할 수 있습니다. 그러나 스크립팅 기능은 단순히 로그를 생성하는 것 이상으로 SystemTap의 유용성을 확장합니다.ltrace
- SystemTap은 커널 모듈을 생성하고 삽입하여 작동합니다. SystemTap 사용은 효율적이며 시스템 또는 애플리케이션 실행 성능이 크게 저하되지 않습니다.
- SystemTap에는 사용 예 집합이 함께 제공됩니다.
-
- GDB
GNU Debugger(GDB)는 주로 로깅이 아닌 디버깅을 위한 것입니다. 그러나 일부 기능은 애플리케이션의 상호 작용이 주요 관심 활동인 시나리오에서도 유용합니다.
- GDB를 사용하면 상호 작용 이벤트 캡처를 편리하게 결합하고 후속 실행 경로를 즉시 디버깅할 수 있습니다.
- GDB는 다른 도구에서 문제가 발생한 상황을 처음 식별한 후에 드물거나 단일 이벤트에 대한 응답을 분석하는 데 가장 적합합니다. 빈번한 이벤트가 있는 모든 시나리오에서 GDB를 사용하는 것은 비효율적이거나 불가능하게 됩니다.
3.3.2. strace를 사용하여 애플리케이션의 시스템 호출 모니터링
strace
툴을 사용하면 애플리케이션에서 수행하는 시스템(커널) 호출을 모니터링할 수 있습니다.
사전 요구 사항
절차
- 모니터링할 시스템 호출을 식별합니다.
strace
를 시작하고 프로그램에 연결합니다.모니터링할 프로그램이 실행되고 있지 않으면
strace
를 시작하고 프로그램을 지정합니다:$ strace -fvttTyy -s 256 -e trace=call program
프로그램이 이미 실행 중인 경우 해당 프로세스 ID(pid)를 찾아
strace
를 연결합니다.$ ps -C program (...) $ strace -fvttTyy -s 256 -e trace=call -ppid
-
호출 을 표시할 시스템 호출로 바꿉니다.
-e trace=call
옵션을 여러 번 사용할 수 있습니다. 제외되는 경우strace
는 모든 시스템 호출 유형을 표시합니다. 자세한 내용은 strace(1) 매뉴얼 페이지를 참조하십시오. -
분기된 프로세스 또는 스레드를 추적하지 않으려면
-f
옵션을 종료합니다.
strace
툴은 애플리케이션에서 수행한 시스템 호출과 세부 정보를 표시합니다.대부분의 경우 시스템 호출에 대한 필터가 설정되지 않은 경우 애플리케이션 및 해당 라이브러리는 많은 호출을 만들고
strace
출력을 즉시 표시합니다.strace
툴은 프로그램이 종료되면 종료됩니다.추적 프로그램이 종료되기 전에 모니터링을 종료하려면
를 누릅니다.-
strace
가 프로그램을 시작하면strace
와 함께 프로그램이 종료됩니다. -
strace
를 이미 실행 중인 프로그램에 연결하면strace
와 함께 프로그램이 종료됩니다.
-
애플리케이션에서 수행한 시스템 호출 목록을 분석합니다.
- 리소스 액세스 또는 가용성 관련 문제는 반환 오류를 호출할 때 로그에 있습니다.
- 시스템 호출 및 호출 시퀀스 패턴에 전달되는 값은 애플리케이션 동작의 원인에 대한 통찰력을 제공합니다.
- 애플리케이션이 충돌하면 중요한 정보가 로그 끝에 있을 수 있습니다.
- 출력에는 불필요한 정보가 많이 포함되어 있습니다. 그러나 관심 있는 시스템 호출에 대한 보다 정확한 필터를 구성하고 절차를 반복할 수 있습니다.
둘 다 출력을 보고 파일에 저장하는 것이 유리합니다. 이 작업을 수행하려면 tee
명령을 사용합니다.
$ strace ... |& tee your_log_file.log
추가 리소스
strace(1) 매뉴얼 페이지:
$ man strace
- strace를 사용하여 명령으로 수행한 시스템 호출을 추적하려면 어떻게 해야 합니까? - Knowledgebase 문서
- Red Hat Developer Toolset 사용자 가이드 - strace
3.3.3. ltrace를 사용하여 애플리케이션의 라이브러리 함수 호출 모니터링
ltrace
툴을 사용하면 라이브러리에서 사용할 수 있는 기능에 대한 애플리케이션의 호출을 모니터링할 수 있습니다(공유 오브젝트).
Red Hat Enterprise Linux 8에서 알려진 문제는 ltrace
가 시스템 실행 파일을 추적하지 못하도록 합니다. 이 제한은 사용자가 빌드한 실행 파일에 적용되지 않습니다.
사전 요구 사항
절차
- 가능한 경우 관심 있는 라이브러리 및 기능을 식별합니다.
ltrace
를 시작하고 프로그램에 연결합니다.모니터링할 프로그램이 실행되지 않는 경우
ltrace
를 시작하고 프로그램을 지정합니다:$ ltrace -f -l library -e function program
프로그램이 이미 실행중인 경우 해당 프로세스 ID (pid)를 찾아
ltrace
를 연결합니다.$ ps -C program (...) $ ltrace -f -l library -e function program -ppid
출력을 필터링하려면
옵션을 사용합니다.-e
,-f
및 -l-
함수로 표시할 함수 이름을 제공합니다 . e
기능
옵션은 여러 번 사용할 수 있습니다. 제외되면ltrace
는 모든 함수에 대한 호출을 표시합니다. -
함수를 지정하는 대신
-l 라이브러리 옵션을
사용하여 전체 라이브러리를 지정할 수 있습니다. 이 옵션은-e 기능
옵션과 유사하게 작동합니다. -
분기된 프로세스 또는 스레드를 추적하지 않으려면
-f
옵션을 종료합니다.
자세한 내용은 ltrace(1)_ 매뉴얼 페이지를 참조하십시오.
-
함수로 표시할 함수 이름을 제공합니다 . e
ltrace
는 애플리케이션에서 수행한 라이브러리 호출을 표시합니다.대부분의 경우 애플리케이션은 필터가 설정되지 않은 경우 많은 수의 호출과
ltrace
출력이 즉시 표시됩니다.ltrace
는 프로그램이 종료되면 종료됩니다.추적 프로그램이 종료되기 전에 모니터링을 종료하려면
를 누릅니다.-
ltrace
가 프로그램을 시작하면 프로그램은ltrace
와 함께 종료됩니다. -
ltrace
를 이미 실행 중인 프로그램에 연결한 경우 프로그램은ltrace
와 함께 종료됩니다.
-
애플리케이션에서 수행한 라이브러리 호출 목록을 분석합니다.
- 애플리케이션이 충돌하면 중요한 정보가 로그 끝에 있을 수 있습니다.
- 출력에는 불필요한 정보가 많이 포함되어 있습니다. 그러나 더 정확한 필터를 생성하고 절차를 반복할 수 있습니다.
둘 다 출력을 보고 파일에 저장하는 것이 유리합니다. 이 작업을 수행하려면 tee
명령을 사용합니다.
$ ltrace ... |& tee your_log_file.log
추가 리소스
ltrace(1) 매뉴얼 페이지:
$ man ltrace
- Red Hat Developer Toolset 사용자 가이드 - ltrace
3.3.4. SystemTap을 사용하여 애플리케이션 시스템 호출 모니터링
SystemTap 툴을 사용하면 커널 이벤트에 대한 사용자 지정 이벤트 핸들러를 등록할 수 있습니다. strace
툴과 비교하여 사용하기는 어렵지만 더 효율적이며 더 복잡한 처리 논리를 사용할 수 있습니다. strace.stp
라는 SystemTap 스크립트는 SystemTap과 함께 설치되며 SystemTap을 사용하여 strace
기능의 근사성을 제공합니다.
사전 요구 사항
절차
모니터링할 프로세스의PID(프로세스 ID)를 찾습니다.
$ ps -aux
strace.stp 스크립트를 사용하여 SystemTap을 실행합니다.
# stap /usr/share/systemtap/examples/process/strace.stp -x pid
pid 값은 프로세스 ID입니다.
스크립트가 커널 모듈로 컴파일된 다음 로드됩니다. 이렇게 하면 명령을 입력하고 출력을 가져오는 사이에 약간의 지연이 발생합니다.
- 프로세스에서 시스템 호출을 수행하면 호출 이름과 해당 매개 변수가 터미널에 출력됩니다.
-
프로세스가 종료되면 스크립트가 종료되거나
Ctrl+C
를 누르면 종료됩니다.
3.3.5. GDB를 사용하여 애플리케이션 시스템 호출 가로채기
GNU Debugger(GDB)를 사용하면 프로그램 실행 중에 발생하는 다양한 상황에서 실행을 중지할 수 있습니다. 프로그램이 시스템 호출을 수행할 때 실행을 중지하려면 GDB catchpoint 를 사용합니다.
절차
catchpoint를 설정합니다.
(gdb) catch syscall syscall-name
명령
catch syscall
은 프로그램이 시스템 호출을 수행할 때 실행을 중지하는 특수한 유형의 중단점을 설정합니다.syscall-name
옵션은 호출 이름을 지정합니다. 다양한 시스템 호출에 대해 여러 catchpoints를 지정할 수 있습니다.syscall-name
옵션을 벗어나면 GDB가 모든 시스템 호출에서 중지됩니다.프로그램 실행을 시작합니다.
프로그램이 실행을 시작하지 않은 경우 시작합니다.
(gdb) r
프로그램 실행이 중지된 경우 다시 시작합니다.
(gdb) c
- GDB는 프로그램이 지정된 시스템 호출을 수행한 후 실행을 중지합니다.
추가 리소스
3.3.6. GDB를 사용하여 애플리케이션별 신호 처리 가로채기
GNU Debugger(GDB)를 사용하면 프로그램 실행 중에 발생하는 다양한 상황에서 실행을 중지할 수 있습니다. 프로그램이 운영 체제에서 신호를 수신할 때 실행을 중지하려면 GDB catchpoint 를 사용합니다.
절차
catchpoint를 설정합니다.
(gdb) catch signal signal-type
명령
catch 신호는
프로그램에서 신호를 수신할 때 실행을 중지하는 특별한 유형의 중단점을 설정합니다.signal-type
옵션은 신호 유형을 지정합니다. 특수 값'all'
을 사용하여 모든 신호를 포착합니다.프로그램이 실행되도록 합니다.
프로그램이 실행을 시작하지 않은 경우 시작합니다.
(gdb) r
프로그램 실행이 중지된 경우 다시 시작합니다.
(gdb) c
- GDB는 프로그램이 지정된 신호를 받은 후 실행을 중지합니다.
3.4. 충돌한 애플리케이션 디버깅
애플리케이션을 직접 디버깅할 수 없는 경우도 있습니다. 이러한 상황에서는 종료 시 애플리케이션에 대한 정보를 수집하고 이후에 분석할 수 있습니다.
3.4.1. 코어 덤프: 무엇이 있고 어떻게 사용하는지
코어 덤프는 애플리케이션이 작동을 중지하고 ELF 형식으로 저장된 애플리케이션 메모리 부분의 사본입니다. 애플리케이션의 내부 변수 및 스택을 모두 포함하므로 애플리케이션의 최종 상태를 검사할 수 있습니다. 각 실행 파일 및 디버깅 정보로 보강된 경우 실행 중인 프로그램 분석과 유사한 방식으로 디버거를 사용하여 코어 덤프 파일을 분석할 수 있습니다.
Linux 운영 체제 커널은 이 기능이 활성화된 경우 코어 덤프를 자동으로 기록할 수 있습니다. 또는 실행 중인 애플리케이션에 신호를 보내 실제 상태와 관계없이 코어 덤프를 생성할 수 있습니다.
일부 제한은 코어 덤프를 생성하는 기능에 영향을 줄 수 있습니다. 현재 제한을 보려면 다음을 수행합니다.
$ ulimit -a
3.4.2. 코어 덤프와 애플리케이션 충돌 기록
애플리케이션 충돌을 기록하려면 코어 덤프 저장을 설정하고 시스템에 대한 정보를 추가합니다.
절차
코어 덤프를 활성화하려면
/etc/systemd/system.conf
파일에 다음 행이 포함되어 있는지 확인하십시오.DumpCore=yes DefaultLimitCORE=infinity
이러한 설정이 이전에 있는지 및 이전 값이 무엇인지에 대한 주석을 추가할 수도 있습니다. 필요한 경우 나중에 이러한 변경 사항을 되돌릴 수 있습니다. 주석은
#
문자로 시작하는 행입니다.파일을 변경하려면 관리자 수준 액세스 권한이 필요합니다.
새 구성을 적용합니다.
# systemctl daemon-reexec
코어 덤프 크기의 제한을 제거합니다.
# ulimit -c unlimited
이 변경을 취소하려면
무제한
이 아니라 값이0
인 명령을 실행합니다.시스템 정보 수집을 위한
sosreport
유틸리티를 제공하는sos
패키지를 설치합니다.# yum install sos
-
애플리케이션이 충돌하면
systemd-coredump
에 의해 코어 덤프가 생성되고 처리됩니다. 시스템에 대한 추가 정보를 제공하는 SOS 보고서를 생성합니다.
# sosreport
이렇게 하면 구성 파일 복사본과 같은 시스템에 대한 정보가 포함된
.tar
아카이브가 생성됩니다.코어 덤프를 찾아서 내보냅니다.
$ coredumpctl list executable-name $ coredumpctl dump executable-name > /path/to/file-for-export
애플리케이션이 여러 번 충돌하면 첫 번째 명령의 출력에 더 캡처된 코어 덤프가 나열됩니다. 이 경우 두 번째 명령의 구문을 구문을 사용하여 다른 정보를 사용하여 보다 정확한 쿼리를 만듭니다. 자세한 내용은 coredumpctl(1) 매뉴얼 페이지를 참조하십시오.
코어 덤프와 SOS 보고서를 디버깅이 수행되는 컴퓨터로 전송합니다. 알려진 경우 실행 파일을 전송합니다.
중요실행 파일을 알 수 없는 경우 코어 파일의 후속 분석이 해당 파일을 식별합니다.
- 선택 사항: 코어 덤프 및 SOS 보고서를 전송 후 제거하여 디스크 공간을 확보합니다.
추가 리소스
- 문서의 systemd 관리 기본 시스템 설정 구성
- 애플리케이션이 충돌하거나 분할 오류가 발생할 때 코어 파일 덤프를 활성화하는 방법 - 기술 자료 문서
- sosreport란 무엇이며 Red Hat Enterprise Linux 4.6 이상에서 생성하는 방법은 무엇입니까? - 기술 자료 문서
3.4.3. 코어 덤프를 사용하여 애플리케이션 크래시 상태 검사
사전 요구 사항
- 오류가 발생한 시스템에서 코어 덤프 파일과 sosreport가 있어야 합니다.
- GDB 및 elfutils가 시스템에 설치되어 있어야 합니다.
절차
충돌이 발생한 실행 파일을 식별하려면 코어 덤프 파일을 사용하여
eu-unstrip
명령을 실행합니다.$ eu-unstrip -n --core=./core.9814 0x400000+0x207000 2818b2009547f780a5639c904cded443e564973e@0x400284 /usr/bin/sleep /usr/lib/debug/bin/sleep.debug [exe] 0x7fff26fff000+0x1000 1e2a683b7d877576970e4275d41a6aaec280795e@0x7fff26fff340 . - linux-vdso.so.1 0x35e7e00000+0x3b6000 374add1ead31ccb449779bc7ee7877de3377e5ad@0x35e7e00280 /usr/lib64/libc-2.14.90.so /usr/lib/debug/lib64/libc-2.14.90.so.debug libc.so.6 0x35e7a00000+0x224000 3ed9e61c2b7e707ce244816335776afa2ad0307d@0x35e7a001d8 /usr/lib64/ld-2.14.90.so /usr/lib/debug/lib64/ld-2.14.90.so.debug ld-linux-x86-64.so.2
출력에는 공백으로 구분된 행의 각 모듈에 대한 세부 정보가 포함되어 있습니다. 정보는 다음 순서로 나열됩니다.
- 모듈이 매핑된 메모리 주소
- 모듈의 build-id 및 검색된 메모리의 위치
-
모듈의 실행 파일 이름, 알 수 없는
경우
또는 로 표시됨 또는 모듈이파일에서
로드되지 않은 경우 -
사용 가능한 경우 파일 이름으로 표시되는 디버깅 정보의 소스입니다
.
실행 파일 자체에 포함된 경우 또는 전혀 표시되지 않는경우
입니다. -
기본 모듈의 공유 라이브러리 이름(soname) 또는
[exe]
이 예에서 중요한 세부 사항은 텍스트
[exe]
를 포함하는 행의 파일 이름/usr/bin/sleep
및 build-id2818b2009547f780a56394cded443e564973e
입니다. 이 정보를 사용하여 코어 덤프를 분석하는 데 필요한 실행 파일을 식별할 수 있습니다.충돌한 실행 파일을 가져옵니다.
- 가능한 경우 충돌이 발생한 시스템에서 복사합니다. 코어 파일에서 추출한 파일 이름을 사용합니다.
시스템에서 동일한 실행 파일을 사용할 수도 있습니다. Red Hat Enterprise Linux를 기반으로 빌드된 각 실행 파일에는 고유한 build-id 값이 포함된 참고 사항이 포함되어 있습니다. 로컬에서 사용 가능한 관련 실행 파일의 build-id를 확인합니다.
$ eu-readelf -n executable_file
이 정보를 사용하여 원격 시스템의 실행 파일과 로컬 사본을 일치시킵니다. 코어 덤프에 나열된 로컬 파일 및 build-id의 build-id가 일치해야 합니다.
-
마지막으로, 애플리케이션이 RPM 패키지에서 설치된 경우 패키지에서 실행 파일을 가져올 수 있습니다.
sosreport
출력을 사용하여 필요한 패키지의 정확한 버전을 찾습니다.
- 실행 파일에서 사용하는 공유 라이브러리를 가져옵니다. 실행 파일에 대해 와 동일한 단계를 사용합니다.
- 애플리케이션이 패키지로 배포되는 경우 GDB에서 실행 파일을 로드하여 누락된 debuginfo 패키지에 대한 힌트를 표시합니다. 자세한 내용은 3.1.4절. “GDB를 사용하여 애플리케이션 또는 라이브러리의 debuginfo 패키지 가져오기” 의 내용을 참조하십시오.
핵심 파일을 자세히 검사하려면 GDB를 사용하여 실행 파일 및 코어 덤프 파일을 로드합니다.
$ gdb -e executable_file -c core_file
누락된 파일 및 디버깅 정보에 대한 추가 메시지는 디버깅 세션에 누락된 항목을 식별하는 데 도움이 됩니다. 필요한 경우 이전 단계로 돌아갑니다.
애플리케이션의 디버깅 정보를 패키지 대신 파일로 사용할 수 있는 경우
기호-file
명령을 사용하여 GDB에서 이 파일을 로드합니다.(gdb) symbol-file program.debug
program.debug 를 실제 파일 이름으로 교체합니다.
참고코어 덤프에 포함된 모든 실행 파일에 대한 디버깅 정보를 설치할 필요가 없을 수도 있습니다. 이러한 실행 가능한 파일은 애플리케이션 코드에서 사용하는 라이브러리입니다. 이러한 라이브러리는 분석 중인 문제에 직접 기여하지 않을 수 있으며, 디버깅 정보를 포함할 필요가 없습니다.
GDB 명령을 사용하여 충돌 시 애플리케이션 상태를 검사합니다. GDB를 사용한 애플리케이션 내부 상태 검사 참조.
참고코어 파일을 분석할 때 GDB는 실행 중인 프로세스에 연결되지 않습니다. 실행을 제어하기 위한 명령에는 아무런 영향이 없습니다.
추가 리소스
- GDB를 사용한 디버깅 - 2.1.1 파일 확인
- GDB - 18.1 파일을 지정하는 명령을 사용하여 디버깅
- GDB를 사용한 디버깅 - 18.3 별도의 파일에서 디버깅 정보 https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
3.4.4. coredumpctl을 사용하여 코어 덤프 생성 및 액세스
systemd
의 coredumpctl
도구는 충돌이 발생한 시스템의 코어 덤프 작업을 크게 간소화할 수 있습니다. 이 절차에서는 응답하지 않는 프로세스의 코어 덤프를 캡처하는 방법을 간략하게 설명합니다.
사전 요구 사항
코어 덤프 처리에
systemd-coredump
를 사용하도록 시스템을 구성해야 합니다. 이것이 사실인지 확인하려면 다음을 수행하십시오.$ sysctl kernel.core_pattern
출력이 다음과 같이 시작되면 구성이 올바릅니다.
kernel.core_pattern = |/usr/lib/systemd/systemd-coredump
절차
실행 파일 이름의 알려진 부분에 따라 중단 프로세스의 PID를 찾습니다.
$ pgrep -a executable-name-fragment
이 명령은 양식으로 행을 출력합니다.
PID command-line
명령줄 값을 사용하여 PID 가 의도한 프로세스에 속하는지 확인합니다.
예를 들면 다음과 같습니다.
$ pgrep -a bc 5459 bc
프로세스에 중단 신호를 보냅니다.
# kill -ABRT PID
core
dumpctl에서 코어
를 캡처했는지 확인합니다.$ coredumpctl list PID
예를 들면 다음과 같습니다.
$ coredumpctl list 5459 TIME PID UID GID SIG COREFILE EXE Thu 2019-11-07 15:14:46 CET 5459 1000 1000 6 present /usr/bin/bc
필요에 따라 핵심 파일을 추가로 검사하거나 사용합니다.
코어 덤프를 PID 및 기타 값으로 지정할 수 있습니다. 자세한 내용은 coredumpctl(1) 매뉴얼 페이지를 참조하십시오.
핵심 파일의 세부 정보를 보려면 다음을 수행합니다.
$ coredumpctl info PID
GDB 디버거에서 코어 파일을 로드하려면 다음을 수행합니다.
$ coredumpctl debug PID
디버깅 정보의 가용성에 따라 GDB에서 실행할 명령을 제안합니다. 예를 들면 다음과 같습니다.
Missing separate debuginfos, use: dnf debuginfo-install bc-1.07.1-5.el8.x86_64
이 프로세스에 대한 자세한 내용은 3.1.4절. “GDB를 사용하여 애플리케이션 또는 라이브러리의 debuginfo 패키지 가져오기” 을 참조하십시오.
다른 곳에서 추가 처리를 위해 코어 파일을 내보내려면 다음을 수행합니다.
$ coredumpctl dump PID > /path/to/file_for_export
/path/to/file_for_export 를 코어 덤프를 배치하려는 파일로 바꿉니다.
3.4.5. gcore
를 사용하여 프로세스 메모리 덤프
코어 덤프 디버깅의 워크플로를 사용하면 프로그램의 상태를 오프라인에서 분석할 수 있습니다. 경우에 따라 프로세스를 사용하여 환경에 액세스하기 어려운 경우와 같이 여전히 실행 중인 프로그램으로 이 워크플로를 사용할 수 있습니다. gcore
명령을 사용하여 실행 중인 동안 프로세스의 메모리를 덤프할 수 있습니다.
절차
프로세스 ID(pid)를 확인합니다.
ps
,pgrep
및top
과 같은 툴 사용 :$ ps -C some-program
이 프로세스의 메모리를 덤프합니다.
$ gcore -o filename pid
그러면 파일 파일 이름이 생성되고 여기에 프로세스 메모리를 덤프합니다. 메모리가 덤프되는 동안 프로세스 실행이 중지됩니다.
- 코어 덤프가 완료되면 프로세스가 정상적인 실행을 재개합니다.
시스템에 대한 추가 정보를 제공하는 SOS 보고서를 생성합니다.
# sosreport
이렇게 하면 구성 파일 복사본과 같은 시스템에 대한 정보가 포함된 tar 아카이브가 생성됩니다.
- 프로그램의 실행 파일, 코어 덤프 및 SOS 보고서를 디버깅이 수행되는 컴퓨터로 전송합니다.
- 선택 사항: 코어 덤프 및 SOS 보고서를 전송 후 제거하여 디스크 공간을 확보합니다.
추가 리소스
- 애플리케이션을 다시 시작하지 않고 코어 파일을 가져오는 방법 - 지식 베이스 문서
3.4.6. GDB로 보호된 프로세스 메모리 덤프
덤프되지 않은 프로세스 메모리를 표시할 수 있습니다. 이렇게 하면 리소스 및 프로세스 메모리에 중요한 데이터가 포함된 경우 추가 보안을 보장할 수 있습니다(예: 은행 또는 계정 애플리케이션 또는 전체 가상 시스템). 커널 코어 덤프(kdump
)와 수동 코어 덤프(gcore
, GDB)는 모두 이러한 방식으로 표시된 메모리를 덤프하지 않습니다.
경우에 따라 이러한 보호에 관계없이 프로세스 메모리의 전체 내용을 덤프해야 합니다. 다음 절차에서는 GDB 디버거를 사용하여 이 작업을 수행하는 방법을 설명합니다.
절차
/proc/PID/coredump_filter
파일의 설정을 무시하도록 GDB를 설정합니다.(gdb) set use-coredump-filter off
메모리 페이지 플래그
VM_DONTDUMP
를 무시하도록 GDB를 설정합니다.(gdb) set dump-excluded-mappings on
메모리를 덤프합니다.
(gdb) gcore core-file
core-file 을 메모리를 덤프하려는 파일의 이름으로 바꿉니다.
추가 리소스
- GDB를 사용한 디버깅 - 프로그램에서 코어 파일을 생성하는 방법 https://sourceware.org/gdb/onlinedocs/gdb/Core-File-Generation.html
3.5. GDB의 호환성 혁신적인 변경 사항
Red Hat Enterprise Linux 8에서 제공되는 GDB 버전에는 호환성이 손상되는 여러 변경 사항이 포함되어 있습니다. 특히 GDB 출력을 터미널에서 직접 읽습니다. 다음 섹션에서는 이러한 변경 사항에 대해 자세히 설명합니다.
GDB의 출력 구문 분석은 권장되지 않습니다. Python GDB API 또는 GDB 머신 인터페이스(MI)를 사용하여 스크립트를 선호합니다.
gdbserver에서 쉘을 사용하여 inferiors를 시작합니다.
열등 명령줄 인수에서 확장 및 변수 대체를 활성화하기 위해 GDBserver는 이제 GDB와 같은 쉘에서 유추를 시작합니다.
쉘 사용을 비활성화하려면 다음을 수행합니다.
-
타겟 extended-remote
GDB 명령을 사용하는 경우set startup-with-shell off
명령으로 쉘을 비활성화합니다. -
대상 원격
GDB 명령을 사용하는 경우 GDBserver의--no-startup-with-shell
옵션으로 쉘을 비활성화합니다.
예 3.1. 원격 GDB 유추에서 쉘 확장의 예
다음 예에서는 GDBserver를 통해 /bin/echo /*
명령을 실행하는 것이 Red Hat Enterprise Linux 버전 7 및 8에서 어떻게 다른지 보여줍니다.
RHEL 7의 경우:
$ gdbserver --multi :1234 $ gdb -batch -ex 'target extended-remote :1234' -ex 'set remote exec-file /bin/echo' -ex 'file /bin/echo' -ex 'run /*' /*
RHEL 8의 경우:
$ gdbserver --multi :1234 $ gdb -batch -ex 'target extended-remote :1234' -ex 'set remote exec-file /bin/echo' -ex 'file /bin/echo' -ex 'run /*' /bin /boot (...) /tmp /usr /var
Gcj
지원 제거
GNU 컴파일러 for Java(gcj
)로 컴파일된 Java 프로그램 디버깅 지원이 제거되었습니다.
유지 관리 명령을 덤프하는 기호의 새로운 구문
이제 기호 덤프 유지 관리 명령 구문에 파일 이름 앞에 옵션이 포함됩니다. 결과적으로 RHEL 7에서 GDB와 함께 작동하는 명령이 RHEL 8에서는 작동하지 않습니다.
예를 들어 다음 명령은 더 이상 파일에 기호를 저장하지 않지만 오류 메시지를 생성합니다.
(gdb) maintenance print symbols /tmp/out main.c
유지 관리 명령을 덤프하는 기호의 새 구문은 다음과 같습니다.
maint print symbols [-pc address] [--] [filename] maint print symbols [-objfile objfile] [-source source] [--] [filename] maint print psymbols [-objfile objfile] [-pc address] [--] [filename] maint print psymbols [-objfile objfile] [-source source] [--] [filename] maint print msymbols [-objfile objfile] [--] [filename]
스레드 번호가 더 이상 글로벌이 아닙니다.
이전에는 GDB가 글로벌 스레드 번호 지정만 사용했습니다. 2.1
과 같은ferior _num.thread_num
형식의 유추에 따라 번호 지정이 표시되도록 확장되었습니다. 결과적으로 $_thread
편의 변수 및Inferior Thread.num
Python 속성의 스레드 번호는 더 이상 유추자 간에 고유하지 않습니다.
GDB는 이제 이전 릴리스의 스레드 번호와 새로 해당하는 새 스레드 ID인 스레드당 두 번째 스레드 ID를 저장합니다. 글로벌 스레드 번호에 액세스하려면 $_gthread
편의 변수와Inferior Thread.global_num
Python 특성을 사용합니다.
이전 버전과의 호환성을 위해MI(Machine Interface) 스레드 ID에는 항상 글로벌 ID가 포함됩니다.
예 3.2. GDB 스레드 번호 변경 예
Red Hat Enterprise Linux 7의 경우:
# debuginfo-install coreutils $ gdb -batch -ex 'file echo' -ex start -ex 'add-inferior' -ex 'inferior 2' -ex 'file echo' -ex start -ex 'info threads' -ex 'pring $_thread' -ex 'inferior 1' -ex 'pring $_thread' (...) Id Target Id Frame * 2 process 203923 "echo" main (argc=1, argv=0x7fffffffdb88) at src/echo.c:109 1 process 203914 "echo" main (argc=1, argv=0x7fffffffdb88) at src/echo.c:109 $1 = 2 (...) $2 = 1
Red Hat Enterprise Linux 8의 경우:
# dnf debuginfo-install coreutils $ gdb -batch -ex 'file echo' -ex start -ex 'add-inferior' -ex 'inferior 2' -ex 'file echo' -ex start -ex 'info threads' -ex 'pring $_thread' -ex 'inferior 1' -ex 'pring $_thread' (...) Id Target Id Frame 1.1 process 4106488 "echo" main (argc=1, argv=0x7fffffffce58) at ../src/echo.c:109 * 2.1 process 4106494 "echo" main (argc=1, argv=0x7fffffffce58) at ../src/echo.c:109 $1 = 1 (...) $2 = 1
값 컨텐츠에 대한 메모리를 제한할 수 있습니다.
이전에는 GDB가 값 콘텐츠에 할당된 메모리 양을 제한하지 않았습니다. 결과적으로 잘못된 프로그램을 디버깅하면 GDB에서 메모리를 너무 많이 할당할 수 있었습니다. 할당된 메모리 양을 제한하기 위해 max-value-size
설정이 추가되었습니다. 이 제한의 기본값은 64KiB입니다. 결과적으로 Red Hat Enterprise Linux 8의 GDB는 너무 큰 값을 표시하지 않지만 값이 너무 크다고 보고합니다.
예를 들어, char s[128*1024]로 정의된 값을 인쇄하고 다른 결과를 생성합니다
.
-
Red Hat Enterprise Linux 7에서
$1 = 'A' <repeats 131072번>
-
Red Hat Enterprise Linux 8에서
값은 131072 바이트가 필요하며, 이는 max-value-size보다
큽니다.
Stab 형식의 Sun 버전은 더 이상 지원되지 않습니다.
stabs
디버그 파일 형식의 Sun 버전에 대한 지원이 제거되었습니다. gcc -gstabs
옵션을 사용하여 RHEL에서 GCC에서 생성된 stab 형식
은 여전히 GDB에서 지원합니다.
sysroot 변경 처리
set sysroot path
명령은 디버깅에 필요한 파일을 검색할 때 시스템 루트를 지정합니다. 이제 이 명령에 제공된 디렉토리 이름을 앞에 target target이 붙을 수 있습니다. 를 추가하여
GDB가 대상 시스템(로컬 및 원격 모두)의 공유 라이브러리를 읽도록 할 수 있습니다. 이전에 사용 가능한 remote:
접두사는 이제 target:
로 처리됩니다. 또한 기본 시스템 루트 값은 이전 버전과의 호환성을 위해 빈 문자열에서 target
으로 변경되었습니다.
지정된 시스템 루트는 기본 실행 파일의 파일 이름 앞에 추가되며, GDB가 원격으로 프로세스를 시작하거나 이미 실행 중인 프로세스(로컬 및 원격 모두)에 첨부된 경우입니다. 즉, 원격 프로세스의 경우 기본값 target:
는 GDB가 항상 원격 시스템의 디버깅 정보를 로드하려고 시도합니다. 이를 방지하려면 대상 원격
명령 앞에 set sysroot
명령을 실행하여 로컬 기호 파일이 원격 명령 앞에 배치되도록 합니다.
HISTSIZE는 더 이상 GDB 명령 기록 크기를 제어하지 않습니다.
이전에는 GDB에서 HISTSIZE
환경 변수를 사용하여 명령 기록을 유지해야 하는 기간을 결정했습니다. GDB가 대신 GDBHISTSIZE
환경 변수를 사용하도록 변경되었습니다. 이 변수는 GDB에만 고유합니다. 가능한 값과 해당 영향은 다음과 같습니다.
- 양수 - 이 크기의 명령 이력을 사용합니다.
-
-1
또는 빈 문자열 - 모든 명령의 기록을 유지합니다. - 숫자가 아닌 값 - 무시됨.
완료 제한 추가
이제 완료 중에 고려되는 최대 후보 수를 set max-completions
명령을 사용하여 제한할 수 있습니다. 현재 제한을 표시하려면 show max-completions
명령을 실행합니다. 기본값은 200입니다. 이 제한은 GDB가 과도하게 큰 완료 목록을 생성하고 응답하지 않는 것을 방지합니다.
예를 들어 p <tabtab> 입력 후의 출력은 다음과 같습니다
.
-
RHEL 7의 경우:
모든 29863 옵션을 표시하시겠습니까? (y 또는 n)
-
RHEL 8의 경우:
200 가능성을 모두 표시하시겠습니까? (y 또는 n)
HP-UX XDB 호환 모드 제거
HP-UX XDB 호환성 모드의 -xdb
옵션이 GDB에서 제거되었습니다.
스레드 신호 처리
이전에는 GDB가 신호가 실제로 전송된 스레드 대신 현재 스레드에 신호를 전달할 수 있었습니다. 이 버그가 수정되어 GDB가 실행을 다시 시작할 때 항상 올바른 스레드로 신호를 전달합니다.
또한 signal
명령은 요청된 신호를 현재 스레드에 항상 올바르게 전달합니다. 프로그램이 신호에 대해 중지되고 사용자가 전환 스레드를 전환하면 GDB에서 확인을 요청합니다.
중단 모드 - 항상 삽입 해제 및 자동 병합
always-inserted
설정이 변경되었습니다. auto
값과 해당 동작이 제거되었습니다. 이제 기본값은 off
입니다. 또한 off
값은 이제 GDB가 모든 스레드가 중지될 때까지 대상에서 중단점을 제거하지 않도록 합니다.
remotebaud 명령은 더 이상 지원되지 않음
set remotebaud
및 show remotebaud
명령은 더 이상 지원되지 않습니다. set serial baud
를 사용하고 대신 직렬 baud 명령을 표시합니다
.
3.6. 컨테이너에서 애플리케이션 디버깅
문제 해결의 다양한 측면에 맞는 다양한 명령줄 툴을 사용할 수 있습니다. 다음은 일반적인 명령줄 툴과 함께 카테고리를 제공합니다.
이는 명령줄 툴의 전체 목록이 아닙니다. 컨테이너 애플리케이션을 디버깅하기 위한 툴 선택은 컨테이너 이미지와 사용 사례에 따라 크게 달라집니다.
예를 들어 systemctl
,journalctl
,ip
,netstat
,ping
,traceroute
,perf
,iostat
툴에서는 보안상의 이유로 rootless 컨테이너에서 제한되는 네트워킹, systemd 서비스 또는 하드웨어 성능 카운터와 같은 시스템 수준 리소스와 상호 작용하므로 루트 액세스 권한이 필요할 수 있습니다.
루트리스 컨테이너는 승격된 권한이 필요 없이 작동하여 사용자 네임스페이스 내에서 루트가 아닌 사용자로 실행하여 호스트 시스템에서 향상된 보안 및 격리를 제공합니다. 호스트와의 제한된 상호 작용, 공격 면적 감소 및 보안 강화를 통해 권한 상승 취약점의 위험을 완화합니다.
루트 저장 컨테이너는 일반적으로 루트 사용자로 승격된 권한으로 실행되며 시스템 리소스 및 기능에 대한 전체 액세스 권한을 부여합니다. 근본 컨테이너는 유연성 및 제어 기능을 제공하지만 권한 상승 및 호스트 시스템의 취약점으로 인해 보안 위험이 발생합니다.
rootful 및 rootless 컨테이너에 대한 자세한 내용은 root less 컨테이너 설정, root리스 컨테이너로 업그레이드, rootless 컨테이너에 대한 특수 고려 사항을 참조하십시오.
systemd 및 프로세스 관리 툴
systemctl
- 컨테이너 내의 systemd 서비스를 제어하여 시작, 중지, 활성화, 작업을 비활성화합니다.
journalctl
- systemd 서비스에서 생성한 로그를 보고 컨테이너 문제 해결에 도움이 됩니다.
네트워킹 툴
ip
- 컨테이너 내에서 네트워크 인터페이스, 라우팅 및 주소를 관리합니다.
netstat
- 네트워크 연결, 라우팅 테이블 및 인터페이스 통계를 표시합니다.
ping
- 컨테이너 또는 호스트 간의 네트워크 연결을 확인합니다.
traceroute
- 네트워크 문제를 진단하는 데 유용한 대상에 도달하는 데 사용하는 경로를 식별합니다.
프로세스 및 성능 툴
ps
- 컨테이너 내에서 현재 실행 중인 프로세스를 나열합니다.
top
- 컨테이너 내 프로세스의 리소스 사용량에 대한 실시간 정보를 제공합니다.
htop
- 리소스 사용률 모니터링을 위한 대화형 프로세스 뷰어입니다.
perf
- CPU 성능 프로파일링, 추적 및 모니터링은 시스템 또는 애플리케이션 내에서 성능 병목 현상을 파악하는 데 도움이 됩니다.
vmstat
- 컨테이너 내의 가상 메모리 통계를 보고하여 성능 분석을 지원합니다.
iostat
- 컨테이너 내에서 블록 장치에 대한 입력/출력 통계를 모니터링합니다.
GDB
(GNU Debugger)- 사용자가 실행을 추적 및 제어하고, 변수를 검사하며, 메모리를 분석하고, 런타임 중에 등록할 수 있도록 하여 프로그램 검사 및 디버깅에 도움이 되는 명령줄 디버거입니다. 자세한 내용은 Red Hat OpenShift 컨테이너 내에서 애플리케이션 디버깅 문서를 참조하십시오.
strace
- 프로그램에서 수행한 시스템 호출을 가로채고 기록하므로 프로그램과 운영 체제 간의 상호 작용을 표시하여 문제를 해결할 수 있습니다.
보안 및 액세스 제어 도구
sudo
- 승격된 권한으로 명령을 실행할 수 있습니다.
chroot
- 명령의 루트 디렉터리를 변경하여 다른 루트 디렉터리 내에서 테스트 또는 문제 해결에 유용합니다.
podman-Specific Tools
Podman 로그
- 배치-실행 시 하나 이상의 컨테이너에 존재하는 모든 로그를 검색합니다.
podman inspect
- 이름 또는 ID로 식별된 대로 컨테이너 및 이미지에 대한 하위 수준 정보를 표시합니다.
Podman 이벤트
-
Podman에서 발생하는 이벤트를 모니터링하고 출력합니다. 각 이벤트에는 타임스탬프, 유형, 상태, 이름(해당되는 경우) 및 이미지(해당되는 경우)가 포함됩니다. 기본 로깅 메커니즘은
journald
입니다. podman run --health-cmd
- 상태 점검을 사용하여 컨테이너 내에서 실행되는 프로세스의 상태 또는 준비 상태를 확인합니다.
podman top
- 컨테이너의 실행 중인 프로세스를 표시합니다.
podman exec
- 실행 중인 컨테이너에서 명령을 실행하거나 연결하는 것은 컨테이너에서 발생하는 상황을 더 잘 이해하는 데 매우 유용합니다.
podman export
- 컨테이너가 실패하면 기본적으로 어떤 일이 발생했는지 알 수 없습니다. 컨테이너에서 파일 시스템 구조를 내보내면 마운트된 볼륨에 없는 다른 로그 파일을 확인할 수 있습니다.
추가 리소스
Red Hat OpenShift 컨테이너 내에서 애플리케이션 디버깅
-
gdb
-
-
코어 덤프,
sosreport
,gdb
,ps
,core
.
-
코어 덤프,
-
Docker exec + env,
netstat
,kubectl
,etcdctl
,journalctl
, docker logs
-
Docker exec + env,
-
podman logs
,systemctl
,
/podman exec
kill
/restart
,podman insect
, podman exec ,podman
exec ,podman export
,paunch
를 확인합니다.
-
외부 링크
4장. 개발을 위한 추가 도구 세트
4.1. GCC Toolset 사용
4.1.1. GCC Toolset이란 무엇입니까.
Red Hat Enterprise Linux 8에서는 최신 버전의 개발 및 성능 분석 도구가 포함된 애플리케이션 스트림인 GCC Toolset이 도입되었습니다. GCC Toolset은 RHEL 7용 Red Hat Developer Toolset 과 유사합니다.
GCC Toolset은 AppStream
리포지토리에서 소프트웨어 컬렉션의 형태로 애플리케이션 스트림으로 사용할 수 있습니다. GCC Toolset은 Red Hat Enterprise Linux 서브스크립션 수준 계약 하에서 완전히 지원되며 기능상 완전하며 생산 용도로 사용됩니다. GCC Toolset에서 제공하는 애플리케이션과 라이브러리는 Red Hat Enterprise Linux 시스템 버전을 대체하지 않고 재정의하지 않으며 자동으로 기본값 또는 기본 선택이 되지 않습니다. 소프트웨어 컬렉션이라는 프레임워크를 사용하여 추가 개발자 툴 세트가 /opt/
디렉터리에 설치되며 scl
유틸리티를 사용하여 필요에 따라 사용자가 명시적으로 활성화합니다. 특정 도구 또는 기능에 대해 별도로 명시하지 않는 한 GCC Toolset은 Red Hat Enterprise Linux에서 지원하는 모든 아키텍처에 사용할 수 있습니다.
4.1.2. GCC Toolset 설치
시스템에 GCC Toolset을 설치하면 주요 도구 및 필요한 모든 종속 항목이 설치됩니다. 도구 세트의 일부는 기본적으로 설치되지 않으며 별도로 설치해야 합니다.
절차
GCC Toolset 버전 N 을 설치하려면 다음을 수행합니다.
# yum install gcc-toolset-N
4.1.3. GCC Toolset에서 개별 패키지 설치
전체 도구 집합 대신 GCC Toolset의 특정 도구 만 설치하려면 사용 가능한 패키지를 나열하고 yum
패키지 관리 도구를 사용하여 선택한 툴을 설치합니다. 이 절차는 도구 집합을 사용하여 기본적으로 설치되지 않는 패키지에도 유용합니다.
절차
GCC Toolset 버전 N 에서 사용 가능한 패키지를 나열하십시오 :
$ yum list available gcc-toolset-N-\*
다음 패키지를 설치하려면 다음을 수행하십시오.
# yum install package_name
package_name 을 공백으로 구분된 설치할 패키지 목록으로 교체합니다. 예를 들어
gcc-toolset-9-gdb-gdbserver 및
패키지를 설치하려면 다음을 실행합니다.gcc-
toolset-9-gdb-doc# yum install gcc-toolset-9-gdb-gdbserver gcc-toolset-9-gdb-doc
4.1.4. GCC Toolset 설치 제거
시스템에서 GCC Toolset을 제거하려면 yum
패키지 관리 도구를 사용하여 설치 제거합니다.
절차
GCC Toolset 버전 N 을 설치 제거하려면 다음을 수행합니다.
# yum remove gcc-toolset-N\*
4.1.5. GCC Toolset에서 툴 실행
GCC Toolset에서 도구를 실행하려면 scl
유틸리티를 사용합니다.
절차
GCC Toolset 버전 N 에서 도구를 실행하려면 :
$ scl enable gcc-toolset-N tool
4.1.6. GCC Toolset을 사용하여 쉘 세션 실행
GCC Toolset을 사용하면 scl
명령을 명시적으로 사용하지 않고 이러한 도구 대신 GCC Toolset 툴 버전이 사용되는 쉘 세션을 실행할 수 있습니다. 이 기능은 개발 설정을 설정하거나 테스트할 때와 같이 도구를 여러 번 시작해야 하는 경우에 유용합니다.
절차
GCC Toolset 버전의 툴 버전이 다음 도구의 시스템 버전을 재정의 하는 쉘 세션을 실행하려면 다음을 수행합니다.
$ scl enable gcc-toolset-N bash
4.2. GCC Toolset 9
GCC Toolset 버전 9와 이 버전에 포함된 툴에 대한 정보를 알아보십시오.
4.2.1. GCC Toolset 9에서 제공하는 도구 및 버전
GCC Toolset 9는 다음 도구 및 버전을 제공합니다.
이름 | 버전 | 설명 |
---|---|---|
GCC | 9.2.1 | C, C++ 및 Fortran을 지원하는 이식 가능한 컴파일러 제품군. |
GDB | 8.3 | C, C++ 및 Fortran으로 작성된 프로그램의 명령줄 디버거. |
valgrind | 3.15.0 | 계측 프레임워크와 메모리 오류를 감지하고 메모리 관리 문제를 식별하며 시스템 호출에서 부적절한 인수를 보고하기 위해 애플리케이션을 프로파일링하는 여러 가지 툴. |
SystemTap | 4.1 | 계측, 재컴파일, 설치 및 재부팅 없이도 전체 시스템의 활동을 모니터링하는 추적 및 프로빙 툴. |
Dyninst | 10.1.0 | 실행 중에 사용자 공간 실행 파일을 계측하고 작업하기 위한 라이브러리. |
binutils | 2.32 | 개체 파일과 바이너리 바이너리를 검사하고 조작하는 바이너리 도구 및 기타 유틸리티 컬렉션. |
elfutils | 0.176 | ELF 파일을 검사하고 조작하기 위한 바이너리 도구 및 기타 유틸리티 모음입니다. |
dwz | 0.12 | 크기를 위해 ELF 공유 라이브러리 및 ELF 실행 파일에 포함된 DWARF 디버깅 정보를 최적화하는 툴입니다. |
make | 4.2.1 | 종속성 추적 빌드 자동화 툴입니다. |
strace | 5.1 | 프로그램이 수신하는 시스템 호출과 신호를 모니터링하는 디버깅 툴입니다. |
ltrace | 0.7.91 | 프로그램에서 수행하는 동적 라이브러리에 대한 호출을 표시하는 디버깅 툴입니다. 또한 프로그램에서 실행되는 시스템 호출을 모니터링할 수 있습니다. |
annobin | 9.08 | 빌드 보안 확인 도구. |
4.2.2. GCC Toolset 9의 C++ 호환성
여기에 제시된 호환성 정보는 GCC Toolset 9의 GCC에만 적용됩니다.
GCC Toolset의 GCC 컴파일러는 다음과 같은 C++ 표준을 사용할 수 있습니다.
- C++14
이것은 GCC Toolset 9의 기본 언어 표준 설정으로, GNU 확장 기능이 있으며, 옵션
-std=gnu++14
를 명시적으로 사용하는 것과 같습니다.해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 6 이상을 사용하여 빌드된 경우 C++14 언어 버전을 사용할 수 있습니다.
- C++11
이 언어 표준은 GCC Toolset 9에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 5 이상을 사용하여 빌드된 경우 C++11 언어 버전을 사용할 수 있습니다.
- C++98
- 이 언어 표준은 GCC Toolset 9에서 사용할 수 있습니다. 이 표준을 사용하여 빌드된 바이너리, 공유 라이브러리 및 개체는 GCC 도구 세트, Red Hat Developer Toolset, RHEL 5, 6, 7 및 8의 GCC와 관계없이 자유롭게 혼합할 수 있습니다.
- C++17, C++2a
- 이러한 언어 표준은 GCC Toolset 9에서 실험적이고 불안정하며 지원되지 않는 기능으로만 사용할 수 있습니다. 또한 이러한 표준을 사용하여 빌드된 오브젝트, 바이너리 파일 및 라이브러리의 호환성은 보장되지 않습니다.
모든 언어 표준은 표준 호환 변형이나 GNU 확장 모두에서 사용할 수 있습니다.
GCC Toolset과 함께 빌드된 개체를 RHEL 툴체인(특히 .o 또는.
a
파일)과 혼합할 때 GCC Toolset 툴체인을 모든 링크에 사용해야 합니다. 이렇게 하면 GCC Toolset에서만 제공되는 최신 라이브러리 기능이 링크 시간에 해결됩니다.
4.2.3. GCC Toolset 9의 GCC 세부 사항
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-9 'gcc -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-9 'gcc objfile.o -lsomelib'
이 권장 사항은 GCC 기본 Red Hat Enterprise Linux 버전을 사용하는 경우에도 적용됩니다.
4.2.4. GCC Toolset 9의 binutils 세부 사항
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-9 'ld -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-9 'ld objfile.o -lsomelib'
이 권장 사항은 기본 Red Hat Enterprise Linux 버전 binutils 를 사용하는 경우에도 적용됩니다.
4.3. GCC Toolset 10
GCC Toolset 버전 10에 특정한 정보와 이 버전에 포함된 툴에 대해 알아보십시오.
4.3.1. GCC Toolset 10에서 제공하는 도구 및 버전
GCC Toolset 10은 다음 도구 및 버전을 제공합니다.
이름 | 버전 | 설명 |
---|---|---|
GCC | 10.2.1 | C, C++ 및 Fortran을 지원하는 이식 가능한 컴파일러 제품군. |
GDB | 9.2 | C, C++ 및 Fortran으로 작성된 프로그램의 명령줄 디버거. |
valgrind | 3.16.0 | 계측 프레임워크와 메모리 오류를 감지하고 메모리 관리 문제를 식별하며 시스템 호출에서 부적절한 인수를 보고하기 위해 애플리케이션을 프로파일링하는 여러 가지 툴. |
SystemTap | 4.4 | 계측, 재컴파일, 설치 및 재부팅 없이도 전체 시스템의 활동을 모니터링하는 추적 및 프로빙 툴. |
Dyninst | 10.2.1 | 실행 중에 사용자 공간 실행 파일을 계측하고 작업하기 위한 라이브러리. |
binutils | 2.35 | 개체 파일과 바이너리 바이너리를 검사하고 조작하는 바이너리 도구 및 기타 유틸리티 컬렉션. |
elfutils | 0.182 | ELF 파일을 검사하고 조작하기 위한 바이너리 도구 및 기타 유틸리티 모음입니다. |
dwz | 0.12 | 크기를 위해 ELF 공유 라이브러리 및 ELF 실행 파일에 포함된 DWARF 디버깅 정보를 최적화하는 툴입니다. |
make | 4.2.1 | 종속성 추적 빌드 자동화 툴입니다. |
strace | 5.7 | 프로그램이 수신하는 시스템 호출과 신호를 모니터링하는 디버깅 툴입니다. |
ltrace | 0.7.91 | 프로그램에서 수행하는 동적 라이브러리에 대한 호출을 표시하는 디버깅 툴입니다. 또한 프로그램에서 실행되는 시스템 호출을 모니터링할 수 있습니다. |
annobin | 9.29 | 빌드 보안 확인 도구. |
4.3.2. GCC Toolset 10의 C++ 호환성
여기에 제시된 호환성 정보는 GCC Toolset 10의 GCC에만 적용됩니다.
GCC Toolset의 GCC 컴파일러는 다음과 같은 C++ 표준을 사용할 수 있습니다.
- C++14
이것은 GCC Toolset 10의 기본 언어 표준 설정으로, GNU 확장 기능이 있어 옵션
-std=gnu++14
를 명시적으로 사용합니다.해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 6 이상을 사용하여 빌드된 경우 C++14 언어 버전을 사용할 수 있습니다.
- C++11
이 언어 표준은 GCC Toolset 10에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 5 이상을 사용하여 빌드된 경우 C++11 언어 버전을 사용할 수 있습니다.
- C++98
- 이 언어 표준은 GCC Toolset 10에서 사용할 수 있습니다. 이 표준을 사용하여 빌드된 바이너리, 공유 라이브러리 및 개체는 GCC 도구 세트, Red Hat Developer Toolset, RHEL 5, 6, 7 및 8의 GCC와 관계없이 자유롭게 혼합할 수 있습니다.
- C++17
- 이 언어 표준은 GCC Toolset 10에서 사용할 수 있습니다.
- C++20
- 이 언어 표준은 GCC Toolset 10에서 실험적이고 불안정하며 지원되지 않는 기능으로만 사용할 수 있습니다. 또한 이 표준을 사용하여 빌드된 오브젝트, 바이너리 파일 및 라이브러리의 호환성은 보장되지 않습니다.
모든 언어 표준은 표준 호환 변형이나 GNU 확장 모두에서 사용할 수 있습니다.
GCC Toolset과 함께 빌드된 개체를 RHEL 툴체인(특히 .o 또는.
a
파일)과 혼합할 때 GCC Toolset 툴체인을 모든 링크에 사용해야 합니다. 이렇게 하면 GCC Toolset에서만 제공되는 최신 라이브러리 기능이 링크 시간에 해결됩니다.
4.3.3. GCC Toolset 10의 GCC 세부 사항
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-10 'gcc -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-10 'gcc objfile.o -lsomelib'
이 권장 사항은 GCC 기본 Red Hat Enterprise Linux 버전을 사용하는 경우에도 적용됩니다.
4.3.4. GCC Toolset의 binutils 세부 사항 10
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-10 'ld -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-10 'ld objfile.o -lsomelib'
이 권장 사항은 기본 Red Hat Enterprise Linux 버전 binutils 를 사용하는 경우에도 적용됩니다.
4.4. GCC Toolset 11
GCC Toolset 버전 11에 특정한 정보와 이 버전에 포함된 툴에 대해 알아보십시오.
4.4.1. GCC Toolset 11에서 제공하는 툴 및 버전
GCC Toolset 11은 다음과 같은 도구와 버전을 제공합니다.
이름 | 버전 | 설명 |
---|---|---|
GCC | 11.2.1 | C, C++ 및 Fortran을 지원하는 이식 가능한 컴파일러 제품군. |
GDB | 10.2 | C, C++ 및 Fortran으로 작성된 프로그램의 명령줄 디버거. |
valgrind | 3.17.0 | 계측 프레임워크와 메모리 오류를 감지하고 메모리 관리 문제를 식별하며 시스템 호출에서 부적절한 인수를 보고하기 위해 애플리케이션을 프로파일링하는 여러 가지 툴. |
SystemTap | 4.5 | 계측, 재컴파일, 설치 및 재부팅 없이도 전체 시스템의 활동을 모니터링하는 추적 및 프로빙 툴. |
Dyninst | 11.0.0 | 실행 중에 사용자 공간 실행 파일을 계측하고 작업하기 위한 라이브러리. |
binutils | 2.36.1 | 개체 파일과 바이너리 바이너리를 검사하고 조작하는 바이너리 도구 및 기타 유틸리티 컬렉션. |
elfutils | 0.185 | ELF 파일을 검사하고 조작하기 위한 바이너리 도구 및 기타 유틸리티 모음입니다. |
dwz | 0.14 | 크기를 위해 ELF 공유 라이브러리 및 ELF 실행 파일에 포함된 DWARF 디버깅 정보를 최적화하는 툴입니다. |
make | 4.3 | 종속성 추적 빌드 자동화 툴입니다. |
strace | 5.13 | 프로그램이 수신하는 시스템 호출과 신호를 모니터링하는 디버깅 툴입니다. |
ltrace | 0.7.91 | 프로그램에서 수행하는 동적 라이브러리에 대한 호출을 표시하는 디버깅 툴입니다. 또한 프로그램에서 실행되는 시스템 호출을 모니터링할 수 있습니다. |
annobin | 10.23 | 빌드 보안 확인 도구. |
4.4.2. GCC Toolset 11의 C++ 호환성
여기에 제시된 호환성 정보는 GCC Toolset 11의 GCC에만 적용됩니다.
GCC Toolset의 GCC 컴파일러는 다음과 같은 C++ 표준을 사용할 수 있습니다.
- C++14
이 언어 표준은 GCC Toolset 11에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 6 이상을 사용하여 빌드된 경우 C++14 언어 버전을 사용할 수 있습니다.
- C++11
이 언어 표준은 GCC Toolset 11에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 5 이상을 사용하여 빌드된 경우 C++11 언어 버전을 사용할 수 있습니다.
- C++98
- 이 언어 표준은 GCC Toolset 11에서 사용할 수 있습니다. 이 표준을 사용하여 빌드된 바이너리, 공유 라이브러리 및 개체는 GCC 도구 세트, Red Hat Developer Toolset, RHEL 5, 6, 7 및 8의 GCC와 관계없이 자유롭게 혼합할 수 있습니다.
- C++17
이 언어 표준은 GCC Toolset 11에서 사용할 수 있습니다.
이는 GCC Toolset 11의 기본 언어 표준 설정이며, GNU 확장 기능을 사용하여 명시적으로
-std=gnu++17
을 사용하는 것과 동일합니다.C++17 언어 버전은 해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 10 이상을 사용하여 빌드된 경우 지원됩니다.
- C++20 및 C++23
이 언어 표준은 GCC Toolset 11에서 실험적이고 불안정하며 지원되지 않는 기능으로만 사용할 수 있습니다. 또한 이 표준을 사용하여 빌드된 오브젝트, 바이너리 파일 및 라이브러리의 호환성은 보장되지 않습니다.
C++20 지원을 활성화하려면 g++ 명령줄 옵션
-std=c++20
을 g++ 명령줄에 추가합니다.C++23 지원을 활성화하려면 g++ 명령줄 옵션
-std=c++2b
를 g++ 명령줄에 추가합니다.
모든 언어 표준은 표준 호환 변형이나 GNU 확장 모두에서 사용할 수 있습니다.
GCC Toolset과 함께 빌드된 개체를 RHEL 툴체인(특히 .o 또는.
a
파일)과 혼합할 때 GCC Toolset 툴체인을 모든 링크에 사용해야 합니다. 이렇게 하면 GCC Toolset에서만 제공되는 최신 라이브러리 기능이 링크 시간에 해결됩니다.
4.4.3. GCC Toolset 11의 GCC 세부 정보
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-11 'gcc -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-11 'gcc objfile.o -lsomelib'
이 권장 사항은 GCC 기본 Red Hat Enterprise Linux 버전을 사용하는 경우에도 적용됩니다.
4.4.4. GCC Toolset 11의 binutils 세부 정보
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-11 'ld -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-11 'ld objfile.o -lsomelib'
이 권장 사항은 기본 Red Hat Enterprise Linux 버전 binutils 를 사용하는 경우에도 적용됩니다.
4.5. GCC Toolset 12
GCC Toolset 버전 12에 특정한 정보와 이 버전에 포함된 툴에 대해 알아보십시오.
4.5.1. GCC Toolset 12에서 제공하는 툴 및 버전
GCC Toolset 12는 다음 도구 및 버전을 제공합니다.
이름 | 버전 | 설명 |
---|---|---|
GCC | 12.2.1 | C, C++ 및 Fortran을 지원하는 이식 가능한 컴파일러 제품군. |
GDB | 11.2 | C, C++ 및 Fortran으로 작성된 프로그램의 명령줄 디버거. |
binutils | 2.38 | 개체 파일과 바이너리 바이너리를 검사하고 조작하는 바이너리 도구 및 기타 유틸리티 컬렉션. |
dwz | 0.14 | 크기를 위해 ELF 공유 라이브러리 및 ELF 실행 파일에 포함된 DWARF 디버깅 정보를 최적화하는 툴입니다. |
annobin | 11.08 | 빌드 보안 확인 도구. |
4.5.2. GCC Toolset 12의 C++ 호환성
여기에 제시된 호환성 정보는 GCC Toolset 12의 GCC에만 적용됩니다.
GCC Toolset의 GCC 컴파일러는 다음과 같은 C++ 표준을 사용할 수 있습니다.
- C++14
이 언어 표준은 GCC Toolset 12에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 6 이상을 사용하여 빌드된 경우 C++14 언어 버전을 사용할 수 있습니다.
- C++11
이 언어 표준은 GCC Toolset 12에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 5 이상을 사용하여 빌드된 경우 C++11 언어 버전을 사용할 수 있습니다.
- C++98
- 이 언어 표준은 GCC Toolset 12에서 사용할 수 있습니다. 이 표준을 사용하여 빌드된 바이너리, 공유 라이브러리 및 개체는 GCC 도구 세트, Red Hat Developer Toolset, RHEL 5, 6, 7 및 8의 GCC와 관계없이 자유롭게 혼합할 수 있습니다.
- C++17
이 언어 표준은 GCC Toolset 12에서 사용할 수 있습니다.
이는 GCC Toolset 12의 기본 언어 표준 설정이며, GNU 확장이
-std=gnu++17
옵션을 사용하는 것과 동일합니다.C++17 언어 버전은 해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 10 이상을 사용하여 빌드된 경우 지원됩니다.
- C++20 및 C++23
이 언어 표준은 GCC Toolset 12에서만 실험적이고 불안정하며 지원되지 않는 기능으로만 사용할 수 있습니다. 또한 이 표준을 사용하여 빌드된 오브젝트, 바이너리 파일 및 라이브러리의 호환성은 보장되지 않습니다.
C++20 지원을 활성화하려면 g++ 명령줄 옵션
-std=c++20
을 g++ 명령줄에 추가합니다.C++23 지원을 활성화하려면 명령줄 옵션
-std=c++23
을 g++ 명령줄에 추가합니다.
모든 언어 표준은 표준 호환 변형이나 GNU 확장 모두에서 사용할 수 있습니다.
GCC Toolset과 함께 빌드된 개체를 RHEL 툴체인(특히 .o 또는.
a
파일)과 혼합할 때 GCC Toolset 툴체인을 모든 링크에 사용해야 합니다. 이렇게 하면 GCC Toolset에서만 제공되는 최신 라이브러리 기능이 링크 시간에 해결됩니다.
4.5.3. GCC Toolset 12의 GCC 관련 세부 사항
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-12 'gcc -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-12 'gcc objfile.o -lsomelib'
이 권장 사항은 GCC 기본 Red Hat Enterprise Linux 버전을 사용하는 경우에도 적용됩니다.
4.5.4. GCC Toolset 12의 binutils 세부 정보
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-12 'ld -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-12 'ld objfile.o -lsomelib'
이 권장 사항은 기본 Red Hat Enterprise Linux 버전 binutils 를 사용하는 경우에도 적용됩니다.
4.5.5. GCC Toolset 12의 annobin 관련 세부 사항
GCC Toolset 12의 annobin
과 gcc
간의 동기화 문제로 인해 다음과 유사한 오류 메시지와 함께 컴파일이 실패할 수 있습니다.
cc1: fatal error: inaccessible plugin file
opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin/gcc-annobin.so
expanded from short plugin name gcc-annobin: No such file or directory
이 문제를 해결하려면 annobin.so
파일에서 gcc-annobin.so
파일로 플러그인 디렉토리에 심볼릭 링크를 만듭니다.
# cd /opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin
# ln -s annobin.so gcc-annobin.so
아키텍처 를 시스템에서 사용하는 아키텍처로 교체합니다.
-
aarch64
-
i686
-
ppc64le
-
s390x
-
x86_64
4.6. GCC Toolset 13
GCC Toolset 버전 13과 이 버전에 포함된 툴에 대한 정보를 알아보십시오.
4.6.1. GCC Toolset 13에서 제공하는 툴 및 버전
GCC Toolset 13은 다음 툴과 버전을 제공합니다.
이름 | 버전 | 설명 |
---|---|---|
GCC | 13.2.1 | C, C++ 및 Fortran을 지원하는 이식 가능한 컴파일러 제품군. |
GDB | 12.1 | C, C++ 및 Fortran으로 작성된 프로그램의 명령줄 디버거. |
binutils | 2.40 | 개체 파일과 바이너리 바이너리를 검사하고 조작하는 바이너리 도구 및 기타 유틸리티 컬렉션. |
dwz | 0.14 | 크기를 위해 ELF 공유 라이브러리 및 ELF 실행 파일에 포함된 DWARF 디버깅 정보를 최적화하는 툴입니다. |
annobin | 12.32 | 빌드 보안 확인 도구. |
4.6.2. GCC Toolset 13의 C++ 호환성
여기에 제시된 호환성 정보는 GCC Toolset 13의 GCC에만 적용됩니다.
GCC Toolset의 GCC 컴파일러는 다음과 같은 C++ 표준을 사용할 수 있습니다.
- C++14
이 언어 표준은 GCC Toolset 13에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 6 이상을 사용하여 빌드된 경우 C++14 언어 버전을 사용할 수 있습니다.
- C++11
이 언어 표준은 GCC Toolset 13에서 사용할 수 있습니다.
해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 5 이상을 사용하여 빌드된 경우 C++11 언어 버전을 사용할 수 있습니다.
- C++98
- 이 언어 표준은 GCC Toolset 13에서 사용할 수 있습니다. 이 표준을 사용하여 빌드된 바이너리, 공유 라이브러리 및 개체는 GCC 도구 세트, Red Hat Developer Toolset, RHEL 5, 6, 7 및 8의 GCC와 관계없이 자유롭게 혼합할 수 있습니다.
- C++17
이 언어 표준은 GCC Toolset 13에서 사용할 수 있습니다.
이는 g
d=gnu++17
옵션을 사용하는 것과 동일한 GNU 확장이 포함된 GCC Toolset 13의 기본 언어 표준 설정입니다.C++17 언어 버전은 해당 플래그로 컴파일된 모든 C++ 개체가 GCC 버전 10 이상을 사용하여 빌드된 경우 지원됩니다.
- C++20 및 C++23
이러한 언어 표준은 실험적이고 불안정하며 지원되지 않는 기능으로만 GCC Toolset 13에서 사용할 수 있습니다. 또한 이 표준을 사용하여 빌드된 오브젝트, 바이너리 파일 및 라이브러리의 호환성은 보장되지 않습니다.
C++20 표준을 활성화하려면 명령줄 옵션
-std=c++20
을 g++ 명령줄에 추가합니다.C++23 표준을 활성화하려면 명령줄 옵션
-std=c++23
을 g++ 명령줄에 추가합니다.
모든 언어 표준은 표준 호환 변형이나 GNU 확장 모두에서 사용할 수 있습니다.
GCC Toolset과 함께 빌드된 개체를 RHEL 툴체인(특히 .o 또는.
a
파일)과 혼합할 때 GCC Toolset 툴체인을 모든 링크에 사용해야 합니다. 이렇게 하면 GCC Toolset에서만 제공되는 최신 라이브러리 기능이 링크 시간에 해결됩니다.
4.6.3. GCC 도구 세트 13의 GCC 세부 사항
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-13 'gcc -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-13 'gcc objfile.o -lsomelib'
이 권장 사항은 GCC 기본 Red Hat Enterprise Linux 버전을 사용하는 경우에도 적용됩니다.
4.6.4. GCC Toolset 13의 binutils 세부 사항
라이브러리의 정적 연결
특정 최신 라이브러리 기능은 여러 버전의 Red Hat Enterprise Linux에서 실행을 지원하기 위해 GCC Toolset으로 구축된 애플리케이션에 정적으로 연결됩니다. 이는 표준 Red Hat Enterprise Linux 에라타가 이 코드를 변경하지 않기 때문에 추가 마이너 보안 위험이 발생합니다. 이러한 위험으로 인해 개발자가 애플리케이션을 다시 빌드해야 하는 경우 Red Hat은 보안 에라타를 사용하여 이를 전달합니다.
이러한 추가 보안 위험 때문에 개발자는 동일한 이유로 전체 애플리케이션을 정적으로 연결하지 않는 것이 좋습니다.
연결할 때 오브젝트 파일 다음에 라이브러리 지정
GCC Toolset에서 라이브러리는 정적 아카이브를 통해 일부 기호를 지정할 수 있는 링커 스크립트를 사용하여 연결됩니다. 이는 여러 버전의 Red Hat Enterprise Linux와의 호환성을 보장하는 데 필요합니다. 그러나 링커 스크립트는 해당 공유 개체 파일의 이름을 사용합니다. 결과적으로 링커는 예상과 다른 기호 처리 규칙을 사용하며 오브젝트 파일을 지정하는 옵션보다 라이브러리 추가 옵션이 지정되기 전에 오브젝트 파일에 필요한 기호를 인식하지 않습니다.
$ scl enable gcc-toolset-13 'ld -lsomelib objfile.o'
이러한 방식으로 GCC Toolset의 라이브러리를 사용하면 링크러 오류 메시지 정의되지 않은 기호 참조가 생성됩니다
. 이 문제를 방지하려면 표준 연결 방법을 따르고 오브젝트 파일을 지정하는 옵션 뒤에 라이브러리 추가 옵션을 지정합니다.
$ scl enable gcc-toolset-13 'ld objfile.o -lsomelib'
이 권장 사항은 기본 Red Hat Enterprise Linux 버전 binutils 를 사용하는 경우에도 적용됩니다.
4.6.5. GCC Toolset 13의 annobin의 세부 사항
경우에 따라 GCC Toolset 13의 annobin
과 gcc
간의 동기화 문제로 인해 다음과 유사한 오류 메시지와 함께 컴파일이 실패할 수 있습니다.
cc1: fatal error: inaccessible plugin file
opt/rh/gcc-toolset-13/root/usr/lib/gcc/architecture-linux-gnu/13/plugin/gcc-annobin.so
expanded from short plugin name gcc-annobin: No such file or directory
이 문제를 해결하려면 annobin.so
파일에서 gcc-annobin.so
파일로 플러그인 디렉토리에 심볼릭 링크를 만듭니다.
# cd /opt/rh/gcc-toolset-13/root/usr/lib/gcc/architecture-linux-gnu/13/plugin
# ln -s annobin.so gcc-annobin.so
아키텍처 를 시스템에서 사용하는 아키텍처로 교체합니다.
-
aarch64
-
i686
-
ppc64le
-
s390x
-
x86_64
4.7. GCC Toolset 컨테이너 이미지 사용
GCC Toolset 13 컨테이너 이미지 만 지원됩니다. 이전 GCC Toolset 버전의 컨테이너 이미지는 더 이상 사용되지 않습니다.
GCC Toolset 13 구성 요소는 GCC Toolset 13 툴체인 컨테이너 이미지에서 사용할 수 있습니다.
GCC Toolset 컨테이너 이미지는 rhel8
기본 이미지를 기반으로 하며 RHEL 8에서 지원하는 모든 아키텍처에서 사용할 수 있습니다.
- AMD 및 Intel 64비트 아키텍처
- 64비트 ARM 아키텍처
- IBM Power Systems, Little Endian
- 64-bit IBM Z
4.7.1. GCC Toolset 컨테이너 이미지 콘텐츠
GCC Toolset 13 컨테이너 이미지에서 제공되는 툴 버전은 GCC Toolset 13 구성 요소 버전과 일치합니다.
GCC Toolset 13 툴체인 콘텐츠
rhel8/gcc-toolset-13-toolchain
이미지는 GCC 컴파일러, GDB 디버거 및 기타 개발 관련 툴을 제공합니다. 컨테이너 이미지는 다음 구성 요소로 구성됩니다.
구성 요소 | 패키지 |
---|---|
| gcc-toolset-13-gcc |
| gcc-toolset-13-gcc-c++ |
| gcc-toolset-13-gcc-gfortran |
| gcc-toolset-13-gdb |
4.7.2. GCC Toolset 컨테이너 이미지에 액세스 및 실행
다음 섹션에서는 GCC Toolset 컨테이너 이미지에 액세스하고 실행하는 방법을 설명합니다.
사전 요구 사항
- Podman이 설치되어 있어야 합니다.
절차
고객 포털 인증 정보를 사용하여 Red Hat Container Registry 에 액세스합니다.
$ podman login registry.redhat.io Username: username Password: ********
root로 관련 명령을 실행하여 필요한 컨테이너 이미지를 가져옵니다.
# podman pull registry.redhat.io/rhel8/gcc-toolset-13-toolchain
참고RHEL 8.1 이상 버전에서는 루트가 아닌 사용자로 컨테이너를 사용하도록 시스템을 설정할 수 있습니다. 자세한 내용은 rootless 컨테이너 설정을 참조하십시오.
선택 사항: 로컬 시스템의 모든 컨테이너 이미지를 나열하는 명령을 실행하여 가져오기가 완료되었는지 확인합니다.
# podman images
컨테이너 내에서 bash 쉘을 시작하여 컨테이너를 실행합니다.
# podman run -it image_name /bin/bash
i
옵션은
대화형 세션을 만듭니다. 이 옵션이 없으면 쉘이 열리고 즉시 종료됩니다.t
옵션은 터미널 세션을 엽니다. 이 옵션이 없으면 쉘에 아무 것도 입력할 수 없습니다.
추가 리소스
- RHEL 8에서 Linux 컨테이너 빌드, 실행 및 관리
- Red Hat 블로그 문서 - 컨테이너 내부 및 외부의 루트 이해
- Red Hat Container Registry의 항목 - GCC Toolset 컨테이너 이미지
4.7.3. 예제: GCC Toolset 13 툴체인 컨테이너 이미지 사용
이 예제에서는 GCC Toolset 13 툴체인 컨테이너 이미지를 가져와서 사용하는 방법을 보여줍니다.
사전 요구 사항
- Podman이 설치되어 있어야 합니다.
절차
고객 포털 인증 정보를 사용하여 Red Hat Container Registry에 액세스합니다.
$ podman login registry.redhat.io Username: username Password: ********
컨테이너 이미지를 root로 가져옵니다.
# podman pull registry.redhat.io/rhel8/gcc-toolset-13-toolchain
대화형 쉘을 root로 사용하여 컨테이너 이미지를 시작합니다.
# podman run -it registry.redhat.io/rhel8/gcc-toolset-13-toolchain /bin/bash
필요한 경우 GCC Toolset 도구를 실행합니다. 예를 들어
gcc
컴파일러 버전을 확인하려면 다음을 실행합니다.bash-4.4$ gcc -v ... gcc version 13.1.1 20231102 (Red Hat 13.1.1-4) (GCC)
컨테이너에 제공된 모든 패키지를 나열하려면 다음을 실행합니다.
bash-4.4$ rpm -qa
4.8. 컴파일러 도구 세트
RHEL 8은 애플리케이션 스트림으로 다음과 같은 컴파일러 도구 집합을 제공합니다.
- LLVM Toolset은 LLVM 컴파일러 인프라 프레임워크, C 및 C++ 언어용 Clang 컴파일러, LLDB 디버거 및 코드 분석을 위한 관련 툴을 제공합니다.
-
rust Toolset은 Rust 프로그래밍 언어 컴파일러
rustc
rustc , loaded 빌드 도구 및 종속성 관리자, loaded-vendor
플러그인 및 필수 라이브러리를 제공합니다. -
Go Toolset은 Go 프로그래밍 언어 도구 및 라이브러리를 제공합니다. go를 다른 방법으로
golang
이라고 합니다.
사용법에 대한 자세한 내용 및 자세한 내용은 Red Hat Developer Tools 페이지에서 컴파일러 툴셋 사용자 가이드를 참조하십시오.
4.9. Annobin 프로젝트
Annobin 프로젝트는 watermark 사양 프로젝트 구현입니다. 워터마크 사양 프로젝트는 속성을 결정하기 위해 ELF(Extutable and Linkable Format) 개체에 마커를 추가하려고 합니다. Annobin 프로젝트는 annobin 플러그인과
annockó 프로그램으로 구성됩니다
.
annobin
플러그인은 GCC(GNU Compiler Collection) 명령줄, 컴파일 상태 및 컴파일 프로세스를 스캔하고 ELF 노트를 생성합니다. ELF 노트에서는 바이너리가 빌드되는 방식을 기록하고, 보안 강화 검사를 수행하기 위해 annocheck
프로그램에 대한 정보를 제공합니다.
보안 강화 검사기는 annocheck
프로그램의 일부이며 기본적으로 활성화되어 있습니다. 바이너리 파일을 검사하여 필요한 보안 강화 옵션으로 빌드되고 올바르게 컴파일되었는지 여부를 확인합니다. nocheck
는 ELF 개체 파일의 디렉터리, 아카이브 및 RPM 패키지를 반복적으로 스캔할 수 있습니다.
파일은 ELF 형식이어야 합니다. nocheck
는 다른 바이너리 파일 유형을 처리하지 않습니다.
다음 섹션에서는 다음 방법을 설명합니다.
-
annobin
플러그인 사용 -
annocheck
프로그램 사용 -
중복
annobin
노트 제거
4.9.1. annobin 플러그인 사용
다음 섹션에서는 다음 방법을 설명합니다.
-
annobin
플러그인 활성화 -
annobin
플러그인에 옵션 전달
4.9.1.1. annobin 플러그인 활성화
다음 섹션에서는 gcc
및 clang
을 통해 annobin
플러그인을 활성화하는 방법을 설명합니다.
절차
gcc
를 사용하여annobin
플러그인을 활성화하려면 다음을 사용합니다.$ gcc -fplugin=annobin
gcc
가annobin
플러그인을 찾지 못하는 경우 다음을 사용합니다.$ gcc -iplugindir=/path/to/directory/containing/annobin/
/path/to/directory/containing/annobin/ 을
annobin
이 포함된 디렉토리의 절대 경로로 바꿉니다.annobin
플러그인이 포함된 디렉터리를 찾으려면 다음을 사용합니다.$ gcc --print-file-name=plugin
clang
으로annobin
플러그인을 활성화하려면 다음을 사용합니다.$ clang -fplugin=/path/to/directory/containing/annobin/
/path/to/directory/containing/annobin/ 을
annobin
이 포함된 디렉토리의 절대 경로로 바꿉니다.
4.9.1.2. annobin 플러그인에 옵션 전달
다음 섹션에서는 gcc
및 clang
을 통해 옵션을 annobin
플러그인에 전달하는 방법을 설명합니다.
절차
gcc
를 사용하여annobin
플러그인에 옵션을 전달하려면 다음을 사용합니다.$ gcc -fplugin=annobin -fplugin-arg-annobin-option file-name
옵션을
annobin
명령줄 인수로 바꾸고 file-name 을 파일 이름으로 교체합니다.예제
실행 중인 annobin
에 대한 추가 세부 정보를 표시하려면 다음을 사용합니다.$ gcc -fplugin=annobin -fplugin-arg-annobin-verbose file-name
file-name 을 파일 이름으로 바꿉니다.
clang
이 있는annobin
플러그인에 옵션을 전달하려면 다음을 사용합니다.$ clang -fplugin=/path/to/directory/containing/annobin/ -Xclang -plugin-arg-annobin -Xclang option file-name
옵션을
annobin
명령줄 인수로 바꾸고 /path/to/directory/containing/annobin/ 를annobin
이 포함된 디렉터리의 절대 경로로 바꿉니다.예제
실행 중인 annobin
에 대한 추가 세부 정보를 표시하려면 다음을 사용합니다.$ clang -fplugin=/usr/lib64/clang/10/lib/annobin.so -Xclang -plugin-arg-annobin -Xclang verbose file-name
file-name 을 파일 이름으로 바꿉니다.
4.9.2. annocheck 프로그램 사용
다음 섹션에서는 annocheck를
사용하여 검사하는 방법을 설명합니다.
- 파일
- 디렉터리
- RPM 패키지
-
추가 툴
확인
nocheck
재귀적으로 ELF 오브젝트 파일의 디렉터리, 아카이브 및 RPM 패키지를 검사합니다. 파일은 ELF 형식이어야 합니다. nocheck
는 다른 바이너리 파일 유형을 처리하지 않습니다.
4.9.2.1. anocheck를 사용하여 파일 검사
다음 섹션에서는 annocheck
를 사용하여 ELF 파일을 검사하는 방법을 설명합니다.
절차
파일을 검사하려면 다음을 사용합니다.
$ annocheck file-name
file-name 을 파일 이름으로 바꿉니다.
파일은 ELF 형식이어야 합니다. nocheck
는 다른 바이너리 파일 유형을 처리하지 않습니다. annocheck
는 ELF 개체 파일을 포함하는 정적 라이브러리를 처리합니다.
추가 정보
-
annocheck
및 가능한 명령줄 옵션에 대한 자세한 내용은annocheck
도움말 페이지를 참조하십시오.
4.9.2.2. nocheck를 사용하여 디렉토리 검사
다음 섹션에서는 annocheck
를 사용하여 디렉터리에서 ELF 파일을 검사하는 방법을 설명합니다.
절차
디렉터리를 검사하려면 다음을 사용합니다.
$ annocheck directory-name
directory-name 을 디렉터리 이름으로 바꿉니다.
annocheck
는 디렉토리 내용, 하위 디렉터리, 디렉터리 내의 모든 아카이브 및 RPM 패키지를 자동으로 검사합니다.
annocheck
는 ELF 파일만 찾습니다. 다른 파일 유형은 무시됩니다.
추가 정보
-
annocheck
및 가능한 명령줄 옵션에 대한 자세한 내용은annocheck
도움말 페이지를 참조하십시오.
4.9.2.3. nocheck를 사용하여 RPM 패키지 검사
다음 섹션에서는 annocheck
를 사용하여 RPM 패키지에서 ELF 파일을 검사하는 방법을 설명합니다.
절차
RPM 패키지를 검사하려면 다음을 사용합니다.
$ annocheck rpm-package-name
rpm-package-name 을 RPM 패키지 이름으로 교체합니다. no
check는
RPM 패키지에 있는 모든 ELF 파일을 반복적으로 검사합니다.
annocheck
는 ELF 파일만 찾습니다. 다른 파일 유형은 무시됩니다.
제공된 디버그 정보 RPM으로 RPM 패키지를 스캔하려면 다음을 사용합니다.
$ annocheck rpm-package-name --debug-rpm debuginfo-rpm
rpm-package-name 을 RPM 패키지 이름으로 바꾸고 debuginfo-rpm 을 바이너리 RPM과 연결된 디버그 정보 RPM의 이름으로 교체합니다.
추가 정보
-
annocheck
및 가능한 명령줄 옵션에 대한 자세한 내용은annocheck
도움말 페이지를 참조하십시오.
4.9.2.4. 추가 툴 확인 사용
annocheck
에는 바이너리 파일을 검사하기 위한 여러 도구가 포함되어 있습니다. 이러한 툴은 명령줄 옵션을 사용하여 활성화할 수 있습니다.
다음 섹션에서는 다음을 활성화하는 방법을 설명합니다.
-
기본 제공
도구 -
참고
도구 -
section-size
툴
여러 도구를 동시에 활성화할 수 있습니다.
강화 검사기는 기본적으로 활성화되어 있습니다.
4.9.2.4.1. 기본 제공 도구
활성화
annocheck
built-by
툴을 사용하여 바이너리 파일을 빌드한 컴파일러의 이름을 찾을 수 있습니다.
절차
내장된 툴
을 활성화하려면 다음을 사용합니다.$ annocheck --enable-built-by
추가 정보
-
기본 제공 도구에
대한 자세한 내용은--help
명령줄 옵션을 참조하십시오.
4.9.2.4.2. 노트
도구 활성화
annocheck
플러그인에서 만든 바이너리 파일 내에 저장된 메모를 표시할 수 있습니다.
노트
도구를 사용하여 anno
bin
절차
노트
도구를 사용하려면 다음을 사용하십시오.$ annocheck --enable-notes
노트는 주소 범위별로 정렬된 시퀀스에 표시됩니다.
추가 정보
-
노트
도구에 대한 자세한 내용은--help
명령줄 옵션을 참조하십시오.
4.9.2.4.3. section-size
도구 활성화
annocheck
섹션-size
도구를 사용하면 명명된 섹션의 크기가 표시됩니다.
절차
section-size
도구를 활성화하려면 다음을 사용합니다.$ annocheck --section-size=name
name 을 named 섹션의 이름으로 바꿉니다. 출력은 특정 섹션으로 제한됩니다. 누적 결과가 마지막에 생성됩니다.
추가 정보
-
section-size
도구에 대한 자세한 내용은--help
명령줄 옵션을 참조하십시오.
4.9.2.4.4. 검사기 기본 강화
강화 검사기는 기본적으로 활성화되어 있습니다. --disable-hardened
명령줄 옵션을 사용하여 강화 검사기를 비활성화할 수 있습니다.
4.9.2.4.4.1. 강화 검사기 옵션
annocheck
프로그램은 다음 옵션을 확인합니다.
-
-z now
linker 옵션을 사용하여 지연 바인딩이 비활성화됩니다. - 프로그램에는 실행 가능한 메모리 영역에 스택이 없습니다.
- GOT 테이블에 대한 재배치는 읽기 전용으로 설정됩니다.
- 프로그램 세그먼트에는 읽기, 쓰기 및 실행 권한 비트가 모두 설정되어 있지 않습니다.
- 실행 중인 코드에 대한 재배치가 없습니다.
- 런타임 시 공유 라이브러리를 찾기 위한 runpath 정보에는 /usr에 루트인 디렉토리만 포함됩니다.
-
이 프로그램은
annobin
메모가 활성화된 상태로 컴파일되었습니다. -
이 프로그램은
-fstack-protector-strong
옵션을 활성화하여 컴파일했습니다. -
프로그램은
-D_FORTIFY_SOURCE=2
로 컴파일되었습니다. -
프로그램은
-D_GLIBCXX_ASSERTIONS
로 컴파일되었습니다. -
프로그램은
-fexceptions가 활성화된 상태로 컴파일
되었습니다. -
프로그램은
-fstack-clash-protection
이 활성화된 상태로 컴파일되었습니다. -
프로그램은
-O2
이상에서 컴파일되었습니다. - 프로그램에는 쓰기 가능한 위치에 있는 재배치가 없습니다.
- 동적 실행 파일에는 동적 세그먼트가 있습니다.
-
공유 라이브러리는
-fPIC 또는
로 컴파일되었습니다.-f
PIE -
동적 실행 파일은
-fPIE
로 컴파일되고-pie
와 연결되었습니다. -
사용 가능한 경우
-fcf-protection=full
옵션이 사용되었습니다. -
사용 가능한 경우
-mbranch-protection
옵션이 사용되었습니다. -
사용 가능한 경우
-mstackrealign
옵션이 사용되었습니다.
4.9.2.4.4.2. 강화 검사기 비활성화
다음 섹션에서는 강화 검사기를 비활성화하는 방법을 설명합니다.
절차
강화 검사기 없이 파일의 메모를 스캔하려면 다음을 사용합니다.
$ annocheck --enable-notes --disable-hardened file-name
file-name 을 파일 이름으로 바꿉니다.
4.9.3. 중복 annobin 노트 제거
annobin
을 사용하면 바이너리 크기가 증가합니다. annobin
으로 컴파일된 바이너리의 크기를 줄이기 위해 중복 annobin
노트를 제거하면 됩니다. 중복 annobin
노트를 제거하려면 binutils
패키지의 일부인 objcopy
프로그램을 사용합니다.
절차
중복된
annobin
노트를 제거하려면 다음을 사용합니다.$ objcopy --merge-notes file-name
file-name 을 파일 이름으로 바꿉니다.
4.9.4. GCC Toolset 12의 annobin 관련 세부 사항
GCC Toolset 12의 annobin
과 gcc
간의 동기화 문제로 인해 다음과 유사한 오류 메시지와 함께 컴파일이 실패할 수 있습니다.
cc1: fatal error: inaccessible plugin file
opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin/gcc-annobin.so
expanded from short plugin name gcc-annobin: No such file or directory
이 문제를 해결하려면 annobin.so
파일에서 gcc-annobin.so
파일로 플러그인 디렉토리에 심볼릭 링크를 만듭니다.
# cd /opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin
# ln -s annobin.so gcc-annobin.so
아키텍처 를 시스템에서 사용하는 아키텍처로 교체합니다.
-
aarch64
-
i686
-
ppc64le
-
s390x
-
x86_64
5장. 보충 주제
5.1. 컴파일러 및 개발 도구의 호환성 혁신적인 변경 사항
librtkaio 제거
이번 업데이트를 통해 librtkaio 라이브러리가 제거되었습니다. 이 라이브러리는 Linux 커널 비동기 I/O 지원(KAIO)을 기반으로 하는 일부 파일에 대해 고성능 실시간 비동기 I/O 액세스를 제공했습니다.
제거의 결과로 다음을 수행하십시오.
-
LD_PRELOAD
방법을 사용하는 애플리케이션에서 librtkaio 에 대한 경고를 표시하고 librt 라이브러리를 로드한 다음 올바르게 실행합니다. -
LD_LIBRARY_PATH
메서드를 사용하는 애플리케이션은 librtkaio 를 로드하고 대신 librt 라이브러리를 로드하고 경고 없이 올바르게 실행됩니다. -
대신 librtkaio에 직접 로드하기 위해
dlopen()
시스템 호출을 사용하는 애플리케이션에서 librt kaio 에 직접 로드합니다.
librtkaio 사용자는 다음과 같은 옵션이 있습니다.
- 애플리케이션을 변경하지 않고 위에서 설명한 대체 메커니즘을 사용합니다.
- 호환되는 POSIX 호환 API를 제공하는 librt 라이브러리를 사용하도록 애플리케이션 코드를 변경합니다.
- 호환되는 API를 제공하는 libaio 라이브러리를 사용하도록 애플리케이션 코드를 변경합니다.
librt 와 libaio 는 모두 특정 조건에서 유사한 기능과 성능을 제공할 수 있습니다.
libaio 패키지에는 Red Hat 호환성 수준이 2인 반면 librtk 및 제거된 librt kaio 수준 1이 있습니다.
자세한 내용은 https://fedoraproject.org/wiki/Changes/GLIBC223_librtkaio_removal를 참조하십시오.
glibc
에서 제거된 Sun RPC 및 NIS 인터페이스
glibc
라이브러리는 더 이상 새 애플리케이션을 위한 Sun RPC 및 NIS 인터페이스를 제공하지 않습니다. 이러한 인터페이스는 이제 레거시 애플리케이션을 실행하는 경우에만 사용할 수 있습니다. 개발자는 NIS 대신 Sun RPC 및 lib
라이브러리를 사용하도록 애플리케이션을 변경해야 합니다. 애플리케이션은 대체 라이브러리에서 IPv6 지원의 이점을 누릴 수 있습니다.
nsl2 대신 lib
tirpc
32비트 Xen을 위한 nosegneg
라이브러리가 제거되었습니다.
이전에는 glibc
i686 패키지에 대체 glibc
빌드가 포함되어 있어 음수 오프셋(nosegneg)으로 스레드 설명자 세그먼트 레지스터를
사용하지 않았습니다. 이 대체 빌드는 전체 반가상화 비용을 줄이기 위한 최적화로 하드웨어 가상화 지원 없이 32비트 버전의 Xen Project 하이퍼바이저에서만 사용되었습니다. 이러한 대체 빌드는 더 이상 사용되지 않으며 제거되었습니다.
새
operator !=
을 지정하면 기존 특정 makefile 구문에 대해 다른 해석이 발생합니다.
!=
쉘 할당 연산자가
BSD makefile과의 호환성을 높이기 위한 기능. 결과적으로 이름이 느낌표로 끝나고 $(shell …)
variable!=value
와 같은 할당이 바로 뒤에 오는 변수가 쉘 할당으로 해석됩니다. 이전 동작을 복원하려면 variable! =value
와 같이 느낌표 뒤에 공백을 추가하십시오.
연산자와 함수 간의 자세한 내용과 차이점은 GNU make
설명서를 참조하십시오.
MPI 디버깅 지원을 위한 Valgrind 라이브러리
valgrind-open
래퍼 라이브러리가 제거되었습니다. 이 라이브러리는 MPI(Message Passing Interface)를 사용하여 디버그 프로그램에 Valgrind 를 활성화했습니다. 이 라이브러리는 이전 버전의 Red Hat Enterprise Linux의 Open MPI 구현 버전에만 해당됩니다.
mpi 패키지에서 제공한 Valgrind 용 libmpi
wrap.so
libmpiwrap.so
사용자는 MPI 구현 및 버전과 관련된 업스트림 소스에서 자체 버전을 빌드하는 것이 좋습니다. LD_PRELOAD
기술을 사용하여 이러한 맞춤형 라이브러리를 Valgrind 에 제공합니다.
valgrind-devel
에서 제거된 개발 헤더 및 정적 라이브러리
이전에는 사용자 정의 valgrind 툴을 개발하기 위한 개발 파일을 포함하는 데 사용되는 valgrind-devel
하위 패키지였습니다. 이번 업데이트에서는 보장된 API가 없고 정적으로 연결해야 하며 지원되지 않으므로 이러한 파일이 제거됩니다. valgrind-devel
패키지에는 여전히 안정적이고 잘 지원되는 memcheck.h, call grind.h,
-aware 프로그램 및 헤더 파일용 개발 파일이 포함되어 있습니다.
callgrind.h,
grindhelgrind
, .h
memcheck.h
와 같은 val
5.2. RHEL 8에서 RHEL 6 또는 7 애플리케이션을 실행하는 옵션
Red Hat Enterprise Linux 8에서 Red Hat Enterprise Linux 6 또는 7 애플리케이션을 실행하려면 다양한 옵션을 사용할 수 있습니다. 시스템 관리자에게는 애플리케이션 개발자의 자세한 지침이 필요합니다. 다음 목록에는 Red Hat에서 제공하는 옵션, 고려 사항 및 리소스가 요약되어 있습니다.
- 일치하는 RHEL 버전 게스트 OS를 사용하여 가상 머신에서 애플리케이션 실행
- 이 옵션에는 리소스 비용이 많이 있지만 환경은 애플리케이션 요구 사항과 거의 일치하며, 이 방법에는 추가 고려 사항이 많이 필요하지 않습니다. 현재 권장되는 옵션입니다.
- 해당 RHEL 버전을 기반으로 컨테이너에서 애플리케이션 실행
- 리소스 비용은 이전 경우보다 낮지만 구성 요구 사항은 더 엄격합니다. 컨테이너 호스트와 게스트 사용자 공간 간의 관계에 대한 자세한 내용은 Red Hat Enterprise Linux Container Compatibility Matrix 를 참조하십시오.
- 기본적으로 RHEL 8에서 애플리케이션 실행
이 옵션은 리소스 비용이 가장 낮지만 가장 엄격한 요구 사항을 제공합니다. 애플리케이션 개발자는 RHEL 8 시스템의 올바른 구성을 결정해야 합니다. 다음 리소스는 이 작업의 개발자에게 도움이 될 수 있습니다.
이 목록은 애플리케이션 호환성을 결정하는 데 필요한 전체 리소스 세트가 아닙니다. 이는 호환되지 않는 알려진 변경 사항 및 호환성과 관련된 Red Hat 정책 목록이 있는 시작 지점입니다.
또한 What is Kernel Application Binary Interface (kABI)? 지식 센터 지원 문서에는 커널 및 호환성과 관련된 정보가 포함되어 있습니다.