1 /* Scheme interface to lazy strings. 2 3 Copyright (C) 2010-2024 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 /* See README file in this directory for implementation notes, coding 21 conventions, et.al. */ 22 23 #include "charset.h" 24 #include "value.h" 25 #include "valprint.h" 26 #include "language.h" 27 #include "guile-internal.h" 28 29 /* The <gdb:lazy-string> smob. */ 30 31 struct lazy_string_smob 32 { 33 /* This always appears first. */ 34 gdb_smob base; 35 36 /* Holds the address of the lazy string. */ 37 CORE_ADDR address; 38 39 /* Holds the encoding that will be applied to the string when the string 40 is printed by GDB. If the encoding is set to NULL then GDB will select 41 the most appropriate encoding when the sting is printed. 42 Space for this is malloc'd and will be freed when the object is 43 freed. */ 44 char *encoding; 45 46 /* If TYPE is an array: If the length is known, then this value is the 47 array's length, otherwise it is -1. 48 If TYPE is not an array: Then this value represents the string's length. 49 In either case, if the value is -1 then the string will be fetched and 50 encoded up to the first null of appropriate width. */ 51 int length; 52 53 /* The type of the string. 54 For example if the lazy string was created from a C "char*" then TYPE 55 represents a C "char*". To get the type of the character in the string 56 call lsscm_elt_type which handles the different kinds of values for TYPE. 57 This is recorded as an SCM object so that we take advantage of support for 58 preserving the type should its owning objfile go away. */ 59 SCM type; 60 }; 61 62 static const char lazy_string_smob_name[] = "gdb:lazy-string"; 63 64 /* The tag Guile knows the lazy string smob by. */ 65 static scm_t_bits lazy_string_smob_tag; 66 67 /* Administrivia for lazy string smobs. */ 69 70 /* The smob "free" function for <gdb:lazy-string>. */ 71 72 static size_t 73 lsscm_free_lazy_string_smob (SCM self) 74 { 75 lazy_string_smob *v_smob = (lazy_string_smob *) SCM_SMOB_DATA (self); 76 77 xfree (v_smob->encoding); 78 79 return 0; 80 } 81 82 /* The smob "print" function for <gdb:lazy-string>. */ 83 84 static int 85 lsscm_print_lazy_string_smob (SCM self, SCM port, scm_print_state *pstate) 86 { 87 lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (self); 88 89 gdbscm_printf (port, "#<%s", lazy_string_smob_name); 90 gdbscm_printf (port, " @%s", hex_string (ls_smob->address)); 91 if (ls_smob->length >= 0) 92 gdbscm_printf (port, " length %d", ls_smob->length); 93 if (ls_smob->encoding != NULL) 94 gdbscm_printf (port, " encoding %s", ls_smob->encoding); 95 scm_puts (">", port); 96 97 scm_remember_upto_here_1 (self); 98 99 /* Non-zero means success. */ 100 return 1; 101 } 102 103 /* Low level routine to create a <gdb:lazy-string> object. 104 The caller must verify: 105 - length >= -1 106 - !(address == 0 && length != 0) 107 - type != NULL */ 108 109 static SCM 110 lsscm_make_lazy_string_smob (CORE_ADDR address, int length, 111 const char *encoding, struct type *type) 112 { 113 lazy_string_smob *ls_smob = (lazy_string_smob *) 114 scm_gc_malloc (sizeof (lazy_string_smob), lazy_string_smob_name); 115 SCM ls_scm; 116 117 gdb_assert (length >= -1); 118 gdb_assert (!(address == 0 && length != 0)); 119 gdb_assert (type != NULL); 120 121 ls_smob->address = address; 122 ls_smob->length = length; 123 if (encoding == NULL || strcmp (encoding, "") == 0) 124 ls_smob->encoding = NULL; 125 else 126 ls_smob->encoding = xstrdup (encoding); 127 ls_smob->type = tyscm_scm_from_type (type); 128 129 ls_scm = scm_new_smob (lazy_string_smob_tag, (scm_t_bits) ls_smob); 130 gdbscm_init_gsmob (&ls_smob->base); 131 132 return ls_scm; 133 } 134 135 /* Return non-zero if SCM is a <gdb:lazy-string> object. */ 136 137 int 138 lsscm_is_lazy_string (SCM scm) 139 { 140 return SCM_SMOB_PREDICATE (lazy_string_smob_tag, scm); 141 } 142 143 /* (lazy-string? object) -> boolean */ 144 145 static SCM 146 gdbscm_lazy_string_p (SCM scm) 147 { 148 return scm_from_bool (lsscm_is_lazy_string (scm)); 149 } 150 151 /* Main entry point to create a <gdb:lazy-string> object. 152 If there's an error a <gdb:exception> object is returned. */ 153 154 SCM 155 lsscm_make_lazy_string (CORE_ADDR address, int length, 156 const char *encoding, struct type *type) 157 { 158 if (length < -1) 159 { 160 return gdbscm_make_out_of_range_error (NULL, 0, 161 scm_from_int (length), 162 _("invalid length")); 163 } 164 165 if (address == 0 && length != 0) 166 { 167 return gdbscm_make_out_of_range_error 168 (NULL, 0, scm_from_int (length), 169 _("cannot create a lazy string with address 0x0," 170 " and a non-zero length")); 171 } 172 173 if (type == NULL) 174 { 175 return gdbscm_make_out_of_range_error 176 (NULL, 0, scm_from_int (0), _("a lazy string's type cannot be NULL")); 177 } 178 179 return lsscm_make_lazy_string_smob (address, length, encoding, type); 180 } 181 182 /* Returns the <gdb:lazy-string> smob in SELF. 183 Throws an exception if SELF is not a <gdb:lazy-string> object. */ 184 185 static SCM 186 lsscm_get_lazy_string_arg_unsafe (SCM self, int arg_pos, const char *func_name) 187 { 188 SCM_ASSERT_TYPE (lsscm_is_lazy_string (self), self, arg_pos, func_name, 189 lazy_string_smob_name); 190 191 return self; 192 } 193 194 /* Return the type of a character in lazy string LS_SMOB. */ 195 196 static struct type * 197 lsscm_elt_type (lazy_string_smob *ls_smob) 198 { 199 struct type *type = tyscm_scm_to_type (ls_smob->type); 200 struct type *realtype; 201 202 realtype = check_typedef (type); 203 204 switch (realtype->code ()) 205 { 206 case TYPE_CODE_PTR: 207 case TYPE_CODE_ARRAY: 208 return realtype->target_type (); 209 default: 210 /* This is done to preserve existing behaviour. PR 20769. 211 E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */ 212 return realtype; 213 } 214 } 215 216 /* Lazy string methods. */ 218 219 /* (lazy-string-address <gdb:lazy-string>) -> address */ 220 221 static SCM 222 gdbscm_lazy_string_address (SCM self) 223 { 224 SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); 225 lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm); 226 227 return gdbscm_scm_from_ulongest (ls_smob->address); 228 } 229 230 /* (lazy-string-length <gdb:lazy-string>) -> integer */ 231 232 static SCM 233 gdbscm_lazy_string_length (SCM self) 234 { 235 SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); 236 lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm); 237 238 return scm_from_int (ls_smob->length); 239 } 240 241 /* (lazy-string-encoding <gdb:lazy-string>) -> string */ 242 243 static SCM 244 gdbscm_lazy_string_encoding (SCM self) 245 { 246 SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); 247 lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm); 248 249 /* An encoding can be set to NULL by the user, so check first. 250 If NULL return #f. */ 251 if (ls_smob != NULL) 252 return gdbscm_scm_from_c_string (ls_smob->encoding); 253 return SCM_BOOL_F; 254 } 255 256 /* (lazy-string-type <gdb:lazy-string>) -> <gdb:type> */ 257 258 static SCM 259 gdbscm_lazy_string_type (SCM self) 260 { 261 SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); 262 lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm); 263 264 return ls_smob->type; 265 } 266 267 /* (lazy-string->value <gdb:lazy-string>) -> <gdb:value> */ 268 269 static SCM 270 gdbscm_lazy_string_to_value (SCM self) 271 { 272 SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); 273 SCM except_scm; 274 struct value *value; 275 276 value = lsscm_safe_lazy_string_to_value (ls_scm, SCM_ARG1, FUNC_NAME, 277 &except_scm); 278 if (value == NULL) 279 gdbscm_throw (except_scm); 280 return vlscm_scm_from_value (value); 281 } 282 283 /* A "safe" version of gdbscm_lazy_string_to_value for use by 284 vlscm_convert_typed_value_from_scheme. 285 The result, upon success, is the value of <gdb:lazy-string> STRING. 286 ARG_POS is the argument position of STRING in the original Scheme 287 function call, used in exception text. 288 If there's an error, NULL is returned and a <gdb:exception> object 289 is stored in *except_scmp. 290 291 Note: The result is still "lazy". The caller must call value_fetch_lazy 292 to actually fetch the value. */ 293 294 struct value * 295 lsscm_safe_lazy_string_to_value (SCM string, int arg_pos, 296 const char *func_name, SCM *except_scmp) 297 { 298 lazy_string_smob *ls_smob; 299 struct value *value = NULL; 300 301 gdb_assert (lsscm_is_lazy_string (string)); 302 303 ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string); 304 305 if (ls_smob->address == 0) 306 { 307 *except_scmp 308 = gdbscm_make_out_of_range_error (func_name, arg_pos, string, 309 _("cannot create a value from NULL")); 310 return NULL; 311 } 312 313 try 314 { 315 struct type *type = tyscm_scm_to_type (ls_smob->type); 316 struct type *realtype = check_typedef (type); 317 318 switch (realtype->code ()) 319 { 320 case TYPE_CODE_PTR: 321 /* If a length is specified we need to convert this to an array 322 of the specified size. */ 323 if (ls_smob->length != -1) 324 { 325 /* PR 20786: There's no way to specify an array of length zero. 326 Record a length of [0,-1] which is how Ada does it. Anything 327 we do is broken, but this one possible solution. */ 328 type = lookup_array_range_type (realtype->target_type (), 329 0, ls_smob->length - 1); 330 value = value_at_lazy (type, ls_smob->address); 331 } 332 else 333 value = value_from_pointer (type, ls_smob->address); 334 break; 335 default: 336 value = value_at_lazy (type, ls_smob->address); 337 break; 338 } 339 } 340 catch (const gdb_exception &except) 341 { 342 *except_scmp = gdbscm_scm_from_gdb_exception (unpack (except)); 343 return NULL; 344 } 345 346 return value; 347 } 348 349 /* Print a lazy string to STREAM using val_print_string. 350 STRING must be a <gdb:lazy-string> object. */ 351 352 void 353 lsscm_val_print_lazy_string (SCM string, struct ui_file *stream, 354 const struct value_print_options *options) 355 { 356 lazy_string_smob *ls_smob; 357 struct type *elt_type; 358 359 gdb_assert (lsscm_is_lazy_string (string)); 360 361 ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string); 362 elt_type = lsscm_elt_type (ls_smob); 363 364 val_print_string (elt_type, ls_smob->encoding, 365 ls_smob->address, ls_smob->length, 366 stream, options); 367 } 368 369 /* Initialize the Scheme lazy-strings code. */ 371 372 static const scheme_function lazy_string_functions[] = 373 { 374 { "lazy-string?", 1, 0, 0, as_a_scm_t_subr (gdbscm_lazy_string_p), 375 "\ 376 Return #t if the object is a <gdb:lazy-string> object." }, 377 378 { "lazy-string-address", 1, 0, 0, 379 as_a_scm_t_subr (gdbscm_lazy_string_address), 380 "\ 381 Return the address of the lazy-string." }, 382 383 { "lazy-string-length", 1, 0, 0, as_a_scm_t_subr (gdbscm_lazy_string_length), 384 "\ 385 Return the length of the lazy-string.\n\ 386 If the length is -1 then the length is determined by the first null\n\ 387 of appropriate width." }, 388 389 { "lazy-string-encoding", 1, 0, 0, 390 as_a_scm_t_subr (gdbscm_lazy_string_encoding), 391 "\ 392 Return the encoding of the lazy-string." }, 393 394 { "lazy-string-type", 1, 0, 0, as_a_scm_t_subr (gdbscm_lazy_string_type), 395 "\ 396 Return the <gdb:type> of the lazy-string." }, 397 398 { "lazy-string->value", 1, 0, 0, 399 as_a_scm_t_subr (gdbscm_lazy_string_to_value), 400 "\ 401 Return the <gdb:value> representation of the lazy-string." }, 402 403 END_FUNCTIONS 404 }; 405 406 void 407 gdbscm_initialize_lazy_strings (void) 408 { 409 lazy_string_smob_tag = gdbscm_make_smob_type (lazy_string_smob_name, 410 sizeof (lazy_string_smob)); 411 scm_set_smob_free (lazy_string_smob_tag, lsscm_free_lazy_string_smob); 412 scm_set_smob_print (lazy_string_smob_tag, lsscm_print_lazy_string_smob); 413 414 gdbscm_define_functions (lazy_string_functions, 1); 415 } 416