Index: gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.288 diff -u -p -r1.288 gdbarch.sh --- gdbarch.sh 14 Nov 2003 21:22:42 -0000 1.288 +++ gdbarch.sh 2 Dec 2003 03:52:38 -0000 @@ -771,6 +771,24 @@ F::FETCH_POINTER_ARGUMENT:CORE_ADDR:fetc # Return the appropriate register set for a core file section with # name SECT_NAME and size SECT_SIZE. M:::const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size + +# Return nonzero if PC points to the first "effective" instruction of +# the function starting at FUNC_START. +# +# The default implementation which should be appropriate for most +# targets is to return nonzero if PC is equal to FUNC_START. However, +# it can happen that the address of a subroutine call instruction +# is changed to jump slightly after the begining of the function, +# thus making the "effective" function start address a bit different +# from the start address read from the symbol table or the debugging +# information. +# +# For instance, on alpha-tru64, the first two instructions of a function +# are often setting up the GP. The linker sometimes determines that +# these instructions are not needed for the proper execution of the +# program and therefore virtually optimizes them out by changing the +# jump address to branch 2 instructions later. +f:2:AT_FUNCTION_START:int:at_function_start:CORE_ADDR pc, CORE_ADDR func_start:pc, func_start::0:default_at_function_start::0 EOF } Index: arch-utils.c =================================================================== RCS file: /cvs/src/src/gdb/arch-utils.c,v retrieving revision 1.108 diff -u -p -r1.108 arch-utils.c --- arch-utils.c 14 Nov 2003 21:22:42 -0000 1.108 +++ arch-utils.c 2 Dec 2003 03:52:39 -0000 @@ -370,6 +370,12 @@ default_stabs_argument_has_addr (struct return 0; } +int +default_at_function_start (CORE_ADDR pc, CORE_ADDR func_start) +{ + return pc == func_start; +} + /* Functions to manipulate the endianness of the target. */ Index: arch-utils.h =================================================================== RCS file: /cvs/src/src/gdb/arch-utils.h,v retrieving revision 1.65 diff -u -p -r1.65 arch-utils.h --- arch-utils.h 23 Nov 2003 21:32:42 -0000 1.65 +++ arch-utils.h 2 Dec 2003 03:52:39 -0000 @@ -142,6 +142,8 @@ extern void legacy_value_to_register (st extern int default_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type); +extern int default_at_function_start (CORE_ADDR pc, CORE_ADDR func_start); + /* For compatibility with older architectures, returns (LEGACY_SIM_REGNO_IGNORE) when the register doesn't have a valid name. */ Index: infrun.c =================================================================== RCS file: /cvs/src/src/gdb/infrun.c,v retrieving revision 1.122 diff -u -p -r1.122 infrun.c --- infrun.c 25 Nov 2003 16:01:36 -0000 1.122 +++ infrun.c 2 Dec 2003 03:52:41 -0000 @@ -2472,7 +2472,7 @@ process_event_stop_test: return; } - if (((stop_pc == ecs->stop_func_start /* Quick test */ + if (((AT_FUNCTION_START (stop_pc, ecs->stop_func_start) || in_prologue (stop_pc, ecs->stop_func_start)) && !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name)) || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name) Index: alpha-osf1-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/alpha-osf1-tdep.c,v retrieving revision 1.16 diff -u -p -r1.16 alpha-osf1-tdep.c --- alpha-osf1-tdep.c 27 Aug 2003 19:02:03 -0000 1.16 +++ alpha-osf1-tdep.c 2 Dec 2003 03:52:41 -0000 @@ -45,6 +45,47 @@ alpha_osf1_sigcontext_addr (struct frame return (read_memory_integer (get_frame_base (frame), 8)); } +static int +alpha_osf1_at_function_start (CORE_ADDR pc, CORE_ADDR func_start) +{ + /* A function prologue typically starts with 2 instructions setting + up the GP. But the linker sometimes changes the jump address of + subroutine calls because it has determined that these 2 instructions + do not make any difference in the execution of the program. So it + has virtually optimized them out by changing the jump address + inside the function call to branch just after these 2 instructions. + + As a consequence, the "effective" start address of a given function + can be either the first instruction of this function, or the third + instruction if the first two instructions are setting up the GP. + + It is important to recognize these two cases during a "next" in + order to properly detect function calls that land into a prologueless + function which first two instructions have been shunted by the linker. */ + + if (pc == func_start) + return 1; + + if (pc == func_start + 8) + { + unsigned int inst; + + /* ldah $gp,n($t12) */ + inst = alpha_read_insn (func_start); + if ((inst & 0xffff0000) != 0x27bb0000) + return 0; + + /* lda $gp,n($gp) */ + inst = alpha_read_insn (func_start + 4); + if ((inst & 0xffff0000) != 0x23bd0000) + return 0; + + return 1; + } + + return 0; +} + static void alpha_osf1_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) @@ -59,6 +100,7 @@ alpha_osf1_init_abi (struct gdbarch_info on multi-processor machines. We need to use software single stepping instead. */ set_gdbarch_software_single_step (gdbarch, alpha_software_single_step); + set_gdbarch_at_function_start (gdbarch, alpha_osf1_at_function_start); tdep->sigcontext_addr = alpha_osf1_sigcontext_addr;