1 /* Jitter: section header.
2 
3    Copyright (C) 2017, 2018, 2019, 2020 Luca Saiu
4    Updated in 2021 by Luca Saiu
5    Written by Luca Saiu
6 
7    This file is part of Jitter.
8 
9    Jitter is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    Jitter is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with Jitter.  If not, see <http://www.gnu.org/licenses/>. */
21 
22 
23 
24 #ifndef JITTER_SECTIONS_H_
25 #define JITTER_SECTIONS_H_
26 
27 
28 /* Include core headers.
29  * ************************************************************************** */
30 
31 /* Include macro definitions about the dispatching model and about the machine. */
32 #include <jitter/jitter.h>
33 
34 
35 
36 
37 /* Introduction.
38  * ************************************************************************** */
39 
40 /* The functionality in this header allows to define a read-only global in
41    assembly, accessible from C.  The assembly code is compiled along with
42    ordinary C code, so that GCC doesn't know about it; the assembly part may
43    refer labels and literals occurring elsewhere in C.
44 
45    This is delicate, since each patch-in placeholder is contained in compiled C
46    code; some patch-in placeholders may even be duplicated or optimized away by
47    GCC.
48 
49    The solution is using assembler subsections: the same inline asm code
50    potentially expanding to instructions in the .text section temporarily enters
51    a subsection, emits data, and then exits the subsection and goes back to
52    .text .
53 
54    The descriptor array is defined, of course within its subsection, from a
55    "header" in top-level inline assembly, which *must* come before the
56    executor code containing patch-in placeholders.  Instead of relying on
57    the no_reorder attribute as I used to do, I now generate header and footer
58    within the same function, relying on the ordering semantics of inline asm
59    statements with dependencies and asm volatile.
60    Similarly, a top-level inline asm "footer" closes the global array
61    definition, and defined a further global storing the array size.
62 
63    Interestingly no assembly *instructions* are required for this: the generated
64    inline assembly contains only data, which is machine-independent.  The
65    subsection mechanism, however, relies on ELF.  Support for other binary
66    formats is almost certainly possible, but not prioritary.  Modern GNU systems
67    use ELF.
68 
69    Syntactic convention: as always every macro whose name starts with
70    JITTER_ASM_ expands to a literal string, meant to be emitted as part of the
71    generated assembly code. */
72 
73 
74 
75 
76 /* Assembly utility.
77  * ************************************************************************** */
78 
79 /* Expand to a string literal for inclusion in inline assembly, skipping the
80    given number of bytes (a constant assembly expression not referring
81    variables) in the current section.  The fill byte is
82    JITTER_ASM_PATCH_IN_FILL_BYTE . */
83 #define JITTER_ASM_SKIP_BYTES(size)                                          \
84   JITTER_ASM_COMMENT_UNIQUE("Skip " JITTER_STRINGIFY(size) "B, but use a "   \
85                             "conditional to avoid a warning if "             \
86                             JITTER_STRINGIFY(size) " is zero")               \
87   ".ifgt (" JITTER_STRINGIFY(size) ")\n"                                     \
88   "  .skip " JITTER_STRINGIFY(size) ", " JITTER_ASM_PATCH_IN_FILL_BYTE "\n"  \
89   ".endif\n"
90 
91 
92 
93 
94 /* Section-changing macros.
95  * ************************************************************************** */
96 
97 /* The macros provide a way of entering a given subsection, and exiting back to
98    .text .  This is a simple wrapper over assembly functionality.
99 
100    ELF systems provide a very simple and elegant functionality based on LIFO
101    logic, where a subsection can be entered and just exited; at exit, the current
102    subsection reverts to the one which was active before entering.
103    This functionality is simple and elegant, but unfortunately not portable
104    to non-ELF systems.  However, since we don't really need our temporary
105    subsection switches to nest, we can use a crude but more portable support
106    from Gas on non-ELF systems and still get some of the functionality.
107 
108    The problem of switching subsections without the section stack on ELF is that
109    debug informations interfere with this mechanism, and Gas complains with
110    messages such as:
111      Error: CFI instruction used without previous .cfi_startproc
112      Error: .cfi_endproc without corresponding .cfi_startproc
113      Error: previous CFI entry not closed (missing .cfi_endproc)
114    and, as a consequence,
115      Error: .size expression for XXXX does not evaluate to a constant
116 
117    For this reason we many need specific ELF support for some dispatches.
118    Anyway some other functionality (such as locations: see
119    jitter-data-locations.h) will be available even based on a simpler
120    mechanism. */
121 
122 
123 
124 
125 /* Section-changing macros: the ELF solution.
126  * ************************************************************************** */
127 
128 /* Macros to enter and exit a subsection, expanding to literal assembly
129    templates.  This is the solution relying on ELF.  The given section name must
130    expand to a literal string. */
131 #define JITTER_ASM_ENTER_SUBSECTION_ELF(_jitter_section_name)  \
132   "\n.pushsection .rodata, " _jitter_section_name "\n\t"
133 #define JITTER_ASM_EXIT_SUBSECTION_ELF  \
134   "\n.popsection\n\t"
135 
136 
137 
138 
139 /* Section-changing macros: the GNU assembler solution.
140  * ************************************************************************** */
141 
142 /* Macros to enter and exit a subsection, expanding to literal assembly
143    templates.  This is the solution just relying on the GNU assembler.  The
144    given section name must expand to a literal string.
145 
146    In order for this to work I have to prevent GCC from generating CFI
147    directives, which don't play well with subsections, and avoid
148    -freorder-functions , which would .text into .text.hot and .text.unlikely
149    and therefore break JITTER_ASM_EXIT_SUBSECTION_GAS preventing a simple
150      .text 0
151    from returning to the previous subsection. */
152 #define JITTER_ASM_ENTER_SUBSECTION_GAS(_jitter_section_name)       \
153   /* Temporarily switch to a .data subsection.  The generated data  \
154      will be read-only. */                                          \
155   "\n.data " _jitter_section_name "\n\t"
156 #define JITTER_ASM_EXIT_SUBSECTION_GAS  \
157   /* Go back to the subsection 0 . */   \
158   "\n.text 0\n\t"
159 
160 
161 
162 
163 /* Section-changing macros: generic wrapper.
164  * ************************************************************************** */
165 
166 /* Macros to enter and exit a subsection, expanding to literal assembly
167    templates.  The section name must expand to a literal string. */
168 
169 #if defined(JITTER_HOST_OS_IS_ELF)
170 # define JITTER_ASM_ENTER_SUBSECTION(_jitter_section_name)  \
171     JITTER_ASM_ENTER_SUBSECTION_ELF(_jitter_section_name)
172 # define JITTER_ASM_EXIT_SUBSECTION  \
173     JITTER_ASM_EXIT_SUBSECTION_ELF
174 #elif defined(JITTER_HOST_ASSEMBLER_IS_GNU)
175 # define JITTER_ASM_ENTER_SUBSECTION(_jitter_section_name)  \
176     JITTER_ASM_ENTER_SUBSECTION_GAS(_jitter_section_name)
177 # define JITTER_ASM_EXIT_SUBSECTION  \
178     JITTER_ASM_EXIT_SUBSECTION_GAS
179 #else
180 # error "Not using ELF, nor the GNU assembler.  This will not work and you"
181 # error "should not have included this header."
182 #endif
183 
184 
185 
186 
187 /* Assembly global definition macros: ELF.
188  * ************************************************************************** */
189 
190 /* The macros here provide a way of generating assembly code to open and close a
191    global definition. */
192 
193 /* Expand to a literal assembly template string opening and closing a definition
194    in the current section.
195    Such a definition will generate two globally visible symbols: one main symbol
196    with the given name, and another with the given name suffixed by
197    "_size_in_bytes", a memory global containing the size in bytes of the main
198    symbol.  The size has as many bytes as a Jitter machine word.
199    The given name must expand to an identifier. */
200 #define JITTER_ASM_OPEN_DEFINITION_IN_CURRENT_SECTION_ELF(_jitter_name)  \
201   "\n"                                                                   \
202   ".balign 16\n"                                                         \
203   ".globl " JITTER_STRINGIFY(_jitter_name) "\n"                          \
204   ".type  " JITTER_STRINGIFY(_jitter_name) ", STT_OBJECT\n"              \
205   JITTER_STRINGIFY(_jitter_name) ":\n\t"
206 #define JITTER_ASM_CLOSE_DEFINITION_IN_CURRENT_SECTION_ELF(_jitter_name)   \
207   "\n"                                                                     \
208   JITTER_STRINGIFY(_jitter_name) "_end:\n"                                 \
209   ".balign 16\n"                                                           \
210   ".globl " JITTER_STRINGIFY(_jitter_name) "_size_in_bytes\n"              \
211   ".type  " JITTER_STRINGIFY(_jitter_name) "_size_in_bytes, STT_OBJECT\n"  \
212   JITTER_STRINGIFY(_jitter_name) "_size_in_bytes:\n\t"                     \
213   JITTER_ASM_WORD " (" JITTER_STRINGIFY(_jitter_name) "_end"               \
214                        " - " JITTER_STRINGIFY(_jitter_name) ")\n\t"
215 
216 
217 
218 
219 /* Assembly global definition macros: COFF.
220  * ************************************************************************** */
221 
222 /* This is conceputally identical to the ELF version above.
223    Implementation note: here the defined global may require an "_" prefix,
224    .def .. .endef , and no .type .
225    About the word size kludge, it may not be very portable.  Still, the only
226    widely used COFF systems are supported this way, and even this effort is
227    more than those systems deserve. */
228 #if JITTER_SIZEOF_VOID_P == 8
229 # define JITTER_ASM_COFF_GLOBAL_PREFIX  \
230     ""
231 #else
232 # define JITTER_ASM_COFF_GLOBAL_PREFIX  \
233     "_"
234 #endif // word size
235 #define JITTER_ASM_OPEN_DEFINITION_IN_CURRENT_SECTION_COFF(_jitter_name)       \
236   "\n"                                                                         \
237   ".balign 16\n"                                                               \
238   ".globl " JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name) "\n"  \
239   ".def " JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name)         \
240      "; .scl 2; .type 32; .endef\n"                                            \
241    JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name) ":\n\t"
242 #define JITTER_ASM_CLOSE_DEFINITION_IN_CURRENT_SECTION_COFF(_jitter_name)      \
243   "\n"                                                                         \
244   JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name) "_end:\n"       \
245   ".balign 16\n"                                                               \
246   ".def " JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name)         \
247      "_size_in_bytes; .scl 2; .type 32; .endef\n"                              \
248   ".globl _" JITTER_STRINGIFY(_jitter_name) "_size_in_bytes\n"                 \
249   JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name)                 \
250      "_size_in_bytes:\n\t"                                                     \
251   JITTER_ASM_WORD                                                              \
252      " (" JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name) "_end"  \
253         " - " JITTER_ASM_COFF_GLOBAL_PREFIX JITTER_STRINGIFY(_jitter_name)     \
254         ")\n"
255 
256 
257 
258 
259 /* Assembly global definition macros: generic wrapper.
260  * ************************************************************************** */
261 
262 #if defined(JITTER_HOST_OS_IS_ELF)
263 # define JITTER_ASM_OPEN_DEFINITION_IN_CURRENT_SECTION(_jitter_name)  \
264     JITTER_ASM_OPEN_DEFINITION_IN_CURRENT_SECTION_ELF (_jitter_name)
265 # define JITTER_ASM_CLOSE_DEFINITION_IN_CURRENT_SECTION(_jitter_name)  \
266     JITTER_ASM_CLOSE_DEFINITION_IN_CURRENT_SECTION_ELF (_jitter_name)
267 #elif defined(JITTER_HOST_OS_IS_COFF)
268 # define JITTER_ASM_OPEN_DEFINITION_IN_CURRENT_SECTION(_jitter_name)  \
269     JITTER_ASM_OPEN_DEFINITION_IN_CURRENT_SECTION_COFF (_jitter_name)
270 # define JITTER_ASM_CLOSE_DEFINITION_IN_CURRENT_SECTION(_jitter_name)  \
271     JITTER_ASM_CLOSE_DEFINITION_IN_CURRENT_SECTION_COFF (_jitter_name)
272 #else
273 # error "Not using ELF or COFF.  This will not work."
274 #endif // #ifdef JITTER_HOST_OS_IS_ELF
275 
276 
277 
278 
279 /* Definitions automatically switching sections: generic wrapper.
280  * ************************************************************************** */
281 
282 /* Expand to the literal string to be used in a top-level inline asm template as
283    a descriptor header or footer.  The generated "code", which contains no
284    machine instructions, switches to the appropriate subsection, opens or closes
285    the definition, and goes back to .text . */
286 #define JITTER_ASM_OPEN_DEFINITION(_jitter_section_name,         \
287                                    _jitter_name)                 \
288   JITTER_ASM_ENTER_SUBSECTION(_jitter_section_name)              \
289     JITTER_ASM_OPEN_DEFINITION_IN_CURRENT_SECTION(_jitter_name)  \
290   JITTER_ASM_EXIT_SUBSECTION
291 #define JITTER_ASM_CLOSE_DEFINITION(_jitter_section_name,         \
292                                     _jitter_name)                 \
293   JITTER_ASM_ENTER_SUBSECTION(_jitter_section_name)               \
294     JITTER_ASM_CLOSE_DEFINITION_IN_CURRENT_SECTION(_jitter_name)  \
295   JITTER_ASM_EXIT_SUBSECTION
296 
297 
298 #endif // #ifndef JITTER_SECTIONS_H_
299