mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 02:50:08 +08:00
Don't throw Scheme exceptions with live std::vector objects
A complication with the Guile code is that we have two types of exceptions to consider: GDB/C++ exceptions, and Guile/SJLJ exceptions. Because Guile exceptions are SJLJ based, we must make sure to not have live local variables of types with non-trivial dtors when a Guile exception is thrown, because the dtors won't be run when a Guile exceptions is thrown. gdbscm_parse_function_args currently violates this: void gdbscm_parse_function_args (const char *func_name, int beginning_arg_pos, const SCM *keywords, const char *format, ...) { ... /* Keep track of malloc'd strings. We need to free them upon error. */ std::vector<char *> allocated_strings; ... for (char *ptr : allocated_strings) xfree (ptr); gdbscm_throw (status); /// dtor of "allocated_strings" is not run! } This commit fixes the above making using of gdbscm_wrap. It would be nice if we had a way to make it impossible to write such code. PR guile/23429 has an idea for that, if someone's interested. gdb/ChangeLog: 2018-08-21 Pedro Alves <palves@redhat.com> * guile/scm-utils.c (gdbscm_parse_function_args_1): New, factored out from gdbscm_parse_function_args. (gdbscm_parse_function_args): Rework to use gdbscm_wrap and gdbscm_parse_function_args_1.
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
2018-08-21 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
* guile/scm-utils.c (gdbscm_parse_function_args_1): New, factored
|
||||||
|
out from gdbscm_parse_function_args.
|
||||||
|
(gdbscm_parse_function_args): Rework to use gdbscm_wrap and
|
||||||
|
gdbscm_parse_function_args_1.
|
||||||
|
|
||||||
2018-08-21 Simon Marchi <simon.marchi@ericsson.com>
|
2018-08-21 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
PR gdb/17816
|
PR gdb/17816
|
||||||
|
@ -306,80 +306,18 @@ lookup_keyword (const SCM *keyword_list, SCM keyword)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Utility to parse required, optional, and keyword arguments to Scheme
|
|
||||||
functions. Modelled on PyArg_ParseTupleAndKeywords, but no attempt is made
|
|
||||||
at similarity or functionality.
|
|
||||||
There is no result, if there's an error a Scheme exception is thrown.
|
|
||||||
|
|
||||||
Guile provides scm_c_bind_keyword_arguments, and feel free to use it.
|
/* Helper for gdbscm_parse_function_args that does most of the work,
|
||||||
This is for times when we want a bit more parsing.
|
in a separate function wrapped with gdbscm_wrap so that we can use
|
||||||
|
non-trivial-dtor objects here. The result is #f upon success or a
|
||||||
|
<gdb:exception> object otherwise. */
|
||||||
|
|
||||||
BEGINNING_ARG_POS is the position of the first argument passed to this
|
static SCM
|
||||||
routine. It should be one of the SCM_ARGn values. It could be > SCM_ARG1
|
gdbscm_parse_function_args_1 (const char *func_name,
|
||||||
if the caller chooses not to parse one or more required arguments.
|
int beginning_arg_pos,
|
||||||
|
const SCM *keywords,
|
||||||
KEYWORDS may be NULL if there are no keywords.
|
const char *format, va_list args)
|
||||||
|
|
||||||
FORMAT:
|
|
||||||
s - string -> char *, malloc'd
|
|
||||||
t - boolean (gdb uses "t", for biT?) -> int
|
|
||||||
i - int
|
|
||||||
u - unsigned int
|
|
||||||
l - long
|
|
||||||
n - unsigned long
|
|
||||||
L - longest
|
|
||||||
U - unsigned longest
|
|
||||||
O - random scheme object
|
|
||||||
| - indicates the next set is for optional arguments
|
|
||||||
# - indicates the next set is for keyword arguments (must follow |)
|
|
||||||
. - indicates "rest" arguments are present, this character must appear last
|
|
||||||
|
|
||||||
FORMAT must match the definition from scm_c_{make,define}_gsubr.
|
|
||||||
Required and optional arguments appear in order in the format string.
|
|
||||||
Afterwards, keyword-based arguments are processed. There must be as many
|
|
||||||
remaining characters in the format string as their are keywords.
|
|
||||||
Except for "|#.", the number of characters in the format string must match
|
|
||||||
#required + #optional + #keywords.
|
|
||||||
|
|
||||||
The function is required to be defined in a compatible manner:
|
|
||||||
#required-args and #optional-arguments must match, and rest-arguments
|
|
||||||
must be specified if keyword args are desired, and/or regular "rest" args.
|
|
||||||
|
|
||||||
Example: For this function,
|
|
||||||
scm_c_define_gsubr ("execute", 2, 3, 1, foo);
|
|
||||||
the format string + keyword list could be any of:
|
|
||||||
1) "ss|ttt#tt", { "key1", "key2", NULL }
|
|
||||||
2) "ss|ttt.", { NULL }
|
|
||||||
3) "ss|ttt#t.", { "key1", NULL }
|
|
||||||
|
|
||||||
For required and optional args pass the SCM of the argument, and a
|
|
||||||
pointer to the value to hold the parsed result (type depends on format
|
|
||||||
char). After that pass the SCM containing the "rest" arguments followed
|
|
||||||
by pointers to values to hold parsed keyword arguments, and if specified
|
|
||||||
a pointer to hold the remaining contents of "rest".
|
|
||||||
|
|
||||||
For keyword arguments pass two pointers: the first is a pointer to an int
|
|
||||||
that will contain the position of the argument in the arg list, and the
|
|
||||||
second will contain result of processing the argument. The int pointed
|
|
||||||
to by the first value should be initialized to -1. It can then be used
|
|
||||||
to tell whether the keyword was present.
|
|
||||||
|
|
||||||
If both keyword and rest arguments are present, the caller must pass a
|
|
||||||
pointer to contain the new value of rest (after keyword args have been
|
|
||||||
removed).
|
|
||||||
|
|
||||||
There's currently no way, that I know of, to specify default values for
|
|
||||||
optional arguments in C-provided functions. At the moment they're a
|
|
||||||
work-in-progress. The caller should test SCM_UNBNDP for each optional
|
|
||||||
argument. Unbound optional arguments are ignored. */
|
|
||||||
|
|
||||||
void
|
|
||||||
gdbscm_parse_function_args (const char *func_name,
|
|
||||||
int beginning_arg_pos,
|
|
||||||
const SCM *keywords,
|
|
||||||
const char *format, ...)
|
|
||||||
{
|
{
|
||||||
va_list args;
|
|
||||||
const char *p;
|
const char *p;
|
||||||
int i, have_rest, num_keywords, position;
|
int i, have_rest, num_keywords, position;
|
||||||
int have_optional = 0;
|
int have_optional = 0;
|
||||||
@ -391,8 +329,6 @@ gdbscm_parse_function_args (const char *func_name,
|
|||||||
have_rest = validate_arg_format (format);
|
have_rest = validate_arg_format (format);
|
||||||
num_keywords = count_keywords (keywords);
|
num_keywords = count_keywords (keywords);
|
||||||
|
|
||||||
va_start (args, format);
|
|
||||||
|
|
||||||
p = format;
|
p = format;
|
||||||
position = beginning_arg_pos;
|
position = beginning_arg_pos;
|
||||||
|
|
||||||
@ -511,15 +447,100 @@ gdbscm_parse_function_args (const char *func_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end (args);
|
/* Return anything not-an-exception. */
|
||||||
return;
|
return SCM_BOOL_F;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
va_end (args);
|
|
||||||
for (char *ptr : allocated_strings)
|
for (char *ptr : allocated_strings)
|
||||||
xfree (ptr);
|
xfree (ptr);
|
||||||
gdbscm_throw (status);
|
|
||||||
|
/* Return the exception, which gdbscm_wrap takes care of
|
||||||
|
throwing. */
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Utility to parse required, optional, and keyword arguments to Scheme
|
||||||
|
functions. Modelled on PyArg_ParseTupleAndKeywords, but no attempt is made
|
||||||
|
at similarity or functionality.
|
||||||
|
There is no result, if there's an error a Scheme exception is thrown.
|
||||||
|
|
||||||
|
Guile provides scm_c_bind_keyword_arguments, and feel free to use it.
|
||||||
|
This is for times when we want a bit more parsing.
|
||||||
|
|
||||||
|
BEGINNING_ARG_POS is the position of the first argument passed to this
|
||||||
|
routine. It should be one of the SCM_ARGn values. It could be > SCM_ARG1
|
||||||
|
if the caller chooses not to parse one or more required arguments.
|
||||||
|
|
||||||
|
KEYWORDS may be NULL if there are no keywords.
|
||||||
|
|
||||||
|
FORMAT:
|
||||||
|
s - string -> char *, malloc'd
|
||||||
|
t - boolean (gdb uses "t", for biT?) -> int
|
||||||
|
i - int
|
||||||
|
u - unsigned int
|
||||||
|
l - long
|
||||||
|
n - unsigned long
|
||||||
|
L - longest
|
||||||
|
U - unsigned longest
|
||||||
|
O - random scheme object
|
||||||
|
| - indicates the next set is for optional arguments
|
||||||
|
# - indicates the next set is for keyword arguments (must follow |)
|
||||||
|
. - indicates "rest" arguments are present, this character must appear last
|
||||||
|
|
||||||
|
FORMAT must match the definition from scm_c_{make,define}_gsubr.
|
||||||
|
Required and optional arguments appear in order in the format string.
|
||||||
|
Afterwards, keyword-based arguments are processed. There must be as many
|
||||||
|
remaining characters in the format string as their are keywords.
|
||||||
|
Except for "|#.", the number of characters in the format string must match
|
||||||
|
#required + #optional + #keywords.
|
||||||
|
|
||||||
|
The function is required to be defined in a compatible manner:
|
||||||
|
#required-args and #optional-arguments must match, and rest-arguments
|
||||||
|
must be specified if keyword args are desired, and/or regular "rest" args.
|
||||||
|
|
||||||
|
Example: For this function,
|
||||||
|
scm_c_define_gsubr ("execute", 2, 3, 1, foo);
|
||||||
|
the format string + keyword list could be any of:
|
||||||
|
1) "ss|ttt#tt", { "key1", "key2", NULL }
|
||||||
|
2) "ss|ttt.", { NULL }
|
||||||
|
3) "ss|ttt#t.", { "key1", NULL }
|
||||||
|
|
||||||
|
For required and optional args pass the SCM of the argument, and a
|
||||||
|
pointer to the value to hold the parsed result (type depends on format
|
||||||
|
char). After that pass the SCM containing the "rest" arguments followed
|
||||||
|
by pointers to values to hold parsed keyword arguments, and if specified
|
||||||
|
a pointer to hold the remaining contents of "rest".
|
||||||
|
|
||||||
|
For keyword arguments pass two pointers: the first is a pointer to an int
|
||||||
|
that will contain the position of the argument in the arg list, and the
|
||||||
|
second will contain result of processing the argument. The int pointed
|
||||||
|
to by the first value should be initialized to -1. It can then be used
|
||||||
|
to tell whether the keyword was present.
|
||||||
|
|
||||||
|
If both keyword and rest arguments are present, the caller must pass a
|
||||||
|
pointer to contain the new value of rest (after keyword args have been
|
||||||
|
removed).
|
||||||
|
|
||||||
|
There's currently no way, that I know of, to specify default values for
|
||||||
|
optional arguments in C-provided functions. At the moment they're a
|
||||||
|
work-in-progress. The caller should test SCM_UNBNDP for each optional
|
||||||
|
argument. Unbound optional arguments are ignored. */
|
||||||
|
|
||||||
|
void
|
||||||
|
gdbscm_parse_function_args (const char *func_name,
|
||||||
|
int beginning_arg_pos,
|
||||||
|
const SCM *keywords,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start (args, format);
|
||||||
|
|
||||||
|
gdbscm_wrap (gdbscm_parse_function_args_1, func_name,
|
||||||
|
beginning_arg_pos, keywords, format, args);
|
||||||
|
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return longest L as a scheme object. */
|
/* Return longest L as a scheme object. */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user