1 /* Jitter: data locations: header. 2 3 Copyright (C) 2019, 2020, 2021 Luca Saiu 4 Written by Luca Saiu 5 6 This file is part of Jitter. 7 8 Jitter is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 Jitter is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with Jitter. If not, see <http://www.gnu.org/licenses/>. */ 20 21 22 #ifndef JITTER_DATA_LOCATIONS_H_ 23 #define JITTER_DATA_LOCATIONS_H_ 24 25 #include <stdio.h> 26 #include <stdbool.h> 27 28 #include <jitter/jitter.h> 29 #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT) 30 # include <jitter/jitter-sections.h> 31 #endif // #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT) 32 #include <jitter/jitter-print.h> 33 #include <jitter/jitter-vm.h> 34 35 36 /* Low-level debugging features relying on assembly: data locations. 37 * ************************************************************************** */ 38 39 /* Information about where a certain datum is held at run time in the 40 executor. */ 41 struct jitter_data_location 42 { 43 /* The datum name. */ 44 const char *name; 45 46 /* The datum location, as text, in assembly notation as emitted by GCC. */ 47 const char *location; 48 49 /* Non-false iff the datum is held in a register. */ 50 bool register_; 51 }; 52 53 /* An array of data locations, with a field holding its size. */ 54 struct jitter_data_locations 55 { 56 /* An array of data, as elements of the struct above. */ 57 struct jitter_data_location *data_locations; 58 59 /* How many data there are. */ 60 size_t data_location_no; 61 62 /* Non-false iff the information contained in data_locations is known to be 63 reliable. The information may not be reliable if some datum is not 64 accessible from a register or as a single memory operand, and instead 65 requires additional loads. That would be a symptom of some problem. */ 66 bool reliable; 67 }; 68 69 /* Given a pointer to the VM data structure, return a pointer to a freshly 70 allocated struct jitter_data_location_data object. This function is used by 71 machine-generated code. */ 72 struct jitter_data_locations * 73 jitter_make_data_locations (const struct jitter_vm *vm) 74 __attribute__ ((nonnull (1), returns_nonnull)); 75 76 /* Destroy the data structure allocated from the previous function. */ 77 void 78 jitter_destroy_data_locations (struct jitter_data_locations *locations) 79 __attribute__ ((nonnull (1))); 80 81 82 83 84 /* Data locations: human-readable output. 85 * ************************************************************************** */ 86 87 /* Output a human-readable message about data locations for the pointed VM to 88 the given print context. */ 89 void 90 jitter_dump_data_locations (jitter_print_context ctx, const struct jitter_vm *vm) 91 __attribute__ ((nonnull (1, 2))); 92 93 94 95 96 /* Data location macros. 97 * ************************************************************************** */ 98 99 /* The following macros provide a way of emitting information about specific 100 data, as registers or register-based memory locations, *as strings* in a 101 separate subsection, all as part of the definition of a global symbol visible 102 from C as a global variable. This can be useful to read from memory and 103 print out to help the user follow VM instruction disassemblies. 104 105 This functionality is used by machine-generated code. */ 106 107 /* This functionality is not actually available if the host binary format is not 108 supported. In that case, define compatibility stubs. */ 109 #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT) 110 /* Data locations are actually supported. */ 111 112 /* The name of the global variable holding data prefixes. */ 113 # define JITTER_DATA_LOCATION_NAME(_jitter_vm_the_prefix) \ 114 JITTER_CONCATENATE_TWO(_jitter_vm_the_prefix, _data_locations) 115 116 /* The subsection number for data locations. */ 117 # define JITTER_ASM_DATA_LOCATION_SUBSECTION \ 118 "12" 119 120 /* Begin the global definition for data locations for the VM with the given 121 vmprefix. This temporarily enters the appropriate subsection, emits a symbol 122 definition, and pops back to the previous subsection. Between a call to this 123 macro and a call to JITTER_DATA_LOCATION_FOOTER the user is supposed to emit 124 location data for every datum, in some predictable order. The defined global 125 is only one. */ 126 # define JITTER_DATA_LOCATION_HEADER(_jitter_vm_the_prefix) \ 127 asm (/* Generate the identifier definition in assembly. */ \ 128 JITTER_ASM_OPEN_DEFINITION (JITTER_ASM_DATA_LOCATION_SUBSECTION, \ 129 JITTER_DATA_LOCATION_NAME \ 130 (_jitter_vm_the_prefix))) 131 132 /* End the global definition for data locations, for the VM with the given 133 vmprefix. This enters, and then exits, the appropriate subsection. */ 134 # define JITTER_DATA_LOCATION_FOOTER(_jitter_vm_the_prefix) \ 135 asm (/* Emit the final empty string as "\0". */ \ 136 JITTER_ASM_ENTER_SUBSECTION( JITTER_ASM_DATA_LOCATION_SUBSECTION) \ 137 ".byte 0\n\t" \ 138 JITTER_ASM_EXIT_SUBSECTION \ 139 /* Close the identifier definition in assembly. */ \ 140 JITTER_ASM_CLOSE_DEFINITION (JITTER_ASM_DATA_LOCATION_SUBSECTION, \ 141 JITTER_DATA_LOCATION_NAME \ 142 (_jitter_vm_the_prefix))) 143 144 /* Emit the location for the given datum with the given name as two 145 '\0'-terminated strings, in the data location subsection. 146 For example, if foo is a local variable currently kept in some hardware 147 register named $r10, then the macro call 148 JITTER_DATA_LOCATION_DATUM("the foo variable", foo); 149 will emit 150 .asciz "the foo variable" 151 .asciz "$r10" 152 in the data location subsection. 153 Notice that: 154 - name_as_string is emitted as is in an extended-asm template, 155 therefore any '%' character must be escaped as "%%"; 156 - name_as_string_literal must never be an empty string, since an 157 empty string terminates the entire data structure. */ 158 # define JITTER_DATA_LOCATION_DATUM(name_as_string_literal, datum) \ 159 asm volatile (JITTER_ASM_ENTER_SUBSECTION( \ 160 JITTER_ASM_DATA_LOCATION_SUBSECTION) \ 161 "\n" JITTER_ASM_COMMENT_PREFIX \ 162 name_as_string_literal " " JITTER_STRINGIFY(datum) "\n" \ 163 ".asciz \"" name_as_string_literal "\"\n" \ 164 ".asciz \"%[datum_from_asm]\"\n\t" \ 165 JITTER_ASM_EXIT_SUBSECTION \ 166 : /* outputs */ \ 167 : [datum_from_asm] "X" (datum) /* inputs */) 168 #else // ! defined (JITTER_HAVE_KNOWN_BINARY_FORMAT) 169 /* Use dummy macros emitting no data locations, for compatibility. */ 170 # define JITTER_DATA_LOCATION_HEADER(_jitter_vm_the_prefix) /* Nothing. */ 171 # define JITTER_DATA_LOCATION_FOOTER(_jitter_vm_the_prefix) /* Nothing. */ 172 # define JITTER_DATA_LOCATION_DATUM(name_as_string_literal, datum) /* Nothing. */ 173 #endif // #if defined (JITTER_HAVE_KNOWN_BINARY_FORMAT) 174 175 176 #endif // #ifndef JITTER_DATA_LOCATIONS_H_ 177