← Documents Documentation/core-api/asm-annotations.rst GitHub 원문 ↗

Linux 6.18.37 · Core API

Assembler Annotations

assembly code와 data symbol의 type, size, linkage를 정확히 표현하는 SYM_FUNC, SYM_CODE, SYM_DATA macro 규약을 설명합니다.

Source pathDocumentation/core-api/asm-annotations.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

asm-annotations.rst:1-222

`SYM_FUNC_*`, `SYM_CODE_*`, `SYM_DATA*`는 표준 function, 특수 calling convention code, data를 구분해 ELF symbol type과 size를 정확히 만듭니다.

정확한 annotation은 debugger뿐 아니라 `objtool`, ORC unwinder, 신뢰 가능한 stack trace와 kernel live patching의 기반이 됩니다.

각 START macro는 대응 END macro와 짝지어야 하고, architecture는 `asm/linkage.h`에서 기본 macro와 symbol type을 override할 수 있습니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 Assembler Annotations
2 =====================
3
4 Copyright (c) 2017-2019 Jiri Slaby
5
6 This document describes the new macros for annotation of data and code in
7 assembly. In particular, it contains information about ``SYM_FUNC_START``,
8 ``SYM_FUNC_END``, ``SYM_CODE_START``, and similar.
9
10 Rationale
11 ---------
12 Some code like entries, trampolines, or boot code needs to be written in
13 assembly. The same as in C, such code is grouped into functions and
14 accompanied with data. Standard assemblers do not force users into precisely
15 marking these pieces as code, data, or even specifying their length.
16 Nevertheless, assemblers provide developers with such annotations to aid
17 debuggers throughout assembly. On top of that, developers also want to mark
18 some functions as *global* in order to be visible outside of their translation
19 units.
20
21 Over time, the Linux kernel has adopted macros from various projects (like
22 ``binutils``) to facilitate such annotations. So for historic reasons,
23 developers have been using ``ENTRY``, ``END``, ``ENDPROC``, and other
24 annotations in assembly. Due to the lack of their documentation, the macros
25 are used in rather wrong contexts at some locations. Clearly, ``ENTRY`` was
26 intended to denote the beginning of global symbols (be it data or code).
27 ``END`` used to mark the end of data or end of special functions with
28 *non-standard* calling convention. In contrast, ``ENDPROC`` should annotate
29 only ends of *standard* functions.
30
31 When these macros are used correctly, they help assemblers generate a nice
32 object with both sizes and types set correctly. For example, the result of
33 ``arch/x86/lib/putuser.S``::
34
35 Num: Value Size Type Bind Vis Ndx Name
36 25: 0000000000000000 33 FUNC GLOBAL DEFAULT 1 __put_user_1
37 29: 0000000000000030 37 FUNC GLOBAL DEFAULT 1 __put_user_2
38 32: 0000000000000060 36 FUNC GLOBAL DEFAULT 1 __put_user_4
39 35: 0000000000000090 37 FUNC GLOBAL DEFAULT 1 __put_user_8
40
41 This is not only important for debugging purposes. When there are properly
42 annotated objects like this, tools can be run on them to generate more useful
43 information. In particular, on properly annotated objects, ``objtool`` can be
44 run to check and fix the object if needed. Currently, ``objtool`` can report
45 missing frame pointer setup/destruction in functions. It can also
46 automatically generate annotations for the ORC unwinder
47 (Documentation/arch/x86/orc-unwinder.rst)
48 for most code. Both of these are especially important to support reliable
49 stack traces which are in turn necessary for kernel live patching
50 (Documentation/livepatch/livepatch.rst).
51
52 Caveat and Discussion
53 ---------------------
54 As one might realize, there were only three macros previously. That is indeed
55 insufficient to cover all the combinations of cases:
56
57 * standard/non-standard function
58 * code/data
59 * global/local symbol
60
61 There was a discussion_ and instead of extending the current ``ENTRY/END*``
62 macros, it was decided that brand new macros should be introduced instead::
63
64 So how about using macro names that actually show the purpose, instead
65 of importing all the crappy, historic, essentially randomly chosen
66 debug symbol macro names from the binutils and older kernels?
67
68 .. _discussion: https://lore.kernel.org/r/20170217104757.28588-1-jslaby@suse.cz
69
70 Macros Description
71 ------------------
72
73 The new macros are prefixed with the ``SYM_`` prefix and can be divided into
74 three main groups:
75
76 1. ``SYM_FUNC_*`` -- to annotate C-like functions. This means functions with
77 standard C calling conventions. For example, on x86, this means that the
78 stack contains a return address at the predefined place and a return from
79 the function can happen in a standard way. When frame pointers are enabled,
80 save/restore of frame pointer shall happen at the start/end of a function,
81 respectively, too.
82
83 Checking tools like ``objtool`` should ensure such marked functions conform
84 to these rules. The tools can also easily annotate these functions with
85 debugging information (like *ORC data*) automatically.
86
87 2. ``SYM_CODE_*`` -- special functions called with special stack. Be it
88 interrupt handlers with special stack content, trampolines, or startup
89 functions.
90
91 Checking tools mostly ignore checking of these functions. But some debug
92 information still can be generated automatically. For correct debug data,
93 this code needs hints like ``UNWIND_HINT_REGS`` provided by developers.
94
95 3. ``SYM_DATA*`` -- obviously data belonging to ``.data`` sections and not to
96 ``.text``. Data do not contain instructions, so they have to be treated
97 specially by the tools: they should not treat the bytes as instructions,
98 nor assign any debug information to them.
99
100 Instruction Macros
101 ~~~~~~~~~~~~~~~~~~
102 This section covers ``SYM_FUNC_*`` and ``SYM_CODE_*`` enumerated above.
103
104 ``objtool`` requires that all code must be contained in an ELF symbol. Symbol
105 names that have a ``.L`` prefix do not emit symbol table entries. ``.L``
106 prefixed symbols can be used within a code region, but should be avoided for
107 denoting a range of code via ``SYM_*_START/END`` annotations.
108
109 * ``SYM_FUNC_START`` and ``SYM_FUNC_START_LOCAL`` are supposed to be **the
110 most frequent markings**. They are used for functions with standard calling
111 conventions -- global and local. Like in C, they both align the functions to
112 architecture specific ``__ALIGN`` bytes. There are also ``_NOALIGN`` variants
113 for special cases where developers do not want this implicit alignment.
114
115 ``SYM_FUNC_START_WEAK`` and ``SYM_FUNC_START_WEAK_NOALIGN`` markings are
116 also offered as an assembler counterpart to the *weak* attribute known from
117 C.
118
119 All of these **shall** be coupled with ``SYM_FUNC_END``. First, it marks
120 the sequence of instructions as a function and computes its size to the
121 generated object file. Second, it also eases checking and processing such
122 object files as the tools can trivially find exact function boundaries.
123
124 So in most cases, developers should write something like in the following
125 example, having some asm instructions in between the macros, of course::
126
127 SYM_FUNC_START(memset)
128 ... asm insns ...
129 SYM_FUNC_END(memset)
130
131 In fact, this kind of annotation corresponds to the now deprecated ``ENTRY``
132 and ``ENDPROC`` macros.
133
134 * ``SYM_FUNC_ALIAS``, ``SYM_FUNC_ALIAS_LOCAL``, and ``SYM_FUNC_ALIAS_WEAK`` can
135 be used to define multiple names for a function. The typical use is::
136
137 SYM_FUNC_START(__memset)
138 ... asm insns ...
139 SYN_FUNC_END(__memset)
140 SYM_FUNC_ALIAS(memset, __memset)
141
142 In this example, one can call ``__memset`` or ``memset`` with the same
143 result, except the debug information for the instructions is generated to
144 the object file only once -- for the non-``ALIAS`` case.
145
146 * ``SYM_CODE_START`` and ``SYM_CODE_START_LOCAL`` should be used only in
147 special cases -- if you know what you are doing. This is used exclusively
148 for interrupt handlers and similar where the calling convention is not the C
149 one. ``_NOALIGN`` variants exist too. The use is the same as for the ``FUNC``
150 category above::
151
152 SYM_CODE_START_LOCAL(bad_put_user)
153 ... asm insns ...
154 SYM_CODE_END(bad_put_user)
155
156 Again, every ``SYM_CODE_START*`` **shall** be coupled by ``SYM_CODE_END``.
157
158 To some extent, this category corresponds to deprecated ``ENTRY`` and
159 ``END``. Except ``END`` had several other meanings too.
160
161 * ``SYM_INNER_LABEL*`` is used to denote a label inside some
162 ``SYM_{CODE,FUNC}_START`` and ``SYM_{CODE,FUNC}_END``. They are very similar
163 to C labels, except they can be made global. An example of use::
164
165 SYM_CODE_START(ftrace_caller)
166 /* save_mcount_regs fills in first two parameters */
167 ...
168
169 SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL)
170 /* Load the ftrace_ops into the 3rd parameter */
171 ...
172
173 SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
174 call ftrace_stub
175 ...
176 retq
177 SYM_CODE_END(ftrace_caller)
178
179 Data Macros
180 ~~~~~~~~~~~
181 Similar to instructions, there is a couple of macros to describe data in the
182 assembly.
183
184 * ``SYM_DATA_START`` and ``SYM_DATA_START_LOCAL`` mark the start of some data
185 and shall be used in conjunction with either ``SYM_DATA_END``, or
186 ``SYM_DATA_END_LABEL``. The latter adds also a label to the end, so that
187 people can use ``lstack`` and (local) ``lstack_end`` in the following
188 example::
189
190 SYM_DATA_START_LOCAL(lstack)
191 .skip 4096
192 SYM_DATA_END_LABEL(lstack, SYM_L_LOCAL, lstack_end)
193
194 * ``SYM_DATA`` and ``SYM_DATA_LOCAL`` are variants for simple, mostly one-line
195 data::
196
197 SYM_DATA(HEAP, .long rm_heap)
198 SYM_DATA(heap_end, .long rm_stack)
199
200 In the end, they expand to ``SYM_DATA_START`` with ``SYM_DATA_END``
201 internally.
202
203 Support Macros
204 ~~~~~~~~~~~~~~
205 All the above reduce themselves to some invocation of ``SYM_START``,
206 ``SYM_END``, or ``SYM_ENTRY`` at last. Normally, developers should avoid using
207 these.
208
209 Further, in the above examples, one could see ``SYM_L_LOCAL``. There are also
210 ``SYM_L_GLOBAL`` and ``SYM_L_WEAK``. All are intended to denote linkage of a
211 symbol marked by them. They are used either in ``_LABEL`` variants of the
212 earlier macros, or in ``SYM_START``.
213
214
215 Overriding Macros
216 ~~~~~~~~~~~~~~~~~
217 Architecture can also override any of the macros in their own
218 ``asm/linkage.h``, including macros specifying the type of a symbol
219 (``SYM_T_FUNC``, ``SYM_T_OBJECT``, and ``SYM_T_NONE``). As every macro
220 described in this file is surrounded by ``#ifdef`` + ``#endif``, it is enough
221 to define the macros differently in the aforementioned architecture-dependent
222 header.
223

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Assembler annotation macro 개요

1-9

`Assembler Annotations` 문서는 Jiri Slaby가 2017-2019년에 저작했으며 assembly의 data와 code를 표시하는 새 macro를 설명합니다.

중심 대상은 `SYM_FUNC_START`, `SYM_FUNC_END`, `SYM_CODE_START`와 그와 비슷한 annotation macro입니다.

정확한 code·data symbol annotation이 필요한 이유

10-50

entry, trampoline, boot code 같은 일부 code는 assembly로 작성해야 합니다. C와 마찬가지로 function과 data로 구성되지만 표준 assembler는 각 조각을 code 또는 data로 정확히 표시하거나 길이를 지정하도록 강제하지 않습니다.

assembler annotation은 debugger가 assembly를 이해하도록 돕고, translation unit 밖에서 보여야 하는 function을 global symbol로 표시할 수 있게 합니다.

Linux kernel은 역사적으로 `binutils` 같은 여러 project의 macro를 받아들여 `ENTRY`, `END`, `ENDPROC` 등을 사용했습니다. 문서가 부족해 잘못된 context에 쓰인 경우도 있습니다. `ENTRY`는 data든 code든 global symbol 시작, `END`는 data 또는 비표준 calling convention function의 끝, `ENDPROC`는 표준 function의 끝을 나타내는 의도였습니다.

올바른 annotation을 사용하면 assembler가 size와 type이 정확한 object를 생성합니다. `arch/x86/lib/putuser.S` 결과의 symbol table은 다음과 같습니다.

Num:    Value          Size Type    Bind   Vis      Ndx Name
 25: 0000000000000000    33 FUNC    GLOBAL DEFAULT    1 __put_user_1
 29: 0000000000000030    37 FUNC    GLOBAL DEFAULT    1 __put_user_2
 32: 0000000000000060    36 FUNC    GLOBAL DEFAULT    1 __put_user_4
 35: 0000000000000090    37 FUNC    GLOBAL DEFAULT    1 __put_user_8

이는 debugging 외에도 중요합니다. 정확히 annotation된 object에는 `objtool`을 실행해 검사하고 필요하면 수정할 수 있습니다. 현재 `objtool`은 function에서 frame pointer 설정·해제 누락을 보고하고 대부분의 code에 ORC unwinder용 annotation을 자동 생성합니다.

이 정보는 신뢰할 수 있는 stack trace를 지원하며, 이는 다시 kernel live patching에 필요합니다. 관련 문서는 `Documentation/arch/x86/orc-unwinder.rst`와 `Documentation/livepatch/livepatch.rst`입니다.

기존 macro의 한계와 새 이름

51-69

기존 macro 세 개만으로는 standard/non-standard function, code/data, global/local symbol의 모든 조합을 표현할 수 없습니다.

  • standard function과 non-standard function
  • code와 data
  • global symbol과 local symbol

논의 결과 기존 `ENTRY/END*`를 확장하는 대신 목적이 이름에 드러나는 완전히 새로운 macro를 도입하기로 했습니다.

So how about using macro names that actually show the purpose, instead
of importing all the crappy, historic, essentially randomly chosen
debug symbol macro names from the binutils and older kernels?

논의 thread는 https://lore.kernel.org/r/20170217104757.28588-1-jslaby@suse.cz 에서 확인할 수 있습니다.

SYM_ macro의 세 그룹

70-99

새 macro는 `SYM_` prefix를 사용하며 세 그룹으로 나뉩니다.

그룹대상tool 처리
SYM_FUNC_*표준 C calling convention functionobjtool이 규약을 검사하고 ORC data 같은 debug 정보를 자동 생성
SYM_CODE_*interrupt handler, trampoline, startup처럼 특수 stack과 calling convention을 쓰는 code대부분 검사를 생략하되 `UNWIND_HINT_REGS` 같은 hint로 debug data 생성
SYM_DATA*`.text`가 아닌 `.data` section의 databyte를 instruction으로 보거나 debug 정보를 붙이지 않음

x86의 `SYM_FUNC_*`는 정해진 위치에 return address가 있고 표준 방식으로 return할 수 있어야 합니다. frame pointer가 활성화되어 있으면 function 시작과 끝에서 각각 저장하고 복원해야 합니다.

`SYM_CODE_*`는 특수 stack content를 가진 interrupt handler, trampoline, startup function에 사용합니다. 정확한 debug data를 위해 개발자가 `UNWIND_HINT_REGS` 같은 hint를 제공해야 할 수 있습니다.

`SYM_DATA*`는 instruction이 없는 data를 명시하므로 tool이 해당 byte를 code로 해석하거나 debug annotation을 부여해서는 안 됩니다.

SYM_FUNC_START, END와 alias

100-145

`objtool`은 모든 code가 ELF symbol 안에 있어야 한다고 요구합니다. `.L` prefix symbol은 symbol table entry를 만들지 않으므로 code region 내부 label에는 쓸 수 있지만 `SYM_*_START/END`로 code 범위를 나타내는 데는 피해야 합니다.

`SYM_FUNC_START`와 `SYM_FUNC_START_LOCAL`은 가장 흔한 표시이며 각각 global·local 표준 calling convention function에 사용합니다. C와 마찬가지로 architecture-specific `__ALIGN` byte에 맞추며 implicit alignment가 필요 없는 특수 경우에는 `_NOALIGN` variant를 사용합니다.

`SYM_FUNC_START_WEAK`와 `SYM_FUNC_START_WEAK_NOALIGN`은 C의 weak attribute에 대응합니다.

모든 start macro는 `SYM_FUNC_END`와 짝지어야 합니다. instruction sequence를 function으로 표시하고 object file에 size를 계산하며, tool이 정확한 function boundary를 쉽게 찾아 검사·처리할 수 있게 합니다.

SYM_FUNC_START(memset)
    ... asm insns ...
SYM_FUNC_END(memset)

이 annotation 조합은 이제 deprecated인 `ENTRY`와 `ENDPROC`에 대응합니다.

`SYM_FUNC_ALIAS`, `SYM_FUNC_ALIAS_LOCAL`, `SYM_FUNC_ALIAS_WEAK`는 function에 여러 이름을 정의할 때 사용합니다.

SYM_FUNC_START(__memset)
    ... asm insns ...
SYN_FUNC_END(__memset)
SYM_FUNC_ALIAS(memset, __memset)

예에서는 `__memset`과 `memset` 어느 이름으로 호출해도 결과가 같지만 instruction의 debug information은 non-ALIAS인 `__memset`에 대해 한 번만 object file에 생성됩니다.

특수 code와 inner label

146-178

`SYM_CODE_START`와 `SYM_CODE_START_LOCAL`은 C calling convention이 아닌 interrupt handler 같은 특수 경우에만 사용해야 합니다. `_NOALIGN` variant도 있으며 FUNC category와 같은 방식으로 씁니다.

SYM_CODE_START_LOCAL(bad_put_user)
    ... asm insns ...
SYM_CODE_END(bad_put_user)

모든 `SYM_CODE_START*`는 반드시 `SYM_CODE_END`와 짝지어야 합니다. 어느 정도 deprecated `ENTRY`와 `END`에 대응하지만, 과거 `END`에는 다른 의미도 있었습니다.

`SYM_INNER_LABEL*`은 `SYM_{CODE,FUNC}_START`와 `SYM_{CODE,FUNC}_END` 사이의 label을 표시합니다. C label과 비슷하지만 global로 만들 수 있습니다.

SYM_CODE_START(ftrace_caller)
    /* save_mcount_regs fills in first two parameters */
    ...

SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL)
    /* Load the ftrace_ops into the 3rd parameter */
    ...

SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
    call ftrace_stub
    ...
    retq
SYM_CODE_END(ftrace_caller)

예에서 `ftrace_caller_op_ptr`와 `ftrace_call`은 `SYM_L_GLOBAL` linkage를 가진 내부 label입니다.

assembly data macro

179-202

`SYM_DATA_START`와 `SYM_DATA_START_LOCAL`은 data 시작을 표시하며 `SYM_DATA_END` 또는 끝 label까지 추가하는 `SYM_DATA_END_LABEL`과 함께 사용해야 합니다.

SYM_DATA_START_LOCAL(lstack)
    .skip 4096
SYM_DATA_END_LABEL(lstack, SYM_L_LOCAL, lstack_end)

위 예에서는 `lstack`과 local `lstack_end`를 모두 참조할 수 있습니다.

`SYM_DATA`와 `SYM_DATA_LOCAL`은 주로 한 줄짜리 단순 data를 위한 variant입니다.

SYM_DATA(HEAP,     .long rm_heap)
SYM_DATA(heap_end, .long rm_stack)

이 macro는 내부적으로 `SYM_DATA_START`와 `SYM_DATA_END` 조합으로 확장됩니다.

support macro, linkage와 architecture override

203-222

앞의 모든 macro는 최종적으로 `SYM_START`, `SYM_END`, `SYM_ENTRY` 호출로 축약됩니다. 일반 개발자는 이 저수준 macro를 직접 사용하지 않는 편이 좋습니다.

`SYM_L_LOCAL`, `SYM_L_GLOBAL`, `SYM_L_WEAK`는 symbol linkage를 나타내며 앞선 macro의 `_LABEL` variant 또는 `SYM_START`에서 사용합니다.

architecture는 자체 `asm/linkage.h`에서 어떤 macro든 override할 수 있으며 symbol type을 지정하는 `SYM_T_FUNC`, `SYM_T_OBJECT`, `SYM_T_NONE`도 포함됩니다. 이 문서의 모든 macro는 `#ifdef`와 `#endif`로 둘러싸여 있으므로 architecture-dependent header에서 다른 정의를 제공하면 충분합니다.