본 포스팅은 https://interrupt.memfault.com/blog/arm-cortexm-with-llvm-clang를 참고하였습니다.
많은 부분을 읽기 편하도록 의역하였으며, 완벽한 번역은 아닙니다. 원문 참조 부탁드립니다.
Apple products, FreeBSD, WebAssembly, Rust 등을 활용하여 개발은 했다면, 광범위하게 사용되는 LLVM을 사용하였을 것입니다. 그러나 임베디드 세상에서는 LLVM 위에서 빌드된 C 컴파일러인 Clang은 많은 관심을 받지 못하고 있습니다.
해당 포스팅에서는 Clang build target을 좀 더 편리하게 만들 수 있도록 만드는 것이며, 툴 체인에 탑재되어 제공되는 풍부한 기능 중 일부를 활용하고 예제를 통해 컴파일 시 memory leaks 또는 mutex deadlocks을 식별하는 방법을 다룰 것입니다.
Background of GCC and Clang
오픈소스 컴파일러와 툴체인의 출현은 1987년으로 거슬러 올라갑니다. 원래 GCC는 C로 작성된 GNU 오픈소스를 컴파일하기 위한 것이었습니다. 하지만, 툴체인은 다양한 언어와 언어를 지원하기 위해 성장하였고, 그 결과 코드의 기능을 확장하기에 많은 부분이 복잡해졌습니다.
LLVM 프로젝트는 컴파일러 분야의 새로운 오프소스 입니다. 이 프로젝트는 University of Illinois at Urbanan-Champaign에서 2000년에 시작되었습니다. 이 프로젝트의 초기 목표는 Standalone libraries를 설계하여 모듈식 컴파일러 툴체인을 만드는 것이었습니다. LLVM 프로젝트의 진정한 시작은 2005년 애플에서 초기 개발자 Chris Lattner를 고용하면서 시작되었고, LLVM을 자신들의 developer ecosystem에 사용되게 만들기 위해 많은 투자를 하였습니다. 이를 통해, GNU GCC 컴파일러의 경쟁자인 LLVM을 위한 프론트엔드인 Clang, C, C++, Objective-C가 나오게 되었습니다.
오늘날, LLVM 툴체인은 소프트웨어 분야 어디에서나 볼 수 있게 되었고, 최근에는 임베디드 분야에서도 채택되고 있습니다. GNU 툴체인에 비해 유리한 라이센스(Apache 2 vs GPL 3)와 모듈라 구조로 만들어진 덕분에 LLVM은 임베디드 컴파일러 시장에서 기본 선택으로 되었습니다. ARM과 SEGGER과 LLVM/Clang 기반의 컴파일러를 기반으로 하고 있습니다.
Benefits of Adding a Clang Build
많은 임베디드 프로젝트는 GCC 또는 IAR 또는 ARM Compiler를 사용합니다. 우리는 LLVM/Clang의 이점을 활용하기 위해 현재 사용하는 컴파일러의 사용을 멈출 필요는 없습니다.
- 정적분석
- 단일 컴파일러의 의존성을 줄여 향후 다른 컴파일러로 이주 시, 쉽게 전환이 가능하도록함
- 두번의 Error flags 설정. 두 컴파일러에서 -Werror를 사용하여, 타겟에서 디버깅 전에 이슈를 최대한 검출
- Clang으로 컴파일함으로, 호스트 플랫폼에서 테스트 가능
Installing LLVM/Clang
LLVM/Clang 툴체인을 가장 손쉽게 얻는 방법은, 공식 홈페이지에서 다운로드 받는 것입니다.
원글은 Ubuntu 18.04를 타겟으로 하였으나, 제 개발 환경은 WSL Ubuntu 16.04 이므로 약간의 명령어 수정을 하였습니다.
LLVM 9.0.1 다운로드 및 PATH 설정
$ wget https://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
$ tar -xf clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
$ export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04/bin:$PATH
설치 확인
$ clang --version
clang version 9.0.0
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: ~/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04/bin
Static Analysis With Clang and scan-build
GCC에서 Clang으로 Migration을 알아보기 전, LLVM/Clang의 놀라운 정적분석과 체크 기능에 대해 살펴보겠습니다.
scan-build는 LLVM 툴체인의 포함된 정적분석기로서, gcc 또는 clang의 호출을 가로채 정적 분석 패스를 생성합니다.
scan-build는 CMake와 Make를 Overiding하여 사용함으로서, 호출하는 것은 다음과 같이 간단합니다.
$ scan-build make
$ scan-build cmake ..
scan-build는 많은 수의 Checkers를 가지고 있고 기본적으로 활성화되어 있습니다.
scan-build --help를 통해 활성화되어 있는 Checker를 확인 가능합니다.
$ scan-build --help
CONTROLLING CHECKERS:
A default group of checkers are always run unless explicitly disabled.
Checkers may be enabled/disabled using the following options:
-enable-checker [checker name]
-disable-checker [checker name]
[...]
AVAILABLE CHECKERS:
+ core.CallAndMessage Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)
+ core.DivideZero Check for division by zero
+ core.DynamicTypePropagation Generate dynamic type information
+ core.NonNullParamChecker Check for null pointers passed as arguments to a function whose arguments are references or marked with the 'nonnull' attribute
+ core.NullDereference Check for dereferences of null pointers
+ core.StackAddressEscape Check that addresses to stack memory do not escape the function
+ core.UndefinedBinaryOperatorResult Check for undefined results of binary operators
[...]
NOTE: "+" indicates that an analysis is enabled by default.
기본 설정은 static-build를 사용하기에 좋은 시작점이고, 손쉽게 Checker를 변경이 가능합니다.
아래 예제를 통해 Clang 또는 GCC 컴파일 과정 중 발견하지 못하는 잠재적 이슈를 발견하는 흥미로운 과정을 볼 수 있습니다.
<예제>
$ git clone https://github.com/memfault/interrupt.git
$ cd interrupt/example/freertos-example-llvm
$ make
위의 명령을 실행하면, 다음과 같은 오류를 만나게 됩니다.
MakeFile 내에서, FreeRTOS를 클론해오는 과정에서 발생하는 문제인데 권한이 없어 발생하는 문제로 보여 아래와 같이 수정을 합니다. (MakeFile 내, 159 번째 라인
$(FREERTOS_PORT_ROOT):
git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git $(FREERTOS_ROOT_DIR)
Running scan-build
scan-build를 구동하기 위해, 원문에서 언급된 것 처럼 scan-build make를 실행하게 되면 다음과 같은 오류를 만나게 됩니다.
이러한 오류를 회피하기 위해, Compiler러 정보를 명시적으로 작성해줍니다.
# clang
$ scan-build --use-cc=clang make
# armgcc
scan-build --use-cc=arm-none-eabi-gcc make
아래와 같이 정상적으로 종료되면, 다음 명령을 통해서 웹으로 확인이 가능합니다.
$ scan-view /tmp/scan-build-2020-08-04-142543-674-1
로컬에서는 http://127.0.0.1:8181를 확인하면 됩니다. (내용만 확인하고 싶다면, https://interrupt.memfault.com/blog/misc/llvm_scan_build_report/)
'ETC' 카테고리의 다른 글
S19 Format 분석 (0) | 2020.08.09 |
---|---|
[번역] Better Firmware with LLVM/Clang (2/2) (0) | 2020.08.04 |