# vdso32-wrap.S — 말로 풀어 읽기
Linux v6.18.37 · arch/arm64/kernel/vdso32-wrap.S

사용자 프로그램이 일부 커널 제공 기능을 매번 예외 진입 없이 호출할 수 있도록 vDSO라는 작은 ELF 이미지를 사용합니다. 이 파일은 그 기능을 구현하는 본체가 아니라, 별도로 빌드된 vDSO 파일을 커널 이미지에 넣는 포장 부분입니다.

## 처음 읽을 때
파일을 포함하는 .incbin과 함수를 호출하는 BL은 전혀 다른 단계에서 동작합니다. 이 파일에서는 CPU 실행 순서보다 최종 이미지에 어떤 바이트가 들어가는지 봅니다.

## 더 깊이 살펴볼 때
페이지 정렬, 시작·끝 심볼, 포함된 ELF의 사용자 매핑 과정을 연결해 보세요. wrapper만으로 개별 vDSO 함수 구현까지 설명되지는 않습니다.

![단계별 개념 그림](../media/vdso32-wrap-overview.png)
화살표는 빌드 시 바이트 포함 또는 사용자 매핑 관계입니다. 세 단계가 이 .S 파일의 CPU 실행 순서는 아닙니다.

## 섹션·정렬·범위 심볼
원본 1–19행

### 6행
```asm
#include <linux/init.h>
```
부팅 때만 사용할 코드·데이터의 섹션 표기를 가져옵니다. 초기화가 끝난 뒤 해제 가능한 영역과 계속 남겨야 하는 영역을 링커가 구분하게 합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

### 7행
```asm
#include <linux/linkage.h>
```
SYM_FUNC_START·SYM_CODE_START·SYM_INNER_LABEL 등의 심볼 선언 규칙을 가져옵니다. 함수인지 코드 내부 라벨인지, 다른 오브젝트에 보일 이름인지와 정렬·크기 정보를 빌드 도구에 전달하는 데 필요합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

### 8행
```asm
#include <linux/const.h>
```
C와 어셈블리 양쪽에서 쓸 정수 상수 표현을 가져옵니다. C용 형 접미사가 어셈블리 식에 그대로 들어가지 않게 하여 PAGE_SIZE 같은 공통 상수를 사용할 수 있게 합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

### 9행
```asm
#include <asm/page.h>
```
빌드가 선택한 페이지 크기와 정렬 단위를 가져옵니다. 4KiB를 항상 가정하지 않고 선택된 PAGE_SIZE로 표와 이미지 경계를 맞추는 데 사용합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

### 11행
```asm
	.globl vdso32_start, vdso32_end
```
AArch32 호환 vDSO 원본의 시작·끝 기호를 다른 오브젝트에서 참조하도록 공개합니다. vdso.c가 이 기호로 원본 ELF를 찾고 페이지 수를 계산합니다.

### 12행
```asm
	.section .rodata
```
AArch32 호환 vDSO 원본 바이트를 커널 읽기 전용 데이터 영역에 넣습니다. 사용자에게 실행 가능하게 연결하는 권한과 주소는 vdso.c의 별도 매핑 경로에서 정합니다. 이는 빌드 중 출력할 바이트의 섹션을 선택하는 지시문이며, 실행 중 PC나 SP를 옮기지 않습니다.

### 13행
```asm
	.balign PAGE_SIZE
```
호환 vDSO 이미지의 경계를 커널 PAGE_SIZE에 맞춥니다. AArch32 프로그램용 코드라도 커널이 관리하는 페이지 단위로 매핑하므로 이 정렬이 필요합니다. .balign의 인자는 바이트 단위의 정렬 크기이며, 어셈블 단계에서 필요한 패딩을 넣습니다.

### 14행
```asm
vdso32_start:
```
AArch32 호환 vDSO ELF 원본 바이트의 시작 주소입니다. 사용자 프로세스에 vDSO 페이지를 매핑할 코드가 이 시작과 끝 기호로 원본 범위를 구합니다. 레이블은 이 위치에 붙인 이름이며, 이름을 적는 것만으로 CPU 명령이 추가되지는 않습니다.

### 15행
```asm
	.incbin "arch/arm64/kernel/vdso32/vdso.so"
```
별도로 빌드한 AArch32 호환 프로그램용 vDSO ELF의 바이트를 커널 읽기 전용 영역에 포함합니다. vDSO는 시각 조회 같은 일부 서비스를 매번 시스템 호출로 진입하지 않고 사용자 공간에서 수행하게 하는 작은 공유 라이브러리입니다. 이 줄은 실행이나 사용자 매핑 자체가 아니라, 뒤의 매핑 코드가 사용할 원본 이미지를 담는 단계입니다.

### 16행
```asm
	.balign PAGE_SIZE
```
호환 vDSO 이미지의 경계를 커널 PAGE_SIZE에 맞춥니다. AArch32 프로그램용 코드라도 커널이 관리하는 페이지 단위로 매핑하므로 이 정렬이 필요합니다. .balign의 인자는 바이트 단위의 정렬 크기이며, 어셈블 단계에서 필요한 패딩을 넣습니다.

### 17행
```asm
vdso32_end:
```
페이지 경계까지 정렬한 AArch32 호환 vDSO 원본의 끝입니다. 시작 주소와의 차이로 매핑할 이미지 크기를 계산할 수 있습니다. 레이블은 이 위치에 붙인 이름이며, 이름을 적는 것만으로 CPU 명령이 추가되지는 않습니다.

### 19행
```asm
	.previous
```
이후 출력할 바이트를 어느 섹션에 넣을지 바꿉니다. 빌드 도구가 코드를 분류하는 작업이며 현재 CPU의 PC나 SP를 옮기는 줄은 아닙니다. 

## 설명한 뒤 함께 생각해 볼 질문

### start와 end는 함수인가요?
이름을 붙인 바이트 범위의 경계입니다. C 코드가 포함된 이미지의 위치와 크기를 계산할 때 사용합니다.

### end−start는 원래 파일 크기와 항상 같은가요?
끝에도 페이지 정렬이 있어 패딩이 포함될 수 있습니다.

### 여기서 vdso.so를 실행하나요?
빌드 시 바이트를 포함할 뿐입니다. 사용자 공간에 매핑하고 호출하는 과정은 별도 코드가 맡습니다.
