DUJINLABS.COM

Linux v6.18.37 · ARM64

vmlinux.lds.S — 말로 풀어 읽기

이 파일은 왜 필요한가요?

여러 소스 파일을 컴파일하면 코드와 데이터 조각이 들어 있는 오브젝트들이 생깁니다. 링커 스크립트는 그 조각을 최종 커널 이미지의 어디에 둘지 정합니다. 여기의 점(.)은 CPU의 PC가 아니라 링커가 현재 배치 중인 위치입니다. 이 관점을 바꾸지 않으면 . += PAGE_SIZE를 실행 중 메모리 할당처럼 오해하기 쉽습니다.

명령·지시문·라벨을 원본 줄 번호에 맞춰 설명합니다. 주석과 빈 줄을 포함한 전체 원문은 아래에 따로 두었습니다. 매크로 정의와 조건부 코드는 모두 차례대로 실행되는 명령 목록이 아닙니다.

기존 코드 분석과 함께 읽기 · 원본 파일 · 설명 원고

먼저 알아둘 개념: 전처리·어셈블·링크·실행, 어셈블러 지시문, 정렬과 경계, 주소와 주소가 가리키는 내용, 가상 주소와 MMU

처음 읽을 때

“모든 .text 조각을 이 위치에 모으고, 현재 위치에 _stext라는 이름을 붙인다”처럼 문장을 만들어 읽어 보세요.

더 깊이 살펴볼 때

로드 가능한 파일 크기와 메모리 크기, BSS와 초기 테이블, 링커 심볼과 런타임 권한 설정, ASSERT가 보장하는 부팅 가정을 나눠 설명해 보세요.

한 줄씩 레지스터와 메모리 상태 보기

각 코드 아래의 ‘행 그림’을 펼치면, 그 줄에서 읽는 값과 실행 전·후의 상태를 나란히 볼 수 있습니다. 여기서 ‘명령 직전’은 지금 보고 있는 명령이 실행되기 바로 전을 뜻합니다. 함수 진입 때나 소스의 바로 윗줄을 가리키는 말은 아닙니다. 앞서 실행한 명령이 값을 바꿨다면 그 결과가 들어 있습니다.

소스로 정해지는 상수, 호출자가 넘기는 값, 실제 실행에서 정해지는 주소를 구분해서 읽어야 합니다. 주소 숫자를 몰라도 무엇을 가리키는지와 어디서 받아 오는지는 설명할 수 있습니다. ‘명령 직전 x0의 값’처럼 일반 표기로 남은 곳은 한 명령의 동작을 나타내며, 특정 호출 경로의 값까지 확인했다는 뜻은 아닙니다.

일반 명령은 그 한 줄의 효과를, 매크로는 여러 명령을 묶은 주요 결과를 표시합니다. 함수 호출은 호출 직후의 PC와 LR까지만 나타냅니다. 메모리 접근은 정상적으로 끝나는 경우를 가정합니다. 생략된 항목까지 모두 보존된다는 뜻은 아닙니다.

화살표 →는 같은 항목의 전후 비교입니다. 메모리 칸에는 주소와 크기를 따로 적었습니다. SP가 줄어들면 낮은 주소 쪽을 사용하며, 화면의 위아래와 메모리 주소 방향은 별개입니다. 전처리·어셈블·링크 지시문은 CPU 실행과 구분합니다.

‘이전·다음 행’은 소스에 적힌 순서입니다. 분기·반복·호출이 있으므로 파일 위에서 아래로 실제 실행된다고 가정하지 않습니다. 값이 여러 줄에 걸쳐 이어지는 모습은 cpu-reset.S의 단계별 예제에서 보실 수 있습니다.

총 274개 줄에 그림을 붙였습니다. 기존 코드와 설명은 그 아래에서 이어집니다.

이 파일은 링크 스크립트입니다. 각 그림은 섹션과 심벌을 배치하는 규칙을 보여 주며, 실행 중 레지스터 값을 나타내지 않습니다.

먼저 그림으로 살펴보기

커널의 코드·데이터·초기 테이블 배치
화살표: 파일·링크 배치 순서입니다. CPU 실행 순서가 아닙니다. 칸 크기는 실제 바이트 비율과 다릅니다.

KVM 섹션과 공통 링커 매크로

원본 1–79행

링커의 점(.)은 실행 중인 PC가 아닙니다

링커의 점(.)은 실행 중인 PC가 아닙니다의 세 단계 비교
화살표는 링크 단계의 수집·배치·검증 관계입니다. 그림의 위아래는 실제 주소 배치를 축척대로 나타내지 않습니다.
그림의 각 단계를 글로 읽기

1. 같은 종류의 조각 수집

한 출력 섹션에 여러 입력 파일의 조각이 모일 수 있습니다.

2. 경계와 정렬 지정

점을 바꾸는 것은 링크 시 주소 계산이며 CPU의 PC나 SP 이동이 아닙니다.

3. 배치 조건 검사

잘못된 이미지가 만들어지지 않도록 실행 전에 검사하는 단계입니다.

#include <asm/hyp_image.h>

KVM nVHE 코드의 섹션 이름에 .hyp 접두사를 붙이는 HYP_SECTION_NAME 등을 가져옵니다. 호스트 커널과 별도 주소 공간에서 실행할 하이퍼바이저의 코드·데이터를 구분하기 위한 정의입니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

8행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include <asm/hyp_image.h>
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_KVM

KVM은 Linux에서 가상 머신을 실행하는 기능입니다. 켜진 빌드는 nVHE 하이퍼바이저용 예외 복구 표와 읽기 전용·쓰기 가능·CPU별 데이터 및 재배치 정보를 각각 수집합니다. 꺼지면 아래 #else에서 이 배치 매크로들을 비웁니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

9행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_KVM
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_EXTABLE					\

EL2의 KVM 코드에서 복구 가능한 예외가 발생했을 때 사용할 예외 표를 모으는 배치 규칙입니다. 표 항목의 시작·끝을 기호로 제공하여 런타임에서 해당 범위를 찾을 수 있게 합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

10행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_EXTABLE \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SZ_8);					\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(SZ_8); \

11행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SZ_8); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__start___kvm_ex_table = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __start___kvm_ex_table = .; \

12행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__start___kvm_ex_table = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(__kvm_ex_table)					\

KVM 코드가 __kvm_ex_table에 기록한 예외 위치와 복구 위치 정보를 모읍니다. 일반 명령 본문을 모으는 곳이 아니라 예외 처리기가 참조할 표입니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

13행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(__kvm_ex_table) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__stop___kvm_ex_table = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __stop___kvm_ex_table = .;

14행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__stop___kvm_ex_table = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_RODATA_SECTIONS				\

nVHE 하이퍼바이저의 상수와 초기화 후 읽기 전용으로 둘 데이터를 페이지 경계로 묶는 배치 규칙입니다. 호스트의 일반 .rodata와 따로 관리할 범위를 제공합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

16행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_RODATA_SECTIONS \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYP_SECTION_NAME(.rodata) : {				\

HYP_SECTION_NAME(.rodata)는 .hyp.rodata로 펼쳐집니다. nVHE 하이퍼바이저가 사용할 읽기 전용 자료를 이 출력 섹션에 넣습니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

17행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYP_SECTION_NAME(.rodata) : { \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

18행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__hyp_rodata_start = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_rodata_start = .; \

19행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_rodata_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(HYP_SECTION_NAME(.data..ro_after_init))	\

nVHE 코드의 초기화 뒤 수정하지 않을 .hyp.data..ro_after_init 데이터를 모읍니다. 처음부터 상수인 아래 .hyp.rodata와 같은 보호 범위로 묶되, 이 링커 문장 자체가 페이지 권한을 바꾸지는 않습니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

20행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(HYP_SECTION_NAME(.data..ro_after_init)) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(HYP_SECTION_NAME(.rodata))			\

nVHE 코드의 상수 데이터를 .hyp.rodata에 모읍니다. 앞뒤 페이지 정렬은 뒤의 메모리 매핑 코드가 다른 종류의 데이터와 분리해 권한을 적용할 수 있도록 합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

21행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(HYP_SECTION_NAME(.rodata)) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

22행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__hyp_rodata_end = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_rodata_end = .; \

23행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_rodata_end = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_DATA_SECTION					\

nVHE 하이퍼바이저가 실행 중 수정할 데이터의 배치 규칙입니다. 읽기 전용 범위와 별도로 페이지 단위의 시작·끝을 잡습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

26행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_DATA_SECTION \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYP_SECTION_NAME(.data) : {				\

nVHE의 쓰기 가능한 .hyp.data 출력 섹션을 시작합니다. 이 영역은 위의 .hyp.rodata와 다른 권한으로 매핑할 수 있어야 합니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

27행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYP_SECTION_NAME(.data) : { \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

28행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__hyp_data_start = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_data_start = .; \

29행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_data_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(HYP_SECTION_NAME(.data))			\

초기값이 있는 nVHE 전역 변수를 .hyp.data로 모읍니다. 0으로 초기화할 변수는 뒤의 .hyp.bss 범위에 놓습니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

30행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(HYP_SECTION_NAME(.data)) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

31행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__hyp_data_end = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_data_end = .; \

32행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_data_end = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_PERCPU_SECTION				\

하이퍼바이저의 CPU별 변수 원본을 별도 영역에 모으는 규칙입니다. 각 CPU가 자기 상태를 독립적으로 갖도록 하는 percpu 영역이며 일반 전역 데이터와 구분합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

35행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_PERCPU_SECTION \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(PAGE_SIZE);					\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

36행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYP_SECTION_NAME(.data..percpu) : {			\

nVHE 코드의 CPU별 데이터 원본을 .hyp.data..percpu 출력 섹션에 모읍니다. 여기서 CPU 수만큼 실제 복사본을 만드는 것은 아닙니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

37행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYP_SECTION_NAME(.data..percpu) : { \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(HYP_SECTION_NAME(.data..percpu))		\

여러 nVHE 오브젝트에 흩어진 percpu 변수들을 한 원본 범위로 연결합니다. CPU별 영역의 배치·초기화에서 이 원본을 사용합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

38행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(HYP_SECTION_NAME(.data..percpu)) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_RELOC_SECTION				\

nVHE 코드가 별도 주소 공간에 놓일 때 주소를 보정할 위치들의 목록을 모읍니다. 일반 커널의 .rela.dyn 재배치와 구분된 hyp 전용 목록입니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

41행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_RELOC_SECTION \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.hyp.reloc : ALIGN(4) {					\

.hyp.reloc 항목을 4바이트 경계에 배치합니다. 각 항목은 nVHE 주소 보정에 사용할 기록이며 이 섹션을 실행하는 것은 아닙니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

42행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과.hyp.reloc : ALIGN(4) { \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__hyp_reloc_begin = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_reloc_begin = .; \

43행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_reloc_begin = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.hyp.reloc)					\

nVHE 빌드에서 생성한 .hyp.reloc 기록을 모읍니다. __hyp_reloc_begin과 __hyp_reloc_end 사이를 순회하여 하이퍼바이저 주소 보정 대상을 찾을 수 있습니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

44행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.hyp.reloc) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__hyp_reloc_end = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_reloc_end = .; \

45행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_reloc_end = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define BSS_FIRST_SECTIONS					\

BSS의 가장 앞에 nVHE 하이퍼바이저의 0 초기화 변수를 놓도록 공통 BSS_SECTION 규칙에 추가합니다. 하이퍼바이저와 호스트 BSS가 같은 시작 주소를 갖는 전제를 뒤의 ASSERT가 확인합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

48행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define BSS_FIRST_SECTIONS \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hyp_bss_start = .;					\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_bss_start = .; \

49행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_bss_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(HYP_SECTION_NAME(.bss))				\

nVHE의 0 초기화 변수를 호스트 BSS의 첫 부분에 모읍니다. 파일에 0을 일일이 저장하기보다 부팅 코드가 이 범위를 0으로 지웁니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

50행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(HYP_SECTION_NAME(.bss)) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(PAGE_SIZE);					\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

51행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hyp_bss_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_bss_end = .;

52행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_bss_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define SBSS_ALIGN			PAGE_SIZE

BSS_SECTION 내부의 빈 .sbss 때문에 __bss_start와 __hyp_bss_start가 어긋나는 링커 배치 문제를 막습니다. KVM 빌드에서는 SBSS 정렬을 한 페이지로 강제합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

60행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define SBSS_ALIGN PAGE_SIZE
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#else /* CONFIG_KVM */

KVM을 빌드하지 않는 경우입니다. 하이퍼바이저 전용 데이터·복구 표·재배치 영역을 추가할 필요가 없어 아래 매크로들을 빈 정의로 만듭니다.

61행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#else
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_EXTABLE

KVM이 꺼져 있으므로 하이퍼바이저 예외 복구 표를 추가하지 않습니다. 뒤의 HYPERVISOR_TEXT 안에서 이 이름을 사용해도 아무 배치 문장이 나오지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

62행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_EXTABLE
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_RODATA_SECTIONS

KVM이 꺼져 있으므로 nVHE 읽기 전용 데이터 섹션을 추가하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

63행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_RODATA_SECTIONS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_DATA_SECTION

KVM이 꺼져 있으므로 nVHE의 쓰기 가능한 데이터 섹션을 추가하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

64행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_DATA_SECTION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_PERCPU_SECTION

KVM이 꺼져 있으므로 nVHE CPU별 데이터 원본 영역을 추가하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

65행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_PERCPU_SECTION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_RELOC_SECTION

KVM이 꺼져 있으므로 nVHE 주소 보정 기록 섹션을 추가하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

66행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_RELOC_SECTION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define SBSS_ALIGN			0

KVM 전용 BSS 시작 정렬 문제를 피하기 위한 추가 정렬을 사용하지 않습니다. 일반 BSS 배치 규칙은 그대로 적용됩니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

67행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define SBSS_ALIGN 0
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

68행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define RO_EXCEPTION_TABLE_ALIGN	4

일반 커널 예외 복구 표를 읽기 전용 데이터 쪽에 4바이트 정렬로 배치하도록 공통 링커 매크로에 전달합니다. 이 표는 접근 오류가 난 명령에서 복구 위치를 찾는 데 쓰입니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

70행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define RO_EXCEPTION_TABLE_ALIGN 4
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define RUNTIME_DISCARD_EXIT

종료용 코드·데이터를 링크 시 바로 버리지 않고 초기화 영역에 남긴 뒤 부팅 후 해제하도록 선택합니다. 대체 명령 표 등 다른 섹션에서 참조하는 주소가 링크 과정에서 사라지는 것을 피합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

71행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define RUNTIME_DISCARD_EXIT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#include <asm-generic/vmlinux.lds.h>

초기화 함수 목록, 읽기 전용 데이터, BSS, percpu 등 여러 아키텍처가 공유하는 배치 규칙을 가져옵니다. 위에서 정한 KVM·예외 표·종료 영역 정책을 이 매크로들이 반영합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

73행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include <asm-generic/vmlinux.lds.h>
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#include <asm/cache.h>

CPU 캐시 라인에 맞춘 데이터 정렬 값을 가져옵니다. 뒤의 PERCPU_SECTION과 RW_DATA가 L1_CACHE_BYTES를 사용합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

74행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include <asm/cache.h>
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#include <asm/kernel-pgtable.h>

초기 identity mapping과 커널 매핑에 필요한 페이지 표 공간 크기 및 표 사이 오프셋을 가져옵니다. 뒤의 공간 예약과 ASSERT가 이 정의에 맞아야 합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

75행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include <asm/kernel-pgtable.h>
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#include <asm/kexec.h>

펌웨어를 다시 거치지 않고 다른 커널을 시작하는 kexec의 제어 페이지 크기 정의를 가져옵니다. 파일 끝에서 재배치 코드가 그 공간에 들어가는지 검사합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

76행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include <asm/kexec.h>
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#include <asm/memory.h>

커널 이미지의 가상 기준 주소 KIMAGE_VADDR와 스택·세그먼트 정렬 등 ARM64 메모리 배치 상수를 가져옵니다. 파일 오프셋과 실행 가상 주소를 정할 때 필요한 정의입니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

77행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include <asm/memory.h>
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#include <asm/page.h>

선택한 커널 페이지 크기 PAGE_SIZE 등의 정의를 가져옵니다. 코드·데이터 경계를 페이지 단위로 분리하여 나중에 각각의 접근 권한을 설정할 수 있게 합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

78행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include <asm/page.h>
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

진입점과 특수 코드 구간

원본 80–145행

#include "image.h"

head.S의 Image 헤더에 넣을 커널 크기와 플래그를 링크 시 계산하는 HEAD_SYMBOLS 정의를 가져옵니다. 커널 엔디언과 관계없이 부트로더가 읽는 헤더 값을 리틀 엔디언으로 만듭니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

80행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include "image.h"
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

OUTPUT_ARCH(aarch64)

최종 결과 파일이 어느 CPU 아키텍처용인지 지정합니다. 여기서는 AArch64입니다.

82행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과OUTPUT_ARCH(aarch64)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ENTRY(_text)

ELF 형식의 진입점 이름을 _text로 정합니다. 이 줄은 CPU의 분기 명령이 아니라 파일의 진입 정보입니다.

83행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ENTRY(_text)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

jiffies = jiffies_64;

타이머 틱 누적값인 jiffies를 64비트 실제 저장소 jiffies_64와 같은 주소로 연결합니다. AArch64의 unsigned long은 64비트이므로 두 이름으로 같은 카운터를 읽을 수 있습니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

85행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과jiffies = jiffies_64;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HYPERVISOR_TEXT					\

EL2 초기 진입용 identity-mapped 코드와 일반 hyp 코드, KVM 예외 복구 표를 묶습니다. 뒤의 경계 기호로 필요한 EL2 코드만 매핑할 수 있습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

87행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HYPERVISOR_TEXT \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

88행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hyp_idmap_text_start = .;			\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_idmap_text_start = .; \

89행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_idmap_text_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(.hyp.idmap.text)				\

물리 주소와 같은 가상 주소에서 실행하도록 작성된 hyp 초기화 코드를 모읍니다. 하이퍼바이저 주소 변환 상태를 바꾸는 짧은 구간에 필요하며 파일 끝에서 한 페이지 이내인지 확인합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

90행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.hyp.idmap.text) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hyp_idmap_text_end = .;			\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_idmap_text_end = .; \

91행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_idmap_text_end = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hyp_text_start = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_text_start = .; \

92행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_text_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(.hyp.text)					\

일반 .hyp.text 코드를 모읍니다. 앞의 짧은 identity-mapped 초기 코드와 경계를 구분하여 각각 필요한 주소 공간에 매핑할 수 있게 합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

93행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.hyp.text) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYPERVISOR_EXTABLE				\

CONFIG_KVM이 켜졌으면 앞에서 정의한 EL2 예외 복구 표를 이 위치에 배치합니다. KVM이 꺼졌으면 빈 매크로이므로 별도 표가 추가되지 않습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

94행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYPERVISOR_EXTABLE \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

95행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hyp_text_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hyp_text_end = .;

96행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hyp_text_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define IDMAP_TEXT					\

MMU 상태를 바꾸는 동안 물리 주소와 같은 가상 주소에서 실행할 .idmap.text 코드를 모으는 규칙입니다. 시작을 4KiB 경계에 놓고 끝에서 한 4KiB 범위를 넘지 않는지 확인합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

98행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define IDMAP_TEXT \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SZ_4K);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(SZ_4K); \

99행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SZ_4K); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__idmap_text_start = .;				\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __idmap_text_start = .; \

100행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__idmap_text_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(.idmap.text)					\

MMU 전환 구간에 필요한 identity-mapped 함수들을 모읍니다. 커널의 높은 가상 주소 매핑을 아직 사용할 수 없거나 바꾸는 시점에 실행할 코드입니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

101행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.idmap.text) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__idmap_text_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __idmap_text_end = .;

102행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__idmap_text_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_HIBERNATION

최대절전은 메모리 상태를 저장했다가 다시 복원하는 기능입니다. 켜진 빌드에서는 복원된 커널로 돌아갈 마지막 전환 코드를 별도 섹션으로 모읍니다. 꺼지면 이 코드 수집 매크로는 비워집니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

104행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_HIBERNATION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HIBERNATE_TEXT					\

최대절전 이미지 복원 후 원래 커널로 넘어갈 .hibernate_exit.text 코드와 경계를 정의합니다. 복원 중 사용할 별도 실행 위치에 복사할 범위를 알 수 있게 합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

105행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HIBERNATE_TEXT \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	ALIGN_FUNCTION();				\

최대절전 복원 진입 함수를 CONFIG_FUNCTION_ALIGNMENT 경계에 맞춥니다. 복사할 코드의 첫 함수가 요구하는 정렬을 링크 결과에서도 유지합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

106행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ALIGN_FUNCTION(); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hibernate_exit_text_start = .;		\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hibernate_exit_text_start = .; \

107행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hibernate_exit_text_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(.hibernate_exit.text)				\

최대절전 복원의 마지막 전환 코드를 모읍니다. 뒤의 ASSERT는 이 범위가 4KiB 안에 들어가고 첫 명령이 swsusp_arch_suspend_exit인지 확인합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

108행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.hibernate_exit.text) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__hibernate_exit_text_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __hibernate_exit_text_end = .;

109행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__hibernate_exit_text_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#else

앞 빌드 조건이 맞지 않을 때 사용할 정의나 코드를 시작합니다. 대상:

110행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#else
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define HIBERNATE_TEXT

최대절전 기능을 빌드하지 않으므로 복원용 전환 코드를 별도 수집하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

111행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define HIBERNATE_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

112행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_KEXEC_CORE

kexec는 현재 커널에서 새 커널로 직접 넘어가는 기능입니다. 켜지면 새 커널 이미지의 위치를 정리하고 진입할 재배치 코드를 별도 범위로 모읍니다. 꺼지면 KEXEC_TEXT는 비어 있습니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

114행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_KEXEC_CORE
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define KEXEC_TEXT					\

새 커널을 시작할 때 안전한 제어 페이지로 복사할 kexec 재배치 코드의 시작·끝을 정합니다. 현재 커널 메모리를 덮어쓰는 중에도 실행할 짧은 코드가 필요하기 때문입니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

115행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define KEXEC_TEXT \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	ALIGN_FUNCTION();				\

kexec 재배치 코드의 첫 함수를 CONFIG_FUNCTION_ALIGNMENT 경계에 맞춥니다. 뒤에서 이 시작 위치가 arm64_relocate_new_kernel인지 함께 검증합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

116행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ALIGN_FUNCTION(); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__relocate_new_kernel_start = .;		\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __relocate_new_kernel_start = .; \

117행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__relocate_new_kernel_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(.kexec_relocate.text)				\

kexec의 마지막 이미지 이동·진입 코드를 모읍니다. 이 범위를 별도 제어 페이지에 옮길 수 있도록 뒤에서 크기와 시작 함수를 검사합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

118행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.kexec_relocate.text) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__relocate_new_kernel_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __relocate_new_kernel_end = .;

119행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__relocate_new_kernel_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#else

앞 빌드 조건이 맞지 않을 때 사용할 정의나 코드를 시작합니다. 대상:

120행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#else
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define KEXEC_TEXT

kexec를 빌드하지 않으므로 새 커널 전환용 재배치 코드의 별도 배치가 필요 없습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

121행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define KEXEC_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

122행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0

KPTI는 사용자 모드에서 커널 매핑 대부분을 빼는 보호 기능입니다. 켜진 빌드는 사용자·커널 페이지 표 사이를 전환하는 작은 진입 trampoline을 별도 페이지에 모읍니다. 실제 사용 여부는 부팅 시 CPU와 정책에 따라 결정됩니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

124행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define TRAMP_TEXT					\

KPTI 예외 진입 trampoline의 실행 코드와 상수를 따로 모읍니다. 사용자용 페이지 표에서도 커널로 넘어가는 데 필요한 이 작은 영역은 접근 가능해야 합니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

125행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define TRAMP_TEXT \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

126행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__entry_tramp_text_start = .;			\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __entry_tramp_text_start = .; \

127행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__entry_tramp_text_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(.entry.tramp.text)				\

entry.S가 만든 .entry.tramp.text 코드를 모읍니다. 예외 발생 시 커널 전체 매핑을 되살린 뒤 정상 벡터로 넘어가는 코드입니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

128행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.entry.tramp.text) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(PAGE_SIZE);				\

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE); \

129행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE); \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__entry_tramp_text_end = .;			\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __entry_tramp_text_end = .; \

130행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__entry_tramp_text_end = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	*(.entry.tramp.rodata)

KPTI trampoline이 참조할 읽기 전용 자료를 코드 뒤에 둡니다. 일반 커널 데이터 전체를 사용자용 페이지 표에 남길 수 없으므로 필요한 자료를 이 별도 섹션에서 찾습니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

131행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.entry.tramp.rodata)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#else

앞 빌드 조건이 맞지 않을 때 사용할 정의나 코드를 시작합니다. 대상:

132행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#else
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define TRAMP_TEXT

KPTI를 빌드하지 않으므로 제한된 매핑에서 실행할 진입 trampoline을 이 위치에 배치하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

133행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define TRAMP_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

134행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_UNWIND_TABLES

컴파일러가 만든 호출 프레임 정보를 보존하는 설정입니다. 이 버전의 ARM64에서는 동적 Shadow Call Stack 구성이 이 설정을 선택하고, 초기 scs_patch가 .eh_frame을 읽어 PAC 명령을 SCS 코드로 바꿀 위치를 찾습니다. 꺼지면 이 섹션 수집 매크로가 비어 있습니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

136행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_UNWIND_TABLES
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define UNWIND_DATA_SECTIONS				\

동적 Shadow Call Stack 패치가 참고할 .eh_frame 범위와 초기 코드용 __pi_ 경계 기호를 정의합니다. 일반 실행 중 스택 추적을 위해 무조건 영구 보존하는 영역으로 해석하면 안 됩니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

137행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNWIND_TABLES

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define UNWIND_DATA_SECTIONS \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.eh_frame : {					\

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .eh_frame : { \

138행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNWIND_TABLES

소스의 규칙
처리 전링크 전의 식
이 줄의 효과.eh_frame : { \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__pi___eh_frame_start = .;		\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi___eh_frame_start = .; \

139행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNWIND_TABLES

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi___eh_frame_start = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.eh_frame)				\

컴파일러의 호출 프레임 정보를 모읍니다. 초기 scs_patch는 이 정보에서 함수의 복귀 주소 처리 위치를 찾아 지원 구성에 맞는 Shadow Call Stack 명령으로 바꿉니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

140행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNWIND_TABLES

소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.eh_frame) \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__pi___eh_frame_end = .;		\

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi___eh_frame_end = .; \

141행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNWIND_TABLES

소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi___eh_frame_end = .; \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#else

앞 빌드 조건이 맞지 않을 때 사용할 정의나 코드를 시작합니다. 대상:

143행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNWIND_TABLES

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#else
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define UNWIND_DATA_SECTIONS

호출 프레임 정보를 보존하지 않는 빌드이므로 이 전용 .eh_frame 배치 규칙을 추가하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

144행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define UNWIND_DATA_SECTIONS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

145행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

PE 파일 정렬과 일반 text

원본 146–198행

PECOFF_FILE_ALIGNMENT = 0x200;

EFI가 해석하는 PE/COFF 이미지의 파일 정렬 단위를 512바이트로 정합니다. 커널의 메모리 페이지 크기와는 별개인 실행 파일 형식의 조건입니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

154행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과PECOFF_FILE_ALIGNMENT = 0x200;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_EFI

EFI 펌웨어가 이 커널 이미지를 PE/COFF 실행 파일로 적재할 수 있게 만드는 빌드입니다. 켜지면 데이터 파일 크기의 512바이트 정렬을 맞추는 padding 섹션을 추가합니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

156행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_EFI
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define PECOFF_EDATA_PADDING	\

EFI용 PE/COFF 데이터 파일 크기를 512바이트 배수로 채우는 규칙을 정의합니다. 실제 padding은 아래 PECOFF_EDATA_PADDING을 사용한 위치에 출력됩니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

157행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_EFI

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define PECOFF_EDATA_PADDING \
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }

0 한 바이트를 실제 파일에 넣고 다음 PE/COFF 파일 정렬 경계까지 채웁니다. _edata까지의 파일 구간 길이가 헤더가 요구하는 512바이트 배수가 되도록 합니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

158행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_EFI

소스의 규칙
처리 전링크 전의 식
이 줄의 효과.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#else

앞 빌드 조건이 맞지 않을 때 사용할 정의나 코드를 시작합니다. 대상:

159행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_EFI

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#else
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#define PECOFF_EDATA_PADDING

EFI용 파일 정렬 보정이 필요 없는 빌드이므로 추가 padding을 출력하지 않습니다. 전처리기는 이후 이 이름이 쓰인 곳에 정의한 내용을 치환합니다. 실행 중 값을 보관하는 변수를 만드는 줄은 아닙니다.

160행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#define PECOFF_EDATA_PADDING
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

161행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: 앞 조건의 반대

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

SECTIONS

이제 여러 오브젝트에서 가져온 코드·데이터 조각을 순서와 주소에 맞춰 배치합니다.

163행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과SECTIONS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	DISCARDS

최종 실행 이미지에 필요하지 않은 .discard 계열과 종료 호출 목록 등 공통 폐기 대상을 제거합니다. 위의 RUNTIME_DISCARD_EXIT 때문에 종료 코드·데이터 자체는 여기서 바로 제거되지 않습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

171행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과DISCARDS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	/DISCARD/ : {

아래에 해당하는 조각들은 최종 커널 이미지에 넣지 않습니다.

172행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과/DISCARD/ : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.interp .dynamic)

사용자 ELF 실행 파일의 동적 로더 경로와 동적 링크 정보는 이 커널 실행 경로에서 쓰지 않으므로 제거합니다. 커널이 처리할 재배치 기록은 아래에서 별도로 보존합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

173행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.interp .dynamic)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.dynsym .dynstr .hash .gnu.hash)

사용자 공간 동적 링커용 심볼·문자열·해시 표를 제거합니다. 커널의 자체 심볼 표나 디버깅용 ELF 심볼 전체를 없앤다는 뜻은 아닙니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

174행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.dynsym .dynstr .hash .gnu.hash)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.ARM.attributes)

입력 오브젝트의 ARM 속성 메타데이터를 최종 커널 이미지에서 제거합니다. CPU가 실행할 코드나 시스템 레지스터 설정을 삭제하는 줄은 아닙니다.

175행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.ARM.attributes)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = KIMAGE_VADDR;

링크할 커널 이미지의 첫 가상 주소를 KIMAGE_VADDR로 정합니다. 뒤의 _text가 정확히 이 주소여야 이미지 상대 주소로 물리·가상 변환을 하는 부팅 코드가 맞게 동작합니다. 여기서 .은 링커의 현재 배치 위치이며 CPU의 PC 레지스터가 아닙니다.

178행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = KIMAGE_VADDR;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.head.text : {

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .head.text : {

180행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.head.text : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		_text = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. _text = .;

181행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과_text = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		HEAD_TEXT

head.S의 .head.text를 이미지 맨 앞에 넣습니다. 부트로더가 읽을 ARM64 Image 헤더와 초기 진입 명령이 여기 있어야 합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

182행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HEAD_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.text : ALIGN(SEGMENT_ALIGN) {	/* Real text segment		*/

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .text : ALIGN(SEGMENT_ALIGN) {

184행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.text : ALIGN(SEGMENT_ALIGN) {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		_stext = .;		/* Text and read-only data	*/

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. _stext = .;

185행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과_stext = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			IRQENTRY_TEXT

하드웨어 인터럽트 진입용으로 표시한 코드들을 연속 범위에 모읍니다. __irqentry_text_start와 끝 기호로 이 종류의 코드 주소를 구별할 수 있게 합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

186행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과IRQENTRY_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			SOFTIRQENTRY_TEXT

softirq 진입용으로 표시된 코드를 모읍니다. 하드웨어 IRQ 진입 범위와 따로 경계를 두어 실행 위치의 성격을 구분합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

187행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과SOFTIRQENTRY_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			ENTRY_TEXT

예외·시스템 호출 진입용 .entry.text를 모으고 범위를 기록합니다. 일반 함수 본문과 달리 특별한 레지스터·추적 규칙을 갖는 진입 코드의 위치를 식별할 수 있게 합니다.

188행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ENTRY_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			TEXT_TEXT

일반 함수 코드와 hot·unlikely·계측 제한 코드 등을 공통 규칙에 맞춰 수집합니다. 실행 빈도나 계측 가능 여부에 따라 구분한 입력 섹션도 최종 실행 영역 안에 들어갑니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

189행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과TEXT_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			SCHED_TEXT

스케줄러의 .sched.text를 모으고 시작·끝을 기록합니다. 호출 주소가 스케줄러 코드에 속하는지 판단할 수 있는 범위를 만듭니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

190행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과SCHED_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			LOCK_TEXT

spinlock 관련 .spinlock.text를 모으고 경계를 기록합니다. 락을 직접 획득하는 링커 명령이 아니라 해당 구현 코드의 주소 범위를 만드는 작업입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

191행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과LOCK_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			KPROBES_TEXT

kprobe와 관련된 특별한 .kprobes.text 코드를 한 범위로 모읍니다. 실행 중 probe를 설치하는 줄은 아니며 코드 주소의 분류에 필요한 경계를 제공합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

192행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과KPROBES_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			HYPERVISOR_TEXT

앞서 정한 EL2 코드와 identity-mapped 초기화 코드, KVM 예외 복구 표를 실행 영역에 배치합니다. KVM 전용 표는 해당 빌드에서만 추가됩니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

193행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYPERVISOR_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

			*(.gnu.warning)

입력 파일들에서 괄호 안 이름 패턴과 맞는 조각을 모두 모읍니다. 파일 하나의 코드뿐 아니라 같은 종류의 여러 오브젝트 내용을 연결합니다. *(.gnu.warning)

194행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.gnu.warning)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SEGMENT_ALIGN);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(SEGMENT_ALIGN);

197행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SEGMENT_ALIGN);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	_etext = .;			/* End of text section */

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. _etext = .;

198행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과_etext = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

읽기 전용 코드와 루트 테이블

원본 199–240행

	RO_DATA(PAGE_SIZE)

상수와 각종 읽기 전용 표를 페이지 단위로 정리하여 배치합니다. 이후 커널이 이 영역에 쓰기 금지·실행 금지 권한을 적용할 수 있도록 코드와 경계를 분리합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

201행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과RO_DATA(PAGE_SIZE)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYPERVISOR_RODATA_SECTIONS

nVHE 하이퍼바이저의 읽기 전용 데이터 범위를 배치합니다. KVM을 빌드하지 않으면 앞에서 빈 매크로로 정의했으므로 아무 섹션도 추가하지 않습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

203행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYPERVISOR_RODATA_SECTIONS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.got : { *(.got) }

주소를 간접 참조할 때 쓰는 Global Offset Table의 항목을 보존합니다. .got은 데이터 표이며 이곳에 함수 본문을 넣는 것이 아닙니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

205행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.got : { *(.got) }
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.got.plt : { *(.got.plt) }

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .got.plt : { *(.got.plt) }

210행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.got.plt : { *(.got.plt) }
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18,

동적 함수 호출 연결용 GOT/PLT 항목이 없거나 예약된 24바이트만 있는지 링크 시 확인합니다. 커널이 처리하지 않는 추가 lazy binding 항목이 생기면 빌드를 중단합니다.

211행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	       "Unexpected GOT/PLT entries detected!")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "Unexpected GOT/PLT entries detected!")

212행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과"Unexpected GOT/PLT entries detected!")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.rodata.text : {

커널의 일반 이미지 매핑에서는 실행하지 않을 전환 코드를 읽기 전용 영역에 둡니다. 각 코드는 identity mapping이나 trampoline 별칭 등 필요한 별도 매핑에서 실행됩니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

215행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.rodata.text : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		TRAMP_TEXT

KPTI의 제한된 주소 공간에서 커널 매핑으로 들어오는 trampoline과 상수를 배치합니다. 일반 커널 매핑에서 이 코드 페이지를 실행 가능하게 둘 필요는 없습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

216행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과TRAMP_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		HIBERNATE_TEXT

최대절전 복원 마지막 단계에 별도 위치에서 실행할 코드를 배치합니다. 기능을 끈 빌드에서는 이 매크로가 비어 있습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

217행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HIBERNATE_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		KEXEC_TEXT

새 커널로 전환할 때 제어 페이지에 복사하여 실행할 kexec 코드를 배치합니다. 기능을 끈 빌드에서는 아무 내용도 추가되지 않습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

218행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과KEXEC_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		IDMAP_TEXT

MMU 전환 중 identity mapping으로 실행할 코드를 배치합니다. 같은 물리 코드가 일반 커널 매핑에서는 읽기 전용 데이터처럼 놓일 수 있습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

219행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과IDMAP_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		. = ALIGN(PAGE_SIZE);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE);

220행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	idmap_pg_dir = .;

identity mapping의 루트 페이지 표가 시작할 주소를 기록합니다. 바로 뒤에서 PAGE_SIZE만큼 공간을 예약하므로 표의 위치와 크기가 연결됩니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

223행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과idmap_pg_dir = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. += PAGE_SIZE;

identity mapping 루트 표 한 페이지를 이미지 주소 공간에 예약합니다. 여기서는 표 항목을 채우지 않으며 부팅 코드가 필요한 매핑을 작성합니다. 링커의 현재 배치 위치를 옮겨 공간을 예약합니다. 부팅 중 동적 메모리를 할당하는 함수 호출이 아닙니다.

224행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. += PAGE_SIZE;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0

사용자 공간에서 커널 매핑을 제거하는 KPTI를 빌드한 경우에만 제한된 trampoline용 루트 표 공간을 마련합니다. 꺼지면 이 표와 예약 공간은 없습니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

226행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	tramp_pg_dir = .;

KPTI trampoline용 페이지 표의 위치를 기록합니다. entry.S가 커널 표와의 고정 오프셋으로 전환하므로 배치가 코드의 상수와 일치해야 합니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

227행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과tramp_pg_dir = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. += PAGE_SIZE;

KPTI trampoline용 루트 표 한 페이지를 예약합니다. 모든 커널 영역을 사용자 주소 공간에 남기는 것이 아니라 필요한 작은 진입 영역을 연결할 표입니다. 링커의 현재 배치 위치를 옮겨 공간을 예약합니다. 부팅 중 동적 메모리를 할당하는 함수 호출이 아닙니다.

228행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과. += PAGE_SIZE;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

229행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	reserved_pg_dir = .;

접근을 막을 때 사용할 예약 페이지 표의 시작을 기록합니다. 정상 커널 표와의 거리는 RESERVED_SWAPPER_OFFSET 검사로 보장합니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

231행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과reserved_pg_dir = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. += PAGE_SIZE;

예약 루트 페이지 표 한 페이지를 확보합니다. 다음 swapper_pg_dir와의 주소 차이를 이용하는 어셈블리 코드가 있어 크기와 순서를 임의로 바꾸면 안 됩니다. 링커의 현재 배치 위치를 옮겨 공간을 예약합니다. 부팅 중 동적 메모리를 할당하는 함수 호출이 아닙니다.

232행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. += PAGE_SIZE;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	swapper_pg_dir = .;

정상 커널 매핑을 담을 swapper 루트 페이지 표의 시작을 기록합니다. 초기 임시 매핑 표와 구별되는 커널의 정식 루트 표입니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

234행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과swapper_pg_dir = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. += PAGE_SIZE;

swapper 루트 표 한 페이지를 예약합니다. 하위 단계 페이지 표 전체가 여기 한 페이지에 모두 들어간다는 뜻은 아닙니다. 링커의 현재 배치 위치를 옮겨 공간을 예약합니다. 부팅 중 동적 메모리를 할당하는 함수 호출이 아닙니다.

235행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. += PAGE_SIZE;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SEGMENT_ALIGN);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(SEGMENT_ALIGN);

237행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SEGMENT_ALIGN);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__init_begin = .;

부팅이 끝나면 해제할 수 있는 초기화 영역의 시작입니다. 이후 코드·데이터는 __init_end까지 일반적인 영구 커널 영역과 구분됩니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

238행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__init_begin = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__inittext_begin = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __inittext_begin = .;

239행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__inittext_begin = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

초기화와 재배치 정보

원본 241–299행

	INIT_TEXT_SECTION(8)

부팅 초기화 전용 함수들을 정렬해 모읍니다. __init 코드의 수명이 끝나면 이 메모리를 돌려줄 수 있도록 일반 .text와 떨어뜨립니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

241행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과INIT_TEXT_SECTION(8)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__exittext_begin = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __exittext_begin = .;

243행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__exittext_begin = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.exit.text : {

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .exit.text : {

244행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.exit.text : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		EXIT_TEXT

종료용 코드도 일단 이 초기화 영역에 모읍니다. 링크 중 대체 명령 표 등의 참조를 유지한 뒤 초기화 메모리와 함께 정리하려는 배치입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

245행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과EXIT_TEXT
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__exittext_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __exittext_end = .;

247행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__exittext_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(4);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(4);

249행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(4);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.altinstructions : {

CPU 기능에 따라 부팅 시 명령열을 교체할 위치와 대체 코드의 정보를 담는 표입니다. 이 섹션이 실제 실행 경로를 고르는 것이 아니라 alternatives 처리 코드가 읽습니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

250행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.altinstructions : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__alt_instructions = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __alt_instructions = .;

251행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__alt_instructions = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.altinstructions)

각 오브젝트가 기록한 대체 명령 메타데이터를 모읍니다. CPU 기능 검사 결과에 맞춰 명령을 패치할 위치·길이 등을 찾는 데 사용합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

252행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.altinstructions)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__alt_instructions_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __alt_instructions_end = .;

253행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__alt_instructions_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	UNWIND_DATA_SECTIONS

설정에 따라 .eh_frame을 초기화 영역에 배치합니다. 동적 SCS 패치가 필요한 부팅에서는 초기 코드가 이 자료를 사용하며, 초기화가 끝나면 해당 범위는 초기화 메모리와 함께 해제할 수 있습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

256행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과UNWIND_DATA_SECTIONS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SEGMENT_ALIGN);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(SEGMENT_ALIGN);

258행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SEGMENT_ALIGN);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__inittext_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __inittext_end = .;

259행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__inittext_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__initdata_begin = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __initdata_begin = .;

260행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__initdata_begin = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pi_init_idmap_pg_dir = .;

초기 위치 독립 코드가 identity mapping을 만들 때 사용할 페이지 표 공간의 시작입니다. 영구 idmap_pg_dir와 이름·수명을 구분합니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

262행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_init_idmap_pg_dir = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. += INIT_IDMAP_DIR_SIZE;

현재 페이지 크기와 주소 변환 단계에 맞춰 계산한 초기 identity-mapping 표 공간을 예약합니다. 필요한 하위 단계 표도 들어가므로 크기를 임의로 PAGE_SIZE로 줄일 수 없습니다. 링커의 현재 배치 위치를 옮겨 공간을 예약합니다. 부팅 중 동적 메모리를 할당하는 함수 호출이 아닙니다.

263행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. += INIT_IDMAP_DIR_SIZE;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pi_init_idmap_pg_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi_init_idmap_pg_end = .;

264행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_init_idmap_pg_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.init.data : {

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .init.data : {

266행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.init.data : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		INIT_DATA

초기화 동안만 필요한 변수와 관련 표를 .init.data에 수집합니다. 이들의 사용이 끝나야 초기화 영역 전체를 해제할 수 있습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

267행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과INIT_DATA
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		INIT_SETUP(16)

커널 명령행 옵션 처리기의 이름·함수 연결 정보를 16바이트 정렬로 모읍니다. 부팅 때 전달받은 옵션을 어느 함수가 처리할지 찾는 자료입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

268행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과INIT_SETUP(16)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		INIT_CALLS

등록된 초기화 함수 포인터를 단계별 순서로 모읍니다. 부팅 코드가 이 목록을 순회하여 서브시스템과 장치를 초기화하며, 링커 자체가 함수를 호출하지는 않습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

269행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과INIT_CALLS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		CON_INITCALL

초기 콘솔 초기화 함수 목록을 일반 initcall 목록과 구분해 모읍니다. 부팅 메시지를 출력할 콘솔을 준비하는 경로가 이 범위를 사용합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

270행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과CON_INITCALL
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		INIT_RAM_FS

빌드에 포함한 초기 루트 파일 시스템 initramfs 이미지와 정보를 모읍니다. 초기 사용자 공간을 준비할 때 풀어 사용할 자료이며, 해당 빌드 기능이 없으면 매크로가 비어 있습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

271행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과INIT_RAM_FS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.init.altinstructions .init.bss)	/* from the EFI stub */

EFI stub가 사용한 대체 명령 정보와 0 초기화 데이터를 커널 초기화 데이터 영역에 넣습니다. 영구 데이터로 남기지 않고 초기화 수명에 맞춰 함께 관리합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

272행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.init.altinstructions .init.bss)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.exit.data : {

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .exit.data : {

274행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.exit.data : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		EXIT_DATA

종료용 데이터를 링크 단계에서는 보존하되 초기화 후 해제할 범위에 둡니다. 위의 RUNTIME_DISCARD_EXIT 정책을 이 배치가 구현합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

275행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과EXIT_DATA
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	RUNTIME_CONST_VARIABLES

dentry 해시 표 포인터와 해시 시프트를 사용하는 명령 위치를 모읍니다. 값이 결정되면 ARM64 runtime-const 코드가 MOVZ/MOVK나 LSR의 즉시값을 고쳐 매번 변수를 읽는 대신 확정된 값을 사용할 수 있게 합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

278행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과RUNTIME_CONST_VARIABLES
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	PERCPU_SECTION(L1_CACHE_BYTES)

일반 커널의 CPU별 변수 원본을 모으고 캐시 라인 기준으로 하위 영역을 정렬합니다. 서로 다른 용도의 값이 불필요하게 같은 캐시 라인을 공유하는 것을 줄이려는 배치입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

280행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과PERCPU_SECTION(L1_CACHE_BYTES)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYPERVISOR_PERCPU_SECTION

KVM nVHE의 CPU별 변수 원본을 별도 페이지 정렬 영역에 둡니다. 일반 커널 percpu 범위와 하이퍼바이저용 범위를 섞지 않습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

281행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYPERVISOR_PERCPU_SECTION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYPERVISOR_RELOC_SECTION

nVHE 하이퍼바이저의 주소 보정 위치 목록을 배치합니다. 아래의 일반 커널 RELA·RELR 표와 별개의 대상입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

283행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYPERVISOR_RELOC_SECTION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.rela.dyn : ALIGN(8) {

명시적 덧셈값을 가진 ELF RELA 재배치 기록을 8바이트 정렬로 모읍니다. 초기 코드가 실제 커널 배치 주소에 맞게 주소를 보정할 때 사용합니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

285행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.rela.dyn : ALIGN(8) {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__pi_rela_start = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi_rela_start = .;

286행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_rela_start = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.rela .rela*)

입력 ELF의 RELA 재배치 기록을 모읍니다. __pi_rela_start부터 끝까지의 기록은 어느 위치의 주소를 어떻게 보정할지 초기 코드에 알려 줍니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

287행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.rela .rela*)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__pi_rela_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi_rela_end = .;

288행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_rela_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.relr.dyn : ALIGN(8) {

상대 재배치 정보를 압축한 RELR 표를 8바이트 정렬로 둡니다. 위의 RELA와 표현 방식이 달라 별도의 시작·끝 기호를 제공합니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

291행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.relr.dyn : ALIGN(8) {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__pi_relr_start = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi_relr_start = .;

292행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_relr_start = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.relr.dyn)

RELR 형식으로 표현된 주소 보정 위치들을 모읍니다. 기록을 해석하는 초기 코드가 한 항목 또는 비트맵이 가리키는 위치들의 주소를 보정합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

293행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.relr.dyn)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__pi_relr_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi_relr_end = .;

294행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_relr_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SEGMENT_ALIGN);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(SEGMENT_ALIGN);

297행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SEGMENT_ALIGN);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__initdata_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __initdata_end = .;

298행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__initdata_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__init_end = .;

초기화 코드·데이터·각종 부팅용 표가 끝나는 위치입니다. __init_begin부터 이 지점까지는 초기화 완료 후 해제할 수 있는 범위로 관리합니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

299행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__init_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

일반 데이터·BSS·초기 스택

원본 300–348행

	.data.rel.ro : { *(.data.rel.ro) }

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .data.rel.ro : { *(.data.rel.ro) }

301행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.data.rel.ro : { *(.data.rel.ro) }
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")

별도 처리되지 않은 .data.rel.ro가 남아 있지 않은지 검사합니다. 주소 재배치 후 읽기 전용으로 둘 데이터가 예상한 배치에서 빠지면 링크를 실패시켜 보호 범위가 어긋나는 것을 막습니다.

302행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	_data = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. _data = .;

304행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과_data = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	_sdata = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. _sdata = .;

305행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과_sdata = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)

초기값이 있는 쓰기 가능 데이터와 초기 태스크 스택 등을 모읍니다. 캐시 라인·페이지·스택 정렬을 각각 전달하여 서로 다른 정렬 요구를 맞춥니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

306행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HYPERVISOR_DATA_SECTION

nVHE 하이퍼바이저가 실행 중 수정할 초기값 있는 데이터를 별도 범위에 배치합니다. KVM이 꺼진 빌드에서는 아무 영역도 추가하지 않습니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

308행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HYPERVISOR_DATA_SECTION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.mmuoff.data.write : ALIGN(SZ_2K) {

MMU를 끈 상태에서 쓰는 데이터를 최대 Cache Writeback Granule에 맞춘 2KiB 경계로 분리합니다. 뒤의 캐시 무효화가 인접한 다른 데이터를 함께 버리지 않게 하려는 배치입니다. 링커가 정하는 섹션 배치와 CPU의 실제 접근 권한은 별개이며, 메모리 권한은 페이지 테이블 설정도 필요합니다.

318행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.mmuoff.data.write : ALIGN(SZ_2K) {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__mmuoff_data_start = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __mmuoff_data_start = .;

319행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__mmuoff_data_start = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.mmuoff.data.write)

MMU를 끈 초기 코드가 기록하는 boot_args 같은 .mmuoff.data.write 값을 모읍니다. MMU를 켠 뒤 읽을 때 캐시 정합성을 다뤄야 하므로 일반 데이터와 떨어뜨립니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

320행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.mmuoff.data.write)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SZ_2K);

MMU-off 쓰기 영역 뒤를 다시 2KiB 경계로 올립니다. 관련 캐시 유지보수로 영향을 받을 범위가 옆 영역과 섞이지 않도록 합니다. 여기서 .은 링커의 현재 배치 위치이며 CPU의 PC 레지스터가 아닙니다.

322행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SZ_2K);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.mmuoff.data.read : {

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .mmuoff.data.read : {

323행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.mmuoff.data.read : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.mmuoff.data.read)

MMU를 끈 CPU가 읽어야 하는 .mmuoff.data.read 데이터를 모읍니다. 앞의 쓰기 영역과 함께 전환 시점의 캐시 관리 대상 경계를 구성합니다. 앞의 *는 링크에 참여한 모든 입력 오브젝트에서 괄호 안 이름과 일치하는 섹션을 모으라는 뜻입니다.

324행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.mmuoff.data.read)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		__mmuoff_data_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __mmuoff_data_end = .;

325행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__mmuoff_data_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	PECOFF_EDATA_PADDING

EFI 빌드이면 PE/COFF가 요구하는 파일 정렬 padding을 여기 넣습니다. _edata와 데이터의 파일 크기를 계산하기 전에 길이를 맞춰야 합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

328행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과PECOFF_EDATA_PADDING
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);

PE/COFF 데이터 섹션이 파일에 실제로 차지하는 길이를 초기화 데이터 시작부터 계산합니다. 뒤의 BSS·초기 페이지 표·스택 등 메모리만 예약하는 부분은 아직 포함하지 않습니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

329행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	_edata = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. _edata = .;

330행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과_edata = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	BSS_SECTION(SBSS_ALIGN, 0, 0)

초기값이 0인 전역 변수들의 BSS 영역을 만듭니다. KVM이 켜진 빌드는 hyp BSS를 맨 앞에 놓고 SBSS_ALIGN을 사용해 시작 경계가 어긋나지 않게 합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

333행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과BSS_SECTION(SBSS_ALIGN, 0, 0)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pi___bss_start = __bss_start;

초기 위치 독립 코드가 BSS의 시작을 참조할 수 있도록 __pi_ 접두사의 별칭을 만듭니다. 별도 BSS를 다시 예약하는 것이 아니라 같은 주소를 가리킵니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

334행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi___bss_start = __bss_start;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(PAGE_SIZE);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(PAGE_SIZE);

336행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(PAGE_SIZE);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pi_init_pg_dir = .;

초기 커널 가상 주소 매핑을 만들 임시 페이지 표 공간의 시작입니다. 부팅 초기 C 코드가 이 범위를 표 저장소로 사용합니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

337행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_init_pg_dir = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. += INIT_DIR_SIZE;

커널 페이지 크기와 매핑 단계에 필요한 INIT_DIR_SIZE만큼 임시 페이지 표 공간을 예약합니다. 바로 앞 BSS와 함께 부팅 초기에 0으로 초기화할 범위에 들어갑니다. 링커의 현재 배치 위치를 옮겨 공간을 예약합니다. 부팅 중 동적 메모리를 할당하는 함수 호출이 아닙니다.

338행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. += INIT_DIR_SIZE;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pi_init_pg_end = .;

현재 위치나 계산한 값에 이름을 붙입니다. 이후 C나 어셈블리 코드가 이 심볼을 사용하면 같은 경계를 찾을 수 있습니다. __pi_init_pg_end = .;

339행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi_init_pg_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. += SZ_4K;		/* stack for the early C runtime */

MMU를 켜기 전 초기 C 함수가 사용할 스택 공간 4KiB를 예약합니다. 정식 태스크 스택이 준비되기 전에 함수 호출과 지역 변수를 보관할 공간입니다. 링커의 현재 배치 위치를 옮겨 공간을 예약합니다. 부팅 중 동적 메모리를 할당하는 함수 호출이 아닙니다.

342행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. += SZ_4K;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	early_init_stack = .;

방금 예약한 4KiB 공간의 높은 주소 쪽 끝을 초기 SP 값으로 지정합니다. AArch64 스택은 SP를 낮추며 사용하므로 head.S가 이 기호를 SP에 넣습니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

343행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과early_init_stack = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	. = ALIGN(SEGMENT_ALIGN);

링커가 다음 조각을 놓을 주소를 맞춥니다. ALIGN은 조건을 만족하는 다음 경계로 올리는 계산입니다. CPU 실행 중 PC를 수정하는 줄이 아닙니다. . = ALIGN(SEGMENT_ALIGN);

345행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과. = ALIGN(SEGMENT_ALIGN);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pecoff_data_size = ABSOLUTE(. - __initdata_begin);

PE/COFF 데이터 섹션이 메모리에서 필요한 전체 길이를 계산합니다. 파일에 저장된 데이터뿐 아니라 BSS와 초기 표·스택·정렬 공간까지 포함하므로 rawsize와 구분됩니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

346행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pecoff_data_size = ABSOLUTE(. - __initdata_begin);
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	_end = .;

커널 이미지가 메모리에서 차지하는 마지막 경계를 기록합니다. 뒤의 Image 헤더 크기 계산은 이 주소에서 _text를 뺍니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

347행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과_end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	__pi__end = .;

커널 끝 주소를 초기 위치 독립 코드도 참조할 수 있도록 __pi_ 이름으로 제공합니다. 이 줄이 메모리를 추가로 예약하지는 않습니다. 링크 단계에서 이 식의 값을 심벌에 부여합니다. 값을 저장할 런타임 변수를 따로 만드는 것은 아닙니다.

348행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과__pi__end = .;
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

심볼 보완과 링크 시 검사

원본 349–411행

	STABS_DEBUG

STABS 형식의 디버깅 정보를 ELF에 보존합니다. 실행할 커널 함수가 아니라 디버거가 소스·기호를 해석할 때 사용하는 메타데이터입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

350행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과STABS_DEBUG
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	DWARF_DEBUG

DWARF 형식의 소스 행·자료형·변수 위치 등 디버깅 정보를 ELF에 모읍니다. 커널 실행 순서를 추가하는 부분이 아닙니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

351행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과DWARF_DEBUG
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	MODINFO

오브젝트에 포함된 모듈 설명 정보를 .modinfo로 모읍니다. 일반 명령 본문이나 장치 초기화 함수 목록과 구분되는 메타데이터입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

352행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과MODINFO
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	ELF_DETAILS

ELF의 기호·문자열·섹션 이름 및 도구 설명 정보를 보존합니다. 실행 시 읽을 일반 커널 데이터 영역과 목적이 다른 파일 메타데이터입니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

353행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ELF_DETAILS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	HEAD_SYMBOLS

Image 헤더에 들어갈 전체 크기와 엔디언·페이지 크기 등의 플래그 값을 확정합니다. 링커만 알 수 있는 _end−_text를 계산하고 리틀 엔디언 필드로 표현합니다. 이는 공통 링커 스크립트 매크로를 펼쳐 섹션과 경계 심벌을 배치하는 과정입니다. CPU가 호출할 함수는 아닙니다.

355행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과HEAD_SYMBOLS
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	.plt : {

최종 이미지 안의 한 구역을 정의하고 그 안에 들어갈 조각을 지정합니다. 섹션 이름과 정렬은 파일 배치를 뜻하며 실제 CPU 접근 권한은 페이지 테이블 설정도 필요합니다. .plt : {

361행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과.plt : {
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

		*(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)

입력 파일들에서 괄호 안 이름 패턴과 맞는 조각을 모두 모읍니다. 파일 하나의 코드뿐 아니라 같은 종류의 여러 오브젝트 내용을 연결합니다. *(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)

362행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과*(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")

커널이 실행 중 외부 동적 링커에 의존하는 PLT 연결 코드가 생기지 않았는지 검사합니다. 예상 밖 연결이 있으면 단순히 버려 손상된 이미지를 만들지 않고 링크를 중단합니다.

364행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#include "image-vars.h"

섹션 주소가 확정된 뒤 EFI stub·초기 위치 독립 코드·KVM nVHE 코드가 사용할 심볼 별칭을 정의합니다. 서로 다른 접두사를 쓰는 코드가 허용된 커널 기호만 공유하도록 합니다. #include는 전처리 단계에서 헤더 내용을 가져옵니다. CPU가 이 줄에서 함수를 호출하는 동작은 없습니다.

367행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#include "image-vars.h"
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(__hyp_idmap_text_end - __hyp_idmap_text_start <= PAGE_SIZE,

EL2 초기 identity-mapped 코드 전체가 한 커널 페이지에 들어가는지 검사합니다. 해당 초기 매핑 크기로 감당하지 못하는 코드가 생성되면 링크를 중단합니다.

374행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(__hyp_idmap_text_end - __hyp_idmap_text_start <= PAGE_SIZE,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	"HYP init code too big")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "HYP init code too big")

375행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과"HYP init code too big")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,

일반 MMU 전환 코드가 정렬된 한 4KiB 범위 안에 들어가는지 검사합니다. 단순 길이뿐 아니라 시작 위치의 어긋남도 포함하여 페이지 경계를 넘는 것을 막습니다.

376행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	"ID map text too big or misaligned")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "ID map text too big or misaligned")

377행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과"ID map text too big or misaligned")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_HIBERNATION

최대절전 복원 코드를 포함한 빌드에서만 아래 크기·시작 주소 검사를 합니다. 기능을 끈 빌드에는 검사할 복원 코드 범위가 없습니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

378행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_HIBERNATION
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(__hibernate_exit_text_end - __hibernate_exit_text_start <= SZ_4K,

최대절전 복원의 마지막 전환 코드가 복사용 4KiB 범위에 들어가는지 확인합니다. 너무 커지면 부팅 가능한 커널 이미지로 링크하지 않습니다.

379행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(__hibernate_exit_text_end - __hibernate_exit_text_start <= SZ_4K,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

       "Hibernate exit text is bigger than 4 KiB")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "Hibernate exit text is bigger than 4 KiB")

380행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과"Hibernate exit text is bigger than 4 KiB")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(__hibernate_exit_text_start == swsusp_arch_suspend_exit,

복원용 코드 범위의 첫 명령이 swsusp_arch_suspend_exit인지 검사합니다. 범위의 시작 주소로 진입하는 코드가 다른 함수나 padding에 들어가는 것을 막습니다.

381행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(__hibernate_exit_text_start == swsusp_arch_suspend_exit,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

       "Hibernate exit text does not start with swsusp_arch_suspend_exit")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "Hibernate exit text does not start with swsusp_arch_suspend_exit")

382행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과"Hibernate exit text does not start with swsusp_arch_suspend_exit")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

383행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_HIBERNATION

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0

KPTI 진입 trampoline을 포함하는 빌드에서만 크기 제한을 검사합니다. 이 설정이 꺼져 있으면 별도 trampoline 섹션도 없습니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

384행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE,

KPTI trampoline의 실행 코드가 예약된 세 페이지 이내인지 확인합니다. entry.S의 여러 완화 방식별 벡터가 이 제한된 매핑 안에 들어가야 합니다.

385행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

	"Entry trampoline text too big")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "Entry trampoline text too big")

386행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과"Entry trampoline text too big")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

387행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_KVM

KVM을 빌드한 경우에만 hyp BSS와 호스트 BSS의 공동 시작 주소를 검증합니다. nVHE의 초기화·메모리 배치가 이 관계에 의존합니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

388행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_KVM
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned")

nVHE BSS가 전체 커널 BSS 맨 앞에서 시작하는지 확인합니다. 위의 BSS_FIRST_SECTIONS와 SBSS_ALIGN으로 의도한 배치가 링커 결과에서도 성립해야 합니다.

389행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

390행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KVM

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned")

Image 헤더의 시작 _text가 커널 기준 가상 주소와 정확히 같은지 검사합니다. 앞쪽에 뜻하지 않은 padding이 끼면 이미지 상대 오프셋을 이용한 물리·가상 주소 변환이 틀어집니다.

394행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(swapper_pg_dir - reserved_pg_dir == RESERVED_SWAPPER_OFFSET,

정상 커널 루트 표와 예약 루트 표의 실제 주소 차이가 어셈블리에서 사용하는 RESERVED_SWAPPER_OFFSET와 같은지 검사합니다. 표 전환의 주소 계산이 다른 데이터를 가리키는 것을 막습니다.

396행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(swapper_pg_dir - reserved_pg_dir == RESERVED_SWAPPER_OFFSET,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

       "RESERVED_SWAPPER_OFFSET is wrong!")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "RESERVED_SWAPPER_OFFSET is wrong!")

397행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과"RESERVED_SWAPPER_OFFSET is wrong!")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0

KPTI가 있는 빌드에서만 trampoline 루트 표와 정상 커널 루트 표 사이의 고정 거리도 검사합니다. 이 거리는 빠른 진입·복귀 표 전환에 사용됩니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

399행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET,

swapper와 trampoline 루트 표의 주소 차이가 TRAMP_SWAPPER_OFFSET와 일치하는지 확인합니다. entry.S의 덧셈·뺄셈으로 표를 바꾸는 코드와 링크 배치를 연결하는 검사입니다.

400행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

       "TRAMP_SWAPPER_OFFSET is wrong!")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "TRAMP_SWAPPER_OFFSET is wrong!")

401행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과"TRAMP_SWAPPER_OFFSET is wrong!")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

402행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_UNMAP_KERNEL_AT_EL0

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#ifdef CONFIG_KEXEC_CORE

kexec를 포함한 빌드에서만 새 커널 전환 코드의 크기·제어 페이지·진입 위치를 검증합니다. 꺼진 빌드에는 해당 코드가 없습니다. 이 조건은 빌드 전처리 단계에서 포함할 코드를 고릅니다. CPU가 실행 중 전처리 조건을 검사하지는 않습니다.

404행 그림 · 링크할 때의 배치
소스의 규칙
처리 전링크 전의 식
이 줄의 효과#ifdef CONFIG_KEXEC_CORE
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(__relocate_new_kernel_end - __relocate_new_kernel_start <= SZ_4K,

kexec 재배치 코드가 4KiB 안에 들어가는지 검사합니다. 현재 커널을 덮어쓰면서도 별도 제어 페이지에서 끝까지 실행할 수 있어야 합니다.

406행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(__relocate_new_kernel_end - __relocate_new_kernel_start <= SZ_4K,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

       "kexec relocation code is bigger than 4 KiB")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "kexec relocation code is bigger than 4 KiB")

407행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과"kexec relocation code is bigger than 4 KiB")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(KEXEC_CONTROL_PAGE_SIZE >= SZ_4K, "KEXEC_CONTROL_PAGE_SIZE is broken")

kexec 제어 페이지가 최소 4KiB인지를 확인합니다. 앞에서 허용한 재배치 코드 크기보다 실제 실행 공간이 작아지는 설정을 막습니다.

408행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(KEXEC_CONTROL_PAGE_SIZE >= SZ_4K, "KEXEC_CONTROL_PAGE_SIZE is broken")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

ASSERT(__relocate_new_kernel_start == arm64_relocate_new_kernel,

복사할 kexec 코드 범위가 arm64_relocate_new_kernel에서 시작하는지 확인합니다. 복사한 범위의 첫 주소로 진입했을 때 올바른 함수가 실행되어야 합니다.

409행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과ASSERT(__relocate_new_kernel_start == arm64_relocate_new_kernel,
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

       "kexec control page does not start with arm64_relocate_new_kernel")

바로 앞의 배치 검사가 실패했을 때 개발자에게 보여 줄 메시지입니다. "kexec control page does not start with arm64_relocate_new_kernel")

410행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과"kexec control page does not start with arm64_relocate_new_kernel")
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

#endif

빌드 조건으로 나누었던 구간을 닫습니다. 대상:

411행 그림 · 링크할 때의 배치

이 줄을 포함하는 조건: #ifdef CONFIG_KEXEC_CORE

소스의 규칙
처리 전링크 전의 식
이 줄의 효과#endif
CPU 레지스터
처리 전CPU 실행 전
이 줄의 효과이 줄은 실행 명령이 아닙니다.

→는 같은 항목의 처리 전과 후를 비교하는 표시입니다. 메모리 주소의 증가 방향이나 데이터 전송 경로를 뜻하지 않습니다.

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

점(.)을 늘리면 부팅 중 CPU가 메모리를 할당하나요?

아닙니다. 링크 단계의 출력 배치에 공간을 예약합니다. CPU의 동적 메모리 할당과는 다릅니다.

BSS를 0으로 지울 때 초기 C 스택도 지워지나요?

이 배치에서는 init_pg_end 뒤에 초기 스택을 둡니다. 해당 0 초기화 범위에 들어 있지 않습니다.

idmap 코드 크기를 ASSERT로 검사하는 이유는 무엇인가요?

실행 시 준비된 매핑 범위 안에 코드가 들어간다는 가정을 빌드 단계에서 확인하기 위해서입니다.

주석을 포함한 전체 원문

Linux stable v6.18.37 · arch/arm64/kernel/vmlinux.lds.S

1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * ld script to make ARM Linux kernel4 * taken from the i386 version by Russell King5 * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>6 */78#include <asm/hyp_image.h>9#ifdef CONFIG_KVM10#define HYPERVISOR_EXTABLE					\11	. = ALIGN(SZ_8);					\12	__start___kvm_ex_table = .;				\13	*(__kvm_ex_table)					\14	__stop___kvm_ex_table = .;1516#define HYPERVISOR_RODATA_SECTIONS				\17	HYP_SECTION_NAME(.rodata) : {				\18		. = ALIGN(PAGE_SIZE);				\19		__hyp_rodata_start = .;				\20		*(HYP_SECTION_NAME(.data..ro_after_init))	\21		*(HYP_SECTION_NAME(.rodata))			\22		. = ALIGN(PAGE_SIZE);				\23		__hyp_rodata_end = .;				\24	}2526#define HYPERVISOR_DATA_SECTION					\27	HYP_SECTION_NAME(.data) : {				\28		. = ALIGN(PAGE_SIZE);				\29		__hyp_data_start = .;				\30		*(HYP_SECTION_NAME(.data))			\31		. = ALIGN(PAGE_SIZE);				\32		__hyp_data_end = .;				\33	}3435#define HYPERVISOR_PERCPU_SECTION				\36	. = ALIGN(PAGE_SIZE);					\37	HYP_SECTION_NAME(.data..percpu) : {			\38		*(HYP_SECTION_NAME(.data..percpu))		\39	}4041#define HYPERVISOR_RELOC_SECTION				\42	.hyp.reloc : ALIGN(4) {					\43		__hyp_reloc_begin = .;				\44		*(.hyp.reloc)					\45		__hyp_reloc_end = .;				\46	}4748#define BSS_FIRST_SECTIONS					\49	__hyp_bss_start = .;					\50	*(HYP_SECTION_NAME(.bss))				\51	. = ALIGN(PAGE_SIZE);					\52	__hyp_bss_end = .;5354/*55 * We require that __hyp_bss_start and __bss_start are aligned, and enforce it56 * with an assertion. But the BSS_SECTION macro places an empty .sbss section57 * between them, which can in some cases cause the linker to misalign them. To58 * work around the issue, force a page alignment for __bss_start.59 */60#define SBSS_ALIGN			PAGE_SIZE61#else /* CONFIG_KVM */62#define HYPERVISOR_EXTABLE63#define HYPERVISOR_RODATA_SECTIONS64#define HYPERVISOR_DATA_SECTION65#define HYPERVISOR_PERCPU_SECTION66#define HYPERVISOR_RELOC_SECTION67#define SBSS_ALIGN			068#endif6970#define RO_EXCEPTION_TABLE_ALIGN	471#define RUNTIME_DISCARD_EXIT7273#include <asm-generic/vmlinux.lds.h>74#include <asm/cache.h>75#include <asm/kernel-pgtable.h>76#include <asm/kexec.h>77#include <asm/memory.h>78#include <asm/page.h>7980#include "image.h"8182OUTPUT_ARCH(aarch64)83ENTRY(_text)8485jiffies = jiffies_64;8687#define HYPERVISOR_TEXT					\88	. = ALIGN(PAGE_SIZE);				\89	__hyp_idmap_text_start = .;			\90	*(.hyp.idmap.text)				\91	__hyp_idmap_text_end = .;			\92	__hyp_text_start = .;				\93	*(.hyp.text)					\94	HYPERVISOR_EXTABLE				\95	. = ALIGN(PAGE_SIZE);				\96	__hyp_text_end = .;9798#define IDMAP_TEXT					\99	. = ALIGN(SZ_4K);				\100	__idmap_text_start = .;				\101	*(.idmap.text)					\102	__idmap_text_end = .;103104#ifdef CONFIG_HIBERNATION105#define HIBERNATE_TEXT					\106	ALIGN_FUNCTION();				\107	__hibernate_exit_text_start = .;		\108	*(.hibernate_exit.text)				\109	__hibernate_exit_text_end = .;110#else111#define HIBERNATE_TEXT112#endif113114#ifdef CONFIG_KEXEC_CORE115#define KEXEC_TEXT					\116	ALIGN_FUNCTION();				\117	__relocate_new_kernel_start = .;		\118	*(.kexec_relocate.text)				\119	__relocate_new_kernel_end = .;120#else121#define KEXEC_TEXT122#endif123124#ifdef CONFIG_UNMAP_KERNEL_AT_EL0125#define TRAMP_TEXT					\126	. = ALIGN(PAGE_SIZE);				\127	__entry_tramp_text_start = .;			\128	*(.entry.tramp.text)				\129	. = ALIGN(PAGE_SIZE);				\130	__entry_tramp_text_end = .;			\131	*(.entry.tramp.rodata)132#else133#define TRAMP_TEXT134#endif135136#ifdef CONFIG_UNWIND_TABLES137#define UNWIND_DATA_SECTIONS				\138	.eh_frame : {					\139		__pi___eh_frame_start = .;		\140		*(.eh_frame)				\141		__pi___eh_frame_end = .;		\142	}143#else144#define UNWIND_DATA_SECTIONS145#endif146147/*148 * The size of the PE/COFF section that covers the kernel image, which149 * runs from _stext to _edata, must be a round multiple of the PE/COFF150 * FileAlignment, which we set to its minimum value of 0x200. '_stext'151 * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned152 * boundary should be sufficient.153 */154PECOFF_FILE_ALIGNMENT = 0x200;155156#ifdef CONFIG_EFI157#define PECOFF_EDATA_PADDING	\158	.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }159#else160#define PECOFF_EDATA_PADDING161#endif162163SECTIONS164{165	/*166	 * XXX: The linker does not define how output sections are167	 * assigned to input sections when there are multiple statements168	 * matching the same input section name.  There is no documented169	 * order of matching.170	 */171	DISCARDS172	/DISCARD/ : {173		*(.interp .dynamic)174		*(.dynsym .dynstr .hash .gnu.hash)175		*(.ARM.attributes)176	}177178	. = KIMAGE_VADDR;179180	.head.text : {181		_text = .;182		HEAD_TEXT183	}184	.text : ALIGN(SEGMENT_ALIGN) {	/* Real text segment		*/185		_stext = .;		/* Text and read-only data	*/186			IRQENTRY_TEXT187			SOFTIRQENTRY_TEXT188			ENTRY_TEXT189			TEXT_TEXT190			SCHED_TEXT191			LOCK_TEXT192			KPROBES_TEXT193			HYPERVISOR_TEXT194			*(.gnu.warning)195	}196197	. = ALIGN(SEGMENT_ALIGN);198	_etext = .;			/* End of text section */199200	/* everything from this point to __init_begin will be marked RO NX */201	RO_DATA(PAGE_SIZE)202203	HYPERVISOR_RODATA_SECTIONS204205	.got : { *(.got) }206	/*207	 * Make sure that the .got.plt is either completely empty or it208	 * contains only the lazy dispatch entries.209	 */210	.got.plt : { *(.got.plt) }211	ASSERT(SIZEOF(.got.plt) == 0 || SIZEOF(.got.plt) == 0x18,212	       "Unexpected GOT/PLT entries detected!")213214	/* code sections that are never executed via the kernel mapping */215	.rodata.text : {216		TRAMP_TEXT217		HIBERNATE_TEXT218		KEXEC_TEXT219		IDMAP_TEXT220		. = ALIGN(PAGE_SIZE);221	}222223	idmap_pg_dir = .;224	. += PAGE_SIZE;225226#ifdef CONFIG_UNMAP_KERNEL_AT_EL0227	tramp_pg_dir = .;228	. += PAGE_SIZE;229#endif230231	reserved_pg_dir = .;232	. += PAGE_SIZE;233234	swapper_pg_dir = .;235	. += PAGE_SIZE;236237	. = ALIGN(SEGMENT_ALIGN);238	__init_begin = .;239	__inittext_begin = .;240241	INIT_TEXT_SECTION(8)242243	__exittext_begin = .;244	.exit.text : {245		EXIT_TEXT246	}247	__exittext_end = .;248249	. = ALIGN(4);250	.altinstructions : {251		__alt_instructions = .;252		*(.altinstructions)253		__alt_instructions_end = .;254	}255256	UNWIND_DATA_SECTIONS257258	. = ALIGN(SEGMENT_ALIGN);259	__inittext_end = .;260	__initdata_begin = .;261262	__pi_init_idmap_pg_dir = .;263	. += INIT_IDMAP_DIR_SIZE;264	__pi_init_idmap_pg_end = .;265266	.init.data : {267		INIT_DATA268		INIT_SETUP(16)269		INIT_CALLS270		CON_INITCALL271		INIT_RAM_FS272		*(.init.altinstructions .init.bss)	/* from the EFI stub */273	}274	.exit.data : {275		EXIT_DATA276	}277278	RUNTIME_CONST_VARIABLES279280	PERCPU_SECTION(L1_CACHE_BYTES)281	HYPERVISOR_PERCPU_SECTION282283	HYPERVISOR_RELOC_SECTION284285	.rela.dyn : ALIGN(8) {286		__pi_rela_start = .;287		*(.rela .rela*)288		__pi_rela_end = .;289	}290291	.relr.dyn : ALIGN(8) {292		__pi_relr_start = .;293		*(.relr.dyn)294		__pi_relr_end = .;295	}296297	. = ALIGN(SEGMENT_ALIGN);298	__initdata_end = .;299	__init_end = .;300301	.data.rel.ro : { *(.data.rel.ro) }302	ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")303304	_data = .;305	_sdata = .;306	RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)307308	HYPERVISOR_DATA_SECTION309310	/*311	 * Data written with the MMU off but read with the MMU on requires312	 * cache lines to be invalidated, discarding up to a Cache Writeback313	 * Granule (CWG) of data from the cache. Keep the section that314	 * requires this type of maintenance to be in its own Cache Writeback315	 * Granule (CWG) area so the cache maintenance operations don't316	 * interfere with adjacent data.317	 */318	.mmuoff.data.write : ALIGN(SZ_2K) {319		__mmuoff_data_start = .;320		*(.mmuoff.data.write)321	}322	. = ALIGN(SZ_2K);323	.mmuoff.data.read : {324		*(.mmuoff.data.read)325		__mmuoff_data_end = .;326	}327328	PECOFF_EDATA_PADDING329	__pecoff_data_rawsize = ABSOLUTE(. - __initdata_begin);330	_edata = .;331332	/* start of zero-init region */333	BSS_SECTION(SBSS_ALIGN, 0, 0)334	__pi___bss_start = __bss_start;335336	. = ALIGN(PAGE_SIZE);337	__pi_init_pg_dir = .;338	. += INIT_DIR_SIZE;339	__pi_init_pg_end = .;340	/* end of zero-init region */341342	. += SZ_4K;		/* stack for the early C runtime */343	early_init_stack = .;344345	. = ALIGN(SEGMENT_ALIGN);346	__pecoff_data_size = ABSOLUTE(. - __initdata_begin);347	_end = .;348	__pi__end = .;349350	STABS_DEBUG351	DWARF_DEBUG352	MODINFO353	ELF_DETAILS354355	HEAD_SYMBOLS356357	/*358	 * Sections that should stay zero sized, which is safer to359	 * explicitly check instead of blindly discarding.360	 */361	.plt : {362		*(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)363	}364	ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")365}366367#include "image-vars.h"368369/*370 * The HYP init code and ID map text can't be longer than a page each. The371 * former is page-aligned, but the latter may not be with 16K or 64K pages, so372 * it should also not cross a page boundary.373 */374ASSERT(__hyp_idmap_text_end - __hyp_idmap_text_start <= PAGE_SIZE,375	"HYP init code too big")376ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,377	"ID map text too big or misaligned")378#ifdef CONFIG_HIBERNATION379ASSERT(__hibernate_exit_text_end - __hibernate_exit_text_start <= SZ_4K,380       "Hibernate exit text is bigger than 4 KiB")381ASSERT(__hibernate_exit_text_start == swsusp_arch_suspend_exit,382       "Hibernate exit text does not start with swsusp_arch_suspend_exit")383#endif384#ifdef CONFIG_UNMAP_KERNEL_AT_EL0385ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE,386	"Entry trampoline text too big")387#endif388#ifdef CONFIG_KVM389ASSERT(__hyp_bss_start == __bss_start, "HYP and Host BSS are misaligned")390#endif391/*392 * If padding is applied before .head.text, virt<->phys conversions will fail.393 */394ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned")395396ASSERT(swapper_pg_dir - reserved_pg_dir == RESERVED_SWAPPER_OFFSET,397       "RESERVED_SWAPPER_OFFSET is wrong!")398399#ifdef CONFIG_UNMAP_KERNEL_AT_EL0400ASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET,401       "TRAMP_SWAPPER_OFFSET is wrong!")402#endif403404#ifdef CONFIG_KEXEC_CORE405/* kexec relocation code should fit into one KEXEC_CONTROL_PAGE_SIZE */406ASSERT(__relocate_new_kernel_end - __relocate_new_kernel_start <= SZ_4K,407       "kexec relocation code is bigger than 4 KiB")408ASSERT(KEXEC_CONTROL_PAGE_SIZE >= SZ_4K, "KEXEC_CONTROL_PAGE_SIZE is broken")409ASSERT(__relocate_new_kernel_start == arm64_relocate_new_kernel,410       "kexec control page does not start with arm64_relocate_new_kernel")411#endif
맨 위로 ↑