8388016d7f
After the previous patch, on Fedora 27 (glibc 2.26), if you try calling strlen in the inferior, you now get: (top-gdb) p strlen ("hello") '__strlen_avx2' has unknown return type; cast the call to its declared return type This is correct, because __strlen_avx2 is written in assembly. We can improve on this though -- if the final ifunc resolved/target function has no debug info, but the ifunc _resolver_ does have debug info, we can try extracting the final function's type from the type that the resolver returns. E.g.,: typedef size_t (*strlen_t) (const char*); size_t my_strlen (const char *) { /* some implementation */ } strlen_t strlen_resolver (unsigned long hwcap) { return my_strlen; } extern size_t strlen (const char *s); __typeof (strlen) strlen __attribute__ ((ifunc ("strlen_resolver"))); In the strlen example above, the resolver returns strlen_t, which is a typedef for pointer to a function that returns size_t. "strlen_t" is the type of both the user-visible "strlen", and of the the target function that implements it. This patch teaches GDB to extract that type. This is done for actual inferior function calls (in infcall.c), and for ptype (in eval_call). By the time we get to either of these places, we've already lost the original symbol/minsym, and only have values and types to work with. Hence the changes to c-exp.y and evaluate_var_msym_value, to ensure that we propagate the ifunc minsymbol's info. The change to make ifunc symbols have no/unknown return type exposes a latent problem -- gdb.compile/compile-ifunc.exp calls a no-debug-info function, but we did not warn about it. The test is fixed by this commit too. gdb/ChangeLog: 2018-04-26 Pedro Alves <palves@redhat.com> * blockframe.c (find_gnu_ifunc_target_type): New function. (find_function_type): New. * eval.c (evaluate_var_msym_value): For GNU ifunc types, always return a value with a memory address. (eval_call): For calls to GNU ifunc functions, try to find the type of the target function from the type that the resolver returns. * gdbtypes.c (objfile_type): Don't install a return type for ifunc symbols. * infcall.c (find_function_return_type): Delete. (find_function_addr): Add 'function_type' parameter. For calls to GNU ifunc functions, try to find the type of the target function from the type that the resolver returns, and return it via FUNCTION_TYPE. (call_function_by_hand_dummy): Adjust to use the function type returned by find_function_addr. (find_function_addr): Add 'function_type' parameter and move description here. * symtab.h (find_function_type, find_gnu_ifunc_target_type): New declarations. gdb/testsuite/ChangeLog: 2018-04-26 Pedro Alves <palves@redhat.com> * gdb.compile/compile-ifunc.exp: Also expect "function has unknown return type" warnings.
76 lines
2.7 KiB
C
76 lines
2.7 KiB
C
/* Perform an inferior function call, for GDB, the GNU debugger.
|
|
|
|
Copyright (C) 2003-2018 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef INFCALL_H
|
|
#define INFCALL_H
|
|
|
|
#include "dummy-frame.h"
|
|
|
|
struct value;
|
|
struct type;
|
|
|
|
/* Determine a function's address and its return type from its value.
|
|
If the function is a GNU ifunc, then return the address of the
|
|
target function, and set *FUNCTION_TYPE to the target function's
|
|
type, and *RETVAL_TYPE to the target function's return type.
|
|
Calls error() if the function is not valid for calling. */
|
|
|
|
extern CORE_ADDR find_function_addr (struct value *function,
|
|
struct type **retval_type,
|
|
struct type **function_type = NULL);
|
|
|
|
/* Perform a function call in the inferior.
|
|
|
|
ARGS is a vector of values of arguments (NARGS of them). FUNCTION
|
|
is a value, the function to be called. Returns a value
|
|
representing what the function returned. May fail to return, if a
|
|
breakpoint or signal is hit during the execution of the function.
|
|
|
|
DFEAULT_RETURN_TYPE is used as function return type if the return
|
|
type is unknown. This is used when calling functions with no debug
|
|
info.
|
|
|
|
ARGS is modified to contain coerced values. */
|
|
|
|
extern struct value *call_function_by_hand (struct value *function,
|
|
type *default_return_type,
|
|
int nargs,
|
|
struct value **args);
|
|
|
|
/* Similar to call_function_by_hand and additional call
|
|
register_dummy_frame_dtor with DUMMY_DTOR and DUMMY_DTOR_DATA for the
|
|
created inferior call dummy frame. */
|
|
|
|
extern struct value *
|
|
call_function_by_hand_dummy (struct value *function,
|
|
type *default_return_type,
|
|
int nargs,
|
|
struct value **args,
|
|
dummy_frame_dtor_ftype *dummy_dtor,
|
|
void *dummy_dtor_data);
|
|
|
|
/* Throw an error indicating that the user tried to call a function
|
|
that has unknown return type. FUNC_NAME is the name of the
|
|
function to be included in the error message; may be NULL, in which
|
|
case the error message doesn't include a function name. */
|
|
|
|
extern void error_call_unknown_return_type (const char *func_name);
|
|
|
|
#endif
|