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

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

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

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

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

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

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

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

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

### 11행
```asm
#include <asm/assembler.h>
```
ARM64의 큰 주소 구성, CPU별 값 조회, 시스템 레지스터 처리, 동기화 등에 쓰는 어셈블리 매크로를 가져옵니다. 각 사용 위치에서 일반 명령 여러 개로 펼쳐지는 작업입니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

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

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

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

### 16행
```asm
	.balign PAGE_SIZE
```
vDSO 이미지의 경계를 PAGE_SIZE에 맞춥니다. 커널이 이 원본을 페이지 단위로 사용자 주소 공간에 연결할 수 있게 하려는 정렬이며, 명령어 한 개의 길이만 맞추는 작업이 아닙니다. .balign의 인자는 바이트 단위의 정렬 크기이며, 어셈블 단계에서 필요한 패딩을 넣습니다.

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

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

### 19행
```asm
	.balign PAGE_SIZE
```
vDSO 이미지의 경계를 PAGE_SIZE에 맞춥니다. 커널이 이 원본을 페이지 단위로 사용자 주소 공간에 연결할 수 있게 하려는 정렬이며, 명령어 한 개의 길이만 맞추는 작업이 아닙니다. .balign의 인자는 바이트 단위의 정렬 크기이며, 어셈블 단계에서 필요한 패딩을 넣습니다.

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

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

### 24행
```asm
emit_aarch64_feature_1_and
```
이 어셈블리 오브젝트에 AArch64 GNU property note를 출력하여 BTI/PAC 등 빌드가 선언한 제어 흐름 보호 속성을 링커에 전달합니다. 방금 포함한 vDSO ELF를 실행하거나 그 내부 명령을 수정하는 작업은 아닙니다.

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

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

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

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