GNU Binutils with patches for OS216
修訂 | f218947cb8901642879d499fc63dd2bd32b5cb03 (tree) |
---|---|
時間 | 2015-10-16 05:25:49 |
作者 | Paul Koning <paul_koning@dell...> |
Commiter | Paul Koning |
convert corelow to to_xclose
This converts corelow to be a to_xclose target. It moves all the
corelow-related globals into a new subclass of target_ops and arranges
for core_open to push an instance of this.
This is preparatory work for multi-target. After this patch, corelow
doesn't rely on global state and multiple instances can readily be
instantiated.
2014-07-29 Tom Tromey <tromey@redhat.com>
* corelow.c (struct core_target_ops_with_data): New struct.
(core_vec, core_gdbarch, core_data): Remove. Now fields of
core_target_ops_with_data.
(sniff_core_bfd): Add core_gdbarch parameter.
(get_core_target_ops): New function.
(core_xclose): Rename from core_close. Update for
core_target_ops_with_data. Free the target.
(core_close_cleanup): Rename parameter. Update.
(core_open): Use TARGET_NEW. Update.
(get_core_register_section, get_core_registers, core_files_info)
(core_xfer_partial, core_read_description, core_pid_to_str): Use
get_core_target_ops. Update.
(init_core_ops): Set to_xclose, not to_close.
* target.c (allocate_target): New function.
* target.h (allocate_target): Declare.
(TARGET_NEW): New macro.
@@ -56,31 +56,36 @@ | ||
56 | 56 | |
57 | 57 | static struct core_fns *core_file_fns = NULL; |
58 | 58 | |
59 | -/* The core_fns for a core file handler that is prepared to read the | |
60 | - core file currently open on core_bfd. */ | |
59 | +/* A subclass of target_ops that also holds data for a core | |
60 | + target. */ | |
61 | 61 | |
62 | -static struct core_fns *core_vec = NULL; | |
62 | +struct core_target_ops_with_data | |
63 | +{ | |
64 | + /* The base class. */ | |
63 | 65 | |
64 | -/* FIXME: kettenis/20031023: Eventually this variable should | |
65 | - disappear. */ | |
66 | + struct target_ops base; | |
66 | 67 | |
67 | -static struct gdbarch *core_gdbarch = NULL; | |
68 | + /* The core_fns for a core file handler that is prepared to read the | |
69 | + core file currently open on core_bfd. */ | |
68 | 70 | |
69 | -/* Per-core data. Currently, only the section table. Note that these | |
70 | - target sections are *not* mapped in the current address spaces' set | |
71 | - of target sections --- those should come only from pure executable | |
72 | - or shared library bfds. The core bfd sections are an | |
73 | - implementation detail of the core target, just like ptrace is for | |
74 | - unix child targets. */ | |
75 | -static struct target_section_table *core_data; | |
71 | + struct core_fns *core_vec; | |
76 | 72 | |
77 | -static void core_files_info (struct target_ops *); | |
73 | + /* FIXME: kettenis/20031023: Eventually this variable should | |
74 | + disappear. */ | |
78 | 75 | |
79 | -static struct core_fns *sniff_core_bfd (bfd *); | |
76 | + struct gdbarch *core_gdbarch; | |
80 | 77 | |
81 | -static int gdb_check_format (bfd *); | |
78 | + /* The section table. Note that these target sections are *not* | |
79 | + mapped in the current address spaces' set of target sections --- | |
80 | + those should come only from pure executable or shared library | |
81 | + bfds. The core bfd sections are an implementation detail of the | |
82 | + core target, just like ptrace is for unix child targets. */ | |
83 | + struct target_section_table core_data; | |
84 | +}; | |
82 | 85 | |
83 | -static void core_close (struct target_ops *self); | |
86 | +static void core_files_info (struct target_ops *); | |
87 | + | |
88 | +static int gdb_check_format (bfd *); | |
84 | 89 | |
85 | 90 | static void core_close_cleanup (void *ignore); |
86 | 91 |
@@ -125,7 +130,7 @@ default_core_sniffer (struct core_fns *our_fns, bfd *abfd) | ||
125 | 130 | selected. */ |
126 | 131 | |
127 | 132 | static struct core_fns * |
128 | -sniff_core_bfd (bfd *abfd) | |
133 | +sniff_core_bfd (bfd *abfd, struct gdbarch *core_gdbarch) | |
129 | 134 | { |
130 | 135 | struct core_fns *cf; |
131 | 136 | struct core_fns *yummy = NULL; |
@@ -183,12 +188,35 @@ gdb_check_format (bfd *abfd) | ||
183 | 188 | return (0); |
184 | 189 | } |
185 | 190 | |
191 | + | |
192 | + | |
193 | +/* Return the core_target_ops_with_data for the current target stack, | |
194 | + if any. */ | |
195 | + | |
196 | +static struct core_target_ops_with_data * | |
197 | +get_core_target_ops (void) | |
198 | +{ | |
199 | + struct target_ops *targ = find_target_at (process_stratum); | |
200 | + | |
201 | + if (targ == NULL || targ->to_identity != &core_ops) | |
202 | + return NULL; | |
203 | + | |
204 | + /* Downcast. */ | |
205 | + return (struct core_target_ops_with_data *) targ; | |
206 | +} | |
207 | + | |
186 | 208 | /* Discard all vestiges of any previous core file and mark data and |
187 | 209 | stack spaces as empty. */ |
188 | 210 | |
189 | 211 | static void |
190 | -core_close (struct target_ops *self) | |
212 | +core_xclose (struct target_ops *self) | |
191 | 213 | { |
214 | + /* Downcast. */ | |
215 | + struct core_target_ops_with_data *cops | |
216 | + = (struct core_target_ops_with_data *) self; | |
217 | + | |
218 | + gdb_assert (self->to_identity == &core_ops); | |
219 | + | |
192 | 220 | if (core_bfd) |
193 | 221 | { |
194 | 222 | int pid = ptid_get_pid (inferior_ptid); |
@@ -201,24 +229,18 @@ core_close (struct target_ops *self) | ||
201 | 229 | comments in clear_solib in solib.c. */ |
202 | 230 | clear_solib (); |
203 | 231 | |
204 | - if (core_data) | |
205 | - { | |
206 | - xfree (core_data->sections); | |
207 | - xfree (core_data); | |
208 | - core_data = NULL; | |
209 | - } | |
210 | - | |
211 | 232 | gdb_bfd_unref (core_bfd); |
212 | 233 | core_bfd = NULL; |
213 | 234 | } |
214 | - core_vec = NULL; | |
215 | - core_gdbarch = NULL; | |
235 | + | |
236 | + xfree (cops->core_data.sections); | |
237 | + xfree (cops); | |
216 | 238 | } |
217 | 239 | |
218 | 240 | static void |
219 | -core_close_cleanup (void *ignore) | |
241 | +core_close_cleanup (void *arg) | |
220 | 242 | { |
221 | - core_close (NULL); | |
243 | + core_xclose (arg); | |
222 | 244 | } |
223 | 245 | |
224 | 246 | /* Look for sections whose names start with `.reg/' so that we can |
@@ -278,7 +300,9 @@ core_open (const char *arg, int from_tty) | ||
278 | 300 | bfd *temp_bfd; |
279 | 301 | int scratch_chan; |
280 | 302 | int flags; |
303 | + volatile struct gdb_exception except; | |
281 | 304 | char *filename; |
305 | + struct core_target_ops_with_data *cops; | |
282 | 306 | |
283 | 307 | target_preopen (from_tty); |
284 | 308 | if (!arg) |
@@ -334,21 +358,21 @@ core_open (const char *arg, int from_tty) | ||
334 | 358 | do_cleanups (old_chain); |
335 | 359 | unpush_target (&core_ops); |
336 | 360 | core_bfd = temp_bfd; |
337 | - old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/); | |
338 | 361 | |
339 | - core_gdbarch = gdbarch_from_bfd (core_bfd); | |
362 | + cops = TARGET_NEW (struct core_target_ops_with_data, &core_ops); | |
363 | + old_chain = make_cleanup (core_close_cleanup, cops); | |
364 | + | |
365 | + cops->core_gdbarch = gdbarch_from_bfd (core_bfd); | |
340 | 366 | |
341 | 367 | /* Find a suitable core file handler to munch on core_bfd */ |
342 | - core_vec = sniff_core_bfd (core_bfd); | |
368 | + cops->core_vec = sniff_core_bfd (core_bfd, cops->core_gdbarch); | |
343 | 369 | |
344 | 370 | validate_files (); |
345 | 371 | |
346 | - core_data = XCNEW (struct target_section_table); | |
347 | - | |
348 | 372 | /* Find the data section */ |
349 | 373 | if (build_section_table (core_bfd, |
350 | - &core_data->sections, | |
351 | - &core_data->sections_end)) | |
374 | + &cops->core_data.sections, | |
375 | + &cops->core_data.sections_end)) | |
352 | 376 | error (_("\"%s\": Can't find sections: %s"), |
353 | 377 | bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ())); |
354 | 378 |
@@ -359,7 +383,7 @@ core_open (const char *arg, int from_tty) | ||
359 | 383 | if (!exec_bfd) |
360 | 384 | set_gdbarch_from_file (core_bfd); |
361 | 385 | |
362 | - push_target (&core_ops); | |
386 | + push_target (&cops->base); | |
363 | 387 | discard_cleanups (old_chain); |
364 | 388 | |
365 | 389 | /* Do this before acknowledging the inferior, so if |
@@ -404,7 +428,7 @@ core_open (const char *arg, int from_tty) | ||
404 | 428 | switch_to_thread (thread->ptid); |
405 | 429 | } |
406 | 430 | |
407 | - post_create_inferior (&core_ops, from_tty); | |
431 | + post_create_inferior (&cops->base, from_tty); | |
408 | 432 | |
409 | 433 | /* Now go through the target stack looking for threads since there |
410 | 434 | may be a thread_stratum target loaded on top of target core by |
@@ -437,11 +461,11 @@ core_open (const char *arg, int from_tty) | ||
437 | 461 | implementation for that gdbarch, as a fallback measure, |
438 | 462 | assume the host signal mapping. It'll be correct for native |
439 | 463 | cores, but most likely incorrect for cross-cores. */ |
440 | - enum gdb_signal sig = (core_gdbarch != NULL | |
441 | - && gdbarch_gdb_signal_from_target_p (core_gdbarch) | |
442 | - ? gdbarch_gdb_signal_from_target (core_gdbarch, | |
443 | - siggy) | |
444 | - : gdb_signal_from_host (siggy)); | |
464 | + enum gdb_signal sig | |
465 | + = (cops->core_gdbarch != NULL | |
466 | + && gdbarch_gdb_signal_from_target_p (cops->core_gdbarch) | |
467 | + ? gdbarch_gdb_signal_from_target (cops->core_gdbarch, siggy) | |
468 | + : gdb_signal_from_host (siggy)); | |
445 | 469 | |
446 | 470 | printf_filtered (_("Program terminated with signal %s, %s.\n"), |
447 | 471 | gdb_signal_to_name (sig), gdb_signal_to_string (sig)); |
@@ -517,6 +541,7 @@ get_core_register_section (struct regcache *regcache, | ||
517 | 541 | struct bfd_section *section; |
518 | 542 | bfd_size_type size; |
519 | 543 | char *contents; |
544 | + struct core_target_ops_with_data *cops = get_core_target_ops (); | |
520 | 545 | |
521 | 546 | xfree (section_name); |
522 | 547 |
@@ -544,10 +569,12 @@ get_core_register_section (struct regcache *regcache, | ||
544 | 569 | if (size != min_size && !(regset->flags & REGSET_VARIABLE_SIZE)) |
545 | 570 | { |
546 | 571 | warning (_("Unexpected size of section `%s' in core file."), |
547 | - section_name); | |
572 | + section_name); | |
548 | 573 | } |
549 | 574 | |
550 | 575 | contents = (char *) alloca (size); |
576 | + | |
577 | + contents = alloca (size); | |
551 | 578 | if (! bfd_get_section_contents (core_bfd, section, contents, |
552 | 579 | (file_ptr) 0, size)) |
553 | 580 | { |
@@ -562,10 +589,10 @@ get_core_register_section (struct regcache *regcache, | ||
562 | 589 | return; |
563 | 590 | } |
564 | 591 | |
565 | - gdb_assert (core_vec); | |
566 | - core_vec->core_read_registers (regcache, contents, size, which, | |
567 | - ((CORE_ADDR) | |
568 | - bfd_section_vma (core_bfd, section))); | |
592 | + gdb_assert (cops->core_vec); | |
593 | + cops->core_vec->core_read_registers (regcache, contents, size, which, | |
594 | + ((CORE_ADDR) | |
595 | + bfd_section_vma (core_bfd, section))); | |
569 | 596 | } |
570 | 597 | |
571 | 598 | /* Callback for get_core_registers that handles a single core file |
@@ -608,20 +635,22 @@ static void | ||
608 | 635 | get_core_registers (struct target_ops *ops, |
609 | 636 | struct regcache *regcache, int regno) |
610 | 637 | { |
638 | + struct core_regset_section *sect_list; | |
611 | 639 | int i; |
612 | - struct gdbarch *gdbarch; | |
640 | + struct core_target_ops_with_data *cops = get_core_target_ops (); | |
613 | 641 | |
614 | - if (!(core_gdbarch && gdbarch_iterate_over_regset_sections_p (core_gdbarch)) | |
615 | - && (core_vec == NULL || core_vec->core_read_registers == NULL)) | |
642 | + if (!(cops->core_gdbarch | |
643 | + && gdbarch_iterate_over_regset_sections_p (cops->core_gdbarch)) | |
644 | + && (cops->core_vec == NULL | |
645 | + || cops->core_vec->core_read_registers == NULL)) | |
616 | 646 | { |
617 | 647 | fprintf_filtered (gdb_stderr, |
618 | 648 | "Can't fetch registers from this type of core file\n"); |
619 | 649 | return; |
620 | 650 | } |
621 | 651 | |
622 | - gdbarch = get_regcache_arch (regcache); | |
623 | - if (gdbarch_iterate_over_regset_sections_p (gdbarch)) | |
624 | - gdbarch_iterate_over_regset_sections (gdbarch, | |
652 | + if (gdbarch_iterate_over_regset_sections_p (cops->core_gdbarch)) | |
653 | + gdbarch_iterate_over_regset_sections (cops->core_gdbarch, | |
625 | 654 | get_core_registers_cb, |
626 | 655 | (void *) regcache, NULL); |
627 | 656 | else |
@@ -641,7 +670,9 @@ get_core_registers (struct target_ops *ops, | ||
641 | 670 | static void |
642 | 671 | core_files_info (struct target_ops *t) |
643 | 672 | { |
644 | - print_section_info (core_data, core_bfd); | |
673 | + struct core_target_ops_with_data *cops = get_core_target_ops (); | |
674 | + | |
675 | + print_section_info (&cops->core_data, core_bfd); | |
645 | 676 | } |
646 | 677 | |
647 | 678 | struct spuid_list |
@@ -709,13 +740,15 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, | ||
709 | 740 | const gdb_byte *writebuf, ULONGEST offset, |
710 | 741 | ULONGEST len, ULONGEST *xfered_len) |
711 | 742 | { |
743 | + struct core_target_ops_with_data *cops = get_core_target_ops (); | |
744 | + | |
712 | 745 | switch (object) |
713 | 746 | { |
714 | 747 | case TARGET_OBJECT_MEMORY: |
715 | 748 | return section_table_xfer_memory_partial (readbuf, writebuf, |
716 | 749 | offset, len, xfered_len, |
717 | - core_data->sections, | |
718 | - core_data->sections_end, | |
750 | + cops->core_data.sections, | |
751 | + cops->core_data.sections_end, | |
719 | 752 | NULL); |
720 | 753 | |
721 | 754 | case TARGET_OBJECT_AUXV: |
@@ -789,16 +822,17 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, | ||
789 | 822 | return TARGET_XFER_E_IO; |
790 | 823 | |
791 | 824 | case TARGET_OBJECT_LIBRARIES: |
792 | - if (core_gdbarch | |
793 | - && gdbarch_core_xfer_shared_libraries_p (core_gdbarch)) | |
825 | + if (cops->core_gdbarch | |
826 | + && gdbarch_core_xfer_shared_libraries_p (cops->core_gdbarch)) | |
794 | 827 | { |
795 | 828 | if (writebuf) |
796 | 829 | return TARGET_XFER_E_IO; |
797 | 830 | else |
798 | 831 | { |
799 | - *xfered_len = gdbarch_core_xfer_shared_libraries (core_gdbarch, | |
800 | - readbuf, | |
801 | - offset, len); | |
832 | + *xfered_len | |
833 | + = gdbarch_core_xfer_shared_libraries (cops->core_gdbarch, | |
834 | + readbuf, | |
835 | + offset, len); | |
802 | 836 | |
803 | 837 | if (*xfered_len == 0) |
804 | 838 | return TARGET_XFER_EOF; |
@@ -809,15 +843,15 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, | ||
809 | 843 | /* FALL THROUGH */ |
810 | 844 | |
811 | 845 | case TARGET_OBJECT_LIBRARIES_AIX: |
812 | - if (core_gdbarch | |
813 | - && gdbarch_core_xfer_shared_libraries_aix_p (core_gdbarch)) | |
846 | + if (cops->core_gdbarch | |
847 | + && gdbarch_core_xfer_shared_libraries_aix_p (cops->core_gdbarch)) | |
814 | 848 | { |
815 | 849 | if (writebuf) |
816 | 850 | return TARGET_XFER_E_IO; |
817 | 851 | else |
818 | 852 | { |
819 | 853 | *xfered_len |
820 | - = gdbarch_core_xfer_shared_libraries_aix (core_gdbarch, | |
854 | + = gdbarch_core_xfer_shared_libraries_aix (cops->core_gdbarch, | |
821 | 855 | readbuf, offset, |
822 | 856 | len); |
823 | 857 |
@@ -941,11 +975,14 @@ core_thread_alive (struct target_ops *ops, ptid_t ptid) | ||
941 | 975 | static const struct target_desc * |
942 | 976 | core_read_description (struct target_ops *target) |
943 | 977 | { |
944 | - if (core_gdbarch && gdbarch_core_read_description_p (core_gdbarch)) | |
978 | + struct core_target_ops_with_data *cops = get_core_target_ops (); | |
979 | + | |
980 | + if (cops->core_gdbarch | |
981 | + && gdbarch_core_read_description_p (cops->core_gdbarch)) | |
945 | 982 | { |
946 | 983 | const struct target_desc *result; |
947 | 984 | |
948 | - result = gdbarch_core_read_description (core_gdbarch, | |
985 | + result = gdbarch_core_read_description (cops->core_gdbarch, | |
949 | 986 | target, core_bfd); |
950 | 987 | if (result != NULL) |
951 | 988 | return result; |
@@ -960,12 +997,13 @@ core_pid_to_str (struct target_ops *ops, ptid_t ptid) | ||
960 | 997 | static char buf[64]; |
961 | 998 | struct inferior *inf; |
962 | 999 | int pid; |
1000 | + struct core_target_ops_with_data *cops = get_core_target_ops (); | |
963 | 1001 | |
964 | 1002 | /* The preferred way is to have a gdbarch/OS specific |
965 | 1003 | implementation. */ |
966 | - if (core_gdbarch | |
967 | - && gdbarch_core_pid_to_str_p (core_gdbarch)) | |
968 | - return gdbarch_core_pid_to_str (core_gdbarch, ptid); | |
1004 | + if (cops->core_gdbarch | |
1005 | + && gdbarch_core_pid_to_str_p (cops->core_gdbarch)) | |
1006 | + return gdbarch_core_pid_to_str (cops->core_gdbarch, ptid); | |
969 | 1007 | |
970 | 1008 | /* Otherwise, if we don't have one, we'll just fallback to |
971 | 1009 | "process", with normal_pid_to_str. */ |
@@ -977,7 +1015,7 @@ core_pid_to_str (struct target_ops *ops, ptid_t ptid) | ||
977 | 1015 | |
978 | 1016 | /* Otherwise, this isn't a "threaded" core -- use the PID field, but |
979 | 1017 | only if it isn't a fake PID. */ |
980 | - inf = find_inferior_ptid (ptid); | |
1018 | + inf = find_inferior_pid (ptid_get_pid (ptid)); | |
981 | 1019 | if (inf != NULL && !inf->fake_pid_p) |
982 | 1020 | return normal_pid_to_str (ptid); |
983 | 1021 |
@@ -1028,7 +1066,7 @@ init_core_ops (void) | ||
1028 | 1066 | core_ops.to_doc = |
1029 | 1067 | "Use a core file as a target. Specify the filename of the core file."; |
1030 | 1068 | core_ops.to_open = core_open; |
1031 | - core_ops.to_close = core_close; | |
1069 | + core_ops.to_xclose = core_xclose; | |
1032 | 1070 | core_ops.to_detach = core_detach; |
1033 | 1071 | core_ops.to_fetch_registers = get_core_registers; |
1034 | 1072 | core_ops.to_xfer_partial = core_xfer_partial; |
@@ -706,6 +706,26 @@ push_target (struct target_ops *t) | ||
706 | 706 | update_current_target (); |
707 | 707 | } |
708 | 708 | |
709 | +/* See target.h. */ | |
710 | + | |
711 | +struct target_ops * | |
712 | +allocate_target (struct target_ops *ops, size_t alloc) | |
713 | +{ | |
714 | + char *mem; | |
715 | + | |
716 | + gdb_assert (ops->to_identity != NULL); | |
717 | + gdb_assert (ops->to_xclose != NULL); | |
718 | + gdb_assert (alloc >= sizeof (struct target_ops)); | |
719 | + | |
720 | + mem = xmalloc (alloc); | |
721 | + memcpy (mem, ops, sizeof (struct target_ops)); | |
722 | + if (alloc > sizeof (struct target_ops)) | |
723 | + memset (&mem[sizeof (struct target_ops)], 0, | |
724 | + alloc - sizeof (struct target_ops)); | |
725 | + | |
726 | + return (struct target_ops *) mem; | |
727 | +} | |
728 | + | |
709 | 729 | /* Remove a target_ops vector from the stack, wherever it may be. |
710 | 730 | Return how many times it was removed (0 or 1). */ |
711 | 731 |
@@ -2289,6 +2289,21 @@ extern void push_target (struct target_ops *); | ||
2289 | 2289 | |
2290 | 2290 | extern int unpush_target (struct target_ops *); |
2291 | 2291 | |
2292 | +/* Allocate a new target object. OPS is the "prototype" | |
2293 | + implementation of the new target; it is copied into the new object. | |
2294 | + ALLOC is the number of bytes to allocate. It may be larger than | |
2295 | + sizeof (struct target_ops) if the target subclasses target_ops to | |
2296 | + store extra data. Returns the new target object. Extra space | |
2297 | + beyond the initial OPS component of the result is zeroed. */ | |
2298 | + | |
2299 | +extern struct target_ops *allocate_target (struct target_ops *ops, | |
2300 | + size_t alloc); | |
2301 | + | |
2302 | +/* A typed convenience wrapper for allocate_target. T is the type of | |
2303 | + the subclass of target_ops to allocate. */ | |
2304 | + | |
2305 | +#define TARGET_NEW(T, OPS) ((T *) (allocate_target ((OPS), sizeof (T)))) | |
2306 | + | |
2292 | 2307 | extern void target_pre_inferior (int); |
2293 | 2308 | |
2294 | 2309 | extern void target_preopen (int); |