GNU Binutils with patches for OS216
Revisión | 50d7492f145a34c6bbe0a5d060b1323d64e1c886 (tree) |
---|---|
Tiempo | 2003-05-13 09:08:58 |
Autor | Jim Blandy <jimb@code...> |
Commiter | Jim Blandy |
Patch from Will Schmidt <willschm@us.ibm.com>:
These changes enable support of PPC64 architecture.
* config/powerpc/ppc64linux.mh: New file.
* config/powerpc/ppc64linux.mt: New file.
* config/powerpc/tm-ppc64linux.h: New file.
* ppc64-linux-tdep.c: New file.
* configure.host: Add clause for powerpc64-*-linux*
* configure.tgt: Add clause for powerpc64-*-linux*
* elfread.c (record_minimal_symbol_and_info): If
DROP_TEXT_NAME_PREFIX_CHAR is #defined, then drop a leading
instance of that char from the names of text symbols.
(elf_symtab_read): If SKIP_DATA_IN_OPD is #defined, ignore data
symbols in the .opd section.
* ppc-linux-nat.c (PTRACE_XFER_TYPE): Change the default for this
to 'long'.
(PPC_PTRACE_POKEUSR_3264, PPC_PTRACE_PEEKUSR_3264,
PPC_PTRACE_POKEDATA_3264, PPC_PTRACE_PEEKDATA_3264): Provide
default definitions for these.
(ARCH64): New macro.
(ppc_wordsize_pid): New function.
(kernel_u_size): Handle 64-bit case.
(ppc_register_u_addr): Same.
(fetch_register): Use the *_3264 requests when
debugging a 64-bit process from a 32-bit GDB.
(store_register): Same.
(GDB_MAX_ALLOCA, child_xfer_memory, udot_info): Copied from
infptrace.c.
(_initialize_ppc_linux_nat): New function, to register our copy of
the udot_info command.
* ppc-linux-tdep.c (TDEP): New macro.
(ppc64_linux_svr4_fetch_link_map_offsets): New function.
(read_memory_addr): Copied from rs6000-tdep.c.
(ppc64_linux_convert_from_func_ptr_addr): New function.
* rs6000-tdep.c (skip_prologue): Recognize more instructions for
saving the 'lr' and 'cr' registers; don't just pre-emptively mask
in the 'st' opcode as soon as we see an 'mflr' or 'mfcr' opcode.
Recognize more instructions for updating the stack pointer, and
loading the TOC pointer.
(registers_powerpc64, registers_a35): New register tables.
(rs6000_gdbarch_init): Register the 64-bit solib functions.
* solib-svr4.c (solib_break_names): If SOLIB_BREAK_NAME is
#defined, include an entry for it.
(enable_break): Call CONVERT_FROM_FUNC_PTR_ADDR when trying to
guess the linker's base address.
* config/powerpc/tm-linux.h
(ppc64_linux_svr4_fetch_link_map_offsets,
ppc64_linux_convert_from_func_ptr_addr): New declarations.
@@ -1,3 +1,52 @@ | ||
1 | +2003-05-12 Will Schmidt <willschm@us.ibm.com> | |
2 | + | |
3 | + These changes enable support of PPC64 architecture. | |
4 | + * config/powerpc/ppc64linux.mh: New file. | |
5 | + * config/powerpc/ppc64linux.mt: New file. | |
6 | + * config/powerpc/tm-ppc64linux.h: New file. | |
7 | + * ppc64-linux-tdep.c: New file. | |
8 | + * configure.host: Add clause for powerpc64-*-linux* | |
9 | + * configure.tgt: Add clause for powerpc64-*-linux* | |
10 | + * elfread.c (record_minimal_symbol_and_info): If | |
11 | + DROP_TEXT_NAME_PREFIX_CHAR is #defined, then drop a leading | |
12 | + instance of that char from the names of text symbols. | |
13 | + (elf_symtab_read): If SKIP_DATA_IN_OPD is #defined, ignore data | |
14 | + symbols in the .opd section. | |
15 | + * ppc-linux-nat.c (PTRACE_XFER_TYPE): Change the default for this | |
16 | + to 'long'. | |
17 | + (PPC_PTRACE_POKEUSR_3264, PPC_PTRACE_PEEKUSR_3264, | |
18 | + PPC_PTRACE_POKEDATA_3264, PPC_PTRACE_PEEKDATA_3264): Provide | |
19 | + default definitions for these. | |
20 | + (ARCH64): New macro. | |
21 | + (ppc_wordsize_pid): New function. | |
22 | + (kernel_u_size): Handle 64-bit case. | |
23 | + (ppc_register_u_addr): Same. | |
24 | + (fetch_register): Use the *_3264 requests when | |
25 | + debugging a 64-bit process from a 32-bit GDB. | |
26 | + (store_register): Same. | |
27 | + (GDB_MAX_ALLOCA, child_xfer_memory, udot_info): Copied from | |
28 | + infptrace.c. | |
29 | + (_initialize_ppc_linux_nat): New function, to register our copy of | |
30 | + the udot_info command. | |
31 | + * ppc-linux-tdep.c (TDEP): New macro. | |
32 | + (ppc64_linux_svr4_fetch_link_map_offsets): New function. | |
33 | + (read_memory_addr): Copied from rs6000-tdep.c. | |
34 | + (ppc64_linux_convert_from_func_ptr_addr): New function. | |
35 | + * rs6000-tdep.c (skip_prologue): Recognize more instructions for | |
36 | + saving the 'lr' and 'cr' registers; don't just pre-emptively mask | |
37 | + in the 'st' opcode as soon as we see an 'mflr' or 'mfcr' opcode. | |
38 | + Recognize more instructions for updating the stack pointer, and | |
39 | + loading the TOC pointer. | |
40 | + (registers_powerpc64, registers_a35): New register tables. | |
41 | + (rs6000_gdbarch_init): Register the 64-bit solib functions. | |
42 | + * solib-svr4.c (solib_break_names): If SOLIB_BREAK_NAME is | |
43 | + #defined, include an entry for it. | |
44 | + (enable_break): Call CONVERT_FROM_FUNC_PTR_ADDR when trying to | |
45 | + guess the linker's base address. | |
46 | + * config/powerpc/tm-linux.h | |
47 | + (ppc64_linux_svr4_fetch_link_map_offsets, | |
48 | + ppc64_linux_convert_from_func_ptr_addr): New declarations. | |
49 | + | |
1 | 50 | 2003-05-08 Andrew Cagney <cagney@redhat.com> |
2 | 51 | |
3 | 52 | * regcache.h (max_register_size): Delete declaration. |
@@ -0,0 +1,14 @@ | ||
1 | +# Host: PowerPC, running Linux | |
2 | + | |
3 | +XM_FILE= xm-linux.h | |
4 | +XM_CLIBS= | |
5 | + | |
6 | +NAT_FILE= nm-linux.h | |
7 | +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \ | |
8 | + core-regset.o ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o \ | |
9 | + gcore.o ppc-sysv-tdep.o | |
10 | + | |
11 | +LOADLIBES = -ldl -lthread_db | |
12 | + | |
13 | +GDBSERVER_DEPFILES= low-linux.o | |
14 | +GDBSERVER_LIBS= -lnss_dns -lnss_files -lresolv |
@@ -0,0 +1,4 @@ | ||
1 | +# Target: PPC running Linux 64bit programs | |
2 | +TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o ppc64-linux-tdep.o solib.o solib-svr4.o solib-legacy.o | |
3 | +TM_FILE= tm-ppc64linux.h | |
4 | + |
@@ -67,4 +67,9 @@ extern int ppc_linux_in_sigtramp (CORE_ADDR pc, char *func_name); | ||
67 | 67 | to be relocated. */ |
68 | 68 | #define SOFUN_ADDRESS_MAYBE_MISSING |
69 | 69 | |
70 | +/* used for ppc64 only, but added here because code is common between ppc and ppc64 */ | |
71 | +struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void); | |
72 | +extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr); | |
73 | + | |
74 | + | |
70 | 75 | #endif /* #ifndef TM_LINUX_H */ |
@@ -0,0 +1,80 @@ | ||
1 | +#ifndef TM_PPC64LINUX_H | |
2 | +#define TM_PPC64LINUX_H | |
3 | + | |
4 | +#include "rs6000/tm-rs6000.h" | |
5 | + | |
6 | +/* Avoid warning from redefinition in tm-sysv4.h (included from tm-linux.h) */ | |
7 | +#undef SKIP_TRAMPOLINE_CODE | |
8 | +#include "tm-linux.h" | |
9 | + | |
10 | +#include "gdbarch.h" | |
11 | +/* Reset these back to the default. Should really fix this for other | |
12 | + powerpc tm.h so it can be chosen at runtime */ | |
13 | +#undef SOFTWARE_SINGLE_STEP_P | |
14 | +#define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_p (current_gdbarch)) | |
15 | +#undef SOFTWARE_SINGLE_STEP | |
16 | +#define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p)) | |
17 | + | |
18 | +#ifdef DEAD_CODE | |
19 | +/* FIXME: tm-linux defines this which a dead interface, as far as I | |
20 | + can tell. The macro is unused and there is no definition for the | |
21 | + function the macro calls. It is here so we know to get rid of it | |
22 | + there. */ | |
23 | +/* Make sure nexti gets the help it needs for debugging assembly code | |
24 | + without symbols */ | |
25 | + | |
26 | +#define AT_SUBROUTINE_CALL_INSTRUCTION_TARGET(prevpc,stoppc) \ | |
27 | + at_subroutine_call_instruction_target(prevpc,stoppc) | |
28 | +extern int at_subroutine_call_instruction_target(); | |
29 | +#endif /* DEAD_CODE */ | |
30 | + | |
31 | +/* We _want_ the SVR4 section offset calculations (see syms_from_objfile() | |
32 | + in symfile.c) */ | |
33 | +#undef IBM6000_TARGET | |
34 | + | |
35 | +/* Default offset from SP where the LR is stored */ | |
36 | +#undef DEFAULT_LR_SAVE | |
37 | +#define DEFAULT_LR_SAVE 16 | |
38 | + | |
39 | +/* Say that we're using ELF, not XCOFF. */ | |
40 | +#define ELF_OBJECT_FORMAT 1 | |
41 | + | |
42 | +/* Say that we're using ELF64 since ABI is closer to XCOFF64. */ | |
43 | +#define ELF64_OBJECT_FORMAT 1 | |
44 | + | |
45 | +#undef PROCESS_LINENUMBER_HOOK | |
46 | + | |
47 | +#undef TEXT_SEGMENT_BASE | |
48 | +#define TEXT_SEGMENT_BASE 1 | |
49 | + | |
50 | +/* don't think it is but it can't hurt (can it?) */ | |
51 | +#define TARGET_BYTE_ORDER_SELECTABLE_P 1 | |
52 | + | |
53 | +/* The value of symbols of type N_SO and N_FUN maybe null when | |
54 | + it shouldn't be. */ | |
55 | +#define SOFUN_ADDRESS_MAYBE_MISSING | |
56 | + | |
57 | +#undef CHILD_SPECIAL_WAITSTATUS | |
58 | + | |
59 | +/* Use generic shared library machinery. */ | |
60 | +#include "solib.h" | |
61 | + | |
62 | +/* function entrypoints have a '.' prepended to them (elfread.c) */ | |
63 | +#define DROP_TEXT_NAME_PREFIX_CHAR '.' | |
64 | +/* skip data symbols if they are from the .opd section (elfread.c) */ | |
65 | +#define SKIP_DATA_IN_OPD | |
66 | + | |
67 | +/* define our own child_xfer_memory() ppc-linux-nat.c */ | |
68 | +#define CHILD_XFER_MEMORY | |
69 | + | |
70 | +#undef bfd_get_start_address | |
71 | +#define bfd_get_start_address(abfd) ppc64_bfd_get_start_address (abfd) | |
72 | +extern CORE_ADDR ppc64_bfd_get_start_address (bfd *); | |
73 | +struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void); | |
74 | +extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr); | |
75 | + | |
76 | +/* define additional name for solib functions (solib-svr4.c) to hinge on. */ | |
77 | +#define SOLIB_BREAK_NAME "._dl_debug_state" | |
78 | + | |
79 | + | |
80 | +#endif /* #ifndef TM_PPC64LINUX_H */ |
@@ -120,6 +120,8 @@ powerpc-*-aix*) gdb_host=aix432 ;; | ||
120 | 120 | powerpc-*-linux*) gdb_host=linux ;; |
121 | 121 | powerpc-*-netbsd*) gdb_host=nbsd ;; |
122 | 122 | |
123 | +powerpc64-*-linux*) gdb_host=ppc64linux ;; | |
124 | + | |
123 | 125 | rs6000-*-lynxos*) gdb_host=rs6000lynx ;; |
124 | 126 | rs6000-*-aix4*) gdb_host=aix4 ;; |
125 | 127 | rs6000-*-*) gdb_host=rs6000 ;; |
@@ -193,6 +193,15 @@ powerpc-*-aix*) gdb_target=aix ;; | ||
193 | 193 | powerpc-*-linux*) gdb_target=linux |
194 | 194 | build_gdbserver=yes |
195 | 195 | ;; |
196 | +powerpc64-*-linux*) gdb_target=ppc64linux | |
197 | + ###HACK -JX | |
198 | + case "${host}" in | |
199 | + powerpc-*-linux*) | |
200 | + ## This host can treat target as native | |
201 | + nativefile=nm-linux.h | |
202 | + ;; | |
203 | + esac | |
204 | + ;; | |
196 | 205 | powerpc-*-vxworks*) gdb_target=vxworks ;; |
197 | 206 | powerpc*-*-*) if test -f ../sim/ppc/Makefile; then |
198 | 207 | gdb_target=ppc-sim |
@@ -141,6 +141,12 @@ record_minimal_symbol_and_info (char *name, CORE_ADDR address, | ||
141 | 141 | if (ms_type == mst_text || ms_type == mst_file_text) |
142 | 142 | address = SMASH_TEXT_ADDRESS (address); |
143 | 143 | |
144 | +#ifdef DROP_TEXT_NAME_PREFIX_CHAR | |
145 | + if ((ms_type == mst_text || ms_type == mst_file_text) | |
146 | + && name[0] == DROP_TEXT_NAME_PREFIX_CHAR) | |
147 | + ++name; | |
148 | +#endif /* DROP_TEXT_NAME_PREFIX_CHAR */ | |
149 | + | |
144 | 150 | return prim_record_minimal_symbol_and_info |
145 | 151 | (name, address, ms_type, info, bfd_section->index, bfd_section, objfile); |
146 | 152 | } |
@@ -363,6 +369,10 @@ elf_symtab_read (struct objfile *objfile, int dynamic) | ||
363 | 369 | { |
364 | 370 | if (sym->section->flags & SEC_LOAD) |
365 | 371 | { |
372 | +#ifdef SKIP_DATA_IN_OPD | |
373 | + if (strcmp(sym->section->name, ".opd") == 0) | |
374 | + continue; | |
375 | +#endif /* SKIP_DATA_IN_OPD */ | |
366 | 376 | ms_type = mst_data; |
367 | 377 | } |
368 | 378 | else |
@@ -444,6 +454,10 @@ elf_symtab_read (struct objfile *objfile, int dynamic) | ||
444 | 454 | symbol processing. */ |
445 | 455 | if (sym->section->flags & SEC_LOAD) |
446 | 456 | { |
457 | +#ifdef SKIP_DATA_IN_OPD | |
458 | + if (strcmp(sym->section->name, ".opd") == 0) | |
459 | + continue; | |
460 | +#endif /* SKIP_DATA_IN_OPD */ | |
447 | 461 | ms_type = mst_file_data; |
448 | 462 | } |
449 | 463 | else |
@@ -48,11 +48,108 @@ | ||
48 | 48 | #define PT_WRITE_U PTRACE_POKEUSR |
49 | 49 | #endif |
50 | 50 | |
51 | -/* Default the type of the ptrace transfer to int. */ | |
51 | +/* Default the type of the ptrace transfer to long. */ | |
52 | 52 | #ifndef PTRACE_XFER_TYPE |
53 | -#define PTRACE_XFER_TYPE int | |
53 | +#define PTRACE_XFER_TYPE long | |
54 | 54 | #endif |
55 | 55 | |
56 | +/* Write DATA into location ADDR within the "user area" on a 64-bit | |
57 | + process from a 32-bit process. */ | |
58 | +#ifndef PPC_PTRACE_POKEUSR_3264 | |
59 | +#define PPC_PTRACE_POKEUSR_3264 0x90 | |
60 | +#endif | |
61 | + | |
62 | +/* Read a register (specified by ADDR) out of the "user area" on a | |
63 | + 64-bit process from a 32-bit process. */ | |
64 | +#ifndef PPC_PTRACE_PEEKUSR_3264 | |
65 | +#define PPC_PTRACE_PEEKUSR_3264 0x91 | |
66 | +#endif | |
67 | + | |
68 | +/* Write word at location ADDR on a 64-bit process from a 32-bit process. */ | |
69 | +#ifndef PPC_PTRACE_POKEDATA_3264 | |
70 | +#define PPC_PTRACE_POKEDATA_3264 0x92 | |
71 | +#endif | |
72 | + | |
73 | +/* Read word at location ADDR on a 64-bit process from a 32-bit | |
74 | + process. */ | |
75 | +#ifndef PPC_PTRACE_PEEKDATA_3264 | |
76 | +#define PPC_PTRACE_PEEKDATA_3264 0x94 | |
77 | +#endif | |
78 | + | |
79 | +#define ARCH64() (REGISTER_RAW_SIZE (0) == 8) | |
80 | + | |
81 | +/* REALLY SHAMELESS HACK: | |
82 | + | |
83 | + 32 bit programs can exec 64 bit programs and so forth. GDB launches | |
84 | + the inferior process by lauching ${SHELL} -c <program and args>. | |
85 | + Fortunately, we know that it only tries to get the PC so we only | |
86 | + have to hack that.. I THINK. | |
87 | + | |
88 | + At this time we are not ready to unify ppc32 and ppc64 as | |
89 | + rs/6000-aix is. and there is know easy way to find out if a process | |
90 | + is running 32 or 64 bits so we have this little hack. | |
91 | + | |
92 | + EVEN MORE SHAMELESS HACK: rs6000-nat.c solves this problem by | |
93 | + expecting the first few ptracex() calls to fail. | |
94 | + | |
95 | +*/ | |
96 | +#include <sys/stat.h> | |
97 | +#include "bfd/elf-bfd.h" | |
98 | +static int | |
99 | +ppc_wordsize_pid(pid_t pid) | |
100 | +{ | |
101 | + static ino_t fino = 0; | |
102 | + static int last = 0; | |
103 | + struct stat sb; | |
104 | + const char fmt[] = "/proc/%u/exe"; | |
105 | + FILE *file; | |
106 | + char *fname = alloca (sizeof(fmt) + 10); /* 10 digit pid.. why not */ | |
107 | + Elf_Internal_Ehdr elfh; | |
108 | + | |
109 | + if ((gdbarch_tdep (current_gdbarch))->wordsize == 4) | |
110 | + return 4; | |
111 | + | |
112 | + sprintf (fname, fmt, pid); | |
113 | + | |
114 | + if (stat(fname, &sb) == -1) | |
115 | + { | |
116 | + internal_error (__FILE__, __LINE__, | |
117 | + "could not stat executable from /proc."); | |
118 | + return 0; | |
119 | + } | |
120 | + | |
121 | + if (fino == sb.st_ino) | |
122 | + return last; | |
123 | + | |
124 | + fino = sb.st_ino; | |
125 | + | |
126 | + /* FIXME: could stat the file and check if inode changed. */ | |
127 | + file = fopen (fname, "rb"); | |
128 | + if (file == NULL) | |
129 | + { | |
130 | + internal_error (__FILE__, __LINE__, | |
131 | + "could not open executable from /proc."); | |
132 | + return 0; | |
133 | + } | |
134 | + | |
135 | + if (fread (elfh.e_ident, EI_NIDENT, 1, file) == 1) | |
136 | + { | |
137 | + if (elfh.e_ident [EI_CLASS] == ELFCLASS64) | |
138 | + last = 8; | |
139 | + else | |
140 | + last = 4; | |
141 | + } | |
142 | + else | |
143 | + { | |
144 | + last = 0; | |
145 | + internal_error (__FILE__, __LINE__, | |
146 | + "could not read executable from /proc."); | |
147 | + } | |
148 | + fclose (file); | |
149 | + | |
150 | + return last; | |
151 | +} | |
152 | + | |
56 | 153 | /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a |
57 | 154 | configure time check. Some older glibc's (for instance 2.2.1) |
58 | 155 | don't have a specific powerpc version of ptrace.h, and fall back on |
@@ -106,7 +203,15 @@ int have_ptrace_getvrregs = 1; | ||
106 | 203 | int |
107 | 204 | kernel_u_size (void) |
108 | 205 | { |
109 | - return (sizeof (struct user)); | |
206 | + if ((gdbarch_tdep (current_gdbarch))->wordsize == sizeof (PTRACE_XFER_TYPE)) | |
207 | + return (sizeof (struct user)); | |
208 | + else | |
209 | + { | |
210 | + /* with a 64-bit kernel, all members of struct user go from 32 | |
211 | + to 64 bit except for the u_comm character array so we can | |
212 | + double everything and subtract sizeof u_comm. */ | |
213 | + return ((sizeof (struct user) * 2) - sizeof (((struct user*)0)->u_comm)); | |
214 | + } | |
110 | 215 | } |
111 | 216 | |
112 | 217 | /* *INDENT-OFF* */ |
@@ -127,32 +232,33 @@ ppc_register_u_addr (int regno) | ||
127 | 232 | { |
128 | 233 | int u_addr = -1; |
129 | 234 | struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); |
235 | + int wordsize = tdep->wordsize; | |
130 | 236 | |
131 | 237 | /* General purpose registers occupy 1 slot each in the buffer */ |
132 | 238 | if (regno >= tdep->ppc_gp0_regnum && regno <= tdep->ppc_gplast_regnum ) |
133 | - u_addr = ((PT_R0 + regno) * 4); | |
239 | + u_addr = ((PT_R0 + regno) * wordsize); | |
134 | 240 | |
135 | 241 | /* Floating point regs: 2 slots each */ |
136 | 242 | if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM) |
137 | - u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4); | |
243 | + u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * wordsize); | |
138 | 244 | |
139 | 245 | /* UISA special purpose registers: 1 slot each */ |
140 | 246 | if (regno == PC_REGNUM) |
141 | - u_addr = PT_NIP * 4; | |
247 | + u_addr = PT_NIP * wordsize; | |
142 | 248 | if (regno == tdep->ppc_lr_regnum) |
143 | - u_addr = PT_LNK * 4; | |
249 | + u_addr = PT_LNK * wordsize; | |
144 | 250 | if (regno == tdep->ppc_cr_regnum) |
145 | - u_addr = PT_CCR * 4; | |
251 | + u_addr = PT_CCR * wordsize; | |
146 | 252 | if (regno == tdep->ppc_xer_regnum) |
147 | - u_addr = PT_XER * 4; | |
253 | + u_addr = PT_XER * wordsize; | |
148 | 254 | if (regno == tdep->ppc_ctr_regnum) |
149 | - u_addr = PT_CTR * 4; | |
255 | + u_addr = PT_CTR * wordsize; | |
150 | 256 | if (regno == tdep->ppc_mq_regnum) |
151 | - u_addr = PT_MQ * 4; | |
257 | + u_addr = PT_MQ * wordsize; | |
152 | 258 | if (regno == tdep->ppc_ps_regnum) |
153 | - u_addr = PT_MSR * 4; | |
259 | + u_addr = PT_MSR * wordsize; | |
154 | 260 | if (regno == tdep->ppc_fpscr_regnum) |
155 | - u_addr = PT_FPSCR * 4; | |
261 | + u_addr = PT_FPSCR * wordsize; | |
156 | 262 | |
157 | 263 | return u_addr; |
158 | 264 | } |
@@ -206,6 +312,16 @@ fetch_register (int tid, int regno) | ||
206 | 312 | unsigned int offset; /* Offset of registers within the u area. */ |
207 | 313 | char buf[MAX_REGISTER_SIZE]; |
208 | 314 | CORE_ADDR regaddr = ppc_register_u_addr (regno); |
315 | + int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize; | |
316 | + | |
317 | + /* Do the easy thing for now which is to silently succeed if we are | |
318 | + attached to a 32-bit process when we are expecting 64-bits */ | |
319 | + if (wordsize != ppc_wordsize_pid(tid)) | |
320 | + { | |
321 | + /* supplying garbage.. but that's ok */ | |
322 | + supply_register (regno, buf); | |
323 | + return; | |
324 | + } | |
209 | 325 | |
210 | 326 | if (altivec_register_p (regno)) |
211 | 327 | { |
@@ -233,8 +349,19 @@ fetch_register (int tid, int regno) | ||
233 | 349 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) |
234 | 350 | { |
235 | 351 | errno = 0; |
236 | - *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, | |
237 | - (PTRACE_ARG3_TYPE) regaddr, 0); | |
352 | + if (wordsize != sizeof (PTRACE_XFER_TYPE)) | |
353 | + { | |
354 | + PTRACE_XFER_TYPE reg; | |
355 | + ptrace (PPC_PTRACE_PEEKUSR_3264, tid, | |
356 | + (PTRACE_ARG3_TYPE) regaddr, ®); | |
357 | + *(PTRACE_XFER_TYPE *) & buf[i] = reg; | |
358 | + } | |
359 | + else | |
360 | + { | |
361 | + *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, | |
362 | + (PTRACE_ARG3_TYPE) regaddr, 0); | |
363 | + } | |
364 | + | |
238 | 365 | regaddr += sizeof (PTRACE_XFER_TYPE); |
239 | 366 | if (errno != 0) |
240 | 367 | { |
@@ -365,6 +492,7 @@ store_register (int tid, int regno) | ||
365 | 492 | register int i; |
366 | 493 | unsigned int offset; /* Offset of registers within the u area. */ |
367 | 494 | char buf[MAX_REGISTER_SIZE]; |
495 | + int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize; | |
368 | 496 | |
369 | 497 | if (altivec_register_p (regno)) |
370 | 498 | { |
@@ -379,8 +507,18 @@ store_register (int tid, int regno) | ||
379 | 507 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) |
380 | 508 | { |
381 | 509 | errno = 0; |
382 | - ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, | |
383 | - *(PTRACE_XFER_TYPE *) & buf[i]); | |
510 | + if (wordsize != sizeof (PTRACE_XFER_TYPE)) | |
511 | + { | |
512 | + PTRACE_XFER_TYPE reg; | |
513 | + ptrace (PPC_PTRACE_POKEUSR_3264, tid, (PTRACE_ARG3_TYPE) regaddr, | |
514 | + *(PTRACE_XFER_TYPE *) & buf[i]); | |
515 | + } | |
516 | + else | |
517 | + { | |
518 | + ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, | |
519 | + *(PTRACE_XFER_TYPE *) & buf[i]); | |
520 | + } | |
521 | + | |
384 | 522 | regaddr += sizeof (PTRACE_XFER_TYPE); |
385 | 523 | |
386 | 524 | if (errno == EIO |
@@ -534,3 +672,243 @@ fill_fpregset (gdb_fpregset_t *fpregsetp, int regno) | ||
534 | 672 | if ((regno == -1) || regno == tdep->ppc_fpscr_regnum) |
535 | 673 | regcache_collect (tdep->ppc_fpscr_regnum, (char *) (*fpregsetp + regi)); |
536 | 674 | } |
675 | + | |
676 | + | |
677 | +#ifdef CHILD_XFER_MEMORY | |
678 | + | |
679 | +/* this is a complete rip off from infptrace.c */ | |
680 | + | |
681 | +#ifndef GDB_MAX_ALLOCA | |
682 | +#define GDB_MAX_ALLOCA 0x1000 | |
683 | +#endif /* GDB_MAX_ALLOCA */ | |
684 | + | |
685 | +/* Copy LEN bytes to or from inferior's memory starting at MEMADDR to | |
686 | + debugger memory starting at MYADDR. Copy to inferior if WRITE is | |
687 | + nonzero. TARGET is ignored. | |
688 | + | |
689 | + Returns the length copied, which is either the LEN argument or | |
690 | + zero. This xfer function does not do partial moves, since | |
691 | + child_ops doesn't allow memory operations to cross below us in the | |
692 | + target stack anyway. */ | |
693 | + | |
694 | +int | |
695 | +child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, | |
696 | + struct mem_attrib *attrib, struct target_ops *target) | |
697 | +{ | |
698 | + int i; | |
699 | + /* Round starting address down to longword boundary. */ | |
700 | + CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE); | |
701 | + /* Round ending address up; get number of longwords that makes. */ | |
702 | + int count = ((((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) | |
703 | + / sizeof (PTRACE_XFER_TYPE)); | |
704 | + int alloc = count * sizeof (PTRACE_XFER_TYPE); | |
705 | + PTRACE_XFER_TYPE *buffer; | |
706 | + struct cleanup *old_chain = NULL; | |
707 | + int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize; | |
708 | + int arch64 = ARCH64(); | |
709 | + | |
710 | + /* Allocate buffer of that many longwords. */ | |
711 | + if (len < GDB_MAX_ALLOCA) | |
712 | + { | |
713 | + buffer = (PTRACE_XFER_TYPE *) alloca (alloc); | |
714 | + } | |
715 | + else | |
716 | + { | |
717 | + buffer = (PTRACE_XFER_TYPE *) xmalloc (alloc); | |
718 | + old_chain = make_cleanup (xfree, buffer); | |
719 | + } | |
720 | + | |
721 | + /* WARNING: from kernel source: "when I and D space are separate, | |
722 | + these will need to be fixed." */ | |
723 | + if (write) | |
724 | + { | |
725 | + /* Fill start and end extra bytes of buffer with existing memory | |
726 | + data. */ | |
727 | + if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE)) | |
728 | + { | |
729 | + /* Need part of initial word -- fetch it. */ | |
730 | + if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64)) | |
731 | + { | |
732 | + buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_ptid), | |
733 | + (PTRACE_ARG3_TYPE) addr, 0); | |
734 | + } | |
735 | + else | |
736 | + { | |
737 | + if (arch64) { | |
738 | + buffer[0] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid), | |
739 | + (unsigned long) addr, 0); | |
740 | + } | |
741 | + else | |
742 | + { | |
743 | + ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid), | |
744 | + (PTRACE_ARG3_TYPE) &addr, buffer); | |
745 | + } | |
746 | + } | |
747 | + } | |
748 | + if (count > 1) /* FIXME, avoid if even boundary. */ | |
749 | + { | |
750 | + CORE_ADDR a64 = (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE)); | |
751 | + if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64)) | |
752 | + { | |
753 | + buffer[count - 1] = ptrace (PT_READ_I, PIDGET (inferior_ptid), | |
754 | + (PTRACE_ARG3_TYPE) a64, 0); | |
755 | + } | |
756 | + else | |
757 | + if (arch64) { | |
758 | + buffer[count-1] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid), | |
759 | + (PTRACE_ARG3_TYPE) &a64, 0); | |
760 | + } | |
761 | + else | |
762 | + { | |
763 | + ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid), | |
764 | + (PTRACE_ARG3_TYPE) &a64, &buffer[count - 1]); | |
765 | + } | |
766 | + } | |
767 | + | |
768 | + /* Copy data to be written over corresponding part of buffer. */ | |
769 | + memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), | |
770 | + myaddr, len); | |
771 | + | |
772 | + /* Write the entire buffer. */ | |
773 | + for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) | |
774 | + { | |
775 | + errno = 0; | |
776 | + if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64)) | |
777 | + { | |
778 | + ptrace (PT_WRITE_D, PIDGET (inferior_ptid), | |
779 | + (PTRACE_ARG3_TYPE) addr, buffer[i]); | |
780 | + } | |
781 | + else | |
782 | + if (arch64) { | |
783 | + ptrace (PT_WRITE_D, PIDGET (inferior_ptid), | |
784 | + (unsigned long) addr, buffer[i]); | |
785 | + } | |
786 | + else | |
787 | + { | |
788 | + ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), | |
789 | + (PTRACE_ARG3_TYPE) &addr, buffer[i]); | |
790 | + } | |
791 | + if (errno) | |
792 | + { | |
793 | + errno = 0; | |
794 | + if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64)) | |
795 | + { | |
796 | + ptrace (PT_WRITE_I, PIDGET (inferior_ptid), | |
797 | + (PTRACE_ARG3_TYPE) addr, buffer[i]); | |
798 | + } | |
799 | + else | |
800 | + if (arch64) { | |
801 | + ptrace (PTRACE_POKEDATA, PIDGET (inferior_ptid), | |
802 | + (PTRACE_ARG3_TYPE) addr, buffer[i]); | |
803 | + } | |
804 | + else | |
805 | + { | |
806 | + ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), | |
807 | + (PTRACE_ARG3_TYPE) &addr, buffer[i]); | |
808 | + } | |
809 | + } | |
810 | + if (errno) | |
811 | + return 0; | |
812 | + } | |
813 | +#ifdef CLEAR_INSN_CACHE | |
814 | + CLEAR_INSN_CACHE (); | |
815 | +#endif | |
816 | + } | |
817 | + else | |
818 | + { | |
819 | + /* Read all the longwords. */ | |
820 | + for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) | |
821 | + { | |
822 | + errno = 0; | |
823 | + if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64)) | |
824 | + { | |
825 | + buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_ptid), | |
826 | + (PTRACE_ARG3_TYPE) addr, 0); | |
827 | + } | |
828 | + else | |
829 | + { | |
830 | + if (arch64) { | |
831 | + buffer[i] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid), | |
832 | + (unsigned long) addr, 0); | |
833 | + } | |
834 | + else | |
835 | + { | |
836 | + ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid), | |
837 | + (PTRACE_ARG3_TYPE) &addr, &buffer[i]); | |
838 | + } | |
839 | + if (errno) | |
840 | + return 0; | |
841 | + QUIT; | |
842 | + } | |
843 | + | |
844 | + /* Copy appropriate bytes out of the buffer. */ | |
845 | + memcpy (myaddr, | |
846 | + (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), | |
847 | + len); | |
848 | + } | |
849 | + } | |
850 | + if (old_chain != NULL) | |
851 | + do_cleanups (old_chain); | |
852 | + return len; | |
853 | + } | |
854 | + | |
855 | + | |
856 | +/* Did not want to add this originally since the kernel will give us a | |
857 | + lot of gargabe (and would probably fail if it wasn't for the | |
858 | + FPU's). But at least you can get the other registers in struct | |
859 | + pt_regs. Perhaps we can get the kernels to co-operate. */ | |
860 | +static void | |
861 | +udot_info (char *dummy1, int dummy2) | |
862 | +{ | |
863 | + int udot_off; /* Offset into user struct */ | |
864 | + int udot_val; /* Value from user struct at udot_off */ | |
865 | + char mess[128]; /* For messages */ | |
866 | + int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize; | |
867 | + | |
868 | + if (!target_has_execution) | |
869 | + { | |
870 | + error ("The program is not being run."); | |
871 | + } | |
872 | + | |
873 | + for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val)) | |
874 | + { | |
875 | + if ((udot_off % 24) == 0) | |
876 | + { | |
877 | + if (udot_off > 0) | |
878 | + { | |
879 | + printf_filtered ("\n"); | |
880 | + } | |
881 | + printf_filtered ("%04x:", udot_off); | |
882 | + } | |
883 | + if (wordsize != sizeof (PTRACE_XFER_TYPE)) | |
884 | + { | |
885 | + PTRACE_XFER_TYPE reg; | |
886 | + /* ptrace will place contents in "data" pointer */ | |
887 | + ptrace (PPC_PTRACE_PEEKUSR_3264, PIDGET (inferior_ptid), | |
888 | + (PTRACE_ARG3_TYPE) udot_off, ®); | |
889 | + udot_val = reg; | |
890 | + } | |
891 | + else | |
892 | + udot_val = ptrace (PT_READ_U, PIDGET (inferior_ptid), | |
893 | + (PTRACE_ARG3_TYPE) udot_off, 0); | |
894 | + if (errno != 0) | |
895 | + { | |
896 | + sprintf (mess, "\nreading user struct at offset 0x%x", udot_off); | |
897 | + perror_with_name (mess); | |
898 | + } | |
899 | + /* Avoid using nonportable (?) "*" in print specs */ | |
900 | + printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val); | |
901 | + } | |
902 | + printf_filtered ("\n"); | |
903 | +} | |
904 | +#endif /* CHILD_XFER_MEMORY */ | |
905 | + | |
906 | +#include "command.h" | |
907 | +void | |
908 | +_initialize_ppc_linux_nat (void) | |
909 | +{ | |
910 | +#ifdef CHILD_XFER_MEMORY | |
911 | + add_info ("udot", udot_info, | |
912 | + "Print contents of kernel ``struct user'' for current child."); | |
913 | +#endif | |
914 | +} |
@@ -63,6 +63,8 @@ | ||
63 | 63 | offsetof(struct sigcontext_struct, handler) == 0x14 */ |
64 | 64 | #define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14) |
65 | 65 | |
66 | +#define TDEP gdbarch_tdep (current_gdbarch) | |
67 | + | |
66 | 68 | /* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */ |
67 | 69 | #define PPC_LINUX_PT_R0 0 |
68 | 70 | #define PPC_LINUX_PT_R1 1 |
@@ -755,3 +757,64 @@ _initialize_ppc_linux_tdep (void) | ||
755 | 757 | ppc_linux_init_abi); |
756 | 758 | add_core_fns (&ppc_linux_regset_core_fns); |
757 | 759 | } |
760 | + | |
761 | +struct link_map_offsets * | |
762 | + ppc64_linux_svr4_fetch_link_map_offsets (void) | |
763 | +{ | |
764 | + static struct link_map_offsets lmo; | |
765 | + static struct link_map_offsets *lmp = NULL; | |
766 | + | |
767 | + if (lmp == NULL) | |
768 | + { | |
769 | + lmp = &lmo; | |
770 | + | |
771 | + lmo.r_debug_size = 16;/* The actual size is xx bytes, but | |
772 | + this is all we need. */ | |
773 | + lmo.r_map_offset = 8; | |
774 | + lmo.r_map_size = 8; | |
775 | + lmo.link_map_size = 40; /* The actual size is xxx bytes, but | |
776 | + this is all we need. */ | |
777 | + lmo.l_addr_offset = 0; | |
778 | + lmo.l_addr_size = 8; | |
779 | + lmo.l_name_offset = 8; | |
780 | + lmo.l_name_size = 8; | |
781 | + lmo.l_next_offset = 24; | |
782 | + lmo.l_next_size = 8; | |
783 | + lmo.l_prev_offset = 32; | |
784 | + lmo.l_prev_size = 8; | |
785 | + } | |
786 | + | |
787 | + return lmp; | |
788 | +} | |
789 | + | |
790 | + | |
791 | +/* Support for CONVERT_FROM_FUNC_PTR_ADDR(ADDR). | |
792 | + Duplicate of RS6000 function, except ppc64_linux requires relocated address. */ | |
793 | +static CORE_ADDR | |
794 | +read_memory_addr (CORE_ADDR memaddr, int len) | |
795 | +{ | |
796 | + return read_memory_unsigned_integer (memaddr, len); | |
797 | +} | |
798 | + | |
799 | + | |
800 | +CORE_ADDR | |
801 | +ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr) | |
802 | +{ | |
803 | + long long my_adder; | |
804 | + struct obj_section *s; | |
805 | + CORE_ADDR retval; | |
806 | + extern struct obj_section *find_pc_section(CORE_ADDR); | |
807 | + | |
808 | + /* this should be the base address that the object (containing the func_ptr_addr) is loaded at. */ | |
809 | + my_adder = 0x7fe0000000; | |
810 | + | |
811 | + s = find_pc_section (my_adder + addr); | |
812 | + if (s && s->the_bfd_section->flags & SEC_CODE) | |
813 | + return addr; | |
814 | + | |
815 | + /* ADDR is in the data space, so it's a special function pointer. */ | |
816 | + retval = read_memory_addr (my_adder + addr, TDEP->wordsize); | |
817 | + /* printf("reading 0x%lx ",my_adder+addr); */ | |
818 | + /* printf("ppc64...convert_func_ptr addr:0x%lx new:0x%lx\n",addr,retval); */ | |
819 | + return retval; | |
820 | +} |
@@ -0,0 +1,80 @@ | ||
1 | +/* Target-dependent code for GDB, the GNU debugger. | |
2 | + | |
3 | + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, | |
4 | + 2000, 2001 Free Software Foundation, Inc. | |
5 | + | |
6 | + This file is part of GDB. | |
7 | + | |
8 | + This program is free software; you can redistribute it and/or modify | |
9 | + it under the terms of the GNU General Public License as published by | |
10 | + the Free Software Foundation; either version 2 of the License, or | |
11 | + (at your option) any later version. | |
12 | + | |
13 | + This program is distributed in the hope that it will be useful, | |
14 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + GNU General Public License for more details. | |
17 | + | |
18 | + You should have received a copy of the GNU General Public License | |
19 | + along with this program; if not, write to the Free Software | |
20 | + Foundation, Inc., 59 Temple Place - Suite 330, | |
21 | + Boston, MA 02111-1307, USA. */ | |
22 | + | |
23 | +#include "defs.h" | |
24 | + | |
25 | + | |
26 | +/* These elfcore fuctions are defined in libbfd.a but only when host | |
27 | + == target, once we can convince the bfd to supply it these can go */ | |
28 | +#define _SYSCALL32 | |
29 | +#include "bfd.h" | |
30 | +#include "sysdep.h" | |
31 | +#include "bfdlink.h" | |
32 | +#include "libbfd.h" | |
33 | +#define ARCH_SIZE 0 | |
34 | +#include "elf-bfd.h" | |
35 | +#include "libiberty.h" | |
36 | +#include <sys/procfs.h> | |
37 | + | |
38 | + | |
39 | +/* | |
40 | + * Initialization | |
41 | + */ | |
42 | +void | |
43 | +_initialize_ppc64_linux_tdep (void) | |
44 | +{ | |
45 | + /* hardware/kernel supports single stepping */ | |
46 | + set_gdbarch_software_single_step (current_gdbarch, NULL); | |
47 | +} | |
48 | + | |
49 | +/* the start_address stored in the bfd is a function descriptor */ | |
50 | +#include "gdb/target.h" | |
51 | +CORE_ADDR | |
52 | +ppc64_bfd_get_start_address (bfd *abfd) | |
53 | +{ | |
54 | + extern struct target_ops exec_ops; | |
55 | + CORE_ADDR myaddr; | |
56 | + xfer_memory(abfd->start_address, (char *)&myaddr, 8, 0, 0, &exec_ops); | |
57 | + return myaddr; | |
58 | +} | |
59 | + | |
60 | +/* Fetch (and possibly build) an appropriate link_map_offsets | |
61 | + structure for GNU/Linux PPC targets using the struct offsets | |
62 | + defined in link.h (but without actual reference to that file). | |
63 | + | |
64 | + This makes it possible to access GNU/Linux PPC shared libraries | |
65 | + from a GDB that was not built on an GNU/Linux PPC host (for cross | |
66 | + debugging). | |
67 | + | |
68 | +*/ | |
69 | +#include "gdbcore.h" | |
70 | +#include "symfile.h" | |
71 | +#include "objfiles.h" | |
72 | + | |
73 | +#include "ppc-tdep.h" | |
74 | +#define TDEP gdbarch_tdep (current_gdbarch) | |
75 | + | |
76 | +static CORE_ADDR | |
77 | +read_memory_addr (CORE_ADDR memaddr, int len) | |
78 | +{ | |
79 | + return read_memory_unsigned_integer (memaddr, len); | |
80 | +} |
@@ -529,13 +529,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata) | ||
529 | 529 | |
530 | 530 | if ((op & 0xfc1fffff) == 0x7c0802a6) |
531 | 531 | { /* mflr Rx */ |
532 | - lr_reg = (op & 0x03e00000) | 0x90010000; | |
532 | + lr_reg = (op & 0x03e00000); | |
533 | 533 | continue; |
534 | 534 | |
535 | 535 | } |
536 | 536 | else if ((op & 0xfc1fffff) == 0x7c000026) |
537 | 537 | { /* mfcr Rx */ |
538 | - cr_reg = (op & 0x03e00000) | 0x90010000; | |
538 | + cr_reg = (op & 0x03e00000); | |
539 | 539 | continue; |
540 | 540 | |
541 | 541 | } |
@@ -561,7 +561,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata) | ||
561 | 561 | { |
562 | 562 | fdata->saved_gpr = reg; |
563 | 563 | if ((op & 0xfc1f0003) == 0xf8010000) |
564 | - op = (op >> 1) << 1; | |
564 | + op &= ~3UL; | |
565 | 565 | fdata->gpr_offset = SIGNED_SHORT (op) + offset; |
566 | 566 | } |
567 | 567 | continue; |
@@ -593,19 +593,49 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata) | ||
593 | 593 | continue; |
594 | 594 | |
595 | 595 | } |
596 | - else if (lr_reg != -1 && (op & 0xffff0000) == lr_reg) | |
597 | - { /* st Rx,NUM(r1) | |
598 | - where Rx == lr */ | |
599 | - fdata->lr_offset = SIGNED_SHORT (op) + offset; | |
596 | + else if (lr_reg != -1 && | |
597 | + /* std Rx || stdu Rx */ | |
598 | + (((op & 0xffff0000) == (lr_reg | 0xf8010000)) || | |
599 | + /* stw Rx */ | |
600 | + ((op & 0xffff0000) == (lr_reg | 0x90010000)) || | |
601 | + /* stwu Rx */ | |
602 | + ((op & 0xffff0000) == (lr_reg | 0x94010000)))) | |
603 | + { /* where Rx == lr */ | |
604 | + fdata->lr_offset = offset; | |
600 | 605 | fdata->nosavedpc = 0; |
601 | 606 | lr_reg = 0; |
607 | + if ((op & 0xfc000003) == 0xf8000000 || /* std Rx */ | |
608 | + (op & 0xfc000000) == 0x90000000) /* stw Rx */ | |
609 | + { | |
610 | + /* does not update r1 add d to lr_offset */ | |
611 | + fdata->lr_offset = SIGNED_SHORT (op); | |
612 | + } | |
613 | + continue; | |
614 | + | |
615 | + } | |
616 | + else if (cr_reg != -1 && | |
617 | + /* std Rx || stdu Rx */ | |
618 | + (((op & 0xffff0000) == (cr_reg | 0xf8010000)) || | |
619 | + /* stw Rx */ | |
620 | + ((op & 0xffff0000) == (cr_reg | 0x90010000)) || | |
621 | + /* stwu Rx */ | |
622 | + ((op & 0xffff0000) == (cr_reg | 0x94010000)))) | |
623 | + { /* where Rx == cr */ | |
624 | + fdata->cr_offset = offset; | |
625 | + cr_reg = 0; | |
626 | + if ((op & 0xfc000003) == 0xf8000000 || | |
627 | + (op & 0xfc000000) == 0x90000000) | |
628 | + { | |
629 | + /* does not update r1 add d to cr_offset */ | |
630 | + fdata->cr_offset += SIGNED_SHORT (op); | |
631 | + } | |
602 | 632 | continue; |
603 | 633 | |
604 | 634 | } |
605 | - else if (cr_reg != -1 && (op & 0xffff0000) == cr_reg) | |
606 | - { /* st Rx,NUM(r1) | |
635 | + else if (cr_reg != -1 && (op & 0xffff0003) == cr_reg) | |
636 | + { /* std Rx,NUM(r1) || stdu Rx,NUM(r1) | |
607 | 637 | where Rx == cr */ |
608 | - fdata->cr_offset = SIGNED_SHORT (op) + offset; | |
638 | + fdata->cr_offset = SIGNED_SHORT (op & ~3UL) + offset; | |
609 | 639 | cr_reg = 0; |
610 | 640 | continue; |
611 | 641 |
@@ -650,30 +680,41 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata) | ||
650 | 680 | this branch */ |
651 | 681 | continue; |
652 | 682 | |
653 | - /* update stack pointer */ | |
654 | 683 | } |
655 | - else if ((op & 0xffff0000) == 0x94210000 || /* stu r1,NUM(r1) */ | |
656 | - (op & 0xffff0003) == 0xf8210001) /* stdu r1,NUM(r1) */ | |
657 | - { | |
684 | + /* update stack pointer */ | |
685 | + else if ((op & 0xfc1f0000) == 0x94010000) | |
686 | + { /* stu rX,NUM(r1) || stwu rX,NUM(r1) */ | |
658 | 687 | fdata->frameless = 0; |
659 | - if ((op & 0xffff0003) == 0xf8210001) | |
660 | - op = (op >> 1) << 1; | |
661 | 688 | fdata->offset = SIGNED_SHORT (op); |
662 | 689 | offset = fdata->offset; |
663 | 690 | continue; |
664 | - | |
665 | 691 | } |
666 | - else if (op == 0x7c21016e) | |
667 | - { /* stwux 1,1,0 */ | |
692 | + else if ((op & 0xfc1f016a) == 0x7c01016e) | |
693 | + { /* stwux rX,r1,rY */ | |
694 | + /* no way to figure out what r1 is going to be */ | |
695 | + fdata->frameless = 0; | |
696 | + offset = fdata->offset; | |
697 | + continue; | |
698 | + } | |
699 | + else if ((op & 0xfc1f0003) == 0xf8010001) | |
700 | + { /* stdu rX,NUM(r1) */ | |
701 | + fdata->frameless = 0; | |
702 | + fdata->offset = SIGNED_SHORT (op & ~3UL); | |
703 | + offset = fdata->offset; | |
704 | + continue; | |
705 | + } | |
706 | + else if ((op & 0xfc1f016a) == 0x7c01016a) | |
707 | + { /* stdux rX,r1,rY */ | |
708 | + /* no way to figure out what r1 is going to be */ | |
668 | 709 | fdata->frameless = 0; |
669 | 710 | offset = fdata->offset; |
670 | 711 | continue; |
671 | - | |
672 | - /* Load up minimal toc pointer */ | |
673 | 712 | } |
674 | - else if ((op >> 22) == 0x20f | |
713 | + /* Load up minimal toc pointer */ | |
714 | + else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */ | |
715 | + (op >> 22) == 0x3af) /* ld r31,... or ld r30,... */ | |
675 | 716 | && !minimal_toc_loaded) |
676 | - { /* l r31,... or l r30,... */ | |
717 | + { | |
677 | 718 | minimal_toc_loaded = 1; |
678 | 719 | continue; |
679 | 720 |
@@ -2456,6 +2497,44 @@ static const struct reg registers_7400[] = | ||
2456 | 2497 | /* FIXME? Add more registers? */ |
2457 | 2498 | }; |
2458 | 2499 | |
2500 | + | |
2501 | +/* PowerPC UISA - a PPC64 processor as viewed by user-level code. */ | |
2502 | +/* Should be able to use the common registers_powerpc[] here, however | |
2503 | + it does not define an fpscr, though both linux and aix get one from | |
2504 | + ptrace(). Can only assume that there is a 32-bit core our there | |
2505 | + that does not have an fpscr. I think we can assert that all 64-bit | |
2506 | + cores do. */ | |
2507 | +static const struct reg registers_powerpc64[] = | |
2508 | +{ | |
2509 | + COMMON_UISA_REGS, | |
2510 | + /* SPRs */ | |
2511 | + /* 66 */ R4(cr), R(lr), R(ctr), R4(xer), | |
2512 | + /* 70 */ R4(fpscr), R0 /* mq? */ | |
2513 | +}; | |
2514 | + | |
2515 | +static const struct reg registers_a35[] = | |
2516 | +{ | |
2517 | + COMMON_UISA_REGS, | |
2518 | + /* SPRs */ | |
2519 | + /* 66 */ R4(cr), R(lr), R(ctr), R4(xer), | |
2520 | + /* 70 */ R4(fpscr), R0 /* mq? */, | |
2521 | + /* 72 */ R(dabr), R(iabr), R4(dsisr), | |
2522 | + /* 75 */ R(dar), R4(dec), R(sdr1), R(srr0), R(srr1), | |
2523 | + /* 80 */ R(sprg0), R(sprg1), R(sprg2), R(sprg3), | |
2524 | + /* 84 */ R64(asr), R4(ear), R4(tbl), R4(tbu), | |
2525 | + /* 88 */ R(ibat0u), R(ibat0l), R(ibat1u), R(ibat1l), | |
2526 | + /* 92 */ R(ibat2u), R(ibat2l), R(ibat3u), R(ibat3l), | |
2527 | + /* 96 */ R(dbat0u), R(dbat0l), R(dbat1u), R(dbat1l), | |
2528 | + /* 100 */ R(dbat2u), R(dbat2l), R(dbat3u), R(dbat3l), | |
2529 | + /* 104 */ R(pir), R4(mmcr0), | |
2530 | + /* 106..121 segment regs 0..15 */ | |
2531 | + /* 106 */ R(sr0), R(sr1), R(sr2), R(sr3), | |
2532 | + /* 110 */ R(sr4), R(sr5), R(sr6), R(sr7), | |
2533 | + /* 114 */ R(sr8), R(sr9), R(sr10), R(sr11), | |
2534 | + /* 118 */ R(sr12), R(sr13), R(sr14), R(sr15), | |
2535 | + /* 122 */ R4(pvr) /* processor version register */ | |
2536 | +}; | |
2537 | + | |
2459 | 2538 | /* Motorola e500. */ |
2460 | 2539 | static const struct reg registers_e500[] = |
2461 | 2540 | { |
@@ -2956,6 +3035,15 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
2956 | 3035 | descriptors). */ |
2957 | 3036 | set_gdbarch_convert_from_func_ptr_addr (gdbarch, |
2958 | 3037 | rs6000_convert_from_func_ptr_addr); |
3038 | + | |
3039 | + /* wordsize 8, ppc64 linux functions */ | |
3040 | + if (osabi == ELFOSABI_LINUX) | |
3041 | + { | |
3042 | + set_solib_svr4_fetch_link_map_offsets | |
3043 | + (gdbarch, ppc64_linux_svr4_fetch_link_map_offsets); | |
3044 | + set_gdbarch_convert_from_func_ptr_addr | |
3045 | + (gdbarch, ppc64_linux_convert_from_func_ptr_addr); | |
3046 | + } | |
2959 | 3047 | } |
2960 | 3048 | set_gdbarch_frame_args_address (gdbarch, rs6000_frame_args_address); |
2961 | 3049 | set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address); |
@@ -76,6 +76,9 @@ struct lm_info | ||
76 | 76 | |
77 | 77 | static char *solib_break_names[] = |
78 | 78 | { |
79 | +#if defined (SOLIB_BREAK_NAME) | |
80 | + SOLIB_BREAK_NAME, | |
81 | +#endif | |
79 | 82 | "r_debug_state", |
80 | 83 | "_r_debug_state", |
81 | 84 | "_dl_debug_state", |
@@ -1015,7 +1018,7 @@ enable_break (void) | ||
1015 | 1018 | the current pc (which should point at the entry point for the |
1016 | 1019 | dynamic linker) and subtracting the offset of the entry point. */ |
1017 | 1020 | if (!load_addr_found) |
1018 | - load_addr = read_pc () - tmp_bfd->start_address; | |
1021 | + load_addr = read_pc () - CONVERT_FROM_FUNC_PTR_ADDR(tmp_bfd->start_address); | |
1019 | 1022 | |
1020 | 1023 | /* Record the relocated start and end address of the dynamic linker |
1021 | 1024 | text and plt section for svr4_in_dynsym_resolve_code. */ |