1 /* Jitter: patch-in 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 #ifndef JITTER_PATCH_IN_H_
24 #define JITTER_PATCH_IN_H_
25 
26 
27 /* Include core headers.
28  * ************************************************************************** */
29 
30 /* Include macro definitions about whether we have a machine file, and about the
31    dispatching model. */
32 #include <jitter/jitter.h>
33 
34 /* Include sectioning macros, if we have section support for this platform. */
35 #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT)
36 # include <jitter/jitter-sections.h>
37 #endif // #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT)
38 
39 
40 
41 
42 /* Do nothing if not using patch-ins.
43  * ************************************************************************** */
44 
45 /* First include the machine header which may contain a CPP definition of
46    JITTER_MACHINE_SUPPORTS_PATCH_IN ; this only makes sense if the dispatch is
47    no-threading, which is only possible if assembly is enabled.
48    If the dispatch is different from no-threading patch-ins are always
49    disabled. */
50 #if defined(JITTER_DISPATCH_NO_THREADING)
51 # include <jitter/jitter-machine-common.h>
52 # include <jitter/machine/jitter-machine.h>
53 # ifdef JITTER_MACHINE_SUPPORTS_PATCH_IN
54 #   define JITTER_HAVE_PATCH_IN 1
55 # endif // #ifdef JITTER_MACHINE_SUPPORTS_PATCH_IN
56 #endif //#if defined(JITTER_DISPATCH_NO_THREADING)
57 
58 /* The rest of this header expands to nothing if patch-ins are not supported in
59    this configuration. */
60 #ifdef JITTER_HAVE_PATCH_IN
61 
62 
63 
64 
65 /* Include headers.
66  * ************************************************************************** */
67 
68 #include <stdio.h>
69 #include <stdbool.h>
70 
71 #include <jitter/jitter.h>
72 #include <jitter/jitter-cpp.h>
73 #include <jitter/jitter-defect.h>
74 #include <jitter/jitter-dynamic-buffer.h>
75 
76 
77 
78 
79 /* Introduction.
80  * ************************************************************************** */
81 
82 /* The generated code in .text , to be expanded from VM instructions, will
83    either skip enough bytes for an instruction to be patched-in later, or will
84    generate temporary instructions with some argument to be replaced later; at
85    the same time, the code generates a patch-in descriptor in a separate
86    subsection, referring the preliminary code to patch with enough information
87    to fill-in the missing data after replication.
88 
89    GCC may optimize away an entire patch-in, when the code is unreachable or, at
90    least in theory, duplicate it.  This is not a problem: if there is no code to
91    patch, no descriptor will refer it; in other words the code in .text 0 and in
92    the subsections are treated as a unit, either both present or both optimized
93    away.  For each code sequence to patch there will be one descriptor.
94 
95    This relies on the functionality in jitter-sections.h . */
96 
97 
98 
99 
100 /* Fast-branch descriptor data structures: C API.
101  * ************************************************************************** */
102 
103 /* These structures are accessed from C, but their only definition is in assembly
104    code; see the page right below this one. */
105 
106 /* The descriptor for a specific patch-in.  Instances of this are defined in
107    assembly, but are meant to be accessed from C as part of a global array.
108    It is convenient that every field be word-sized.  Reordering fields requires
109    changes in the assembly code below. */
110 struct jitter_patch_in_descriptor
111 {
112   /* The specialized instruction opcode for this patch-in. */
113   jitter_uint specialized_instruction_opcode;
114 
115   /* The patch-in offset, in bytes, from the beginning of the specialized
116      instruction code. */
117   jitter_uint offset;
118 
119   /* The patch-in length, in bytes.  This information might be redundant if
120      patch_in_case assumes a known length, as it is the case now, but I keep
121      this for future extensibility. */
122   jitter_uint length;
123 
124   /* The patch-in case, indicating the kind of patching to perform.  In order to
125      prevent mistakes, zero will not be used as a valid case. */
126   jitter_uint patch_in_case;
127 
128   /* The following fields are case-dependent arguments, not all used for every
129      case. */
130 
131   /* 0-th case-dependent word.  Each word is implemented as a union of
132      word-sized elements, to make access more convenient from C code. */
133   union
134   {
135     /* For a fast goto: fast label index, 0-based. */
136     jitter_uint residual_index;
137 
138     /* Generic 0-th word, as an unsigned datum. */
139     jitter_uint case_dependent_word_0_uint;
140 
141     /* Generic 0-th word, as an signed datum. */
142     jitter_int  case_dependent_word_0_int;
143   } __attribute__ ((packed));
144 
145   /* 1-st case-dependent word, not used yet. */
146   union
147   {
148     jitter_uint case_dependent_word_1_uint;
149     jitter_int  case_dependent_word_1_int;
150   } __attribute__ ((packed));
151 
152   /* 2-nd case-dependent word, not used yet. */
153   union
154   {
155     jitter_uint case_dependent_word_2_uint;
156     jitter_int  case_dependent_word_2_int;
157   } __attribute__ ((packed));
158 
159   /* 3-rd case-dependent word, not used yet. */
160   union
161   {
162     jitter_uint case_dependent_word_3_uint;
163     jitter_int  case_dependent_word_3_int;
164   } __attribute__ ((packed));
165 } __attribute__ ((packed));
166 
167 
168 
169 
170 /* Prefix-dependent names for globals.
171  * ************************************************************************** */
172 
173 /* The name of the global descriptor vector. */
174 #define JITTER_PATCH_IN_DESCRIPTORS_NAME(_jitter_vm_the_prefix)  \
175   JITTER_CONCATENATE_TWO(_jitter_vm_the_prefix,                  \
176                          _patch_in_descriptors)
177 
178 /* The name of the global descriptor vector. */
179 #define JITTER_PATCH_IN_DESCRIPTORS_SIZE_IN_BYTES_NAME(_jitter_vm_the_prefix)  \
180   JITTER_CONCATENATE_TWO(JITTER_PATCH_IN_DESCRIPTORS_NAME(                     \
181                            _jitter_vm_the_prefix),                             \
182                          _size_in_bytes)
183 
184 /* Expand to extern declaration of the variables defined in assembly, to be used
185    from C. */
186 #define JITTER_PATCH_IN_DESCRIPTOR_DECLARATIONS_(_jitter_vm_the_prefix)   \
187   extern const struct jitter_patch_in_descriptor                          \
188   JITTER_PATCH_IN_DESCRIPTORS_NAME(_jitter_vm_the_prefix) [];             \
189   extern const jitter_uint                                                \
190   JITTER_PATCH_IN_DESCRIPTORS_SIZE_IN_BYTES_NAME(_jitter_vm_the_prefix);
191 
192 
193 
194 
195 /* Patch-in descriptor macros.
196  * ************************************************************************** */
197 
198 /* Each patch-in descriptor contains information about one patch-in
199    placeholder. */
200 
201 /* Expand to a string literal containing the .rodata subsection number
202    containing the patch-in descriptors. */
203 #define JITTER_ASM_PATCH_IN_SUBSECTION  \
204   "10"
205 
206 /* Expand to an inline asm statement containing the patch-in header.  Here
207    volatility serves to force this statement to be emitted before the other asm
208    volatile statements within the executor and before the footer, therefore
209    forcing a correct order in the generated assembly file. */
210 #define JITTER_PATCH_IN_HEADER(_jitter_vm_the_prefix)                 \
211   asm (JITTER_ASM_OPEN_DEFINITION                                     \
212           (JITTER_ASM_PATCH_IN_SUBSECTION,                            \
213           JITTER_PATCH_IN_DESCRIPTORS_NAME (_jitter_vm_the_prefix)))
214 
215 /* Expand to an inline asm statement containing the patch-in footer.  See the
216    comment above.*/
217 #define JITTER_PATCH_IN_FOOTER(_jitter_vm_the_prefix)                  \
218   asm (JITTER_ASM_CLOSE_DEFINITION                                     \
219           (JITTER_ASM_PATCH_IN_SUBSECTION,                             \
220            JITTER_PATCH_IN_DESCRIPTORS_NAME (_jitter_vm_the_prefix)))
221 
222 
223 
224 
225 /* Patch-in placeholder macros.
226  * ************************************************************************** */
227 
228 /* Expand to a string literal meant to be used as the the assembly template for
229    a patch-in, referring the named input argument
230    "jitter_vm_instruction_beginning".
231 
232    The "l" in the assembly template does *not* indicate a "gotolabel" argument
233    for asm goto: jitter_vm_instruction_beginning is not passed as a gotolabel,
234    but as an ordinary input argument.
235    I used to pass the argument as a gotolabel, but the label was sometimes
236    resolved to a slightly different address compared to what is computed by the
237    prefix && operator under GCC 6 -- which broke patch-ins.  Elsewhere in Jitter
238    I use prefix && to delimit the beginning and end of VM instruction code, so
239    it is sensible to always compute these address the same way.
240 
241    The "l" modifier serves to omit the immediate-argument prefix "$" on i386 and
242    x86_64, which would be syntactically incorrect in this context, out of an
243    instruction.
244    This "l" is documented in the GCC manual as one of the "x86 Operand
245    Modifiers", but I see it working on any architecture -- doing nothing on
246    architectures different from i386 and x86_64.  Should GCC's behavior change
247    in the future it will be trivial to replace "l" with an architecture-specific
248    macro expanding to "l" on i386 and x86_64 and nothing on every other. */
249 #define JITTER_ASM_PATCH_IN_PLACEHOLDER(size_in_bytes, case,          \
250                                         arg0, arg1, arg2, arg3)       \
251   JITTER_ASM_COMMENT_UNIQUE("Patch-in " JITTER_STRINGIFY(case))       \
252   "\n1:\n\t"                                                          \
253   JITTER_ASM_SKIP_BYTES(size_in_bytes) "\n"                           \
254   JITTER_ASM_ENTER_SUBSECTION(JITTER_ASM_PATCH_IN_SUBSECTION)         \
255     JITTER_ASM_WORD " "                                               \
256       JITTER_STRINGIFY(JITTER_SPECIALIZED_INSTRUCTION_OPCODE) "\n\t"  \
257     JITTER_ASM_WORD " (1b - %l[jitter_vm_instruction_beginning])\n\t" \
258     JITTER_ASM_WORD " " JITTER_STRINGIFY(size_in_bytes) "\n\t"        \
259     JITTER_ASM_WORD " " JITTER_STRINGIFY(case) "\n\t"                 \
260     JITTER_ASM_WORD " " JITTER_STRINGIFY(arg0) "\n\t"                 \
261     JITTER_ASM_WORD " " JITTER_STRINGIFY(arg1) "\n\t"                 \
262     JITTER_ASM_WORD " " JITTER_STRINGIFY(arg2) "\n\t"                 \
263     JITTER_ASM_WORD " " JITTER_STRINGIFY(arg3) "\n"                   \
264   JITTER_ASM_EXIT_SUBSECTION
265 
266 /* Expand to the (named) input constraint jitter_vm_instruction_beginning for an
267    inline asm template generated by JITTER_ASM_PATCH_IN_PLACEHOLDER.
268 
269    The constraint is given as "X" rather than the more intuitive "i" because of
270    the SH architecture, where that constraint would fail because of the small
271    immediate size.
272    Should this prove inadequate, it will be easy to make the constraint an
273    architecture-specific macro in the future.  Anyway a failure will be very
274    visible, since any problem caused by this will happen early, at compile
275    or assemble time. */
276 #define JITTER_INPUT_VM_INSTRUCTION_BEGINNING             \
277   [jitter_vm_instruction_beginning]                       \
278      "X" (&& JITTER_SPECIALIZED_INSTRUCTION_BEGIN_LABEL)
279 
280 /* Likewise for the instruction end. */
281 #define JITTER_INPUT_VM_INSTRUCTION_END                 \
282   [jitter_vm_instruction_end]                           \
283      "X" (&& JITTER_SPECIALIZED_INSTRUCTION_END_LABEL)
284 
285 /* Expand to a C statement (currently not protected with do..while (false), as
286    this is meant to be only used within other macros) containing the given
287    patch-in for an unconditional VM branch.
288 
289    Notice how the (only) input argument is the label for the beginning of the
290    current VM instruction, obtained by the prefix && operator: see the comment
291    before JITTER_ASM_PATCH_IN_PLACEHOLDER . */
292 #define JITTER_PATCH_IN_PLACEHOLDER_GOTO_(size_in_bytes, case,       \
293                                           arg0, arg1, arg2, arg3)    \
294   asm goto (JITTER_ASM_DEFECT_DESCRIPTOR                             \
295             JITTER_ASM_PATCH_IN_PLACEHOLDER(size_in_bytes, case,     \
296                                             arg0, arg1, arg2, arg3)  \
297             : /* outputs */                                          \
298             : JITTER_PATCH_IN_INPUTS_FOR_EVERY_CASE,                 \
299               JITTER_INPUT_VM_INSTRUCTION_BEGINNING /* inputs */     \
300             : /* clobbers */                                         \
301             : jitter_dispatch_label /* gotolabels */)
302 
303 /* The inline asm inputs to be used as part of the input constraints for every
304    patch-in. */
305 #define JITTER_PATCH_IN_INPUTS_FOR_EVERY_CASE  \
306   [_jitter_dummy] "X" (jitter_ip)
307 
308 
309 
310 
311 /* Fallback fill-in byte.
312  * ************************************************************************** */
313 
314 /* Unless a definition is not already in machine-specific code. define the byte
315    with which placeholder code is to be filled in.  This default is easy to
316    recognize at a glance, but the best choice is machine-specific: ideally the
317    byte should always be invalid at the beginning of an instruction, to make
318    spotting mistakes easier. */
319 #ifndef JITTER_ASM_PATCH_IN_FILL_BYTE
320 # define JITTER_ASM_PATCH_IN_FILL_BYTE "0xff"
321 #endif // #ifndef JITTER_ASM_PATCH_IN_FILL_BYTE
322 
323 
324 
325 
326 /* Patch-in efficient data structures.
327  * ************************************************************************** */
328 
329 /* Compiling code with patch-ins yields an object file containing all the
330    required information, but the subsection hack leaves the data ordered in a
331    very inconvenient and inefficient way.  This functionality generates a C
332    array which can be indexed by a specialized instruction opcode, whose
333    elements each point to an array of patch-in descriptor pointers for the
334    specialized instruction.
335 
336    The C array can be built just once at initialization time for each VM, at a
337    cost linear in its instruction number.  Each patch-in filling, at run time,
338    will then be O(1). */
339 
340 /* The patch-ins for an instruction. */
341 struct patch_in_table_entry
342 {
343   /* How many descriptors there are. */
344   size_t descriptor_no;
345 
346   /* An array of pointers to descriptrs, of length descriptor_no. */
347   const struct jitter_patch_in_descriptor **descriptors;
348 };
349 
350 /* Return a freshly allocated C array of struct patch_in_table_entry objects,
351    one element per specialized instruction. */
352 struct patch_in_table_entry *
353 jitter_make_patch_in_table (const struct jitter_patch_in_descriptor *descs,
354                             size_t desc_no,
355                             size_t specialized_instruction_no)
356   __attribute__ ((nonnull (1)));
357 
358 /* Free resources for a patch-in table as generated by
359    jitter_make_patch_in_table . */
360 void
361 jitter_destroy_patch_in_table (struct patch_in_table_entry *,
362                                size_t specialized_instruction_no)
363   __attribute__ ((nonnull (1)));
364 
365 
366 
367 
368 /* Patch-in debugging.
369  * ************************************************************************** */
370 
371 /* Dump the pointed patch-in descriptor in human-readable form to the pointed
372    stream. */
373 void
374 jitter_dump_patch_in_descriptor (FILE *f,
375                                  const struct jitter_patch_in_descriptor *p)
376   __attribute__ ((nonnull (1, 2)));
377 
378 /* Like jitter_dump_patch_in_descriptor, but prepend the given string to each
379    printed line. */
380 void
381 jitter_dump_patch_in_descriptor_with_prefix
382    (FILE *f,
383     const char *prefix,
384     const struct jitter_patch_in_descriptor *p)
385   __attribute__ ((nonnull (1, 2, 3)));
386 
387 /* Dump the given patch-in descriptor array, having the given size in
388    elements, in human-readable form to the pointed stream. */
389 void
390 jitter_dump_patch_in_descriptors
391    (FILE *f,
392     const struct jitter_patch_in_descriptor patch_ins [],
393     size_t patch_in_no)
394   __attribute__ ((nonnull (1)));
395 
396 /* A convenience macro to call jitter_dump_patch_in_descriptors with the correct
397    parameters. */
398 #define JITTER_DUMP_PATCH_IN_DESCRIPTORS(_jitter_vm_the_prefix)     \
399   do                                                                \
400     {                                                               \
401       size_t patch_in_no                                            \
402         = (JITTER_PATCH_IN_DESCRIPTORS_SIZE_IN_BYTES_NAME(          \
403               _jitter_vm_the_prefix)                                \
404            / sizeof (struct jitter_patch_in_descriptor));           \
405       jitter_dump_patch_in_descriptors                              \
406          (stderr,                                                   \
407           JITTER_PATCH_IN_DESCRIPTORS_NAME(_jitter_vm_the_prefix),  \
408           patch_in_no);                                             \
409     }                                                               \
410   while (false)
411 
412 #endif // #ifdef JITTER_HAVE_PATCH_IN
413 #endif // #ifndef JITTER_PATCH_IN_H_
414