X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/b2715b270ae27eccefe8edbbacb3910bc7cc9383..HEAD:/gdb/guile/scm-lazy-string.c diff --git a/gdb/guile/scm-lazy-string.c b/gdb/guile/scm-lazy-string.c index 10494ea2ee..d260e09b91 100644 --- a/gdb/guile/scm-lazy-string.c +++ b/gdb/guile/scm-lazy-string.c @@ -1,6 +1,6 @@ /* Scheme interface to lazy strings. - Copyright (C) 2010-2014 Free Software Foundation, Inc. + Copyright (C) 2010-2022 Free Software Foundation, Inc. This file is part of GDB. @@ -23,15 +23,13 @@ #include "defs.h" #include "charset.h" #include "value.h" -#include "exceptions.h" #include "valprint.h" #include "language.h" -#include "gdb_assert.h" #include "guile-internal.h" /* The smob. */ -typedef struct +struct lazy_string_smob { /* This always appears first. */ gdb_smob base; @@ -46,15 +44,21 @@ typedef struct freed. */ char *encoding; - /* Holds the length of the string in characters. If the length is -1, - then the string will be fetched and encoded up to the first null of - appropriate width. */ + /* If TYPE is an array: If the length is known, then this value is the + array's length, otherwise it is -1. + If TYPE is not an array: Then this value represents the string's length. + In either case, if the value is -1 then the string will be fetched and + encoded up to the first null of appropriate width. */ int length; - /* This attribute holds the type that is represented by the lazy - string's type. */ - struct type *type; -} lazy_string_smob; + /* The type of the string. + For example if the lazy string was created from a C "char*" then TYPE + represents a C "char*". To get the type of the character in the string + call lsscm_elt_type which handles the different kinds of values for TYPE. + This is recorded as an SCM object so that we take advantage of support for + preserving the type should its owning objfile go away. */ + SCM type; +}; static const char lazy_string_smob_name[] = "gdb:lazy-string"; @@ -63,14 +67,6 @@ static scm_t_bits lazy_string_smob_tag; /* Administrivia for lazy string smobs. */ -/* The smob "mark" function for . */ - -static SCM -lsscm_mark_lazy_string_smob (SCM self) -{ - return SCM_BOOL_F; -} - /* The smob "free" function for . */ static size_t @@ -105,7 +101,10 @@ lsscm_print_lazy_string_smob (SCM self, SCM port, scm_print_state *pstate) } /* Low level routine to create a object. - The caller must verify !(address == 0 && length != 0). */ + The caller must verify: + - length >= -1 + - !(address == 0 && length != 0) + - type != NULL */ static SCM lsscm_make_lazy_string_smob (CORE_ADDR address, int length, @@ -115,18 +114,17 @@ lsscm_make_lazy_string_smob (CORE_ADDR address, int length, scm_gc_malloc (sizeof (lazy_string_smob), lazy_string_smob_name); SCM ls_scm; - /* Caller must verify this. */ + gdb_assert (length >= -1); gdb_assert (!(address == 0 && length != 0)); gdb_assert (type != NULL); ls_smob->address = address; - /* Coerce all values < 0 to -1. */ - ls_smob->length = length < 0 ? -1 : length; + ls_smob->length = length; if (encoding == NULL || strcmp (encoding, "") == 0) ls_smob->encoding = NULL; else ls_smob->encoding = xstrdup (encoding); - ls_smob->type = type; + ls_smob->type = tyscm_scm_from_type (type); ls_scm = scm_new_smob (lazy_string_smob_tag, (scm_t_bits) ls_smob); gdbscm_init_gsmob (&ls_smob->base); @@ -157,11 +155,18 @@ SCM lsscm_make_lazy_string (CORE_ADDR address, int length, const char *encoding, struct type *type) { + if (length < -1) + { + return gdbscm_make_out_of_range_error (NULL, 0, + scm_from_int (length), + _("invalid length")); + } + if (address == 0 && length != 0) { return gdbscm_make_out_of_range_error (NULL, 0, scm_from_int (length), - _("cannot create a lazy string with address 0x0" + _("cannot create a lazy string with address 0x0," " and a non-zero length")); } @@ -185,6 +190,28 @@ lsscm_get_lazy_string_arg_unsafe (SCM self, int arg_pos, const char *func_name) return self; } + +/* Return the type of a character in lazy string LS_SMOB. */ + +static struct type * +lsscm_elt_type (lazy_string_smob *ls_smob) +{ + struct type *type = tyscm_scm_to_type (ls_smob->type); + struct type *realtype; + + realtype = check_typedef (type); + + switch (realtype->code ()) + { + case TYPE_CODE_PTR: + case TYPE_CODE_ARRAY: + return realtype->target_type (); + default: + /* This is done to preserve existing behaviour. PR 20769. + E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */ + return realtype; + } +} /* Lazy string methods. */ @@ -233,7 +260,7 @@ gdbscm_lazy_string_type (SCM self) SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm); - return tyscm_scm_from_type (ls_smob->type); + return ls_smob->type; } /* (lazy-string->value ) -> */ @@ -242,22 +269,13 @@ static SCM gdbscm_lazy_string_to_value (SCM self) { SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); - lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm); - struct value *value = NULL; - volatile struct gdb_exception except; - - if (ls_smob->address == 0) - { - gdbscm_throw (gdbscm_make_out_of_range_error (FUNC_NAME, SCM_ARG1, self, - _("cannot create a value from NULL"))); - } - - TRY_CATCH (except, RETURN_MASK_ALL) - { - value = value_at_lazy (ls_smob->type, ls_smob->address); - } - GDBSCM_HANDLE_GDB_EXCEPTION (except); + SCM except_scm; + struct value *value; + value = lsscm_safe_lazy_string_to_value (ls_scm, SCM_ARG1, FUNC_NAME, + &except_scm); + if (value == NULL) + gdbscm_throw (except_scm); return vlscm_scm_from_value (value); } @@ -278,28 +296,49 @@ lsscm_safe_lazy_string_to_value (SCM string, int arg_pos, { lazy_string_smob *ls_smob; struct value *value = NULL; - volatile struct gdb_exception except; gdb_assert (lsscm_is_lazy_string (string)); ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string); - *except_scmp = SCM_BOOL_F; if (ls_smob->address == 0) { *except_scmp - = gdbscm_make_out_of_range_error (FUNC_NAME, SCM_ARG1, string, + = gdbscm_make_out_of_range_error (func_name, arg_pos, string, _("cannot create a value from NULL")); return NULL; } - TRY_CATCH (except, RETURN_MASK_ALL) + try { - value = value_at_lazy (ls_smob->type, ls_smob->address); + struct type *type = tyscm_scm_to_type (ls_smob->type); + struct type *realtype = check_typedef (type); + + switch (realtype->code ()) + { + case TYPE_CODE_PTR: + /* If a length is specified we need to convert this to an array + of the specified size. */ + if (ls_smob->length != -1) + { + /* PR 20786: There's no way to specify an array of length zero. + Record a length of [0,-1] which is how Ada does it. Anything + we do is broken, but this one possible solution. */ + type = lookup_array_range_type (realtype->target_type (), + 0, ls_smob->length - 1); + value = value_at_lazy (type, ls_smob->address); + } + else + value = value_from_pointer (type, ls_smob->address); + break; + default: + value = value_at_lazy (type, ls_smob->address); + break; + } } - if (except.reason < 0) + catch (const gdb_exception &except) { - *except_scmp = gdbscm_scm_from_gdb_exception (except); + *except_scmp = gdbscm_scm_from_gdb_exception (unpack (except)); return NULL; } @@ -314,12 +353,14 @@ lsscm_val_print_lazy_string (SCM string, struct ui_file *stream, const struct value_print_options *options) { lazy_string_smob *ls_smob; + struct type *elt_type; gdb_assert (lsscm_is_lazy_string (string)); ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (string); + elt_type = lsscm_elt_type (ls_smob); - val_print_string (ls_smob->type, ls_smob->encoding, + val_print_string (elt_type, ls_smob->encoding, ls_smob->address, ls_smob->length, stream, options); } @@ -328,29 +369,32 @@ lsscm_val_print_lazy_string (SCM string, struct ui_file *stream, static const scheme_function lazy_string_functions[] = { - { "lazy-string?", 1, 0, 0, gdbscm_lazy_string_p, + { "lazy-string?", 1, 0, 0, as_a_scm_t_subr (gdbscm_lazy_string_p), "\ Return #t if the object is a object." }, - { "lazy-string-address", 1, 0, 0, gdbscm_lazy_string_address, + { "lazy-string-address", 1, 0, 0, + as_a_scm_t_subr (gdbscm_lazy_string_address), "\ Return the address of the lazy-string." }, - { "lazy-string-length", 1, 0, 0, gdbscm_lazy_string_length, + { "lazy-string-length", 1, 0, 0, as_a_scm_t_subr (gdbscm_lazy_string_length), "\ Return the length of the lazy-string.\n\ If the length is -1 then the length is determined by the first null\n\ of appropriate width." }, - { "lazy-string-encoding", 1, 0, 0, gdbscm_lazy_string_encoding, + { "lazy-string-encoding", 1, 0, 0, + as_a_scm_t_subr (gdbscm_lazy_string_encoding), "\ Return the encoding of the lazy-string." }, - { "lazy-string-type", 1, 0, 0, gdbscm_lazy_string_type, + { "lazy-string-type", 1, 0, 0, as_a_scm_t_subr (gdbscm_lazy_string_type), "\ Return the of the lazy-string." }, - { "lazy-string->value", 1, 0, 0, gdbscm_lazy_string_to_value, + { "lazy-string->value", 1, 0, 0, + as_a_scm_t_subr (gdbscm_lazy_string_to_value), "\ Return the representation of the lazy-string." }, @@ -362,7 +406,6 @@ gdbscm_initialize_lazy_strings (void) { lazy_string_smob_tag = gdbscm_make_smob_type (lazy_string_smob_name, sizeof (lazy_string_smob)); - scm_set_smob_mark (lazy_string_smob_tag, lsscm_mark_lazy_string_smob); scm_set_smob_free (lazy_string_smob_tag, lsscm_free_lazy_string_smob); scm_set_smob_print (lazy_string_smob_tag, lsscm_print_lazy_string_smob);