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