diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 99f0db879b..59dd921e6e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2000-02-24 Kevin Buettner + + * ppc-linux-tdep.c (ppc_sysv_abi_push_arguments): Put address + of return structure in r3 if necessary. + (ppc_linux_memory_remove_breakpoints): New function. + * rs6000-tdep.c (skip_prologue): Make sure that the cases + for storing either cr or lr to the stack only handle those + cases. (I.e, don't let these cases match 0x00000000 which is + found found in the shared library trampoline prior to the + loading of the shared library.) + * config/powerpc/tm-linux.h (ppc_linux_memory_remove_breakpoint): + Declare. + (MEMORY_REMOVE_BREAKPOINT): Define. + Wed Feb 23 23:27:48 2000 Andrew Cagney * hppah-nat.c: Include "gdb_wait.h" instead of . diff --git a/gdb/config/powerpc/tm-linux.h b/gdb/config/powerpc/tm-linux.h index 271c302c41..43fa60ffd4 100644 --- a/gdb/config/powerpc/tm-linux.h +++ b/gdb/config/powerpc/tm-linux.h @@ -93,6 +93,13 @@ CORE_ADDR ppc_sysv_abi_push_arguments PARAMS ((int, struct value **, CORE_ADDR, #define PROLOGUE_FIRSTLINE_OVERLAP #endif +/* Needed to handled the self-modifying code situation due to the dynamic + linker. */ +int ppc_linux_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache); +#undef MEMORY_REMOVE_BREAKPOINT +#define MEMORY_REMOVE_BREAKPOINT(addr, contents_cache) \ + ppc_linux_memory_remove_breakpoint(addr, contents_cache) + /* N_FUN symbols in shared libaries have 0 for their values and need to be relocated. */ #define SOFUN_ADDRESS_MAYBE_MISSING diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index b7182f90da..0716eddb97 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -522,6 +522,14 @@ ppc_sysv_abi_push_arguments (nargs, args, sp, struct_return, struct_addr) structoffset = argoffset + argstkspace; freg = 1; greg = 3; + /* Fill in r3 with the return structure, if any */ + if (struct_return) + { + char val_buf[4]; + store_address (val_buf, 4, struct_addr); + memcpy (®isters[REGISTER_BYTE (greg)], val_buf, 4); + greg++; + } /* Now fill in the registers and stack... */ for (argno = 0; argno < nargs; argno++) { @@ -606,3 +614,29 @@ ppc_sysv_abi_push_arguments (nargs, args, sp, struct_return, struct_addr) target_store_registers (-1); return sp; } + +/* This version of ppc_linux_memory_remove_breakpoints handles the + case of self modifying code */ +int +ppc_linux_memory_remove_breakpoint (CORE_ADDR addr, char *contents_cache) +{ + unsigned char *bp; + int val; + int bplen; + char old_contents[BREAKPOINT_MAX]; + + /* Determine appropriate breakpoint contents and size for this address. */ + bp = BREAKPOINT_FROM_PC (&addr, &bplen); + if (bp == NULL) + error ("Software breakpoints not implemented for this target."); + + val = target_read_memory (addr, old_contents, bplen); + + /* If our breakpoint is no longer at the address, this means that the + program modified the code on us, so it is wrong to put back the + old value */ + if (val == 0 && memcmp (bp, old_contents, bplen) == 0) + val = target_write_memory (addr, contents_cache, bplen); + + return val; +} diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 29ca4ca6b9..ca094c74cf 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -313,8 +313,8 @@ skip_prologue (pc, fdata) char buf[4]; unsigned long op; long offset = 0; - int lr_reg = 0; - int cr_reg = 0; + int lr_reg = -1; + int cr_reg = -1; int reg; int framep = 0; int minimal_toc_loaded = 0; @@ -391,7 +391,7 @@ skip_prologue (pc, fdata) continue; } - else if ((op & 0xffff0000) == lr_reg) + else if (lr_reg != -1 && (op & 0xffff0000) == lr_reg) { /* st Rx,NUM(r1) where Rx == lr */ fdata->lr_offset = SIGNED_SHORT (op) + offset; @@ -400,7 +400,7 @@ skip_prologue (pc, fdata) continue; } - else if ((op & 0xffff0000) == cr_reg) + else if (cr_reg != -1 && (op & 0xffff0000) == cr_reg) { /* st Rx,NUM(r1) where Rx == cr */ fdata->cr_offset = SIGNED_SHORT (op) + offset;