[RFC/RFA] Deal with -g1 generated DWARF2 debug info

Mark Kettenis
2005-12-04T18:59:59Z

In an attempt to improve backtraces in bug reports, we now build
libraries with -g1 on OpenBSD. This revealed an interesting gdb
issue. A few testsuite tests now FAILed with:

No memory available to program: call to malloc failed

That's pretty annoying, since it makes passing strings to C functions
basicallt impossible. I noticed that where previously we had:

(gdb) ptype malloc
type = int ()

with -g1 we get:

(gdb) ptype malloc
type = void ()

As a result GDB thinks there is no return value from malloc and things
the malloc call failed.

The cause of the problem is that DWARF2 doesn't really have the
possibility to indicate that it doesn't know the return type of a
function. The absence of DW_AT_type for a DW_TAG_subprogram indicates
a void function. Indeed the debug info generated by -g1 for malloc
looks like:

$ readelf -wi /usr/lib/libc.so.38.4:
...
<1><af59>: Abbrev Number: 2 (DW_TAG_subprogram)
DW_AT_name : (indirect string, offset: 0x6484): imalloc
DW_AT_decl_file : 1
DW_AT_decl_line : 1123
DW_AT_low_pc : 0x67ca0
DW_AT_high_pc : 0x67d9f
DW_AT_frame_base : 1 byte block: 57 (DW_OP_reg7)
...

My proposal to deal with this issue is to check in
valops.c:find_function_in_inferior() whether the function is
prototyped or not. If the function isn't prototyped, fall back on the
code that's already there that uses the minimal symbol info and
creates the return value type "by hand".

Mark

Index: ChangeLog
from Mark Kettenis <kettenis@gnu.org>

* valops.c (find_function_in_inferior): Only use full symbol info
if it is prototyped.

Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.161
diff -u -p -r1.161 valops.c
--- valops.c 27 May 2005 04:39:32 -0000 1.161
+++ valops.c 4 Dec 2005 18:44:39 -0000
@@ -141,37 +141,36 @@ struct value *
find_function_in_inferior (const char *name)
{
struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
sym = lookup_symbol (name, 0, VAR_DOMAIN, 0, NULL);
if (sym != NULL)
{
if (SYMBOL_CLASS (sym) != LOC_BLOCK)
- {
- error (_("\"%s\" exists in this program but is not a function."),
- name);
- }
- return value_of_variable (sym, NULL);
+ error (_("\"%s\" exists in this program but is not a function."),
+ name);
+
+ if (TYPE_PROTOTYPED (SYMBOL_TYPE (sym)))
+ return value_of_variable (sym, NULL);
}
- else
+
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol != NULL)
{
- struct minimal_symbol *msymbol = lookup_minimal_symbol (name, NULL, NULL);
- if (msymbol != NULL)
- {
- struct type *type;
- CORE_ADDR maddr;
- type = lookup_pointer_type (builtin_type_char);
- type = lookup_function_type (type);
- type = lookup_pointer_type (type);
- maddr = SYMBOL_VALUE_ADDRESS (msymbol);
- return value_from_pointer (type, maddr);
- }
- else
- {
- if (!target_has_execution)
- error (_("evaluation of this expression requires the target program to be active"));
- else
- error (_("evaluation of this expression requires the program to have a function \"%s\"."), name);
- }
+ struct type *type;
+ CORE_ADDR maddr;
+
+ type = lookup_pointer_type (builtin_type_char);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ maddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ return value_from_pointer (type, maddr);
}
+
+ if (!target_has_execution)
+ error (_("evaluation of this expression requires the target program to be active"));
+ else
+ error (_("evaluation of this expression requires the program to have a function \"%s\"."), name);
}

/* Allocate NBYTES of space in the inferior using the inferior's malloc