임베디드 면접 용어 사전
펌웨어 빌드VMA · LMA

VMA / LMA

실행 시 주소(VMA)와 적재 시 주소(LMA). .data처럼 둘이 다른 섹션이 startup 복사의 이유다.

섹션이 실행 시 있어야 할 주소(VMA)파일에 저장된 주소(LMA).

VMA (Virtual Memory Address) — 실행 중에 이 주소에 있다고 가정하고 코드가 생성된다

  • LMA (Load Memory Address) — — 펌웨어 이미지에서 이 주소에 기록된다

대부분은 같다

  • .text — : VMA = LMA = 0x08000000 (플래시에서 그대로 실행)
  • .rodata: VMA = LMA = 플래시
  • .bss — : 초기 데이터가 없으므로 LMA가 무의미

다른 경우 — .data

.data
  LMA = 0x08010000 (플래시)  ← 초기값이 저장된 곳
  VMA = 0x20000000 (RAM)     ← 실행 중에 있어야 할 곳

startup 코드가 LMA에서 VMA로 복사한다

"어디에 저장하고 어디서 실행하는가"가 다를 때 이 개념이 필요하다.

링커 스크립트 표기

.data : {
    _sdata = .;          /* VMA 시작 */
    *(.data*)
    _edata = .;
} > RAM AT> FLASH
  ↑        ↑
 VMA      LMA

> RAM이 VMA, AT> FLASH가 LMA를 지정한다.

  • _sidata = LOADADDR(.data); — /* LMA 값을 심볼로 */

LOADADDR()로 LMA를 얻어 startup 코드에 전달한다.

왜 이 구분이 필요한가

① .data 복사 (가장 흔함)

초기값은 비휘발성 저장소에 있어야 하고, 실행 중에는 쓰기 가능한 곳에 있어야 한다.

② RAM에서 실행하는 함수

.RamFunc
  LMA = 플래시  (펌웨어에 포함)
  VMA = RAM     (여기서 실행)

플래시 쓰기 루틴처럼 자기가 있는 플래시를 지우면 안 되는 코드에 필요하다.

③ 부트로더 + 애플리케이션

앱을 다른 주소에 링크하고, 부트로더가 그 위치로 복사하거나 점프한다.

④ 압축 이미지

LMA = 압축된 데이터가 저장된 위치 VMA = 압축 해제 후 실행할 위치 startup 코드가 압축을 풀며 복사 플래시 공간이 부족할 때 쓴다.

확인 방법

arm-none-eabi-objdump -h firmware.elf

Sections:
Idx Name      Size      VMA       LMA       File off
  1 .text     0000b0d0  08000000  08000000  00010000
  2 .data     0000019c  20000000  0800b0d0  00020000
                        ↑         ↑
                       VMA       LMA  ← 다르다!
  3 .bss      00002000  2000019c  2000019c  0002019c

.data만 VMA와 LMA가 다른 것이 정상적인 모습이다.

잘못됐을 때의 증상

LMA를 지정하지 않으면 (> RAM 만 쓰고 AT> FLASH 를 빠뜨림)
→ 링커가 .data 를 RAM 주소에 "저장"하려 한다
→ 바이너리 파일이 이상하게 커지거나
→ 초기값이 펌웨어에 포함되지 않아 전역 변수가 쓰레기 값

"전역 변수 초기값이 이상하다" 면 링커 스크립트와 startup 복사 루프를 함께 확인해야 한다.

bin 파일과 hex 파일

arm-none-eabi-objcopy -O binary firmware.elf firmware.bin
arm-none-eabi-objcopy -O ihex   firmware.elf firmware.hex

.bin은 주소 정보가 없는 순수 바이트열이다. LMA 순서대로 배치되며, 중간에 빈 공간이 있으면 0xFF로 채워진다. 어느 주소에 써야 하는지는 사람이 알아야 한다.

.hex는 주소 정보를 포함한다. 그래서 여러 영역에 흩어진 데이터도 하나의 파일로 다룰 수 있고, 프로그래머가 알아서 올바른 위치에 쓴다.

부트로더가 있는 시스템에서 .bin을 잘못된 주소에 쓰는 실수가 흔하므로 .hex를 쓰는 편이 안전하다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 펌웨어 빌드·부팅 — 빌드 과정·메모리 섹션(.data/.bss)·링커·startup·OTA