From 9391c9977e934749cd973dd55cde6df7f787b6ec Mon Sep 17 00:00:00 2001 From: Fred Fish Date: Sun, 26 May 1996 21:41:40 +0000 Subject: [PATCH] Changes from: David Mosberger-Tang * NEWS: Add Alpha Linux as a new native configuration. * mdebugread.c (parse_symbol): When we find a malloc() symbol with return type VOID, assume no debugging info is available for that object file and patch the return value into VOID *. Otherwise, operations requiring an implicit call to malloc() will fail. * infrun.c (wait_for_inferior): The criterion to detect entering a sigtramp handler is now: (a) the current pc is inside a sigtramp handler, (b) the previous pc is not in a sigtramp handler, and (c) the current stack pointer is "inner" than the old one. Condition (c) is new to avoid mistaking a return from a signal handler into sigtramp as a new sigtramp invocation. * dcache.c (struct dcache_block): Declare addr as CORE_ADDR. An int may not be big enough to hold an address. (dcache_hit): Ditto. (dcache_peek_byte): Fix indentation. * configure.in (alpha-*-linux*): Add target. * configure: Rebuild * config/alpha/tm-alpha.h (PROC_DESC_IS_DYN_SIGTRAMP): New macro. (SET_PROC_DESC_IS_DYN_SIGTRAMP): Ditto. (DYNAMIC_SIGTRAMP_OFFSET): Ditto. (SIGCONTEXT_ADDR): Ditto. (FRAME_PAST_SIGTRAMP_FRAME): Ditto. * config/alpha/alpha-linux.mh: New file. * config/alpha/alpha-linux.mt: Ditto. * config/alpha/nm-linux.h: Ditto. * config/alpha/tm-alphalinux.h: Ditto. * config/alpha/xm-alphalinux.h: Ditto. * config/alpha/xm-alphaosf.h: Renamed from xm-alpha.h. * config/alpha/alpha-osf1.mh (XM_FILE): Change from xm-alpha.h to xm-alphaosf.h. * config/alpha/alpha-osf2.mh: Ditto. * blockframe.c (find_pc_partial_function): Pass PC to SIGTRAMP_START and SIGTRAMP_END macros for the benefit of systems that detect sigtramp code via designated code sequences (as is the case for Linux/Alpha, for example). * config/i386/tm-i386bsd.h: Change SIGTRAMP_START and SIGTRAMP_END to ignore new PC argument. * config/m68k/tm-hp300bsd.h: Ditto. * config/vax/tm-vax.h: Ditto. * alpha-tdep.c (alpha_linux_sigtramp_offset): New function. (alpha_osf_skip_sigtramp_frame): Ditto. (push_sigtramp_desc): Ditto. (alpha_find_saved_regs): Use SIGCONTEXT_ADDR macro to extract sigcontext address from frame. (alpha_saved_pc_after_call): When in sigtramp, use alpha_frame_saved_pc() instead of read-register(). (after_prologue): When inside a dynamically generated sigtramp function, there is no prologue, so return address of first instruction. (alpha_in_prologue): Fix typo in comment. (find_proc_desc): Use macro DYNAMIC_SIGTRAMP_OFFSET to determine whether we're inside a dynamicaly generated sigtramp function. If so, create and push and appropriate procedure descriptor. (alpha_frame_chain): Use macro FRAME_PAST_SIGTRAMP_FRAME to obtain the frame past a sigtramp frame (if the current frame is indeed a sigtramp function). (init_extra_frame_info): Don't read next frame register off of stack-pointer when inside a dynamiccaly generated sigtramp. (alpha_pop_frame): Also unlink and destroy procedure descriptors created for dynamically generated sigtramp functions. * alpha-nat.c: When compiling under Linux, include and instead of --- gdb/ChangeLog | 77 ++++++++++++++++++ gdb/NEWS | 6 ++ gdb/alpha-nat.c | 7 +- gdb/alpha-tdep.c | 147 +++++++++++++++++++++++++++++----- gdb/config/alpha/xm-alpha.h | 29 ------- gdb/config/i386/tm-i386bsd.h | 4 +- gdb/config/m68k/tm-hp300bsd.h | 4 +- gdb/config/vax/tm-vax.h | 4 +- gdb/configure | 2 + gdb/configure.in | 2 + gdb/dcache.c | 8 +- gdb/mdebugread.c | 18 ++++- 12 files changed, 246 insertions(+), 62 deletions(-) delete mode 100644 gdb/config/alpha/xm-alpha.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2c1748f34d3..fbb447ad502 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,80 @@ +Sun May 26 14:14:49 1996 Fred Fish + + Changes from: David Mosberger-Tang + + * NEWS: Add Alpha Linux as a new native configuration. + + * mdebugread.c (parse_symbol): When we find a malloc() symbol with + return type VOID, assume no debugging info is available for that + object file and patch the return value into VOID *. Otherwise, + operations requiring an implicit call to malloc() will fail. + + * infrun.c (wait_for_inferior): The criterion to detect entering a + sigtramp handler is now: (a) the current pc is inside a sigtramp + handler, (b) the previous pc is not in a sigtramp handler, and (c) + the current stack pointer is "inner" than the old one. Condition + (c) is new to avoid mistaking a return from a signal handler into + sigtramp as a new sigtramp invocation. + + * dcache.c (struct dcache_block): Declare addr as CORE_ADDR. An + int may not be big enough to hold an address. + (dcache_hit): Ditto. + (dcache_peek_byte): Fix indentation. + + * configure.in (alpha-*-linux*): Add target. + * configure: Rebuild + + * config/alpha/tm-alpha.h (PROC_DESC_IS_DYN_SIGTRAMP): New macro. + (SET_PROC_DESC_IS_DYN_SIGTRAMP): Ditto. + (DYNAMIC_SIGTRAMP_OFFSET): Ditto. + (SIGCONTEXT_ADDR): Ditto. + (FRAME_PAST_SIGTRAMP_FRAME): Ditto. + + * config/alpha/alpha-linux.mh: New file. + * config/alpha/alpha-linux.mt: Ditto. + * config/alpha/nm-linux.h: Ditto. + * config/alpha/tm-alphalinux.h: Ditto. + * config/alpha/xm-alphalinux.h: Ditto. + * config/alpha/xm-alphaosf.h: Renamed from xm-alpha.h. + * config/alpha/alpha-osf1.mh (XM_FILE): Change from xm-alpha.h to + xm-alphaosf.h. + * config/alpha/alpha-osf2.mh: Ditto. + + * blockframe.c (find_pc_partial_function): Pass PC to + SIGTRAMP_START and SIGTRAMP_END macros for the benefit of systems + that detect sigtramp code via designated code sequences (as is the + case for Linux/Alpha, for example). + + * config/i386/tm-i386bsd.h: Change SIGTRAMP_START and SIGTRAMP_END + to ignore new PC argument. + * config/m68k/tm-hp300bsd.h: Ditto. + * config/vax/tm-vax.h: Ditto. + + * alpha-tdep.c (alpha_linux_sigtramp_offset): New function. + (alpha_osf_skip_sigtramp_frame): Ditto. + (push_sigtramp_desc): Ditto. + (alpha_find_saved_regs): Use SIGCONTEXT_ADDR macro to extract + sigcontext address from frame. + (alpha_saved_pc_after_call): When in sigtramp, use + alpha_frame_saved_pc() instead of read-register(). + (after_prologue): When inside a dynamically generated sigtramp + function, there is no prologue, so return address of first + instruction. + (alpha_in_prologue): Fix typo in comment. + (find_proc_desc): Use macro DYNAMIC_SIGTRAMP_OFFSET to determine + whether we're inside a dynamicaly generated sigtramp function. If + so, create and push and appropriate procedure descriptor. + (alpha_frame_chain): Use macro FRAME_PAST_SIGTRAMP_FRAME to obtain + the frame past a sigtramp frame (if the current frame is indeed a + sigtramp function). + (init_extra_frame_info): Don't read next frame register off of + stack-pointer when inside a dynamiccaly generated sigtramp. + (alpha_pop_frame): Also unlink and destroy procedure descriptors + created for dynamically generated sigtramp functions. + + * alpha-nat.c: When compiling under Linux, include and + instead of + Thu May 23 15:13:56 1996 Jeffrey A Law (law@cygnus.com) * h8300-tdep.c (IS_PUSH): Refine. diff --git a/gdb/NEWS b/gdb/NEWS index 979a878e4da..c6c3841c203 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -1,6 +1,12 @@ What has changed in GDB? (Organized release by release) +*** Changes since GDB-4.16: + +* New native configurations + +Alpha Linux alpha-*-linux* + *** Changes in GDB-4.16: * New native configurations diff --git a/gdb/alpha-nat.c b/gdb/alpha-nat.c index b027116804f..0102a7bc4b9 100644 --- a/gdb/alpha-nat.c +++ b/gdb/alpha-nat.c @@ -22,7 +22,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdbcore.h" #include "target.h" #include -#include +#ifdef __linux__ +# include +# include +#else +# include +#endif #include /* Size of elements in jmpbuf */ diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index 7fbf6422e70..d778bf22e29 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -131,6 +131,110 @@ struct linked_proc_info struct linked_proc_info *next; } *linked_proc_desc_table = NULL; + +/* Under Linux, signal handler invocations can be identified by the + designated code sequence that is used to return from a signal + handler. In particular, the return address of a signal handler + points to the following sequence (the first instruction is quadword + aligned): + + bis $30,$30,$16 + addq $31,0x67,$0 + call_pal callsys + + Each instruction has a unique encoding, so we simply attempt to + match the instruction the pc is pointing to with any of the above + instructions. If there is a hit, we know the offset to the start + of the designated sequence and can then check whether we really are + executing in a designated sequence. If not, -1 is returned, + otherwise the offset from the start of the desingated sequence is + returned. + + There is a slight chance of false hits: code could jump into the + middle of the designated sequence, in which case there is no + guarantee that we are in the middle of a sigreturn syscall. Don't + think this will be a problem in praxis, though. +*/ +long +alpha_linux_sigtramp_offset (CORE_ADDR pc) +{ + unsigned int i[3], w; + long off, res; + + if (read_memory_nobpt(pc, (char *) &w, 4) != 0) + return -1; + + off = -1; + switch (w) + { + case 0x47de0410: off = 0; break; /* bis $30,$30,$16 */ + case 0x43ecf400: off = 4; break; /* addq $31,0x67,$0 */ + case 0x00000083: off = 8; break; /* call_pal callsys */ + default: return -1; + } + pc -= off; + if (pc & 0x7) + { + /* designated sequence is not quadword aligned */ + return -1; + } + + if (read_memory_nobpt(pc, (char *) i, sizeof(i)) != 0) + return -1; + + if (i[0] == 0x47de0410 && i[1] == 0x43ecf400 && i[2] == 0x00000083) + return off; + + return -1; +} + + +/* Under OSF/1, the __sigtramp routine is frameless and has a frame + size of zero, but we are able to backtrace through it. */ +CORE_ADDR +alpha_osf_skip_sigtramp_frame (frame, pc) + struct frame_info *frame; + CORE_ADDR pc; +{ + char *name; + find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL, (CORE_ADDR *)NULL); + if (IN_SIGTRAMP (pc, name)) + return frame->frame; + else + return 0; +} + + +/* Dynamically create a signal-handler caller procedure descriptor for + the signal-handler return code starting at address LOW_ADDR. The + descriptor is added to the linked_proc_desc_table. */ + +alpha_extra_func_info_t +push_sigtramp_desc (CORE_ADDR low_addr) +{ + struct linked_proc_info *link; + alpha_extra_func_info_t proc_desc; + + link = (struct linked_proc_info *) + xmalloc (sizeof (struct linked_proc_info)); + link->next = linked_proc_desc_table; + linked_proc_desc_table = link; + + proc_desc = &link->info; + + proc_desc->numargs = 0; + PROC_LOW_ADDR (proc_desc) = low_addr; + PROC_HIGH_ADDR (proc_desc) = low_addr + 3 * 4; + PROC_DUMMY_FRAME (proc_desc) = 0; + PROC_FRAME_OFFSET (proc_desc) = 0x298; /* sizeof(struct sigcontext_struct) */ + PROC_FRAME_REG (proc_desc) = SP_REGNUM; + PROC_REG_MASK (proc_desc) = 0xffff; + PROC_FREG_MASK (proc_desc) = 0xffff; + PROC_PC_REG (proc_desc) = 26; + PROC_LOCALOFF (proc_desc) = 0; + SET_PROC_DESC_IS_DYN_SIGTRAMP (proc_desc); +} + /* Guaranteed to set frame->saved_regs to some values (it never leaves it NULL). */ @@ -161,14 +265,9 @@ alpha_find_saved_regs (frame) #endif if (frame->signal_handler_caller) { - CORE_ADDR sigcontext_pointer_addr; CORE_ADDR sigcontext_addr; - if (frame->next) - sigcontext_pointer_addr = frame->next->frame; - else - sigcontext_pointer_addr = frame->frame; - sigcontext_addr = read_memory_integer(sigcontext_pointer_addr, 8); + sigcontext_addr = SIGCONTEXT_ADDR (frame); for (ireg = 0; ireg < 32; ireg++) { reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8; @@ -285,7 +384,10 @@ alpha_saved_pc_after_call (frame) proc_desc = find_proc_desc (pc, frame->next); pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM; - return read_register (pcreg); + if (frame->signal_handler_caller) + return alpha_frame_saved_pc (frame); + else + return read_register (pcreg); } @@ -471,6 +573,9 @@ after_prologue (pc, proc_desc) if (proc_desc) { + if (PROC_DESC_IS_DYN_SIGTRAMP (proc_desc)) + return PROC_LOW_ADDR (proc_desc); /* "prologue" is in kernel */ + /* If function is frameless, then we need to do it the hard way. I strongly suspect that frameless always means prologueless... */ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM @@ -493,7 +598,7 @@ after_prologue (pc, proc_desc) } /* Return non-zero if we *might* be in a function prologue. Return zero if we - are definatly *not* in a function prologue. */ + are definitively *not* in a function prologue. */ static int alpha_in_prologue (pc, proc_desc) @@ -599,6 +704,8 @@ find_proc_desc (pc, next_frame) } else { + long offset; + /* Is linked_proc_desc_table really necessary? It only seems to be used by procedure call dummys. However, the procedures being called ought to have their own proc_descs, and even if they don't, @@ -610,6 +717,12 @@ find_proc_desc (pc, next_frame) && PROC_HIGH_ADDR(&link->info) > pc) return &link->info; + /* If PC is inside a dynamically generated sigtramp handler, + create and push a procedure descriptor for that code: */ + offset = DYNAMIC_SIGTRAMP_OFFSET (pc); + if (offset >= 0) + return push_sigtramp_desc (pc - offset); + if (startaddr == 0) startaddr = heuristic_proc_start (pc); @@ -650,17 +763,7 @@ alpha_frame_chain(frame) /* The previous frame from a sigtramp frame might be frameless and have frame size zero. */ && !frame->signal_handler_caller) - { - /* The alpha __sigtramp routine is frameless and has a frame size - of zero, but we are able to backtrace through it. */ - char *name; - find_pc_partial_function (saved_pc, &name, - (CORE_ADDR *)NULL, (CORE_ADDR *)NULL); - if (IN_SIGTRAMP (saved_pc, name)) - return frame->frame; - else - return 0; - } + return FRAME_PAST_SIGTRAMP_FRAME (frame, saved_pc); else return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc)) + PROC_FRAME_OFFSET(proc_desc); @@ -696,7 +799,8 @@ init_extra_frame_info (frame) /* This may not be quite right, if proc has a real frame register. Get the value of the frame relative sp, procedure might have been interrupted by a signal at it's very start. */ - else if (frame->pc == PROC_LOW_ADDR (proc_desc) && !PROC_DESC_IS_DUMMY (proc_desc)) + else if (frame->pc == PROC_LOW_ADDR (proc_desc) + && !PROC_DESC_IS_DYN_SIGTRAMP (proc_desc)) frame->frame = read_next_frame_reg (frame->next, SP_REGNUM); else frame->frame = read_next_frame_reg (frame->next, PROC_FRAME_REG (proc_desc)) @@ -984,7 +1088,8 @@ alpha_pop_frame() write_register (SP_REGNUM, new_sp); flush_cached_frames (); - if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc)) + if (proc_desc && (PROC_DESC_IS_DUMMY(proc_desc) + || PROC_DESC_IS_DYN_SIGTRAMP (proc_desc))) { struct linked_proc_info *pi_ptr, *prev_ptr; diff --git a/gdb/config/alpha/xm-alpha.h b/gdb/config/alpha/xm-alpha.h deleted file mode 100644 index d9f85be51ed..00000000000 --- a/gdb/config/alpha/xm-alpha.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Host definitions for GDB running on an alpha under OSF/1 - Copyright (C) 1992, 1993 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 2 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, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#if !defined (HOST_BYTE_ORDER) -#define HOST_BYTE_ORDER LITTLE_ENDIAN -#endif - -/* The alpha has no siginterrupt routine. */ -#define NO_SIGINTERRUPT - -/* HAVE_SGTTY also works, but we have termios, so use it. */ - -#define HAVE_TERMIOS diff --git a/gdb/config/i386/tm-i386bsd.h b/gdb/config/i386/tm-i386bsd.h index 0b0e3d93917..8b8c3a9708a 100644 --- a/gdb/config/i386/tm-i386bsd.h +++ b/gdb/config/i386/tm-i386bsd.h @@ -32,8 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ the user area. Using constants here allows for cross debugging. These are tested for BSDI but should work on 386BSD. */ -#define SIGTRAMP_START 0xfdbfdfc0 -#define SIGTRAMP_END 0xfdbfe000 +#define SIGTRAMP_START(pc) 0xfdbfdfc0 +#define SIGTRAMP_END(pc) 0xfdbfe000 /* Saved Pc. Get it from sigcontext if within sigtramp. */ diff --git a/gdb/config/m68k/tm-hp300bsd.h b/gdb/config/m68k/tm-hp300bsd.h index 1c4871d3685..cdd75dc881a 100644 --- a/gdb/config/m68k/tm-hp300bsd.h +++ b/gdb/config/m68k/tm-hp300bsd.h @@ -52,8 +52,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* For 4.4, it is actually right 20 bytes *before* STACK_END_ADDR, so include that in the area we test for. */ -#define SIGTRAMP_START (STACK_END_ADDR - 20) -#define SIGTRAMP_END (STACK_END_ADDR + TARGET_UPAGES * TARGET_NBPG) +#define SIGTRAMP_START(pc) (STACK_END_ADDR - 20) +#define SIGTRAMP_END(pc) (STACK_END_ADDR + TARGET_UPAGES * TARGET_NBPG) /* Address of end of stack space. */ diff --git a/gdb/config/vax/tm-vax.h b/gdb/config/vax/tm-vax.h index 1e5dacd1933..7e9774d3c50 100644 --- a/gdb/config/vax/tm-vax.h +++ b/gdb/config/vax/tm-vax.h @@ -63,8 +63,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* On the VAX, sigtramp is in the u area. Can't check the exact addresses because for cross-debugging we don't have VAX include files around. This should be close enough. */ -#define SIGTRAMP_START STACK_END_ADDR -#define SIGTRAMP_END 0x80000000 +#define SIGTRAMP_START(pc) STACK_END_ADDR +#define SIGTRAMP_END(pc) 0x80000000 /* Stack grows downward. */ diff --git a/gdb/configure b/gdb/configure index cd53d46183b..13619779067 100755 --- a/gdb/configure +++ b/gdb/configure @@ -3194,6 +3194,7 @@ case "${host}" in a29k-*-*) gdb_host=ultra3 ;; +alpha-*-linux*) gdb_host=alpha-linux ;; alpha-*-osf1*) gdb_host=alpha-osf1 ;; alpha-*-osf2*) gdb_host=alpha-osf2 ;; alpha-*-osf[3456789]*) gdb_host=alpha-osf3 ;; @@ -3351,6 +3352,7 @@ a29k-*-sym1*) gdb_target=ultra3 ;; a29k-*-udi*) gdb_target=a29k-udi ;; a29k-*-vxworks*) gdb_target=vx29k ;; +alpha-*-linux*) gdb_target=alpha-linux ;; alpha-*-osf*) gdb_target=alpha-osf1 ;; # start-sanitize-arc diff --git a/gdb/configure.in b/gdb/configure.in index 5023140ac7e..f5f5bdb54db 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -305,6 +305,7 @@ a29k-*-*) gdb_host=ultra3 ;; alpha-*-osf1*) gdb_host=alpha-osf1 ;; alpha-*-osf2*) gdb_host=alpha-osf2 ;; alpha-*-osf[3456789]*) gdb_host=alpha-osf3 ;; +alpha-*-linux*) gdb_host=alpha-linux ;; arm-*-*) gdb_host=arm ;; @@ -460,6 +461,7 @@ a29k-*-udi*) gdb_target=a29k-udi ;; a29k-*-vxworks*) gdb_target=vx29k ;; alpha-*-osf*) gdb_target=alpha-osf1 ;; +alpha-*-linux*) gdb_target=alpha-linux ;; # start-sanitize-arc arc-*-*) gdb_target=arc ;; diff --git a/gdb/dcache.c b/gdb/dcache.c index f110a0c0b4f..60caa29077f 100644 --- a/gdb/dcache.c +++ b/gdb/dcache.c @@ -111,7 +111,7 @@ struct dcache_block { struct dcache_block *p; /* next in list */ - unsigned int addr; /* Address for which data is recorded. */ + CORE_ADDR addr; /* Address for which data is recorded. */ char data[LINE_SIZE]; /* bytes at given address */ unsigned char state[LINE_SIZE]; /* what state the data is in */ @@ -155,7 +155,7 @@ static int dcache_peek_byte PARAMS ((DCACHE *dcache, CORE_ADDR addr, char *ptr)); static struct dcache_block * -dcache_hit PARAMS ((DCACHE *dcache, unsigned int addr)); +dcache_hit PARAMS ((DCACHE *dcache, CORE_ADDR addr)); static int dcache_write_line PARAMS ((DCACHE *dcache,struct dcache_block *db)); @@ -207,7 +207,7 @@ dcache_flush (dcache) static struct dcache_block * dcache_hit (dcache, addr) DCACHE *dcache; - unsigned int addr; + CORE_ADDR addr; { register struct dcache_block *db; @@ -338,7 +338,7 @@ dcache_peek_byte (dcache, addr, ptr) else db = dcache_alloc (dcache); immediate_quit++; - db->addr = MASK (addr); + db->addr = MASK (addr); while (done < LINE_SIZE) { int try = diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c index 3fe4f962c88..89015ba96b2 100644 --- a/gdb/mdebugread.c +++ b/gdb/mdebugread.c @@ -835,7 +835,23 @@ parse_symbol (sh, ax, ext_sh, bigend, section_offsets) if (sh->sc == scUndefined || sh->sc == scNil) t = mdebug_type_int; else - t = parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name); + { + t = parse_type (cur_fd, ax, sh->index + 1, 0, bigend, name); + if (STREQ(name, "malloc") && t->code == TYPE_CODE_VOID) + { + /* I don't know why, but, at least under Linux/Alpha, + when linking against a malloc without debugging + symbols, its read as a function returning void---this + is bad because it means we cannot call functions with + string arguments interactively; i.e., "call + printf("howdy\n")" would fail with the error message + "program has no memory available". To avoid this, we + patch up the type and make it void* + instead. (davidm@azstarnet.com) + */ + t = t->pointer_type; + } + } b = top_stack->cur_block; if (sh->st == stProc) {