목록2025/06/03 (37)
지노랩 /JinoLab
nm(GNU binutils 패키지)는 실행 파일(ELF), 오브젝트(.o), 라이브러리(.a) 안에포함된 심볼-‐함수·변수·섹션·링커 심볼-‐을 목록화해주소·크기·속성(정의/미정의, 글로벌/로컬 등)을 보여주는 전통적인 유틸리티입니다.임베디드 펌웨어에서는링크 오류(undefined reference) 원인 추적용량 분석(어떤 함수가 몇 바이트?)링커 최적화 확인(제거 기대 함수가 남아 있나?)섹션/메모리 경계 검증등에 매우 유용합니다.1. 기본 호출arm-none-eabi-nm firmware.elf # ELF 전체 심볼arm-none-eabi-nm build/main.o # 개별 오브젝트 심볼기본 출력 형식(오프셋·타입·이름) 예:08000000 T Reset_Handler08000..
1. 왜 필요할까?궁금증 size로 바로 확인플래시가 초과되는데 어느 섹션이 큰가?.text(코드)·.rodata·.data·.bss 바이트 수 출력특정 모듈(.o) 이 얼마나 차지하나?오브젝트 파일을 직접 지정해 개별 크기 확인옵티마이저/링커 옵션 적용 효과는?빌드 전후 size 결과 diff 로 변동 추적2. 기본 사용법arm-none-eabi-size firmware.elf text data bss dec hex filename 63236 48 1360 64644 fbbc firmware.elftext : 코드 + 상수(FLASH)data : 초기화 전역/정적 변수 크기(FLASH에 저장→부팅 시 RAM 복사)bss : 0으로 초기화할 RAM ..
1. objcopy가 하는 일범주 활용 예 대표 옵션포맷 변환ELF → BIN, HEX(S-rec, Intel HEX), ACM 등-O binary, -O ihex, -O srec섹션 조작- 섹션 제거/추가/이동- 실행 속성(rwx) 변경--remove-section, --add-section, --rename-section, --set-section-flags, --change-section-vma심볼 조작- 심볼명 변경·삭제·추가- 심볼 값(주소) 재설정--rename-symbol, --strip-symbol, --add-symbol, --redefine-sym, --set-symbol-value전체 심볼 스트립릴리스 ELF 용량 최소화, 소스 유출 방지--strip-all, --strip-debug..
objdump는 컴파일·링크가 끝난 ELF(또는 오브젝트, 라이브러리) 파일에서어셈블리 코드(디스어셈블)심볼 테이블디버그 정보섹션·헤더 등의 메타데이터를 텍스트 형태로 꺼내 주는 만능 해부 도구입니다.임베디드 펌웨어 개발에서 “빌드 후(Post-build) 분석” 단계에 가장 많이 쓰입니다.1. 자주 쓰는 핵심 옵션옵션 의미 사용 예시-d실행 가능한 섹션(코드 영역)만 디스어셈블objdump -d firmware.elf > firmware.lst-D모든 섹션을 디스어셈블디버그·RODATA도 보고 싶을 때-S-d 또는 -D와..
─ -Wl,-Map= 옵션 1. 맵 파일이란?링커가 최종 ELF를 생성하면서 기록한 “주소 배치 보고서”다음 정보를 텍스트로 제공합니다.메모리 공간별 사용량 (FLASH, RAM 등)각 오브젝트(.o) 또는 라이브러리(.a)의 섹션 크기함수·변수·심볼별 절대 주소링크 순서, 섹션 정렬, 누가 어느 섹션을 차지했는지 상세 로그2. 언제 도움이 되나?문제 상황 / 요구 맵 파일로 해결 방법플래시·RAM 초과 오류섹션별·모듈별 크기를 확인해 “용량 범인”을 즉시 파악실행 중 HardFault at 0x0800412A해당 주소가 맵에서 어떤 함수/변수인지 역추적섹션이 의도한 메모리에 안 들어감.data/.bss 배치가 제대로 이루어졌는지 검증링크 최적화(--gc-sections) 누락 확인제거되길 기대한 함수가..
1. “스타트업 파일( startup file )”이란?GCC 링커는 기본적으로 C 런타임 초기화 코드(CRT, crt0.o, crti.o, crtbegin.o …)를 자동 포함합니다.이 코드들은 호스트 PC나 리눅스 같은 환경을 가정해__libc_init_array() 호출전역 C++ 생성자 실행main() 진입exit() 처리등을 수행합니다.MCU에서는 부팅 직후 바로 플래시에서 실행되므로, 해당 초기화 흐름이 맞지 않거나 아예 동작하지 않습니다.대신 사용자 정의 스타트업 코드(벡터 테이블·Reset_Handler, .data 복사 및 .bss 초기화 등)가 필요합니다.2. -nostartfiles 옵션의 동작옵션 없음(기본) -nostartfiles 사용링크 단계에서 GCC 기본 CRT 오브젝트 자..
1. -T 옵션이 없다면?링커(LD) 는 GCC 패키지에 포함된 기본/범용 스크립트를 적용합니다.MCU 플래시·RAM 레이아웃과 맞지 않아_estack, _sdata, _sbss 등 필수 심볼 미정의부트 코드가 요구하는 _stack_top 주소를 찾지 못함→ “undefined reference” 링크 오류 발생.2. 링커 스크립트가 하는 일역할 설명메모리 영역 선언MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K ; RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K ;}섹션 배치 - .isr_vector(인터럽트 벡터) - .text(코드) → FLASH - .data(초기화 전역) - .bss(미초기화..
(-s 옵션과 혼동 주의!)1. 개념 : 전처리 → 컴파일 → 어셈블 → 링크단계 산출물 GCC 플래그전처리.i (또는 .E)-E컴파일*.s (어셈블리)-S어셈블.o-c링크.elf(링커 스크립트 등)⚠️ -S(대문자) : 컴파일까지만 수행하고 어셈블은 하지 않음⚠️ -s(소문자) : 링크 후 심볼을 Strip(디버그 정보 제거) → 전혀 다른 옵션2. Makefile 규칙 예시# ① .c → .i (전처리)%.i : %.c $(CC) $(CFLAGS) -E $-S 단계에서 어셈블리 코드가 생성되므로, 내부 최적화 결과·레지스터 배치 등을 분석할 수 있다..SECONDARY 지시어를 추가해 Make가 .i/.s를 자동 삭제하지 않도록 한다..SECONDARY:3. 실행 결과 확인make clean && ..
― Makefile 전체 흐름을 바꿔 “모든 중간 파일”을 보존하기1. 왜 전처리(Pre-processing) 산출물을 보고 싶을까?필요 상황 전처리 파일이 있으면 좋은 점복잡한 매크로/조건부 컴파일 디버그매크로가 실제로 어떤 값으로 치환됐는지, #ifdef 분기가 어떻게 펼쳐졌는지 한눈에 확인컴파일 오류 원인 추적“헤더 순환 포함”, “매크로 재정의” 같은 문제를 빠르게 찾을 수 있음자동 코드 생성/후처리전처리 산출물에 스크립트를 돌려 코드 조각을 삽입하거나 분석 → 그다음 단계(컴파일)로 전달2. GCC 옵션 정리옵션 기능-E전처리만 수행 → 확장자는 보통 .i(C)·.ii(C++) 혹은 지정한 이름-c전처리+컴파일+어셈블까지 수행, 링크는 하지 않음(없음)소스 하나 컴파일 후 곧바로 링커 호출 → ..
1. 왜 헤더 경로를 알려줘야 할까?전처리기(pre-processor) 는 소스 파일을 읽다가 같은 지시문을 만나면 헤더 파일을 찾기 시작합니다.#include "foo.h" #include 기본 탐색 순서는현재 소스 파일의 디렉터리컴파일러 내장(include) 경로-I 옵션으로 지정한 디렉터리 목록 입니다.프로젝트가 Inc/, Drivers/Inc/, Common/Inc/… 등 다단계 폴더를 갖고 있으면,전처리기는 경로를 모른 채 헤더를 찾다 “No such file or directory” 오류를 냅니다.2. 실험 시나리오단계 작업 결과① 새 헤더 선언main.c에#include "additional.h" 추가컴파일 → 오류 : 헤더를 못 찾음② 헤더 파일 생성External/Inc/additiona..
구분 -c 옵션을 사용하지 않을 때 -c 옵션을 사용할 때컴파일러 동작각 소스 파일을 개별적으로 컴파일 → 바로 링커 호출즉, main.c → main.o → main.elf → 다음 파일 반복프로젝트의 모든 소스를 .o로만 생성링크는 나중에 한 번에 수행필요한 입력링커 스크립트·스타트업 파일을 매 파일마다 요구함마지막 단계에서 한꺼번에 제공문제점‣ 디폴트 스타트업/링커스크립트가 사용돼 심볼 미해결 오류 발생‣ 빌드 시간 & 로그 복잡‣ 원하는 스타트업・링커스크립트로 정확히 한 번만 링크‣ Makefile 규칙( all_objs ⇒ firmware.elf) 이 깔끔하게 동작Makefile 패턴ma..
1. 최적화 레벨과 디버깅 싱크 문제레벨 특징 디버깅 시 주의-O0 (또는 -Og)- 전처리 이후 거의 최적화 없음- C 소스 한 줄 ↔ 어셈블리 대응이 1:1에 가깝다디버그용으로 가장 안전-O1 ~ -O3코드 크기·속도 최적화 점진 강화루프 전개·인라인·명령 재배치로 소스 라인과 실행 지점이 엇갈림-Os / -Oz크기 절감에 초점, 속도 일부 희생디버깅 어려움은 -O2와 유사-OfastIEEE/표준 준수 일부 무시, FPU·DSP 적극 활용임베디드에서는 예기치 않은 동작 가능—배포 전 검증 필수-Og(g 소문자)는 GCC·Clang에서 “디버그 친화 최적화”.실제로는 O0+약간의 인라인/레지스터 할당만 켜져 있어 디버깅 편의와 빌드 속도를 모두 확보합니다.2. -g 옵션ELF에 DWARF 심볼 삽입 →..
역할 컴파일 시 ELF 내부에 DWARF 디버그 심볼(소스 파일·행 번호, 지역·전역 변수 정보, 인라인 함수 매핑 등)을 삽입합니다.효과 GDB·VS Code Cortex-Debug·Ozone 같은 도구가 소스 단위 브레이크포인트, 변수 값 조회, 스택 트레이스를 지원할 수 있게 됩니다.실행 코드 영향 명령어(opcode)·섹션 배치는 그대로이므로, 실제 MCU에 플래시되는 BIN/HEX 크기·실행 속도는 변하지 않습니다.ELF 용량 증가 디버그 심볼이 들어가면서 ELF 자체는 수 KB ~ 수 MB까지 커질 수 있습니다.실험 과정 요약단계 설정 관찰 포인트① 디버그 빌드-O0 -g(추가 -ggdb·-gdwarf-3 삭제)• ELF ≈ 137 kB• BIN 크기 ①② 디버그 빌드(-g 제거)-O0• EL..
단계 -O0(기본) -O2(추천) 차이 & 이유컴파일 옵션-O0 -g-O2 -g-O2는 불필요한 코드 제거·루프 단순화·레지스터 활용 등 50여 개 내부 패스를 켜서 코드 크기를 줄이고 실행 속도를 높임빌드 후 파일program.elfprogram.lst(objdump)동일ELF 크기는 메타데이터(DWARF, 심볼) 때문에 직접 비교 불가BIN 변환objcopy -O binary program.elf program.bin″BIN(순수 opcode) 로 변환해야 실실행 크기 비교 가능바이트수 확인hexdump · size program.elf″예시: -O0 BIN 마지막 오프셋 0x0270(→ 0x271 바이트)-O2 BIN 마지막 오프셋 0x0100(→ 0x101 바이트) → 약 60 % 감소디스어셈블o..
(Cortex-M 임베디드 프로젝트를 직접 빌드할 때 최소로 알아야 할 스위치만 추려 설명합니다)목적 꼭 알아둘 옵션 효과 & 예시입·출력 지정소스.c (옵션 없이 바로)GCC는 인자로 전달된 파일을 입력 소스로 인식합니다. -c컴파일·어셈블까지만 실행, 절대 링크 X → main.o 생성gcc -c main.c -o build/main.o -o 결과 파일 이름 지정단계별 작업만 실행-S전처리+컴파일 → 어셈블리(.s) 출력 (객체 X) -E전처리만 실행 → .i 출력/표준 출력아키텍처 / 코어-mcpu=Cortex-M4, M7 … 정확히 지정해야 올바른 명령어 생성-mcpu=cortex-m4 -march= (거의 필요 X, 예외용)-march=armv7e-m 등. -mcpu가 포함 관계라면 생략 가능T..
전제GCC 소스코드는 크로스-컴파일 옵션에 따라 RISC-V, x86, MIPS, ARM Cortex-M 등 어떤 아키텍처용 툴체인으로도 빌드할 수 있습니다.여러분 PC에 설치한 Arm GNU Toolchain은 Cortex-M 타깃으로 컴파일된 GCC 버전이며, 실행 파일 이름 앞에 반드시 arm-none-eabi-가 붙습니다.1. 핵심 실행 파일들 (…\bin 폴더 내부)범주 실행 파일 주요 역할 특징 / 사용 시점컴파일러arm-none-eabi-gcc.c(C) 소스 → 전처리·컴파일·어셈블 → .o.s 파일도 입력 가능 → 전처리 매크로(#ifdef) 지원C++ 컴파일러arm-none-eabi-g++C++ 프로젝트일 때 사용 어셈블러arm-none-eabi-as순수 .s 파일 → .o전처리 불가 ⇒..
1. 폴더·파일 구성경로 역할Makefile + *.mk• GCC·어셈블러·링커 지정• 소스·헤더·링커스크립트 목록화• 규칙: *.c → *.o / *.o → firmware.elfsrc/main.c애플리케이션 main() 함수include/전역 헤더 모음drivers/주변장치 드라이버 C/Hboot/ • vector_table.c • startup.cCortex-M 필수 부팅 코드• 인터럽트 벡터 테이블 배열• Reset_Handler(): 데이터 초기화→main() 호출linker/STM32F4.ld메모리 맵(FLASH, RAM)·섹션 배치 정의2. 툴체인 선택과 장단점단계 기본 설정 특징전처리 / 컴파일 / 어셈블arm-none-eabi-gcc하나의 명령으로 3단계 처리(선택) 독립 ASM 빌드ar..
1. 왜 환경변수(PATH)가 필요할까?cmd 또는 PowerShell을 열었을 때 어디에서나make, arm-none-eabi-gcc 같은 실행 파일을 인식해야 빌드 스크립트가 오류 없이 동작합니다.이를 위해 툴이 들어있는 bin 폴더 경로를 시스템 (PATH)이나 사용자용 PATH에 추가합니다.2. 환경변수 편집 단계Windows 검색창 → “환경 변수” 입력 →〈환경 변수 편집(사용자용)〉 또는〈시스템 환경 변수 편집〉 클릭(개인 PC라면 사용자용·시스템용 아무 쪽이나 상관없지만, 관리자 권한이 없으면 사용자용을 선택하세요.)[환경 변수(N)…] 버튼 클릭 →[사용자 변수] 영역에서 Path 선택 → [편집(E)…].[새로 만들기] 클릭 후 다음 경로들을 하나씩 입력합니다.GNU Make 설치 위치..
아래 표는 arm-none-eabi GCC 툴체인(STM32·NRF·Cortex-M 계열에서 가장 널리 쓰이는 크로스 컴파일러)에 포함된 나머지 주요 헬퍼 툴을 한눈에 정리한 것입니다.이미 익숙한 objdump / objcopy / size 외에도, 현업에서는 nm·strip·readelf 같은 도구를 수시로 호출해 디버그·배포·용량 관리 작업을 수행합니다.툴 이름 (접두어 생략*) 핵심 기능 자주 쓰는 옵션·예시 실전 활용 포인트nmELF/객체 파일에 들어 있는 심볼(함수·변수) 이름·주소·크기 열람-n 주소순, -S 크기 표시, --size-sort 크기순 정렬`nm -S --size-sort firmware.elftail`stripELF/라이브러리에서 디버그·심볼·주석 섹션 제거 → 파일 최소화--..
1. size가 하는 일기능 설명섹션별 바이트 수 계산ELF 또는 객체(.o) 파일을 읽어 .text, .data, .bss 등 표준 섹션의 크기를 10진수·16진수로 출력합니다.메모리 초과 여부 즉시 확인플래시(코드+초기 데이터)·RAM(BSS+초기 데이터) 사용량을 빌드 직후 바로 확인할 수 있습니다.용량 추적커밋 간 차이를 비교해 어느 빌드에서 플래시가 증가했는지 빠르게 파악할 수 있습니다.2. 기본 호출 형식arm-none-eabi-size 대표 출력 예$ arm-none-eabi-size firmware.elf text data bss dec hex filename 32768 512 2048 35328 8a60 firmware.elf열 의미..