Accepting request 1246565 from devel:gcc
- Maintenance script qa.sh: * Add PR32712 kfail. - Mention changes in GDB 15: * The MPX commands "show/set mpx bound" have been deprecated, as Intel listed MPX as removed in 2019. * GDB index now contains information about the main function. * This speeds up startup when it is being used for some large binaries. * On hosts where threading is available, DWARF reading is now done in the background, resulting in faster startup. This can be controlled using "maint set dwarf synchronous". * Changed commands: * disassemble: Attempting to use both the 'r' and 'b' flags with the disassemble command will now give an error. Previously the 'b' flag would always override the 'r' flag. * gcore, generate-core-file: GDB now generates sparse core files, on systems that support it. * maintenance info line-table: Add an EPILOGUE-BEGIN column to the output of the command. It indicates if the line is considered the start of the epilogue, and thus a point at which the frame can be considered destroyed. * set unwindonsignal on|off, show unwindonsignal: These commands are now aliases for the new set/show unwind-on-signal. * target record-full: This command now gives an error if any unexpected arguments are found after the command. * list .: When using the command "list ." in a location that has no debug information or no file loaded, GDB now says that there is no debug information to print lines. This makes it more obvious that there is no information, as opposed to implying there is no inferior loaded. * New commands: * info missing-debug-handler: List all the registered missing debug handlers. * enable missing-debug-handler LOCUS HANDLER, disable missing-debug-handler LOCUS HANDLER: Enable or disable a missing debug handler with a name matching the regular expression HANDLER, in LOCUS. LOCUS can be 'global' to operate on global missing debug handler, 'progspace' to operate on handlers within the current program space, or can be a regular expression which is matched against the filename of the primary executable in each program space. * maintenance info linux-lwps: List all LWPs under control of the linux-nat target. * set remote thread-options-packet, show remote thread-options-packet: Set/show the use of the thread options packet. * set direct-call-timeout SECONDS, show direct-call-timeout, set indirect-call-timeout SECONDS, show indirect-call-timeout: These new settings can be used to limit how long GDB will wait for an inferior function call to complete. The direct timeout is used for inferior function calls from e.g. 'call' and 'print' commands, while the indirect timeout is used for inferior function calls from within a conditional breakpoint expression. The default for the direct timeout is unlimited, while the default for the indirect timeout is 30 seconds. These timeouts will only have an effect for targets that are operating in async mode. For non-async targets the timeouts are ignored, GDB will wait indefinitely for an inferior function to complete, unless interrupted by the user using Ctrl-C. * set unwind-on-timeout on|off, show unwind-on-timeout: These commands control whether GDB should unwind the stack when a timeout occurs during an inferior function call. The default is off, in which case the inferior will remain in the frame where the timeout occurred. When on, GDB will unwind the stack removing the dummy frame that was added for the inferior call, and restoring the inferior state to how it was before the inferior call started. * set unwind-on-signal on|off, show unwind-on-signal: These new commands replaces the existing set/show unwindonsignal. The old command is maintained as an alias. * New features in the GDB remote stub, GDBserver: * The --remote-debug and --event-loop-debug command line options have been removed. * The --debug command line option now takes an optional comma separated list of components to emit debug for. The currently supported components are: all, threads, event-loop, and remote. If no components are given then threads is assumed. * The 'monitor set remote-debug' and 'monitor set event-loop-debug' command have been removed. * The 'monitor set debug 0|1' command has been extended to take a component name, e.g.: 'monitor set debug COMPONENT off|on'. Possible component names are: all, threads, event-loop, and remote. * Python API: * New function gdb.notify_mi(NAME, DATA), that emits custom GDB/MI async notification. * New read/write attribute gdb.Value.bytes that contains a bytes object holding the contents of this value. * New module gdb.missing_debug that facilitates dealing with objfiles that are missing any debug information. * New function gdb.missing_debug.register_handler that can register an instance of a sub-class of gdb.missing_debug.MissingDebugInfo as a handler for objfiles that are missing debug information. * New class gdb.missing_debug.MissingDebugInfo which can be sub-classed to create handlers for objfiles with missing debug information. * Stop events now have a "details" attribute that holds a dictionary that carries the same information as an MI "*stopped" event. * New function gdb.interrupt(), that interrupts GDB as if the user typed control-c. * New gdb.InferiorThread.ptid_string attribute. This read-only attribute contains the string that appears in the 'Target Id' column of the 'info threads' command output. * It is no longer possible to create new gdb.Progspace object using 'gdb.Progspace()', this will result in a TypeError. Progspace objects can still be obtained through calling other API functions, for example 'gdb.current_progspace()'. * User defined attributes can be added to a gdb.Inferior object, these will be stored in the object's new Inferior.__dict__ attribute. * User defined attributes can be added to a gdb.InferiorThread object, these will be stored in the object's new InferiorThread.__dict__ attribute. * New constants gdb.SYMBOL_TYPE_DOMAIN, gdb.SYMBOL_FUNCTION_DOMAIN, and gdb.SEARCH_*_DOMAIN corresponding to all the existing symbol domains. Symbol lookup can now search in multiple domains at once, and can also narrowly search for just a type or function. * Debugger Adapter Protocol changes: * GDB now emits the "process" event. * GDB now supports the "cancel" request. * The "attach" request now supports specifying the program. * New command "set debug dap-log-level" controls DAP logging. * The "set debug dap-log-file" command is now documented. This command was available in GDB 14 but not documented. * Guile API: * New constants SYMBOL_TYPE_DOMAIN, SYMBOL_FUNCTION_DOMAIN, and SEARCH_*_DOMAIN corresponding to all the existing symbol domains. Symbol lookup can now search in multiple domains at once, and can also narrowly search for just a type or function. * Remote packets: * New stop reason clone: Indicates that a clone system call was executed. * New remote packets: * QThreadOptions: Enable/disable optional event reporting, on a per-thread basis. Currently supported options are GDB_THREAD_OPTION_CLONE, to enable clone event reporting, and GDB_THREAD_OPTION_EXIT to enable thread exit event reporting. * QThreadOptions in qSupported: * The qSupported packet allows GDB to inform the stub it supports the QThreadOptions packet, and the qSupported response can contain the set of thread options the remote stub supports. * qIsAddressTagged: This new packet allows GDB to query the stub about a given address to check if it is tagged or not. Many memory tagging-related GDB commands need to perform this check before they read/write the allocation tag related to an address. Currently, however, this is done through a 'vFile' request to read the file /proc/<PID>/smaps and check if the address is in a region reported as memory tagged. Since not all targets have a notion of what the smaps file is about, this new packet provides a more generic way to perform such a check. - Maintenance script qa.sh: * Fix 16.0 handling. - Patches added: * gdb-testsuite-fix-gdb.python-py-format-string.exp-wi.patch * gdb-testsuite-fix-gdb.python-py-mi-cmd.exp-with-pyth.patch * gdb-testsuite-fix-gdb.ada-mi_task_arg.exp-on-arm-lin.patch * gdb-testsuite-fix-regexp-in-gdb.ada-mi_var_access.ex.patch * gdb-testsuite-check-gnatmake-version-in-gdb.ada-scal.patch * gdb-testsuite-fix-gdb.arch-arm-pseudo-unwind.exp-wit.patch * gdb-symtab-fix-target-type-of-complex-long-double-on.patch * gdb-testsuite-don-t-use-set-auto-solib-add-off.patch * gdb-tdep-fix-arm-thumb2-hw-breakpoint.patch * gdb-testsuite-fix-gdb.cp-m-static.exp-on-arm.patch * gdb-testsuite-fix-gdb.dwarf2-dw2-fixed-point.exp-on-.patch * gdb-testsuite-fix-gdb.dwarf2-dw2-lines.exp-on-arm-li.patch * gdb-exp-fix-gdb.fortran-intrinsics.exp-fail-on-arm.patch * gdb-tdep-handle-sycall-statx-for-arm-linux.patch * gdb-tdep-fix-recording-of-t1-push.patch * gdb-tdep-handle-syscall-clock_gettime64-for-arm-linu.patch * fix-gdb.dwarf2-shortpiece.exp-on-s390x.patch * handle-address-class-annotation-for-s390x-in-some-te.patch * fix-gdb.dap-step-out.exp-on-s390x.patch * use-setvariable-in-gdb.dap-scopes.exp.patch * fix-gdb.base-finish-pretty.exp-on-s390x.patch * fix-gdb.base-readnever.exp-on-s390x.patch * add-dwarf_expr_piece.op.patch * add-gdbarch_dwarf2_reg_piece_offset-hook.patch * fix-gdb.base-store.exp-on-s390x.patch * fix-gdb.ada-o2_float_param.exp-on-s390x-linux.patch * gdb-testsuite-fix-gdb.base-branch-to-self.exp-on-arm.patch * gdb-tdep-fix-gdb.cp-non-trivial-retval.exp-on-riscv6.patch * gdb-testsuite-fix-gdb.cp-non-trivial-retval.exp-on-a.patch * gdb-testsuite-fix-gdb.rust-completion.exp-timeout-on.patch * gdb-testsuite-require-supports_process_record-in-gdb.patch * gdb-testsuite-fix-regexp-in-gdb.arch-i386-disp-step-.patch * gdb-testsuite-fix-gdb.arch-arm-single-step-kernel-he.patch * gdb-testsuite-fix-gdb.python-py-format-address.exp-o.patch * gdb-testsuite-fix-gdb.arch-riscv-tdesc-regs.exp.patch * gdb-testsuite-fix-gdb.base-list-dot-nodebug-and-make.patch * gdb-testsuite-fix-gdb.base-list-dot-nodebug.exp-on-o.patch * gdb-testsuite-fix-gdb.base-empty-host-env-vars.exp.patch * gdb-prune-inferior-after-switching-inferior.patch * gdb-testsuite-use-nostdlib-in-gdb.base-list-dot-node.patch * gdb-testsuite-fix-timeout-in-gdb.mi-mi-multi-command.patch * gdb-testsuite-require-can_spawn_for_attach-in-gdb.ba.patch * fixup-gdb-6.5-gcore-buffer-limit-test.patch * gdb-testsuite-fix-gdb.ada-big_packed_array.exp-on-s3.patch * gdb-testsuite-fix-gdb.ada-convvar_comp.exp-on-s390x-.patch * gdb-testsuite-fix-regexp-in-gdb.threads-stepi-over-c.patch - Maintenance script qa.sh: * Add kfail for PR32678. * Add kfail for missing g++ on SLE-12. * Drop Leap 15.5, add 16.0. * Move PR32167 kfail from kfail_sle12 to kfail, and extend pattern. - Use gcc 11 instead gcc 9 for SLE-12. - Maintenance script qa-local.sh: * Drop Leap 15.5, add 16.0. - Patches dropped: * gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch * gdb-test-bt-cfi-without-die.patch * fixup-gdb-rhbz1261564-aarch64-hw-watchpoint-test.pat.patch * fixup-gdb-test-bt-cfi-without-die.patch - Maintenance script import-fedora.sh: * Add gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch and gdb-test-bt-cfi-without-die.patch to skip_patches. - Update to fedora rawhide @ a2f2e9e. - Patches dropped: * gdb-6.5-bz243845-stale-testing-zombie-test.patch * fixup-gdb-6.5-bz243845-stale-testing-zombie-test.patch - Update to fedora rawhide @ 1116b36. - Patches dropped: * gdb-test-dw2-aranges.patch * fixup-gdb-test-dw2-aranges.patch - Update to fedora rawhide @ 7c66c1c. - Patches dropped: * gdb-6.6-testsuite-timeouts.patch - Update to fedora rawhide @ 2294280. - Patches dropped: * gdb-simultaneous-step-resume-breakpoint-test.patch - Update to fedora rawhide @ 926c064 (gdb 15.2). - Patches dropped: * gdb-6.5-section-num-fixup-test.patch * gdb-rhbz1007614-memleak-infpy_read_memory-test.patch - Maintenance script qa-local.sh: * Update version to 15.2. - Update to fedora rawhide @ 4b0a2e1. - Patches added: * gdb-catchpoint-re-set.patch - Update to fedora rawhide @ d8b64d9. - Patches dropped: * gdb-6.6-bz229517-gcore-without-terminal.patch - Update to fedora rawhide @ a93b826. - Patches dropped: * gdb-rhbz947564-findvar-assertion-frame-failed-testcase.patch - Maintenance script import-fedora.sh: * Add gdb-remove-use-of-py-isascii to skip_patches. * Remove gdb-6.7-ppc-clobbered-registers-O2-test.patch from skip_patches. - Always BuildRequire gcc-c++ to fix missing testing compiler on SLE-12. - Patches added: * gdb-testsuite-handle-unordered-dict-in-gdb.python-py.patch - Maintenance script qa.sh: * Add PR32167 kfail. - Maintenance script qa.sh: * Extend SLE-12 -static unix/-fPIE/-fpie kfails. * Extend ppc64le watchpoint kfail. * Extend PR29405 kfail. - Patches added: * gdb-testsuite-fix-gdb.threads-leader-exit-attach.exp.patch * gdb-testsuite-use-c-flag-in-c-test-cases.patch - Update to fedora rawhide @ a8e0b3d (gdb 15.1). - Use gcc-9 for SLE-12 (default gcc 4.8.5 doesn't support C++17). - Maintenance script qa-local.sh: * Update version to 15.1. - Maintenance script qa.sh: * Add kfails due to gcc 4.8.5 DW_TAG_lexical_block oddity. * Extend PR24845 kfails. * Add PR31721 and PR32608 kfails. - Patches added: * gdb-guile-use-scm_debug_typing_strictness-0.patch * gdb-doc-fix-gdb.unwinder-docs.patch * gdb-doc-fix-qisaddresstagged-anchor.patch * gdb-doc-fix-standard-replies-xref.patch * gdb-testsuite-fix-gdb_py_module_available-for-python.patch * gdb-testsuite-fix-another-regexp-in-gdb.threads-step.patch * gdb-testsuite-fix-timeouts-in-gdb.threads-step-over-.patch - Patches updated: * gdb-6.3-gstack-20050411.patch * gdb-6.6-buildid-locate-solib-missing-ids.patch * gdb-6.6-buildid-locate.patch * gdb-add-rpm-suggestion-script.patch * gdb-gcore-bash.patch * gdb-python-avoid-depending-on-the-curses-library.patch * gdb-python-finishbreakpoint-update.patch - Patches dropped: * gdb-add-missing-debug-ext-lang-hook.patch * gdb-add-missing-debug-info-python-hook.patch * gdb-do-not-import-py-curses-ascii-module.patch * gdb-ftbs-swapped-calloc-args.patch * gdb-handle-no-python-gdb-module.patch * gdb-merge-debug-symbol-lookup.patch * gdb-refactor-find-and-add-separate-symbol-file.patch * gdb-reformat-missing-debug-py-file.patch * gdb-remove-path-in-test-name.patch * gdb-rhbz-2232086-cpp-ify-mapped-symtab.patch * gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch * gdb-rhbz-2232086-generate-gdb-index-consistently.patch * gdb-rhbz-2232086-reduce-size-of-gdb-index.patch * gdb-rhbz2232086-refactor-selftest-support.patch * gdb-rhbz2250652-avoid-PyOS_ReadlineTState.patch * gdb-rhbz2250652-gdbpy_gil.patch * gdb-rhbz2261580-intrusive_list-assertion-fix.patch * gdb-rhbz2277160-apx-disasm.patch * gdb-rhel2295897-pre-read-DWZ-file-in-DWARF-reader.patch * gdb-sync-coffread-with-elfread.patch * gdb-remove-use-of-py-isascii * change-gdb.base-examine-backwards.exp-for-aix.patch * fix-regression-on-aarch64-linux-gdbserver.patch * fix-the-gdb.ada-inline-section-gc.exp-test.patch * fixup-powerpc-and-aarch64-fix-reverse-stepping-failu.patch * gdb-arm-fix-epilogue-frame-id.patch * gdb-arm-remove-thumb-bit-in-arm_adjust_breakpoint_ad.patch * gdb-arm-remove-tpidruro-register-from-non-freebsd-ta.patch * gdb-build-fix-gdbserver-linux-aarch64-low.cc-build.patch * gdb-exp-fix-cast-handling-for-indirection.patch * gdb-exp-fix-printing-of-out-of-bounds-struct-members.patch * gdb-exp-redo-cast-handling-for-indirection.patch * gdb-fix-heap-use-after-free-in-select_event_lwp.patch * gdb-fix-segfault-in-for_each_block-part-1.patch * gdb-fix-segfault-in-for_each_block-part-2.patch * gdb-python-fix-gdb.python-py-disasm.exp-on-arm-linux.patch * gdb-python-make-gdb.unwindinfo.add_saved_register-mo-fixup.patch * gdb-python-make-gdb.unwindinfo.add_saved_register-mo.patch * gdb-remote-fix-abort-on-remote_close_error.patch * gdb-s390-add-arch14-record-replay-support.patch * gdb-symtab-add-producer_is_gas.patch * gdb-symtab-don-t-defer-backward-refs-inter-cu-intra-.patch * gdb-symtab-factor-out-m_deferred_entries-usage.patch * gdb-symtab-factor-out-m_die_range_map-usage.patch * gdb-symtab-fix-dw_tag_inlined_subroutine-entries-in-.patch * gdb-symtab-handle-nullptr-parent-in-parent_map-set_p.patch * gdb-symtab-keep-track-of-all-parents-for-cooked-inde.patch * gdb-symtab-keep-track-of-processed-dies-in-shard.patch * gdb-symtab-refactor-condition-in-scan_attributes.patch * gdb-symtab-resolve-deferred-entries-inter-shard-case.patch * gdb-symtab-resolve-deferred-entries-intra-shard-case.patch * gdb-symtab-work-around-gas-pr28629.patch * gdb-symtab-work-around-pr-gas-29517-dwarf2-case.patch * gdb-symtab-work-around-pr-gas-29517.patch * gdb-symtab-workaround-pr-gas-31115.patch * gdb-tdep-fix-catching-syscall-execve-exit-for-arm.patch * gdb-tdep-fix-gdb.base-watch-bitfields.exp-on-aarch64.patch * gdb-tdep-fix-gdb.base-watchpoint-running-on-arm-ppc6.patch * gdb-tdep-fix-gdb.base-watchpoint-unaligned.exp-on-aa.patch * gdb-tdep-fix-nr-array-elements-in-ppc64_aggregate_ca.patch * gdb-tdep-fix-reverse-execution-of-ldr-immediate-t4.patch * gdb-testsuite-add-gdb.dwarf2-backward-spec-inter-cu..patch * gdb-testsuite-add-gdb.dwarf2-forward-spec-inter-cu.e.patch * gdb-testsuite-add-missing-include-in-gdb.base-ctf-pt.patch * gdb-testsuite-add-missing-include-in-gdb.base-rtld-s.patch * gdb-testsuite-add-missing-includes-in-gdb.trace-coll.patch * gdb-testsuite-add-missing-no-prompt-anchor-in-gdb.ba.patch * gdb-testsuite-add-pr-gdb-26967-kfail-in-two-more-tes.patch * gdb-testsuite-call-ldd-version-in-gdb.testsuite-dump.patch * gdb-testsuite-factor-out-proc-get_portnum.patch * gdb-testsuite-factor-out-proc-lock_dir.patch * gdb-testsuite-factor-out-proc-with_lock.patch * gdb-testsuite-fix-gdb.ada-verylong.exp-on-32-bit-tar.patch * gdb-testsuite-fix-gdb.base-eh_return.exp.patch * gdb-testsuite-fix-gdb.base-ending-run.exp-on-manjaro.patch * gdb-testsuite-fix-gdb.base-list-no-debug.exp-on-debi.patch * gdb-testsuite-fix-gdb.cp-namespace.exp-with-read1.patch * gdb-testsuite-fix-gdb.dwarf2-dw2-gas-workaround.exp.patch * gdb-testsuite-fix-gdb.mi-mi-dprintf.exp-with-read1.patch * gdb-testsuite-fix-gdbserver-pid-in-gdb.server-server.patch * gdb-testsuite-fix-gdb.server-server-connect.exp-for-.patch * gdb-testsuite-fix-license-text-in-gdb.reverse-map-to.patch * gdb-testsuite-fix-missing-return-type-in-gdb.linespe.patch * gdb-testsuite-fix-regexp-in-vgdb_start.patch * gdb-testsuite-fix-spurious-fails-with-examine-backwa.patch * gdb-testsuite-fix-test-case-gdb.threads-attach-stopp.patch * gdb-testsuite-fix-test-in-gdb.python-py-finish-break.patch * gdb-testsuite-fix-typo-in-gdb.base-catch-syscall.exp.patch * gdb-testsuite-fix-valgrind-tests-on-debian.patch * gdb-testsuite-further-handle-long-filenames-in-gdb.b.patch * gdb-testsuite-handle-core-without-build-id-in-gdb.ba.patch * gdb-testsuite-handle-pac-marker.patch * gdb-testsuite-make-gdb.base-solib-search.exp-more-ro.patch * gdb-testsuite-make-portnum-a-persistent-global.patch * gdb-testsuite-move-gpu-parallel.lock-to-cache-dir.patch * gdb-testsuite-remove-spurious-in-save_vars.patch * gdb-testsuite-reset-errcnt-and-warncnt-in-default_gd.patch * gdb-testsuite-simplify-gdb.server-server-kill-python.patch * gdb-testsuite-use-find_gnatmake-instead-of-gdb_find_.patch * gdb-testsuite-use-more-progbits-for-arm.patch * gdb-testsuite-use-unique-portnum-in-parallel-testing-check-slash-slash-case.patch * gdb-testsuite-use-unique-portnum-in-parallel-testing.patch * gdb-tui-allow-command-window-of-1-or-2-lines.patch * gdb-tui-fix-resizing-of-terminal-to-1-or-2-lines.patch * gdb-tui-fix-wmaybe-uninitialized-in-tui_find_disasse.patch * make-pascal_language-print_type-handle-varstring-nul.patch * powerpc-and-aarch64-fix-reverse-stepping-failure.patch * powerpc-fix-test-gdb.ada-finish-large.exp.patch * riscv-lrsc.patch * rs6000-unwind-on-each-instruction-fix.patch * s390-provide-ibm-z16-arch14-instruction-descriptions.patch - Patches added: * gdb-testsuite-record-less-in-gdb.reverse-time-revers.patch * gdb-cli-print-at_hwcap3-and-at_hwcap4.patch - Update to fedora rawhide @ a455470. - Patches added: * gdb-rhel2295897-pre-read-DWZ-file-in-DWARF-reader.patch - Update to fedora rawhide @ 62add57. - Patches updated: * gdb-add-rpm-suggestion-script.patch - Update to fedora rawhide @ 199e8a4. - Patches dropped: * fixup-gdb-glibc-strstr-workaround.patch * gdb-glibc-strstr-workaround.patch - Update to fedora rawhide @ a247406. - Patches dropped: * gdb-core-open-vdso-warning.patch - Update to fedora rawhide @ 485076c. - Patches updated: * gdb-add-rpm-suggestion-script.patch - Update to fedora rawhide @ 1672291. - Patches updated: * gdb-6.6-buildid-locate-rpm-suse.patch * gdb-add-rpm-suggestion-script.patch - Update to fedora rawhide @ f9386b1. - Patches dropped: * gdb-fedora-libncursesw.patch - Update to fedora rawhide @ 93db514. - Patches added: * gdb-rhbz2277160-apx-disasm.patch - Update to fedora rawhide @ deb8227. - Patches dropped: * fixup-gdb-linux_perf-bundle.patch * gdb-linux_perf-bundle.patch - Update to fedora rawhide @ 7b0d0c4. - Patches dropped: * gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch - Patches updated: * gdb-6.6-buildid-locate.patch * gdb-add-missing-debug-info-python-hook.patch - Update to fedora rawhide @ 94829f0. - Patches dropped: * fixup-gdb-bz634108-solib_address.patch * gdb-bz634108-solib_address.patch - Update to fedora rawhide @ 2024966. - Maintenance script import-fedora.sh: * Remove gdb-container-rh-pkg.patch from skip_patches. - Patches dropped (unused): * fixup-gdb-6.3-attach-see-vdso-test.patch - Update to fedora rawhide @ a54b5ef. - Patches dropped: * gdb-6.3-attach-see-vdso-test.patch - Update to fedora rawhide @ 08bfd0a. - Patches dropped: * fixup-gdb-6.3-gstack-20050411.patch * fixup-skip-tests.patch * gdb-6.6-buildid-locate-rpm-librpm-workaround.patch * gdb-6.6-buildid-locate-rpm.patch - Patches added: * gdb-add-missing-debug-ext-lang-hook.patch * gdb-add-missing-debug-info-python-hook.patch * gdb-add-rpm-suggestion-script.patch * gdb-do-not-import-py-curses-ascii-module.patch * gdb-handle-no-python-gdb-module.patch * gdb-merge-debug-symbol-lookup.patch * gdb-python-avoid-depending-on-the-curses-library.patch * gdb-refactor-find-and-add-separate-symbol-file.patch * gdb-reformat-missing-debug-py-file.patch * gdb-remove-path-in-test-name.patch * gdb-remove-use-of-py-isascii * gdb-sync-coffread-with-elfread.patch - Patches updated: * fixup-gdb-bz634108-solib_address.patch * gdb-6.3-gstack-20050411.patch * gdb-6.6-buildid-locate-rpm-suse.patch * gdb-6.6-buildid-locate-solib-missing-ids.patch * gdb-6.6-buildid-locate.patch * gdb-archer-next-over-throw-cxx-exec.patch * gdb-bz634108-solib_address.patch * gdb-fedora-libncursesw.patch * gdb-glibc-strstr-workaround.patch * gdb-rhbz1007614-memleak-infpy_read_memory-test.patch - Update to fedora rawhide @ f379362. - Patches modified: * gdb-6.6-buildid-locate.patch - Update to fedora rawhide @ e27fd6f. - Patches modified: * gdb-6.6-buildid-locate-rpm.patch * gdb-6.6-buildid-locate.patch - Add "BuildRequires: libgo23" to fix unresolved for factory. OBS-URL: https://build.opensuse.org/request/show/1246565 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/gdb?expand=0&rev=183
This commit is contained in:
commit
0af202c239
100
add-dwarf_expr_piece.op.patch
Normal file
100
add-dwarf_expr_piece.op.patch
Normal file
@ -0,0 +1,100 @@
|
||||
From 89cf6ba4a207f5342db58d9e43178ae516cc220e Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 15 Jan 2025 17:02:00 +0100
|
||||
Subject: [PATCH 23/46] Add dwarf_expr_piece.op
|
||||
|
||||
Add a new field "dwarf_location_atom op" to dwarf_expr_piece to keep track of
|
||||
which dwarf_location_atom caused a dwarf_expr_piece to be added.
|
||||
|
||||
This is used in the following patch.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/dwarf2/expr.c | 10 ++++++----
|
||||
gdb/dwarf2/expr.h | 6 +++++-
|
||||
2 files changed, 11 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
|
||||
index cb80dbf60b1..03107f90575 100644
|
||||
--- a/gdb/dwarf2/expr.c
|
||||
+++ b/gdb/dwarf2/expr.c
|
||||
@@ -1198,13 +1198,15 @@ dwarf_expr_context::stack_empty_p () const
|
||||
|
||||
/* Add a new piece to the dwarf_expr_context's piece list. */
|
||||
void
|
||||
-dwarf_expr_context::add_piece (ULONGEST size, ULONGEST offset)
|
||||
+dwarf_expr_context::add_piece (ULONGEST size, ULONGEST offset,
|
||||
+ enum dwarf_location_atom op)
|
||||
{
|
||||
dwarf_expr_piece &p = this->m_pieces.emplace_back ();
|
||||
|
||||
p.location = this->m_location;
|
||||
p.size = size;
|
||||
p.offset = offset;
|
||||
+ p.op = op;
|
||||
|
||||
if (p.location == DWARF_VALUE_LITERAL)
|
||||
{
|
||||
@@ -2169,7 +2171,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
|
||||
|
||||
/* Record the piece. */
|
||||
op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
|
||||
- add_piece (8 * size, 0);
|
||||
+ add_piece (8 * size, 0, op);
|
||||
|
||||
/* Pop off the address/regnum, and reset the location
|
||||
type. */
|
||||
@@ -2187,7 +2189,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
|
||||
/* Record the piece. */
|
||||
op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
|
||||
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uleb_offset);
|
||||
- add_piece (size, uleb_offset);
|
||||
+ add_piece (size, uleb_offset, op);
|
||||
|
||||
/* Pop off the address/regnum, and reset the location
|
||||
type. */
|
||||
@@ -2389,7 +2391,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
|
||||
pointer, then make a pieced value. This is ok because we can't
|
||||
have implicit pointers in contexts where pieces are invalid. */
|
||||
if (this->m_location == DWARF_VALUE_IMPLICIT_POINTER)
|
||||
- add_piece (8 * this->m_addr_size, 0);
|
||||
+ add_piece (8 * this->m_addr_size, 0, DW_OP_implicit_pointer);
|
||||
|
||||
this->m_recursion_depth--;
|
||||
gdb_assert (this->m_recursion_depth >= 0);
|
||||
diff --git a/gdb/dwarf2/expr.h b/gdb/dwarf2/expr.h
|
||||
index b02cc531640..957c58f30c4 100644
|
||||
--- a/gdb/dwarf2/expr.h
|
||||
+++ b/gdb/dwarf2/expr.h
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "leb128.h"
|
||||
#include "dwarf2/call-site.h"
|
||||
+#include "dwarf2.h"
|
||||
|
||||
struct dwarf2_per_objfile;
|
||||
|
||||
@@ -54,6 +55,9 @@ enum dwarf_value_location
|
||||
/* A piece of an object, as recorded by DW_OP_piece or DW_OP_bit_piece. */
|
||||
struct dwarf_expr_piece
|
||||
{
|
||||
+ /* The DWARF operation for which the piece was created. */
|
||||
+ enum dwarf_location_atom op;
|
||||
+
|
||||
enum dwarf_value_location location;
|
||||
|
||||
union
|
||||
@@ -208,7 +212,7 @@ struct dwarf_expr_context
|
||||
struct type *address_type () const;
|
||||
void push (struct value *value, bool in_stack_memory);
|
||||
bool stack_empty_p () const;
|
||||
- void add_piece (ULONGEST size, ULONGEST offset);
|
||||
+ void add_piece (ULONGEST size, ULONGEST offset, enum dwarf_location_atom op);
|
||||
void execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end);
|
||||
void pop ();
|
||||
struct value *fetch (int n);
|
||||
--
|
||||
2.43.0
|
||||
|
220
add-gdbarch_dwarf2_reg_piece_offset-hook.patch
Normal file
220
add-gdbarch_dwarf2_reg_piece_offset-hook.patch
Normal file
@ -0,0 +1,220 @@
|
||||
From 29b185c531fcd933da62142debcb088321be7c4c Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 15 Jan 2025 17:02:00 +0100
|
||||
Subject: [PATCH 24/46] Add gdbarch_dwarf2_reg_piece_offset hook
|
||||
|
||||
In rw_pieced_value, when reading/writing part of a register, DW_OP_piece and
|
||||
DW_OP_bit_piece are handled the same, but the standard tells us:
|
||||
- DW_OP_piece: if the piece is located in a register, but does not occupy the
|
||||
entire register, the placement of the piece within that register is defined
|
||||
by the ABI.
|
||||
- DW_OP_bit_piece: if the location is a register, the offset is from the least
|
||||
significant bit end of the register.
|
||||
|
||||
Add a new hook gdbarch_dwarf2_reg_piece_offset that allows us to define the
|
||||
ABI-specific behaviour for DW_OP_piece.
|
||||
|
||||
The default implementation of the hook is the behaviour of DW_OP_bit_piece, so
|
||||
there should not be any functional changes.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/dwarf2/expr.c | 31 +++++++++++++++++++++++++------
|
||||
gdb/findvar.c | 18 ++++++++++++++++++
|
||||
gdb/gdbarch-gen.h | 8 ++++++++
|
||||
gdb/gdbarch.c | 22 ++++++++++++++++++++++
|
||||
gdb/gdbarch_components.py | 16 ++++++++++++++++
|
||||
gdb/value.h | 2 ++
|
||||
6 files changed, 91 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
|
||||
index 03107f90575..ece713ee7cd 100644
|
||||
--- a/gdb/dwarf2/expr.c
|
||||
+++ b/gdb/dwarf2/expr.c
|
||||
@@ -211,14 +211,33 @@ rw_pieced_value (value *v, value *from, bool check_optimized)
|
||||
ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum);
|
||||
int optim, unavail;
|
||||
|
||||
- if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
|
||||
- && p->offset + p->size < reg_bits)
|
||||
+ if (p->offset + p->size < reg_bits)
|
||||
{
|
||||
- /* Big-endian, and we want less than full size. */
|
||||
- bits_to_skip += reg_bits - (p->offset + p->size);
|
||||
+ /* We want less than full size. */
|
||||
+
|
||||
+ if (p->op == DW_OP_piece)
|
||||
+ {
|
||||
+ gdb_assert (p->offset == 0);
|
||||
+
|
||||
+ /* If the piece is located in a register, but does not
|
||||
+ occupy the entire register, the placement of the piece
|
||||
+ within that register is defined by the ABI. */
|
||||
+ bits_to_skip
|
||||
+ += 8 * gdbarch_dwarf2_reg_piece_offset (arch, gdb_regnum,
|
||||
+ p->size / 8);
|
||||
+ }
|
||||
+ else if (p->op == DW_OP_bit_piece)
|
||||
+ {
|
||||
+ /* If the location is a register, the offset is from the
|
||||
+ least significant bit end of the register. */
|
||||
+ if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG)
|
||||
+ bits_to_skip += reg_bits - (p->offset + p->size);
|
||||
+ else
|
||||
+ bits_to_skip += p->offset;
|
||||
+ }
|
||||
+ else
|
||||
+ error (_("Don't know how to get part of implicit pointer"));
|
||||
}
|
||||
- else
|
||||
- bits_to_skip += p->offset;
|
||||
|
||||
this_size = bits_to_bytes (bits_to_skip, this_size_bits);
|
||||
buffer.resize (this_size);
|
||||
diff --git a/gdb/findvar.c b/gdb/findvar.c
|
||||
index df4ab1a28b9..3b20974474a 100644
|
||||
--- a/gdb/findvar.c
|
||||
+++ b/gdb/findvar.c
|
||||
@@ -541,6 +541,24 @@ default_value_from_register (gdbarch *gdbarch, type *type, int regnum,
|
||||
return value;
|
||||
}
|
||||
|
||||
+/* Default implementation of gdbarch_dwarf2_reg_piece_offset. Implements
|
||||
+ DW_OP_bits_piece for DW_OP_piece. */
|
||||
+
|
||||
+ULONGEST
|
||||
+default_dwarf2_reg_piece_offset (gdbarch *gdbarch, int gdb_regnum, ULONGEST size)
|
||||
+{
|
||||
+ ULONGEST reg_size = register_size (gdbarch, gdb_regnum);
|
||||
+ gdb_assert (size <= reg_size);
|
||||
+ if (reg_size == size)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
|
||||
+ return reg_size - size;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* VALUE must be an lval_register value. If regnum is the value's
|
||||
associated register number, and len the length of the value's type,
|
||||
read one or more registers in VALUE's frame, starting with register REGNUM,
|
||||
diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h
|
||||
index b982fd7cd09..2e20a9dbccd 100644
|
||||
--- a/gdb/gdbarch-gen.h
|
||||
+++ b/gdb/gdbarch-gen.h
|
||||
@@ -430,6 +430,14 @@ typedef struct value * (gdbarch_value_from_register_ftype) (struct gdbarch *gdba
|
||||
extern struct value * gdbarch_value_from_register (struct gdbarch *gdbarch, struct type *type, int regnum, const frame_info_ptr &this_frame);
|
||||
extern void set_gdbarch_value_from_register (struct gdbarch *gdbarch, gdbarch_value_from_register_ftype *value_from_register);
|
||||
|
||||
+/* For a DW_OP_piece located in a register, but not occupying the
|
||||
+ entire register, return the placement of the piece within that
|
||||
+ register as defined by the ABI. */
|
||||
+
|
||||
+typedef ULONGEST (gdbarch_dwarf2_reg_piece_offset_ftype) (struct gdbarch *gdbarch, int regnum, ULONGEST size);
|
||||
+extern ULONGEST gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch, int regnum, ULONGEST size);
|
||||
+extern void set_gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch, gdbarch_dwarf2_reg_piece_offset_ftype *dwarf2_reg_piece_offset);
|
||||
+
|
||||
typedef CORE_ADDR (gdbarch_pointer_to_address_ftype) (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf);
|
||||
extern CORE_ADDR gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf);
|
||||
extern void set_gdbarch_pointer_to_address (struct gdbarch *gdbarch, gdbarch_pointer_to_address_ftype *pointer_to_address);
|
||||
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
|
||||
index 58e9ebbdc59..ed5b5859277 100644
|
||||
--- a/gdb/gdbarch.c
|
||||
+++ b/gdb/gdbarch.c
|
||||
@@ -109,6 +109,7 @@ struct gdbarch
|
||||
gdbarch_register_to_value_ftype *register_to_value = nullptr;
|
||||
gdbarch_value_to_register_ftype *value_to_register = nullptr;
|
||||
gdbarch_value_from_register_ftype *value_from_register = default_value_from_register;
|
||||
+ gdbarch_dwarf2_reg_piece_offset_ftype *dwarf2_reg_piece_offset = default_dwarf2_reg_piece_offset;
|
||||
gdbarch_pointer_to_address_ftype *pointer_to_address = unsigned_pointer_to_address;
|
||||
gdbarch_address_to_pointer_ftype *address_to_pointer = unsigned_address_to_pointer;
|
||||
gdbarch_integer_to_address_ftype *integer_to_address = nullptr;
|
||||
@@ -371,6 +372,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of value_from_register, invalid_p == 0 */
|
||||
/* Skip verify of pointer_to_address, invalid_p == 0 */
|
||||
/* Skip verify of address_to_pointer, invalid_p == 0 */
|
||||
+ /* Skip verify of dwarf2_reg_piece_offset, invalid_p == 0. */
|
||||
/* Skip verify of integer_to_address, has predicate. */
|
||||
/* Skip verify of return_value, invalid_p == 0 */
|
||||
if ((gdbarch->return_value_as_value == default_gdbarch_return_value) == (gdbarch->return_value == nullptr))
|
||||
@@ -783,6 +785,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
gdb_printf (file,
|
||||
"gdbarch_dump: value_from_register = <%s>\n",
|
||||
host_address_to_string (gdbarch->value_from_register));
|
||||
+ gdb_printf (file,
|
||||
+ "gdbarch_dump: dwarf2_reg_piece_offset = <%s>\n",
|
||||
+ host_address_to_string (gdbarch->dwarf2_reg_piece_offset));
|
||||
gdb_printf (file,
|
||||
"gdbarch_dump: pointer_to_address = <%s>\n",
|
||||
host_address_to_string (gdbarch->pointer_to_address));
|
||||
@@ -2573,6 +2578,23 @@ set_gdbarch_value_from_register (struct gdbarch *gdbarch,
|
||||
gdbarch->value_from_register = value_from_register;
|
||||
}
|
||||
|
||||
+ULONGEST
|
||||
+gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch, int regnum, ULONGEST size)
|
||||
+{
|
||||
+ gdb_assert (gdbarch != NULL);
|
||||
+ gdb_assert (gdbarch->dwarf2_reg_piece_offset != NULL);
|
||||
+ if (gdbarch_debug >= 2)
|
||||
+ gdb_printf (gdb_stdlog, "gdbarch_dwarf2_reg_piece_offset called\n");
|
||||
+ return gdbarch->dwarf2_reg_piece_offset (gdbarch, regnum, size);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+set_gdbarch_dwarf2_reg_piece_offset (struct gdbarch *gdbarch,
|
||||
+ gdbarch_dwarf2_reg_piece_offset_ftype dwarf2_reg_piece_offset)
|
||||
+{
|
||||
+ gdbarch->dwarf2_reg_piece_offset = dwarf2_reg_piece_offset;
|
||||
+}
|
||||
+
|
||||
CORE_ADDR
|
||||
gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf)
|
||||
{
|
||||
diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py
|
||||
index 4006380076d..4a228b5d27c 100644
|
||||
--- a/gdb/gdbarch_components.py
|
||||
+++ b/gdb/gdbarch_components.py
|
||||
@@ -829,6 +829,22 @@ allocate and return a struct value with all value attributes
|
||||
invalid=False,
|
||||
)
|
||||
|
||||
+Method(
|
||||
+ comment="""
|
||||
+For a DW_OP_piece located in a register, but not occupying the
|
||||
+entire register, return the placement of the piece within that
|
||||
+register as defined by the ABI.
|
||||
+""",
|
||||
+ type="ULONGEST",
|
||||
+ name="dwarf2_reg_piece_offset",
|
||||
+ params=[
|
||||
+ ("int", "regnum"),
|
||||
+ ("ULONGEST", "size")
|
||||
+ ],
|
||||
+ predefault="default_dwarf2_reg_piece_offset",
|
||||
+ invalid=False,
|
||||
+)
|
||||
+
|
||||
Method(
|
||||
type="CORE_ADDR",
|
||||
name="pointer_to_address",
|
||||
diff --git a/gdb/value.h b/gdb/value.h
|
||||
index 9d7e88d9433..47df66e0961 100644
|
||||
--- a/gdb/value.h
|
||||
+++ b/gdb/value.h
|
||||
@@ -1128,6 +1128,8 @@ extern value *default_value_from_register (gdbarch *gdbarch, type *type,
|
||||
int regnum,
|
||||
const frame_info_ptr &this_frame);
|
||||
|
||||
+extern ULONGEST default_dwarf2_reg_piece_offset (gdbarch *gdbarch, int regnum, ULONGEST size);
|
||||
+
|
||||
extern struct value *value_from_register (struct type *type, int regnum,
|
||||
const frame_info_ptr &frame);
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,53 +0,0 @@
|
||||
From acc7b542a08819bec4aae767de547c531a7ab62e Mon Sep 17 00:00:00 2001
|
||||
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
|
||||
Date: Mon, 6 Nov 2023 07:26:24 -0600
|
||||
Subject: [PATCH 03/48] Change gdb.base/examine-backwards.exp for AIX.
|
||||
|
||||
In AIX unused or constant variables are collected as garbage by the linker and in the dwarf dump
|
||||
an address with all f's in hexadecimal are assigned. Hence the testcase fails with many failures stating
|
||||
it cannot access memory.
|
||||
|
||||
This patch is a small change to get it working in AIX as well.
|
||||
---
|
||||
gdb/testsuite/gdb.base/examine-backward.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/examine-backward.c b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
index e30b58fb005..354c2e2f323 100644
|
||||
--- a/gdb/testsuite/gdb.base/examine-backward.c
|
||||
+++ b/gdb/testsuite/gdb.base/examine-backward.c
|
||||
@@ -36,11 +36,11 @@ literals. The content of each array is the same as followings:
|
||||
TestStrings, to avoid showing garbage when we look for strings
|
||||
backwards from TestStrings. */
|
||||
|
||||
-const unsigned char Barrier[] = {
|
||||
+unsigned char Barrier[] = {
|
||||
0x00,
|
||||
};
|
||||
|
||||
-const unsigned char TestStrings[] = {
|
||||
+unsigned char TestStrings[] = {
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
|
||||
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
@@ -54,7 +54,7 @@ const unsigned char TestStrings[] = {
|
||||
0x00
|
||||
};
|
||||
|
||||
-const short TestStringsH[] = {
|
||||
+short TestStringsH[] = {
|
||||
0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
|
||||
0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
|
||||
0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
|
||||
@@ -67,7 +67,7 @@ const short TestStringsH[] = {
|
||||
0x0000
|
||||
};
|
||||
|
||||
-const int TestStringsW[] = {
|
||||
+int TestStringsW[] = {
|
||||
0x00000041, 0x00000042, 0x00000043, 0x00000044,
|
||||
0x00000045, 0x00000046, 0x00000047, 0x00000048,
|
||||
0x00000049, 0x0000004a, 0x0000004b, 0x0000004c,
|
||||
--
|
||||
2.35.3
|
||||
|
144
fix-gdb.ada-o2_float_param.exp-on-s390x-linux.patch
Normal file
144
fix-gdb.ada-o2_float_param.exp-on-s390x-linux.patch
Normal file
@ -0,0 +1,144 @@
|
||||
From 0ac8e9af3cd6713f4b230e9e335e1398c3161210 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 10 Jan 2025 21:25:53 +0100
|
||||
Subject: [PATCH 26/46] Fix gdb.ada/O2_float_param.exp on s390x-linux
|
||||
|
||||
With test-case gdb.ada/O2_float_param.exp on s390x-linux, I get:
|
||||
...
|
||||
(gdb) frame^M
|
||||
#0 callee.increment (val=99.0, val@entry=<error reading variable: \
|
||||
register has not been saved in frame>, msg=...) at callee.adb:19^M
|
||||
19 procedure Increment (Val : in out Float; Msg: String) is^M
|
||||
(gdb) FAIL: $exp: scenario=all: frame
|
||||
...
|
||||
|
||||
The frame command calls read_frame_arg to get:
|
||||
- the current value of val, and
|
||||
- the value of val at function entry.
|
||||
|
||||
The first scenario succeeds, and the second scenario fails.
|
||||
|
||||
For context and contrast, let's also investigate the first scenario: getting
|
||||
the current value of val.
|
||||
|
||||
Function parameter val:
|
||||
...
|
||||
<2><b51>: Abbrev Number: 4 (DW_TAG_formal_parameter)
|
||||
<b52> DW_AT_name : val
|
||||
<b58> DW_AT_type : <0xb86>
|
||||
<b5c> DW_AT_location : 0xab (location list)
|
||||
...
|
||||
has location list:
|
||||
...
|
||||
000000ab 0000000001002928 0000000001002967
|
||||
(DW_OP_reg16 (f0))
|
||||
000000be 0000000001002967 0000000001002968
|
||||
(DW_OP_reg24 (f8))
|
||||
000000d1 0000000001002968 0000000001002974
|
||||
(DW_OP_GNU_regval_type: 24 (f8) <0xb29>;
|
||||
DW_OP_GNU_const_type: <0xb29> 4 byte block: 3f 80 0 0 ; DW_OP_plus;
|
||||
DW_OP_stack_value)
|
||||
000000ef 0000000001002974 0000000001002982
|
||||
(DW_OP_GNU_entry_value: (DW_OP_GNU_regval_type: 16 (f0) <0xb29>);
|
||||
DW_OP_GNU_const_type: <0xb29> 4 byte block: 3f 80 0 0 ; DW_OP_plus;
|
||||
DW_OP_stack_value)
|
||||
0000010f <End of list>
|
||||
...
|
||||
and since we're stopped at address 0x1002928:
|
||||
...
|
||||
(gdb) print $pc
|
||||
$1 = (access procedure) 0x1002928 <callee.increment>
|
||||
...
|
||||
we get the value from dwarf register 16.
|
||||
|
||||
The s390x ABI [1] specifies that dwarf register 16 maps onto 8-byte register
|
||||
f0 or 16-byte register v0 (where f0 is part of v0), and in this case (because
|
||||
the v0 register is available) s390_dwarf_reg_to_regnum maps it to v0.
|
||||
|
||||
Val is only 4 bytes:
|
||||
...
|
||||
(gdb) ptype val
|
||||
type = <4-byte float>
|
||||
...
|
||||
and s390_value_from_register takes care to get the value from the correct part
|
||||
of v0.
|
||||
|
||||
The value of v0 is found in the prologue cache, and the value of parameter val
|
||||
is printed.
|
||||
|
||||
Now the second scenario: getting the value of val at function entry.
|
||||
|
||||
FWIW, since we're stopped at function entry, we could simply return the same
|
||||
value, reading the same register, but that's currently not implemented [2].
|
||||
|
||||
Instead we start from the fact that val is in dwarf reg 16 at function entry,
|
||||
and then use call site information:
|
||||
...
|
||||
<4><cf7>: Abbrev Number: 13 (DW_TAG_GNU_call_site)
|
||||
<cf8> DW_AT_low_pc : 0x1002a46
|
||||
<d00> DW_AT_abstract_origin: <0xdda>
|
||||
<5><d04>: Abbrev Number: 12 (DW_TAG_GNU_call_site_parameter)
|
||||
<d05> DW_AT_location : 1 byte block: 60 (DW_OP_reg16 (f0))
|
||||
<d07> DW_AT_GNU_call_site_value: 3 byte block: f5 18 2d \
|
||||
(DW_OP_GNU_regval_type: 24 (f8) <0xc42>)
|
||||
<5><d0b>: Abbrev Number: 12 (DW_TAG_GNU_call_site_parameter)
|
||||
...
|
||||
to conclude that the value we're looking for is in dwarf reg 24, which
|
||||
s390_dwarf_reg_to_regnum maps to v8.
|
||||
|
||||
As before, s390_value_from_register takes care to get the value from the
|
||||
correct part of v8.
|
||||
|
||||
However, v8 is not available in the prologue cache, and we take a different
|
||||
path and end up in s390_unwind_pseudo_register, where v8 and similar
|
||||
(regnum_is_vxr_full) is unhandled, and we get:
|
||||
...
|
||||
return value::allocate_optimized_out (type);
|
||||
...
|
||||
which eventually causes the "error reading variable: register has not been
|
||||
saved in frame".
|
||||
|
||||
Fix this by handling the regnum_is_vxr_full case in
|
||||
s390_unwind_pseudo_register, similar to how that is done in
|
||||
s390_pseudo_register_read.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
This also fixes test-case gdb.base/savedregs.exp.
|
||||
|
||||
[1] https://github.com/IBM/s390x-abi
|
||||
[2] https://sourceware.org/pipermail/gdb-patches/2024-September/211589.html
|
||||
---
|
||||
gdb/s390-tdep.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index a7c58b37276..31730296ef1 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -2332,6 +2332,22 @@ s390_unwind_pseudo_register (const frame_info_ptr &this_frame, int regnum)
|
||||
return value_cast (type, val);
|
||||
}
|
||||
|
||||
+ if (regnum_is_vxr_full (tdep, regnum))
|
||||
+ {
|
||||
+ struct value *val = value::allocate_register (this_frame, regnum);
|
||||
+
|
||||
+ int reg = regnum - tdep->v0_full_regnum;
|
||||
+ struct value *val1
|
||||
+ = frame_unwind_register_value (this_frame, S390_F0_REGNUM + reg);
|
||||
+ struct value *val2
|
||||
+ = frame_unwind_register_value (this_frame, S390_V0_LOWER_REGNUM + reg);
|
||||
+
|
||||
+ val1->contents_copy (val, 0, 0, 8);
|
||||
+ val2->contents_copy (val, 8, 0, 8);
|
||||
+
|
||||
+ return value_cast (type, val);
|
||||
+ }
|
||||
+
|
||||
return value::allocate_optimized_out (type);
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
188
fix-gdb.base-finish-pretty.exp-on-s390x.patch
Normal file
188
fix-gdb.base-finish-pretty.exp-on-s390x.patch
Normal file
@ -0,0 +1,188 @@
|
||||
From de696a57729423bf643e530fdb638dff6cf3c08b Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 4 Jan 2025 11:31:02 +0100
|
||||
Subject: [PATCH 21/46] Fix gdb.base/finish-pretty.exp on s390x
|
||||
|
||||
On s390x-linux, with test-case gdb.base/finish-pretty.exp I ran into:
|
||||
...
|
||||
(gdb) finish
|
||||
Run till exit from #0 foo () at finish-pretty.c:28
|
||||
main () at finish-pretty.c:40
|
||||
40 return v.a + v.b;
|
||||
Value returned has type: struct s. Cannot determine contents
|
||||
(gdb) FAIL: $exp: finish foo prettyprinted function result
|
||||
...
|
||||
|
||||
The function being finished is foo, which returns a value of type struct s.
|
||||
|
||||
The ABI [1] specifies:
|
||||
- that the value is returned in a storage buffer allocated by the caller, and
|
||||
- that the address of this buffer is passed as a hidden argument in r2.
|
||||
|
||||
GDB fails to print the value when finishing foo, because it doesn't know the
|
||||
address of the buffer.
|
||||
|
||||
Implement the gdbarch_get_return_buf_addr hook for s390x to fix this.
|
||||
|
||||
This is based on ppc_sysv_get_return_buf_addr, the only other implementation
|
||||
of gdbarch_get_return_buf_addr. For readability I've factored out
|
||||
dwarf_reg_on_entry.
|
||||
|
||||
There is one difference with ppc_sysv_get_return_buf_addr: only
|
||||
NO_ENTRY_VALUE_ERROR is caught. If this patch is approved, I intend to submit
|
||||
a follow-up patch to fix this in ppc_sysv_get_return_buf_addr as well.
|
||||
|
||||
The hook is not guaranteed to work, because it attempts to get the value r2
|
||||
had at function entry.
|
||||
|
||||
The hook can be called after function entry, and the ABI doesn't guarantee
|
||||
that r2 is the same throughout the function.
|
||||
|
||||
Using -fvar-tracking adds debug information, which allows the hook to succeed
|
||||
more often, and indeed after adding this to the test-case, it passes.
|
||||
|
||||
Do likewise in one more test-case.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Fixes:
|
||||
- gdb.ada/finish-large.exp
|
||||
- gdb.base/finish-pretty.exp
|
||||
- gdb.base/retval-large-struct.exp
|
||||
- gdb.cp/non-trivial-retval.exp
|
||||
- gdb.ada/array_return.exp
|
||||
|
||||
AFAICT, I've also enabled the hook for s390 and from the ABI I get the
|
||||
impression that it should work, but I haven't been able to test it.
|
||||
|
||||
[1] https://github.com/IBM/s390x-abi
|
||||
---
|
||||
gdb/s390-tdep.c | 58 ++++++++++++++++++++++++
|
||||
gdb/testsuite/gdb.ada/array_return.exp | 8 +++-
|
||||
gdb/testsuite/gdb.base/finish-pretty.exp | 8 +++-
|
||||
3 files changed, 72 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 4844b7e9bc8..4e7dce70c12 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "trad-frame.h"
|
||||
#include "value.h"
|
||||
#include "inferior.h"
|
||||
+#include "dwarf2/loc.h"
|
||||
|
||||
#include "features/s390-linux32.c"
|
||||
#include "features/s390x-linux64.c"
|
||||
@@ -2119,6 +2120,62 @@ s390_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
return rvc;
|
||||
}
|
||||
|
||||
+/* Try to get the value of DWARF_REG in FRAME at function entry. If successful,
|
||||
+ return it as value of type VAL_TYPE. */
|
||||
+
|
||||
+static struct value *
|
||||
+dwarf_reg_on_entry (int dwarf_reg, struct type *val_type,
|
||||
+ const frame_info_ptr &frame)
|
||||
+{
|
||||
+ enum call_site_parameter_kind kind = CALL_SITE_PARAMETER_DWARF_REG;
|
||||
+ union call_site_parameter_u kind_u = { .dwarf_reg = dwarf_reg };
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ return value_of_dwarf_reg_entry (val_type, frame, kind, kind_u);
|
||||
+ }
|
||||
+ catch (const gdb_exception_error &e)
|
||||
+ {
|
||||
+ if (e.error == NO_ENTRY_VALUE_ERROR)
|
||||
+ return nullptr;
|
||||
+
|
||||
+ throw;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Both the 32-bit and 64-bit ABIs specify that values of some types are
|
||||
+ returned in a storage buffer provided by the caller. Return the address of
|
||||
+ that storage buffer, if possible. Implements the
|
||||
+ gdbarch_get_return_buf_addr hook. */
|
||||
+
|
||||
+static CORE_ADDR
|
||||
+s390_get_return_buf_addr (struct type *val_type,
|
||||
+ const frame_info_ptr &cur_frame)
|
||||
+{
|
||||
+ /* The address of the storage buffer is provided as a hidden argument in
|
||||
+ register r2. */
|
||||
+ int dwarf_reg = 2;
|
||||
+
|
||||
+ /* The ABI does not guarantee that the register will not be changed while
|
||||
+ executing the function. Hence, it cannot be assumed that it will still
|
||||
+ contain the address of the storage buffer when execution reaches the end
|
||||
+ of the function.
|
||||
+
|
||||
+ Attempt to determine the value on entry using the DW_OP_entry_value DWARF
|
||||
+ entries. This requires compiling the user program with -fvar-tracking. */
|
||||
+ struct value *val_on_entry
|
||||
+ = dwarf_reg_on_entry (dwarf_reg, lookup_pointer_type (val_type), cur_frame);
|
||||
+
|
||||
+ if (val_on_entry == nullptr)
|
||||
+ {
|
||||
+ warning ("Cannot determine the function return value.\n"
|
||||
+ "Try compiling with -fvar-tracking.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return value_as_address (val_on_entry);
|
||||
+}
|
||||
+
|
||||
/* Frame unwinding. */
|
||||
|
||||
/* Implement the stack_frame_destroyed_p gdbarch method. */
|
||||
@@ -7183,6 +7240,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_dummy_id (gdbarch, s390_dummy_id);
|
||||
set_gdbarch_frame_align (gdbarch, s390_frame_align);
|
||||
set_gdbarch_return_value (gdbarch, s390_return_value);
|
||||
+ set_gdbarch_get_return_buf_addr (gdbarch, s390_get_return_buf_addr);
|
||||
|
||||
/* Frame handling. */
|
||||
/* Stack grows downward. */
|
||||
diff --git a/gdb/testsuite/gdb.ada/array_return.exp b/gdb/testsuite/gdb.ada/array_return.exp
|
||||
index c6edee11f17..d1fc2ac2c98 100644
|
||||
--- a/gdb/testsuite/gdb.ada/array_return.exp
|
||||
+++ b/gdb/testsuite/gdb.ada/array_return.exp
|
||||
@@ -19,7 +19,13 @@ require allow_ada_tests
|
||||
|
||||
standard_ada_testfile p
|
||||
|
||||
-if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
|
||||
+set opts {}
|
||||
+lappend opts debug
|
||||
+if { [have_fvar_tracking] } {
|
||||
+ lappend opts "additional_flags=-fvar-tracking"
|
||||
+}
|
||||
+
|
||||
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $opts] != ""} {
|
||||
return -1
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/finish-pretty.exp b/gdb/testsuite/gdb.base/finish-pretty.exp
|
||||
index 44f3340f41c..0b6bea6681d 100644
|
||||
--- a/gdb/testsuite/gdb.base/finish-pretty.exp
|
||||
+++ b/gdb/testsuite/gdb.base/finish-pretty.exp
|
||||
@@ -18,7 +18,13 @@
|
||||
|
||||
standard_testfile
|
||||
|
||||
-if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
|
||||
+set opts {}
|
||||
+lappend opts debug
|
||||
+if { [have_fvar_tracking] } {
|
||||
+ lappend opts "additional_flags=-fvar-tracking"
|
||||
+}
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
187
fix-gdb.base-readnever.exp-on-s390x.patch
Normal file
187
fix-gdb.base-readnever.exp-on-s390x.patch
Normal file
@ -0,0 +1,187 @@
|
||||
From 1d761604714b32883d2bbc4a5f274fc3e2c668fe Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 9 Jan 2025 14:32:19 +0100
|
||||
Subject: [PATCH 22/46] Fix gdb.base/readnever.exp on s390x
|
||||
|
||||
On s390x-linux, I run into:
|
||||
...
|
||||
(gdb) backtrace
|
||||
#0 0x000000000100061a in fun_three ()
|
||||
#1 0x000000000100067a in fun_two ()
|
||||
#2 0x000003fffdfa9470 in ?? ()
|
||||
Backtrace stopped: frame did not save the PC
|
||||
(gdb) FAIL: gdb.base/readnever.exp: backtrace
|
||||
...
|
||||
|
||||
This is really due to a problem handling the fun_three frame. When generating
|
||||
a backtrace from fun_two, everying looks ok:
|
||||
...
|
||||
$ gdb -readnever -q -batch outputs/gdb.base/readnever/readnever \
|
||||
-ex "b fun_two" \
|
||||
-ex run \
|
||||
-ex bt
|
||||
...
|
||||
#0 0x0000000001000650 in fun_two ()
|
||||
#1 0x00000000010006b6 in fun_one ()
|
||||
#2 0x00000000010006ee in main ()
|
||||
...
|
||||
|
||||
For reference the frame info with debug info (without -readnever) looks like this:
|
||||
...
|
||||
$ gdb -q -batch outputs/gdb.base/readnever/readnever \
|
||||
-ex "b fun_three" \
|
||||
-ex run \
|
||||
-ex "info frame"
|
||||
...
|
||||
Stack level 0, frame at 0x3fffffff140:
|
||||
pc = 0x1000632 in fun_three (readnever.c:20); saved pc = 0x100067a
|
||||
called by frame at 0x3fffffff1f0
|
||||
source language c.
|
||||
Arglist at 0x3fffffff140, args: a=10, b=49 '1', c=0x3fffffff29c
|
||||
Locals at 0x3fffffff140, Previous frame's sp in v0
|
||||
...
|
||||
|
||||
But with -readnever, like this instead:
|
||||
...
|
||||
Stack level 0, frame at 0x0:
|
||||
pc = 0x100061a in fun_three; saved pc = 0x100067a
|
||||
called by frame at 0x3fffffff140
|
||||
Arglist at 0xffffffffffffffff, args:
|
||||
Locals at 0xffffffffffffffff, Previous frame's sp in r15
|
||||
...
|
||||
|
||||
An obvious difference is the "Previous frame's sp in" v0 vs. r15.
|
||||
|
||||
Looking at the code:
|
||||
...
|
||||
0000000001000608 <fun_three>:
|
||||
1000608: b3 c1 00 2b ldgr %f2,%r11
|
||||
100060c: b3 c1 00 0f ldgr %f0,%r15
|
||||
1000610: e3 f0 ff 50 ff 71 lay %r15,-176(%r15)
|
||||
1000616: b9 04 00 bf lgr %r11,%r15
|
||||
...
|
||||
it becomes clear what is going on. This is an unusual prologue.
|
||||
|
||||
Rather than saving r11 (frame pointer) and r15 (stack pointer) to stack,
|
||||
instead they're saved into call-clobbered floating point registers.
|
||||
|
||||
[ For reference, this is the prologue of fun_two:
|
||||
...
|
||||
0000000001000640 <fun_two>:
|
||||
1000640: eb bf f0 58 00 24 stmg %r11,%r15,88(%r15)
|
||||
1000646: e3 f0 ff 50 ff 71 lay %r15,-176(%r15)
|
||||
100064c: b9 04 00 bf lgr %r11,%r15
|
||||
...
|
||||
where the first instruction stores registers r11 to r15 to stack. ]
|
||||
|
||||
Gdb fails to properly analyze the prologue, which causes the problems getting
|
||||
the frame info.
|
||||
|
||||
Fix this by:
|
||||
- adding handling of the ldgr insn [1] in s390_analyze_prologue, and
|
||||
- recognizing the insn as saving a register in
|
||||
s390_prologue_frame_unwind_cache.
|
||||
|
||||
This gets us instead:
|
||||
...
|
||||
Stack level 0, frame at 0x0:
|
||||
pc = 0x100061a in fun_three; saved pc = 0x100067a
|
||||
called by frame at 0x3fffffff1f0
|
||||
Arglist at 0xffffffffffffffff, args:
|
||||
Locals at 0xffffffffffffffff, Previous frame's sp in f0
|
||||
...
|
||||
and:
|
||||
...
|
||||
(gdb) backtrace^M
|
||||
#0 0x000000000100061a in fun_three ()^M
|
||||
#1 0x000000000100067a in fun_two ()^M
|
||||
#2 0x00000000010006b6 in fun_one ()^M
|
||||
#3 0x00000000010006ee in main ()^M
|
||||
(gdb) PASS: gdb.base/readnever.exp: backtrace
|
||||
...
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
PR tdep/32417
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32417
|
||||
|
||||
Approved-By: Andreas Arnez <arnez@linux.ibm.com>
|
||||
|
||||
[1] https://www.ibm.com/support/pages/sites/default/files/2021-05/SA22-7871-10.pdf
|
||||
---
|
||||
gdb/s390-tdep.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||
gdb/s390-tdep.h | 1 +
|
||||
2 files changed, 40 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 4e7dce70c12..2609b42f797 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -855,6 +855,11 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
|
||||
|| is_rre (insn64, op_lgr, &r1, &r2))
|
||||
data->gpr[r1] = data->gpr[r2];
|
||||
|
||||
+ /* LDGR r1, r2 --- load from register to floating-point register
|
||||
+ (64-bit version). */
|
||||
+ else if (is_rre (insn64, op_ldgr, &r1, &r2))
|
||||
+ data->fpr[r1] = data->gpr[r2];
|
||||
+
|
||||
/* L r1, d2(x2, b2) --- load. */
|
||||
/* LY r1, d2(x2, b2) --- load (long-displacement version). */
|
||||
/* LG r1, d2(x2, b2) --- load (64-bit version). */
|
||||
@@ -2542,6 +2547,40 @@ s390_prologue_frame_unwind_cache (const frame_info_ptr &this_frame,
|
||||
&& data.fpr_slot[i] != 0)
|
||||
info->saved_regs[S390_F0_REGNUM + i].set_addr (cfa - data.fpr_slot[i]);
|
||||
|
||||
+ /* Handle this type of prologue:
|
||||
+ ldgr %f2,%r11
|
||||
+ ldgr %f0,%r15
|
||||
+ where call-clobbered floating point registers are used as register save
|
||||
+ slots. */
|
||||
+ for (i = 0; i < S390_NUM_FPRS; i++)
|
||||
+ {
|
||||
+ int fpr = S390_F0_REGNUM + i;
|
||||
+
|
||||
+ /* Check that fpr is a call-clobbered register. */
|
||||
+ if (s390_register_call_saved (gdbarch, fpr))
|
||||
+ continue;
|
||||
+
|
||||
+ /* Check that fpr contains the value of a register at function
|
||||
+ entry. */
|
||||
+ if (data.fpr[i].kind != pvk_register)
|
||||
+ continue;
|
||||
+
|
||||
+ int entry_val_reg = data.fpr[i].reg;
|
||||
+
|
||||
+ /* Check that entry_val_reg is a call-saved register. */
|
||||
+ if (!s390_register_call_saved (gdbarch, entry_val_reg))
|
||||
+ continue;
|
||||
+
|
||||
+ /* In the prologue, we've copied:
|
||||
+ - the value of a call-saved register (entry_val_reg) at function
|
||||
+ entry, to
|
||||
+ - a call-clobbered floating point register (fpr).
|
||||
+
|
||||
+ Heuristic: assume that makes the floating point register a register
|
||||
+ save slot, leaving the value constant throughout the function. */
|
||||
+ info->saved_regs[entry_val_reg].set_realreg (fpr);
|
||||
+ }
|
||||
+
|
||||
/* Function return will set PC to %r14. */
|
||||
info->saved_regs[S390_PSWA_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM];
|
||||
|
||||
diff --git a/gdb/s390-tdep.h b/gdb/s390-tdep.h
|
||||
index 10f775f468f..b098d735a13 100644
|
||||
--- a/gdb/s390-tdep.h
|
||||
+++ b/gdb/s390-tdep.h
|
||||
@@ -82,6 +82,7 @@ enum
|
||||
op1_lgfi = 0xc0, op2_lgfi = 0x01,
|
||||
op_lr = 0x18,
|
||||
op_lgr = 0xb904,
|
||||
+ op_ldgr = 0xb3c1,
|
||||
op_l = 0x58,
|
||||
op1_ly = 0xe3, op2_ly = 0x58,
|
||||
op1_lg = 0xe3, op2_lg = 0x04,
|
||||
--
|
||||
2.43.0
|
||||
|
143
fix-gdb.base-store.exp-on-s390x.patch
Normal file
143
fix-gdb.base-store.exp-on-s390x.patch
Normal file
@ -0,0 +1,143 @@
|
||||
From 69e165afa3d45cfac89ed6be298ac6465c84c0fd Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 15 Jan 2025 17:02:00 +0100
|
||||
Subject: [PATCH 25/46] Fix gdb.base/store.exp on s390x
|
||||
|
||||
On s390x-linux, I get:
|
||||
...
|
||||
(gdb) print l^M
|
||||
$29 = 0^M
|
||||
(gdb) FAIL: gdb.base/store.exp: var doublest l; print old l, expecting -1
|
||||
...
|
||||
|
||||
So, we're in wack_doublest trying to print l, which is a copy of parameter u:
|
||||
...
|
||||
register doublest l = u, r = v;
|
||||
...
|
||||
which does have the expected value:
|
||||
...
|
||||
(gdb) p u
|
||||
$1 = -1
|
||||
...
|
||||
which is a long double, 16 bytes and looks like this:
|
||||
...
|
||||
(gdb) p /x u
|
||||
$3 = 0xbfff0000000000000000000000000000
|
||||
...
|
||||
|
||||
Parameter u is passed in two registers:
|
||||
...
|
||||
<2><6a5>: Abbrev Number: 15 (DW_TAG_formal_parameter)
|
||||
<6a6> DW_AT_name : v
|
||||
<69e> DW_AT_location : 6 byte block: 50 93 8 51 93 8 \
|
||||
(DW_OP_reg0 (r0); DW_OP_piece: 8; DW_OP_reg1 (r1); DW_OP_piece: 8)
|
||||
...
|
||||
and indeed we find the msw in r0 and the lsw in r1:
|
||||
...
|
||||
(gdb) p /x $r0
|
||||
$4 = 0xbfff000000000000
|
||||
(gdb) p /x $r1
|
||||
$5 = 0x0
|
||||
(gdb)
|
||||
...
|
||||
|
||||
Likewise, variable l consists of two registers:
|
||||
...
|
||||
<2><6b5>: Abbrev Number: 13 (DW_TAG_variable)
|
||||
<6b6> DW_AT_name : l
|
||||
<6be> DW_AT_location : 6 byte block: 68 93 8 69 93 8 \
|
||||
(DW_OP_reg24 (f8); DW_OP_piece: 8; DW_OP_reg25 (f10); DW_OP_piece: 8)
|
||||
...
|
||||
and we find the same values there:
|
||||
...
|
||||
(gdb) p /x $f8
|
||||
$6 = 0xbfff000000000000
|
||||
(gdb) p /x $f10
|
||||
$7 = 0x0
|
||||
...
|
||||
|
||||
So, we get the expected results when fetching the value from two gprs, but not
|
||||
when fetching the value from two fprs.
|
||||
|
||||
When fetching the values from the two fprs, we stumble upon a particularity of
|
||||
the DWARF register numbers as defined by the s390x ABI [1]: dwarf register 24
|
||||
maps to both floating-point register f8 (8 bytes), and vector register v8
|
||||
(16 bytes).
|
||||
|
||||
In s390_dwarf_reg_to_regnum, it's determined which of the two is chosen, and
|
||||
if available vector registers are preferred over floating-point registers, so
|
||||
v8 is chosen, and used to fetch the value.
|
||||
|
||||
Since the size of the DW_OP_piece is 8 bytes, and the register size is 16
|
||||
bytes, this bit in rw_pieced_value is activated:
|
||||
...
|
||||
/* If the piece is located in a register, but does not
|
||||
occupy the entire register, the placement of the piece
|
||||
within that register is defined by the ABI. */
|
||||
bits_to_skip
|
||||
+= 8 * gdbarch_dwarf2_reg_piece_offset (arch, gdb_regnum,
|
||||
p->size / 8);
|
||||
...
|
||||
but since the default implemention default_dwarf2_reg_piece_offset does not
|
||||
match the s390x ABI, we get the wrong answer.
|
||||
|
||||
This is a known problem, see FOSDEM 2018 presentation "DWARF Pieces And Other
|
||||
DWARF Location Woes" [2].
|
||||
|
||||
Fix this by adding s390_dwarf2_reg_piece_offset, roughly implementing the same
|
||||
logic as in s390_value_from_register.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
[1] https://github.com/IBM/s390x-abi
|
||||
[2] https://archive.fosdem.org/2018/schedule/event/dwarfpieces
|
||||
---
|
||||
gdb/s390-tdep.c | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 2609b42f797..a7c58b37276 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -1260,6 +1260,28 @@ s390_value_from_register (gdbarch *gdbarch, type *type, int regnum,
|
||||
return value;
|
||||
}
|
||||
|
||||
+/* Implementation of the gdbarch_dwarf2_reg_piece_offset hook. */
|
||||
+
|
||||
+static ULONGEST
|
||||
+s390_dwarf2_reg_piece_offset (gdbarch *gdbarch, int gdb_regnum, ULONGEST size)
|
||||
+{
|
||||
+ s390_gdbarch_tdep *tdep = gdbarch_tdep<s390_gdbarch_tdep> (gdbarch);
|
||||
+
|
||||
+ /* Floating point register. */
|
||||
+ if (gdb_regnum >= S390_F0_REGNUM && gdb_regnum <= S390_F15_REGNUM)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Vector register, v0 - v15. */
|
||||
+ if (regnum_is_vxr_full (tdep, gdb_regnum))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Vector register, v16 - v31. */
|
||||
+ if (gdb_regnum >= S390_V16_REGNUM && gdb_regnum <= S390_V31_REGNUM)
|
||||
+ return 0;
|
||||
+
|
||||
+ return default_dwarf2_reg_piece_offset (gdbarch, gdb_regnum, size);
|
||||
+}
|
||||
+
|
||||
/* Implement pseudo_register_name tdesc method. */
|
||||
|
||||
static const char *
|
||||
@@ -7259,6 +7281,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_stab_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum);
|
||||
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum);
|
||||
set_gdbarch_value_from_register (gdbarch, s390_value_from_register);
|
||||
+ set_gdbarch_dwarf2_reg_piece_offset (gdbarch, s390_dwarf2_reg_piece_offset);
|
||||
|
||||
/* Pseudo registers. */
|
||||
set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
|
||||
--
|
||||
2.43.0
|
||||
|
97
fix-gdb.dap-step-out.exp-on-s390x.patch
Normal file
97
fix-gdb.dap-step-out.exp-on-s390x.patch
Normal file
@ -0,0 +1,97 @@
|
||||
From 6775ce3f5e936a50d883abfb60cafa80f8b76cf6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 10 Dec 2024 11:53:31 +0100
|
||||
Subject: [PATCH 19/46] Fix gdb.dap/step-out.exp on s390x
|
||||
|
||||
With test-case gdb.dap/step-out.exp on s390x-linux, I get:
|
||||
...
|
||||
>>> {"seq": 7, "type": "request", "command": "scopes", "arguments": {"frameId": 0}}
|
||||
Content-Length: 569^M
|
||||
^M
|
||||
{"request_seq": 7, "type": "response", "command": "scopes", "body": {"scopes": [{"variablesReference": 1, "name": "Locals", "presentationHint": "locals", "expensive": false, "namedVariables": 1, "line": 35, "source": {"name": "step-out.c", "path": "/home/vries/gdb/src/gdb/testsuite/gdb.dap/step-out.c"}}, {"variablesReference": 2, "name": "Registers", "presentationHint": "registers", "expensive": false, "namedVariables": 114, "line": 35, "source": {"name": "step-out.c", "path": "/home/vries/gdb/src/gdb/testsuite/gdb.dap/step-out.c"}}]}, "success": true, "seq": 21}PASS: gdb.dap/step-out.exp: get scopes success
|
||||
FAIL: gdb.dap/step-out.exp: three scopes
|
||||
...
|
||||
|
||||
The problem is that the test-case expects three scopes:
|
||||
...
|
||||
lassign $scopes scope reg_scope return_scope
|
||||
...
|
||||
but the return_scope is missing because this doesn't work:
|
||||
...
|
||||
$ gdb -q -batch outputs/gdb.dap/step-out/step-out \
|
||||
-ex "b function_breakpoint_here" \
|
||||
-ex run \
|
||||
-ex finish
|
||||
...
|
||||
Value returned has type: struct result. Cannot determine contents
|
||||
...
|
||||
|
||||
This is likely caused by a problem in gdb, but there's nothing wrong the DAP
|
||||
support.
|
||||
|
||||
Fix this by:
|
||||
- allowing two scopes, and
|
||||
- declaring the tests of return_scope unsupported.
|
||||
|
||||
Tested on s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/gdb.dap/step-out.exp | 42 ++++++++++++++++--------------
|
||||
1 file changed, 23 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dap/step-out.exp b/gdb/testsuite/gdb.dap/step-out.exp
|
||||
index 757f4ebdaca..491eaf71197 100644
|
||||
--- a/gdb/testsuite/gdb.dap/step-out.exp
|
||||
+++ b/gdb/testsuite/gdb.dap/step-out.exp
|
||||
@@ -59,24 +59,28 @@ set scopes [dap_check_request_and_response "get scopes" scopes \
|
||||
[format {o frameId [i %d]} $frame_id]]
|
||||
set scopes [dict get [lindex $scopes 0] body scopes]
|
||||
|
||||
-gdb_assert {[llength $scopes] == 2} "two scopes"
|
||||
-
|
||||
-lassign $scopes scope reg_scope
|
||||
-gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
|
||||
-gdb_assert {[dict get $scope presentationHint] == "locals"} \
|
||||
- "locals presentation hint"
|
||||
-gdb_assert {[dict get $scope namedVariables] == 2} "two vars in scope"
|
||||
-
|
||||
-set num [dict get $scope variablesReference]
|
||||
-set refs [lindex [dap_check_request_and_response "fetch arguments" \
|
||||
- "variables" \
|
||||
- [format {o variablesReference [i %d]} $num]] \
|
||||
- 0]
|
||||
-set varlist [lindex [dict get $refs body variables] 0]
|
||||
-
|
||||
-gdb_assert {[dict get $varlist variablesReference] > 0} \
|
||||
- "variable has children"
|
||||
-gdb_assert {[dict get $varlist name] == "(return)"} \
|
||||
- "variable is return value"
|
||||
+gdb_assert {[llength $scopes] == 2 || [llength $scopes] == 3} "two or three scopes"
|
||||
+lassign $scopes scope reg_scope return_scope
|
||||
+
|
||||
+set test "scope is locals"
|
||||
+if { $return_scope == "" } {
|
||||
+ unsupported $test
|
||||
+} else {
|
||||
+ gdb_assert {[dict get $scope presentationHint] == "locals"} \
|
||||
+ "locals presentation hint"
|
||||
+ gdb_assert {[dict get $scope namedVariables] == 2} "two vars in scope"
|
||||
+
|
||||
+ set num [dict get $scope variablesReference]
|
||||
+ set refs [lindex [dap_check_request_and_response "fetch arguments" \
|
||||
+ "variables" \
|
||||
+ [format {o variablesReference [i %d]} $num]] \
|
||||
+ 0]
|
||||
+ set varlist [lindex [dict get $refs body variables] 0]
|
||||
+
|
||||
+ gdb_assert {[dict get $varlist variablesReference] > 0} \
|
||||
+ "variable has children"
|
||||
+ gdb_assert {[dict get $varlist name] == "(return)"} \
|
||||
+ "variable is return value"
|
||||
+}
|
||||
|
||||
dap_shutdown
|
||||
--
|
||||
2.43.0
|
||||
|
56
fix-gdb.dwarf2-shortpiece.exp-on-s390x.patch
Normal file
56
fix-gdb.dwarf2-shortpiece.exp-on-s390x.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 2ccefe53891d9c1393853f5179f8e8046c95a6ce Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 19 Jun 2024 10:04:22 +0200
|
||||
Subject: [PATCH 17/46] Fix gdb.dwarf2/shortpiece.exp on s390x
|
||||
|
||||
On s390x-linux, I run into:
|
||||
...
|
||||
(gdb) p (short []) s1^M
|
||||
$3 = {0, 1, 0, <optimized out>}^M
|
||||
(gdb) FAIL: gdb.dwarf2/shortpiece.exp: p (short []) s1
|
||||
...
|
||||
while this is expected:
|
||||
...
|
||||
(gdb) p (short []) s1^M
|
||||
$3 = {1, 0, 0, <optimized out>}^M
|
||||
(gdb) PASS: gdb.dwarf2/shortpiece.exp: p (short []) s1
|
||||
...
|
||||
|
||||
The type of s1 is:
|
||||
...
|
||||
(gdb) ptype s1
|
||||
type = struct S {
|
||||
myint a;
|
||||
myushort b;
|
||||
}
|
||||
...
|
||||
so the difference is due the fact that viewing an int as two shorts gives
|
||||
different results depending on the endianness.
|
||||
|
||||
Fix this by allowing both results.
|
||||
|
||||
Tested on x86_64-linux and s390x-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/testsuite/gdb.dwarf2/shortpiece.exp | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/shortpiece.exp b/gdb/testsuite/gdb.dwarf2/shortpiece.exp
|
||||
index f7ff805de7c..4fcdfcae57a 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/shortpiece.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/shortpiece.exp
|
||||
@@ -138,7 +138,9 @@ gdb_test "p s2" \
|
||||
# This test verifies that GDB can print a pieced value casted to a
|
||||
# different type.
|
||||
gdb_test "p (int \[\]) s1" " = \\{1, <optimized out>\\}"
|
||||
-gdb_test "p (short \[\]) s1" " = \\{1, 0, 0, <optimized out>\\}"
|
||||
+set re_little [string_to_regexp "{1, 0, 0, <optimized out>}"]
|
||||
+set re_big [string_to_regexp "{0, 1, 0, <optimized out>}"]
|
||||
+gdb_test {p (short []) s1} " = ($re_little|$re_big)"
|
||||
|
||||
# Test for correct output if the size of the original object is not a
|
||||
# multiple of the array's element size.
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,366 +0,0 @@
|
||||
From 2a7e48ca27f4c080151ce9da5a29239aa5d3b66f Mon Sep 17 00:00:00 2001
|
||||
From: Tom Tromey <tromey@adacore.com>
|
||||
Date: Fri, 19 Apr 2024 07:54:19 -0600
|
||||
Subject: [PATCH 15/48] Fix regression on aarch64-linux gdbserver
|
||||
|
||||
Commit 9a03f218 ("Fix gdb.base/watchpoint-unaligned.exp on aarch64")
|
||||
fixed a watchpoint bug in gdb -- but did not touch the corresponding
|
||||
code in gdbserver.
|
||||
|
||||
This patch moves the gdb code into gdb/nat, so that it can be shared
|
||||
with gdbserver, and then changes gdbserver to use it, fixing the bug.
|
||||
|
||||
This is yet another case where having a single back end would prevent
|
||||
bugs.
|
||||
|
||||
I tested this using the AdaCore internal gdb testsuite.
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29423
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
---
|
||||
gdb/aarch64-nat.c | 115 ---------------------------------
|
||||
gdb/aarch64-nat.h | 8 ---
|
||||
gdb/nat/aarch64-hw-point.c | 115 +++++++++++++++++++++++++++++++++
|
||||
gdb/nat/aarch64-hw-point.h | 8 +++
|
||||
gdbserver/linux-aarch64-low.cc | 38 +----------
|
||||
5 files changed, 126 insertions(+), 158 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch64-nat.c b/gdb/aarch64-nat.c
|
||||
index a173e4e18d5..97e3048568a 100644
|
||||
--- a/gdb/aarch64-nat.c
|
||||
+++ b/gdb/aarch64-nat.c
|
||||
@@ -225,121 +225,6 @@ aarch64_remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/* See aarch64-nat.h. */
|
||||
-
|
||||
-bool
|
||||
-aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
- CORE_ADDR addr_trap, CORE_ADDR *addr_p)
|
||||
-{
|
||||
- bool found = false;
|
||||
- for (int phase = 0; phase <= 1; ++phase)
|
||||
- for (int i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
- {
|
||||
- if (!(state->dr_ref_count_wp[i]
|
||||
- && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])))
|
||||
- {
|
||||
- /* Watchpoint disabled. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- const enum target_hw_bp_type type
|
||||
- = aarch64_watchpoint_type (state->dr_ctrl_wp[i]);
|
||||
- if (type == hw_execute)
|
||||
- {
|
||||
- /* Watchpoint disabled. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (phase == 0)
|
||||
- {
|
||||
- /* Phase 0: No hw_write. */
|
||||
- if (type == hw_write)
|
||||
- continue;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Phase 1: Only hw_write. */
|
||||
- if (type != hw_write)
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- const unsigned int offset
|
||||
- = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
- const unsigned int len
|
||||
- = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
- const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
- const CORE_ADDR addr_watch_aligned
|
||||
- = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
- const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
-
|
||||
- /* ADDR_TRAP reports the first address of the memory range
|
||||
- accessed by the CPU, regardless of what was the memory
|
||||
- range watched. Thus, a large CPU access that straddles
|
||||
- the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
- ADDR_TRAP that is lower than the
|
||||
- ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
-
|
||||
- addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
- |---- range watched ----|
|
||||
- |----------- range accessed ------------|
|
||||
-
|
||||
- In this case, ADDR_TRAP will be 4.
|
||||
-
|
||||
- The access size also can be larger than that of the watchpoint
|
||||
- itself. For instance, the access size of an stp instruction is 16.
|
||||
- So, if we use stp to store to address p, and set a watchpoint on
|
||||
- address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
|
||||
- RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
|
||||
- for this situation introduces the possibility of false positives,
|
||||
- so we only do this for hw_write watchpoints. */
|
||||
- const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
|
||||
- const CORE_ADDR addr_watch_base = addr_watch_aligned -
|
||||
- (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
- if (!(addr_trap >= addr_watch_base
|
||||
- && addr_trap < addr_watch + len))
|
||||
- {
|
||||
- /* Not a match. */
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* To match a watchpoint known to GDB core, we must never
|
||||
- report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
- range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
- positive on kernels older than 4.10. See PR
|
||||
- external/20207. */
|
||||
- if (addr_p != nullptr)
|
||||
- *addr_p = addr_orig;
|
||||
-
|
||||
- if (phase == 0)
|
||||
- {
|
||||
- /* Phase 0: Return first match. */
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- /* Phase 1. */
|
||||
- if (addr_p == nullptr)
|
||||
- {
|
||||
- /* First match, and we don't need to report an address. No need
|
||||
- to look for other matches. */
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- if (!found)
|
||||
- {
|
||||
- /* First match, and we need to report an address. Look for other
|
||||
- matches. */
|
||||
- found = true;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- /* More than one match, and we need to return an address. No need to
|
||||
- look for further matches. */
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return found;
|
||||
-}
|
||||
-
|
||||
/* Define AArch64 maintenance commands. */
|
||||
|
||||
static void
|
||||
diff --git a/gdb/aarch64-nat.h b/gdb/aarch64-nat.h
|
||||
index fee6bda2577..f95a9d745e5 100644
|
||||
--- a/gdb/aarch64-nat.h
|
||||
+++ b/gdb/aarch64-nat.h
|
||||
@@ -45,14 +45,6 @@ struct aarch64_debug_reg_state *aarch64_get_debug_reg_state (pid_t pid);
|
||||
|
||||
void aarch64_remove_debug_reg_state (pid_t pid);
|
||||
|
||||
-/* Helper for the "stopped_data_address" target method. Returns TRUE
|
||||
- if a hardware watchpoint trap at ADDR_TRAP matches a set
|
||||
- watchpoint. The address of the matched watchpoint is returned in
|
||||
- *ADDR_P. */
|
||||
-
|
||||
-bool aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
- CORE_ADDR addr_trap, CORE_ADDR *addr_p);
|
||||
-
|
||||
/* Helper functions used by aarch64_nat_target below. See their
|
||||
definitions. */
|
||||
|
||||
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c
|
||||
index 3b8cdcba23b..9eb78923e86 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.c
|
||||
+++ b/gdb/nat/aarch64-hw-point.c
|
||||
@@ -647,3 +647,118 @@ aarch64_region_ok_for_watchpoint (CORE_ADDR addr, int len)
|
||||
the checking is costly. */
|
||||
return 1;
|
||||
}
|
||||
+
|
||||
+/* See nat/aarch64-hw-point.h. */
|
||||
+
|
||||
+bool
|
||||
+aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
+ CORE_ADDR addr_trap, CORE_ADDR *addr_p)
|
||||
+{
|
||||
+ bool found = false;
|
||||
+ for (int phase = 0; phase <= 1; ++phase)
|
||||
+ for (int i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
+ {
|
||||
+ if (!(state->dr_ref_count_wp[i]
|
||||
+ && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])))
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const enum target_hw_bp_type type
|
||||
+ = aarch64_watchpoint_type (state->dr_ctrl_wp[i]);
|
||||
+ if (type == hw_execute)
|
||||
+ {
|
||||
+ /* Watchpoint disabled. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: No hw_write. */
|
||||
+ if (type == hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Phase 1: Only hw_write. */
|
||||
+ if (type != hw_write)
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ const unsigned int offset
|
||||
+ = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
+ const unsigned int len
|
||||
+ = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
+ const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
+ const CORE_ADDR addr_watch_aligned
|
||||
+ = align_down (state->dr_addr_wp[i], AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
+ const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
+
|
||||
+ /* ADDR_TRAP reports the first address of the memory range
|
||||
+ accessed by the CPU, regardless of what was the memory
|
||||
+ range watched. Thus, a large CPU access that straddles
|
||||
+ the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
+ ADDR_TRAP that is lower than the
|
||||
+ ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
+
|
||||
+ addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
+ |---- range watched ----|
|
||||
+ |----------- range accessed ------------|
|
||||
+
|
||||
+ In this case, ADDR_TRAP will be 4.
|
||||
+
|
||||
+ The access size also can be larger than that of the watchpoint
|
||||
+ itself. For instance, the access size of an stp instruction is 16.
|
||||
+ So, if we use stp to store to address p, and set a watchpoint on
|
||||
+ address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
|
||||
+ RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
|
||||
+ for this situation introduces the possibility of false positives,
|
||||
+ so we only do this for hw_write watchpoints. */
|
||||
+ const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
|
||||
+ const CORE_ADDR addr_watch_base = addr_watch_aligned -
|
||||
+ (max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
|
||||
+ if (!(addr_trap >= addr_watch_base
|
||||
+ && addr_trap < addr_watch + len))
|
||||
+ {
|
||||
+ /* Not a match. */
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* To match a watchpoint known to GDB core, we must never
|
||||
+ report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
+ range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
+ positive on kernels older than 4.10. See PR
|
||||
+ external/20207. */
|
||||
+ if (addr_p != nullptr)
|
||||
+ *addr_p = addr_orig;
|
||||
+
|
||||
+ if (phase == 0)
|
||||
+ {
|
||||
+ /* Phase 0: Return first match. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ /* Phase 1. */
|
||||
+ if (addr_p == nullptr)
|
||||
+ {
|
||||
+ /* First match, and we don't need to report an address. No need
|
||||
+ to look for other matches. */
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ {
|
||||
+ /* First match, and we need to report an address. Look for other
|
||||
+ matches. */
|
||||
+ found = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* More than one match, and we need to return an address. No need to
|
||||
+ look for further matches. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return found;
|
||||
+}
|
||||
diff --git a/gdb/nat/aarch64-hw-point.h b/gdb/nat/aarch64-hw-point.h
|
||||
index 71ae2864927..2386cf60f90 100644
|
||||
--- a/gdb/nat/aarch64-hw-point.h
|
||||
+++ b/gdb/nat/aarch64-hw-point.h
|
||||
@@ -110,6 +110,14 @@ unsigned int aarch64_watchpoint_offset (unsigned int ctrl);
|
||||
unsigned int aarch64_watchpoint_length (unsigned int ctrl);
|
||||
enum target_hw_bp_type aarch64_watchpoint_type (unsigned int ctrl);
|
||||
|
||||
+/* Helper for the "stopped_data_address" target method. Returns TRUE
|
||||
+ if a hardware watchpoint trap at ADDR_TRAP matches a set
|
||||
+ watchpoint. The address of the matched watchpoint is returned in
|
||||
+ *ADDR_P. */
|
||||
+
|
||||
+bool aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
|
||||
+ CORE_ADDR addr_trap, CORE_ADDR *addr_p);
|
||||
+
|
||||
int aarch64_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr,
|
||||
int len, int is_insert, ptid_t ptid,
|
||||
struct aarch64_debug_reg_state *state);
|
||||
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
|
||||
index fcbe7bb64d7..14346b89822 100644
|
||||
--- a/gdbserver/linux-aarch64-low.cc
|
||||
+++ b/gdbserver/linux-aarch64-low.cc
|
||||
@@ -577,41 +577,9 @@ aarch64_target::low_stopped_data_address ()
|
||||
|
||||
/* Check if the address matches any watched address. */
|
||||
state = aarch64_get_debug_reg_state (pid_of (current_thread));
|
||||
- for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
|
||||
- {
|
||||
- const unsigned int offset
|
||||
- = aarch64_watchpoint_offset (state->dr_ctrl_wp[i]);
|
||||
- const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
|
||||
- const CORE_ADDR addr_watch = state->dr_addr_wp[i] + offset;
|
||||
- const CORE_ADDR addr_watch_aligned = align_down (state->dr_addr_wp[i], 8);
|
||||
- const CORE_ADDR addr_orig = state->dr_addr_orig_wp[i];
|
||||
-
|
||||
- if (state->dr_ref_count_wp[i]
|
||||
- && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
|
||||
- && addr_trap >= addr_watch_aligned
|
||||
- && addr_trap < addr_watch + len)
|
||||
- {
|
||||
- /* ADDR_TRAP reports the first address of the memory range
|
||||
- accessed by the CPU, regardless of what was the memory
|
||||
- range watched. Thus, a large CPU access that straddles
|
||||
- the ADDR_WATCH..ADDR_WATCH+LEN range may result in an
|
||||
- ADDR_TRAP that is lower than the
|
||||
- ADDR_WATCH..ADDR_WATCH+LEN range. E.g.:
|
||||
-
|
||||
- addr: | 4 | 5 | 6 | 7 | 8 |
|
||||
- |---- range watched ----|
|
||||
- |----------- range accessed ------------|
|
||||
-
|
||||
- In this case, ADDR_TRAP will be 4.
|
||||
-
|
||||
- To match a watchpoint known to GDB core, we must never
|
||||
- report *ADDR_P outside of any ADDR_WATCH..ADDR_WATCH+LEN
|
||||
- range. ADDR_WATCH <= ADDR_TRAP < ADDR_ORIG is a false
|
||||
- positive on kernels older than 4.10. See PR
|
||||
- external/20207. */
|
||||
- return addr_orig;
|
||||
- }
|
||||
- }
|
||||
+ CORE_ADDR result;
|
||||
+ if (aarch64_stopped_data_address (state, addr_trap, &result))
|
||||
+ return result;
|
||||
|
||||
return (CORE_ADDR) 0;
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,80 +0,0 @@
|
||||
From c21fd9f7d5911fce0c17af7094d8861d1195dfda Mon Sep 17 00:00:00 2001
|
||||
From: Carl Love <cel@linux.ibm.com>
|
||||
Date: Mon, 13 Nov 2023 14:14:08 -0500
|
||||
Subject: [PATCH 01/48] Fix the gdb.ada/inline-section-gc.exp test
|
||||
|
||||
The original intention of the test appears to be checking to make sure
|
||||
setting a breakpoint in an inlined function didn't set multiple
|
||||
breakpoints where one of them was at address 0.
|
||||
|
||||
The gdb.ada/inline-section-gc.exp test may pass or fail depending on the
|
||||
version of gnat. Per the discussion on IRC, the ada inlining appears to
|
||||
have some target dependencies. In this test there are two functions,
|
||||
callee and caller. Function calee is inlined into caller. The test sets
|
||||
a breakpoint in function callee. The reported location where the
|
||||
breakpoint is set may be at the requested location in callee or the
|
||||
location in caller after callee has been inlined. The test needs to
|
||||
accept either location as correct provided the breakpoint address is not
|
||||
zero.
|
||||
|
||||
This patch checks to see if the reported breakpoint is in function callee
|
||||
or function caller and fails if the breakpoint address is 0x0. The line
|
||||
number where the breakpoint is set will match the requested line if the
|
||||
breakpoint location is reported is callee.adb. If the breakpoint is
|
||||
reported in caller.adb, the line number in caller is the breakpoint
|
||||
location in callee where it is inlined into caller.
|
||||
|
||||
This patch fixes the single regression failure for the test on PowerPC.
|
||||
It does not introduce any failures on X86-64.
|
||||
---
|
||||
gdb/testsuite/gdb.ada/inline-section-gc.exp | 21 ++++++++++++++++---
|
||||
.../gdb.ada/inline-section-gc/caller.adb | 3 ++-
|
||||
2 files changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.ada/inline-section-gc.exp b/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
index b707335eb04..4f8b8c95395 100644
|
||||
--- a/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
+++ b/gdb/testsuite/gdb.ada/inline-section-gc.exp
|
||||
@@ -34,8 +34,23 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $options] != ""} {
|
||||
|
||||
clean_restart ${testfile}
|
||||
|
||||
-set bp_location [gdb_get_line_number "BREAK" ${testdir}/callee.adb]
|
||||
+
|
||||
+# Depending on the version of gnat, the location of the set breakpoint may
|
||||
+# be reported as being at the requested location in file callee.adb or in
|
||||
+# file caller.adb where the callee function was inlined. Either way, only
|
||||
+# one breakpoint should be reported and its address should not be at 0x0.
|
||||
+set bp_location1 [gdb_get_line_number "BREAK" ${testdir}/callee.adb]
|
||||
+set bp_location2 [gdb_get_line_number "CALLEE_LOC" ${testdir}/caller.adb]
|
||||
+set test "break callee.adb:$bp_location1"
|
||||
+set message "Breakpoint set"
|
||||
+
|
||||
# The bug here was that gdb would set a breakpoint with two locations,
|
||||
# one of them at 0x0.
|
||||
-gdb_test "break callee.adb:$bp_location" \
|
||||
- "Breakpoint $decimal at $hex: file .*callee.adb, line $bp_location."
|
||||
+gdb_test_multiple $test $message {
|
||||
+ -re "Breakpoint $decimal at $hex: file .*callee.adb, line $bp_location1." {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "Breakpoint $decimal at $hex: file .*caller.adb, line $bp_location2." {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb b/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
index 66eb2d9a910..161f3e85542 100644
|
||||
--- a/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
+++ b/gdb/testsuite/gdb.ada/inline-section-gc/caller.adb
|
||||
@@ -18,4 +18,5 @@ with Callee;
|
||||
procedure Caller is
|
||||
begin
|
||||
Callee;
|
||||
-end Caller;
|
||||
+end Caller; -- CALLEE_LOC, this is where the inlined callee breakpoint
|
||||
+ -- is located.
|
||||
|
||||
base-commit: 582fc35843fdf71b82d645d83d2903e2546cc21a
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 19dc95258888a9e110ad54fa25a613611956a13f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 13 Jun 2023 15:04:32 +0200
|
||||
Subject: [PATCH 5/6] fixup gdb-6.3-attach-see-vdso-test.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/attach-see-vdso.exp | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/attach-see-vdso.exp b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
index 5457ec4129d..35c49731f0b 100644
|
||||
--- a/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
+++ b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
@@ -34,10 +34,11 @@ set escapedbinfile [string_to_regexp [standard_output_file ${testfile}]]
|
||||
# The kernel VDSO is used for the syscalls returns only on i386 (not x86_64).
|
||||
#
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-m32}] != "" } {
|
||||
- gdb_suppress_entire_file "Testcase nonthraded compile failed, so all tests in this file will automatically fail."
|
||||
+ unsupported "Testcase nonthreaded compile failed, so all tests in this file will automatically fail."
|
||||
+ return
|
||||
}
|
||||
|
||||
-if [get_compiler_info ${binfile}] {
|
||||
+if [get_compiler_info] {
|
||||
return -1
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,25 +0,0 @@
|
||||
From 8c0ae8c3c6fa34f046131f76871db13bc392a440 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 13 Jun 2023 14:56:55 +0200
|
||||
Subject: [PATCH 4/6] fixup gdb-6.3-gstack-20050411.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gstack.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gstack.exp b/gdb/testsuite/gdb.base/gstack.exp
|
||||
index 089407ec04a..a5dacd582ff 100644
|
||||
--- a/gdb/testsuite/gdb.base/gstack.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gstack.exp
|
||||
@@ -52,7 +52,7 @@ gdb_expect {
|
||||
# exiting the function. Still we could retry the gstack command if we fail.
|
||||
|
||||
set test "spawn gstack"
|
||||
-set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $BUILD_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
|
||||
+set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $GDB_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
|
||||
set res [remote_spawn host $command];
|
||||
if { $res < 0 || $res == "" } {
|
||||
perror "Spawning $command failed."
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,35 +0,0 @@
|
||||
Fixup gdb.base/tracefork-zombie.exp
|
||||
|
||||
Fix ERROR:
|
||||
...
|
||||
PASS: gdb.base/tracefork-zombie.exp: attach
|
||||
ERROR: tcl error sourcing gdb/testsuite/gdb.base/tracefork-zombie.exp.
|
||||
ERROR: tcl error code POSIX ESRCH {no such process}
|
||||
ERROR: error reading "file12": no such process
|
||||
while executing
|
||||
"read $statusfi"
|
||||
("foreach" body line 5)
|
||||
invoked from within
|
||||
...
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/tracefork-zombie.exp | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/tracefork-zombie.exp b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
index 03f790d4c5d..3e2e5517d46 100644
|
||||
--- a/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
+++ b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
@@ -58,8 +58,10 @@ foreach procpid [glob -directory /proc -type d {[0-9]*}] {
|
||||
if {[catch {open $procpid/status} statusfi]} {
|
||||
continue
|
||||
}
|
||||
- set status [read $statusfi]
|
||||
- close $statusfi
|
||||
+ if {[catch {read $statusfi} status]} {
|
||||
+ continue
|
||||
+ }
|
||||
+ catch {close $statusfi}
|
||||
if {1
|
||||
&& [regexp -line {^Name:\tgdb$} $status]
|
||||
&& [regexp -line {^PPid:\t1$} $status]
|
25
fixup-gdb-6.5-gcore-buffer-limit-test.patch
Normal file
25
fixup-gdb-6.5-gcore-buffer-limit-test.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 388654c78086e5240fec47260e47d1deff4af43d Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 6 Feb 2025 13:27:57 +0100
|
||||
Subject: [PATCH 43/46] fixup-gdb-6.5-gcore-buffer-limit-test.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gcore-excessive-memory.exp | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-excessive-memory.exp b/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
index 31cf88ce78a..1ef595923ad 100644
|
||||
--- a/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-excessive-memory.exp
|
||||
@@ -14,6 +14,8 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
+require can_spawn_for_attach
|
||||
+
|
||||
if {[use_gdb_stub]} {
|
||||
untested "skipping test because of use_gdb_stub"
|
||||
return -1
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,22 +0,0 @@
|
||||
From 023314feb400836eb377a5bc9151850fcdd81b11 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 6 Jun 2023 09:43:36 +0200
|
||||
Subject: [PATCH 3/4] Fixup gdb-bz634108-solib_address.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.python/rh634108-solib_address.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/rh634108-solib_address.exp b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
index 99e6aaba831..ebf00babc34 100644
|
||||
--- a/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
+++ b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
@@ -21,4 +21,4 @@ gdb_start
|
||||
# Skip all tests if Python scripting is not enabled.
|
||||
if { [skip_python_tests] } { continue }
|
||||
|
||||
-gdb_test "python print (gdb.solib_name(-1))" "None" "gdb.solib_name exists"
|
||||
+gdb_test "python print (gdb.solib_name(0))" "None" "gdb.solib_name exists"
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,19 +0,0 @@
|
||||
fixup-gdb-glibc-strstr-workaround.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
index 889f8c6f584..052bd84d420 100644
|
||||
--- a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
@@ -68,7 +68,7 @@ gdb_test_multiple $test $test {
|
||||
set addr $expect_out(1,string)
|
||||
pass "$test (fixed glibc)"
|
||||
}
|
||||
- -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <(__GI_)?strstr>\r\n$gdb_prompt $" {
|
||||
untested "$test (gnu-ifunc not in use by glibc)"
|
||||
return 0
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
From af4a87e2b3c2ac5acae1e6f4405fc59e1218de74 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 18 Apr 2024 14:26:58 +0200
|
||||
Subject: [PATCH] fixup-gdb-linux_perf-bundle
|
||||
|
||||
---
|
||||
gdb/gdb.c | 8 --------
|
||||
1 file changed, 8 deletions(-)
|
||||
|
||||
diff --git a/gdb/gdb.c b/gdb/gdb.c
|
||||
index 41a9b70c222..6e3ff0755ab 100644
|
||||
--- a/gdb/gdb.c
|
||||
+++ b/gdb/gdb.c
|
||||
@@ -21,10 +21,6 @@
|
||||
#include "interps.h"
|
||||
#include "run-on-main-thread.h"
|
||||
|
||||
-#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
-extern "C" void __libipt_init(void);
|
||||
-#endif
|
||||
-
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -36,10 +32,6 @@ main (int argc, char **argv)
|
||||
|
||||
struct captured_main_args args;
|
||||
|
||||
-#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
- __libipt_init();
|
||||
-#endif
|
||||
-
|
||||
memset (&args, 0, sizeof args);
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
|
||||
base-commit: 254988c36fe592e89af5d92e1d35a6eb4b09cbb0
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,43 +0,0 @@
|
||||
From e452307ba07f5d798edad73631182e137265da7d Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 13 Jun 2023 17:58:42 +0200
|
||||
Subject: [PATCH 9/9] fixup gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch
|
||||
|
||||
---
|
||||
.../rhbz1261564-aarch64-watchpoint.exp | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
index b1cf7115663..42ebc25cc49 100644
|
||||
--- a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
@@ -20,12 +20,22 @@ if { [prepare_for_testing rhbz1261564-aarch64-watchpoint.exp "rhbz1261564-aarch6
|
||||
if { ! [ runto main ] } then { return 0 }
|
||||
|
||||
set test "rwatch aligned.var4"
|
||||
-if [istarget "s390*-*-*"] {
|
||||
- gdb_test $test {Target does not support this type of hardware watchpoint\.}
|
||||
- untested "s390* does not support hw read watchpoint"
|
||||
+
|
||||
+set supported 1
|
||||
+gdb_test_multiple $test "" {
|
||||
+ -re -wrap "Hardware read watchpoint \[0-9\]+: aligned.var4" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "Target does not support this type of hardware watchpoint\\." {
|
||||
+ set supported 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if { !$supported } {
|
||||
+ unsupported $test
|
||||
return
|
||||
}
|
||||
-gdb_test $test "Hardware read watchpoint \[0-9\]+: aligned.var4"
|
||||
+
|
||||
|
||||
proc checkvar { address } {
|
||||
global gdb_prompt
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,38 +0,0 @@
|
||||
fixup-gdb-test-bt-cfi-without-die.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/cfi-without-die.exp | 13 ++++++++-----
|
||||
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cfi-without-die.exp b/gdb/testsuite/gdb.base/cfi-without-die.exp
|
||||
index 5880d46f6d2..db1726646f8 100644
|
||||
--- a/gdb/testsuite/gdb.base/cfi-without-die.exp
|
||||
+++ b/gdb/testsuite/gdb.base/cfi-without-die.exp
|
||||
@@ -37,19 +37,22 @@ if ![runto callback] then {
|
||||
fail "verify unwinding: Can't run to callback"
|
||||
return 0
|
||||
}
|
||||
-set test "verify unwinding breaks without CFI"
|
||||
-gdb_test_multiple "bt" $test {
|
||||
+
|
||||
+set as_expected 1
|
||||
+gdb_test_multiple "bt" "" {
|
||||
-re " in \[?\]\[?\] .*\r\n$gdb_prompt $" {
|
||||
# It may backtrace through some random frames even to main().
|
||||
- pass $test
|
||||
}
|
||||
-re " in main .*\r\n$gdb_prompt $" {
|
||||
- fail $test
|
||||
+ set as_expected 0
|
||||
}
|
||||
-re "\r\n$gdb_prompt $" {
|
||||
- pass $test
|
||||
}
|
||||
}
|
||||
+if { ! $as_expected } {
|
||||
+ untested ${testfile}.exp
|
||||
+ return -1
|
||||
+}
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srccallerfile}" ${objcallerfile} \
|
||||
object [list {additional_flags=-fomit-frame-pointer -funwind-tables -fasynchronous-unwind-tables}]] != ""
|
@ -1,21 +0,0 @@
|
||||
From 81a7585502092b3c133534ac6ecb34fd56d05337 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 16 Feb 2023 12:56:41 +0100
|
||||
Subject: [PATCH 09/11] fixup gdb-test-dw2-aranges.patch
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.dwarf2/dw2-aranges.S | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-aranges.S b/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
|
||||
index d5b9ca5a3c6..b811f6644cb 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
|
||||
@@ -138,3 +138,4 @@ main:
|
||||
.byte 0 /* aranges segment_size */
|
||||
|
||||
.Laranges_end:
|
||||
+ .section .note.GNU-stack,"",@progbits
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,70 +0,0 @@
|
||||
From d60b57fe1a98094a7e4f19481193b2b5a9bb1e57 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 2 May 2024 12:02:50 +0200
|
||||
Subject: [PATCH 079/147] fixup PowerPC and aarch64: Fix reverse stepping
|
||||
failure
|
||||
|
||||
---
|
||||
gdb/infrun.c | 2 +-
|
||||
gdb/symtab.c | 3 +--
|
||||
gdb/symtab.h | 3 +--
|
||||
3 files changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 069ef144a76..7be98cfc252 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -6897,7 +6897,7 @@ update_line_range_start (CORE_ADDR pc, struct execution_control_state *ecs)
|
||||
Given the PC, check the line table and return the PC that corresponds
|
||||
to the line table entry for the source line that PC is in. */
|
||||
CORE_ADDR start_line_pc = ecs->event_thread->control.step_range_start;
|
||||
- std::optional<CORE_ADDR> real_range_start;
|
||||
+ gdb::optional<CORE_ADDR> real_range_start;
|
||||
|
||||
/* Call find_line_range_start to get the smallest address in the
|
||||
linetable for multiple Line X entries in the line table. */
|
||||
diff --git a/gdb/symtab.c b/gdb/symtab.c
|
||||
index ef63ec93c5a..9a47796e5e0 100644
|
||||
--- a/gdb/symtab.c
|
||||
+++ b/gdb/symtab.c
|
||||
@@ -73,7 +73,6 @@
|
||||
#include "gdbsupport/gdb_string_view.h"
|
||||
#include "gdbsupport/pathstuff.h"
|
||||
#include "gdbsupport/common-utils.h"
|
||||
-#include <optional>
|
||||
|
||||
/* Forward declarations for local functions. */
|
||||
|
||||
@@ -3328,7 +3327,7 @@ sal_line_symtab_matches_p (const symtab_and_line &sal1,
|
||||
|
||||
/* See symtah.h. */
|
||||
|
||||
-std::optional<CORE_ADDR>
|
||||
+gdb::optional<CORE_ADDR>
|
||||
find_line_range_start (CORE_ADDR pc)
|
||||
{
|
||||
struct symtab_and_line current_sal = find_pc_line (pc, 0);
|
||||
diff --git a/gdb/symtab.h b/gdb/symtab.h
|
||||
index e17d15c595b..6a611d42880 100644
|
||||
--- a/gdb/symtab.h
|
||||
+++ b/gdb/symtab.h
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "gdb-demangle.h"
|
||||
#include "split-name.h"
|
||||
#include "frame.h"
|
||||
-#include <optional>
|
||||
|
||||
/* Opaque declarations. */
|
||||
struct ui_file;
|
||||
@@ -2377,7 +2376,7 @@ extern struct symtab_and_line find_pc_sect_line (CORE_ADDR,
|
||||
the starting PC of line X, and the ranges are contiguous.
|
||||
*/
|
||||
|
||||
-extern std::optional<CORE_ADDR> find_line_range_start (CORE_ADDR pc);
|
||||
+extern gdb::optional<CORE_ADDR> find_line_range_start (CORE_ADDR pc);
|
||||
|
||||
/* Wrapper around find_pc_line to just return the symtab. */
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,101 +0,0 @@
|
||||
From c1da0d6449415cc1fe6f863526735e4325b0b3ac Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 May 2024 12:43:41 +0200
|
||||
Subject: [PATCH 1/2] fixup-skip-tests
|
||||
|
||||
---
|
||||
gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp | 4 +---
|
||||
gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp | 4 +---
|
||||
gdb/testsuite/gdb.cp/cxxexec.exp | 2 +-
|
||||
.../py-gdb-rhbz1007614-memleak-infpy_read_memory.exp | 4 ++--
|
||||
gdb/testsuite/gdb.python/rh634108-solib_address.exp | 6 +++---
|
||||
5 files changed, 8 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
index 0c46489f315..5879319f27c 100644
|
||||
--- a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
@@ -13,9 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-if {[skip_shlib_tests]} {
|
||||
- return 0
|
||||
-}
|
||||
+require allow_shlib_tests
|
||||
|
||||
set testfile "gcore-buildid-exec-but-not-solib"
|
||||
set srcmainfile ${testfile}-main.c
|
||||
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
index 052bd84d420..73a9bb64903 100644
|
||||
--- a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
+++ b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
@@ -17,9 +17,7 @@
|
||||
# invalid IFUNC DW_AT_linkage_name: memmove strstr time
|
||||
# http://sourceware.org/bugzilla/show_bug.cgi?id=14166
|
||||
|
||||
-if {[skip_shlib_tests]} {
|
||||
- return 0
|
||||
-}
|
||||
+require allow_shlib_tests
|
||||
|
||||
set testfile "gnu-ifunc-strstr-workaround"
|
||||
set executable ${testfile}
|
||||
diff --git a/gdb/testsuite/gdb.cp/cxxexec.exp b/gdb/testsuite/gdb.cp/cxxexec.exp
|
||||
index 77c85587407..089a679a1a9 100644
|
||||
--- a/gdb/testsuite/gdb.cp/cxxexec.exp
|
||||
+++ b/gdb/testsuite/gdb.cp/cxxexec.exp
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-if { [skip_cplus_tests] } { continue }
|
||||
+require allow_cplus_tests
|
||||
|
||||
set testfile cxxexec
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.cc {c++ debug}] } {
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
index 2e6786d499a..d2693cfef1d 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
@@ -13,6 +13,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
+require allow_python_tests
|
||||
+
|
||||
set testfile py-gdb-rhbz1007614-memleak-infpy_read_memory
|
||||
set srcfile ${testfile}.c
|
||||
set binfile [standard_output_file ${testfile}]
|
||||
@@ -21,8 +23,6 @@ if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
-if { [skip_python_tests] } { continue }
|
||||
-
|
||||
set pid_of_gdb [exp_pid -i [board_info host fileid]]
|
||||
|
||||
proc memory_v_pages_get {} {
|
||||
diff --git a/gdb/testsuite/gdb.python/rh634108-solib_address.exp b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
index ebf00babc34..2d950b79951 100644
|
||||
--- a/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
+++ b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
@@ -15,10 +15,10 @@
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=634108
|
||||
|
||||
+# Skip all tests if Python scripting is not enabled.
|
||||
+require allow_python_tests
|
||||
+
|
||||
gdb_exit
|
||||
gdb_start
|
||||
|
||||
-# Skip all tests if Python scripting is not enabled.
|
||||
-if { [skip_python_tests] } { continue }
|
||||
-
|
||||
gdb_test "python print (gdb.solib_name(0))" "None" "gdb.solib_name exists"
|
||||
|
||||
base-commit: 50ee7556c2430effed45ca542852f36368336dce
|
||||
--
|
||||
2.35.3
|
||||
|
BIN
gdb-14.2.tar.bz2
(Stored with Git LFS)
BIN
gdb-14.2.tar.bz2
(Stored with Git LFS)
Binary file not shown.
3
gdb-15.2.tar.bz2
Normal file
3
gdb-15.2.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:843d09d5a24cbf7b75ee26016ba7f5428b35172e4479fcdbeb55f49e19443b5d
|
||||
size 32259376
|
@ -1,120 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.3-attach-see-vdso-test.patch
|
||||
|
||||
;; Test kernel VDSO decoding while attaching to an i386 process.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/attach-see-vdso.c b/gdb/testsuite/gdb.base/attach-see-vdso.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/attach-see-vdso.c
|
||||
@@ -0,0 +1,25 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2007 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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. */
|
||||
+
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+int main ()
|
||||
+{
|
||||
+ pause ();
|
||||
+ return 1;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/attach-see-vdso.exp b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/attach-see-vdso.exp
|
||||
@@ -0,0 +1,77 @@
|
||||
+# Copyright 2007
|
||||
+
|
||||
+# 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.
|
||||
+
|
||||
+# This file was created by Jan Kratochvil <jan.kratochvil@redhat.com>.
|
||||
+
|
||||
+# This test only works on Linux
|
||||
+if { ![istarget "*-*-linux-gnu*"] } {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+if {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set testfile "attach-see-vdso"
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+set escapedbinfile [string_to_regexp [standard_output_file ${testfile}]]
|
||||
+
|
||||
+# The kernel VDSO is used for the syscalls returns only on i386 (not x86_64).
|
||||
+#
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-m32}] != "" } {
|
||||
+ gdb_suppress_entire_file "Testcase nonthraded compile failed, so all tests in this file will automatically fail."
|
||||
+}
|
||||
+
|
||||
+if [get_compiler_info ${binfile}] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Start the program running and then wait for a bit, to be sure
|
||||
+# that it can be attached to.
|
||||
+
|
||||
+set testpid [eval exec $binfile &]
|
||||
+
|
||||
+# Avoid some race:
|
||||
+sleep 2
|
||||
+
|
||||
+# Start with clean gdb
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+# Never call: gdb_load ${binfile}
|
||||
+# as the former problem would not reproduce otherwise.
|
||||
+
|
||||
+set test "attach"
|
||||
+gdb_test_multiple "attach $testpid" "$test" {
|
||||
+ -re "Attaching to process $testpid\r?\n.*$gdb_prompt $" {
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_test "bt" "#0 *0x\[0-9a-f\]* in \[^?\].*" "backtrace decodes VDSO"
|
||||
+
|
||||
+# Exit and detach the process.
|
||||
+
|
||||
+gdb_exit
|
||||
+
|
||||
+# Make sure we don't leave a process around to confuse
|
||||
+# the next test run (and prevent the compile by keeping
|
||||
+# the text file busy), in case the "set should_exit" didn't
|
||||
+# work.
|
||||
+
|
||||
+remote_exec build "kill -9 ${testpid}"
|
@ -16,7 +16,7 @@ Subject: gdb-6.3-gstack-20050411.patch
|
||||
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
--- a/gdb/Makefile.in
|
||||
+++ b/gdb/Makefile.in
|
||||
@@ -2035,7 +2035,7 @@ info install-info clean-info dvi pdf install-pdf html install-html: force
|
||||
@@ -2071,7 +2071,7 @@ info install-info clean-info dvi install-dvi pdf install-pdf html install-html:
|
||||
install: all
|
||||
@$(MAKE) $(FLAGS_TO_PASS) install-only
|
||||
|
||||
@ -25,7 +25,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e "$$t"` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -2085,7 +2085,25 @@ install-guile:
|
||||
@@ -2121,7 +2121,25 @@ install-guile:
|
||||
install-python:
|
||||
$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR)/python/gdb
|
||||
|
||||
@ -52,7 +52,7 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
transformed_name=`t='$(program_transform_name)'; \
|
||||
echo gdb | sed -e $$t` ; \
|
||||
if test "x$$transformed_name" = x; then \
|
||||
@@ -2116,6 +2134,18 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
@@ -2152,6 +2170,28 @@ uninstall: force $(CONFIG_UNINSTALL)
|
||||
rm -f $(DESTDIR)$(bindir)/$$transformed_name
|
||||
@$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
|
||||
|
||||
@ -68,9 +68,19 @@ diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
||||
+ rm -f $(DESTDIR)$(bindir)/$$transformed_name$(EXEEXT) \
|
||||
+ $(DESTDIR)$(man1dir)/$$transformed_name.1
|
||||
+
|
||||
# The C++ name parser can be built standalone for testing.
|
||||
test-cp-name-parser.o: cp-name-parser.c
|
||||
$(COMPILE) -DTEST_CPNAMES cp-name-parser.c
|
||||
+# The C++ name parser can be built standalone for testing.
|
||||
+test-cp-name-parser.o: cp-name-parser.c
|
||||
+ $(COMPILE) -DTEST_CPNAMES cp-name-parser.c
|
||||
+ $(POSTCOMPILE)
|
||||
+
|
||||
+test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
|
||||
+ $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) \
|
||||
+ -o test-cp-name-parser$(EXEEXT) test-cp-name-parser.o \
|
||||
+ $(LIBIBERTY)
|
||||
+
|
||||
# We do this by grepping through sources. If that turns out to be too slow,
|
||||
# maybe we could just require every .o file to have an initialization routine
|
||||
# of a given name (top.o -> _initialize_top, etc.).
|
||||
diff --git a/gdb/gstack.sh b/gdb/gstack.sh
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
@ -226,7 +236,7 @@ new file mode 100644
|
||||
+# exiting the function. Still we could retry the gstack command if we fail.
|
||||
+
|
||||
+set test "spawn gstack"
|
||||
+set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $BUILD_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
|
||||
+set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $GDB_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
|
||||
+set res [remote_spawn host $command];
|
||||
+if { $res < 0 || $res == "" } {
|
||||
+ perror "Spawning $command failed."
|
||||
|
@ -1,265 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-bz185337-resolve-tls-without-debuginfo-v2.patch
|
||||
|
||||
;; Support TLS symbols (+`errno' suggestion if no pthread is found) (BZ 185337).
|
||||
;;=push+jan: It should be replaced by Infinity project.
|
||||
|
||||
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=185337
|
||||
|
||||
2008-02-24 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Port to GDB-6.8pre.
|
||||
|
||||
currently for trivial nonthreaded helloworld with no debug info up to -ggdb2 you
|
||||
will get:
|
||||
(gdb) p errno
|
||||
[some error]
|
||||
|
||||
* with -ggdb2 and less "errno" in fact does not exist anywhere as it was
|
||||
compiled to "(*__errno_location ())" and the macro definition is not present.
|
||||
Unfortunately gdb will find the TLS symbol and it will try to access it but
|
||||
as the program has been compiled without -lpthread the TLS base register
|
||||
(%gs on i386) is not setup and it will result in:
|
||||
Cannot access memory at address 0x8
|
||||
|
||||
Attached suggestion patch how to deal with the most common "errno" symbol
|
||||
for the most common under-ggdb3 compiled programs.
|
||||
|
||||
Original patch hooked into target_translate_tls_address. But its inferior
|
||||
call invalidates `struct frame *' in the callers - RH BZ 690908.
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1166549
|
||||
|
||||
2007-11-03 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* ./gdb/dwarf2read.c (read_partial_die, dwarf2_linkage_name): Prefer
|
||||
DW_AT_MIPS_linkage_name over DW_AT_name now only for non-C.
|
||||
|
||||
glibc-debuginfo-2.7-2.x86_64: /usr/lib/debug/lib64/libc.so.6.debug:
|
||||
<81a2> DW_AT_name : (indirect string, offset: 0x280e): __errno_location
|
||||
<81a8> DW_AT_MIPS_linkage_name: (indirect string, offset: 0x2808): *__GI___errno_location
|
||||
|
||||
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
|
||||
--- a/gdb/printcmd.c
|
||||
+++ b/gdb/printcmd.c
|
||||
@@ -1308,6 +1308,11 @@ process_print_command_args (const char *args, value_print_options *print_opts,
|
||||
|
||||
if (exp != nullptr && *exp)
|
||||
{
|
||||
+ /* '*((int *(*) (void)) __errno_location) ()' is incompatible with
|
||||
+ function descriptors. */
|
||||
+ if (target_has_execution () && strcmp (exp, "errno") == 0)
|
||||
+ exp = "*(*(int *(*)(void)) __errno_location) ()";
|
||||
+
|
||||
/* This setting allows large arrays to be printed by limiting the
|
||||
number of elements that are loaded into GDB's memory; we only
|
||||
need to load as many array elements as we plan to print. */
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno.c b/gdb/testsuite/gdb.dwarf2/dw2-errno.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2005, 2007 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ errno = 42;
|
||||
+
|
||||
+ return 0; /* breakpoint */
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno.exp b/gdb/testsuite/gdb.dwarf2/dw2-errno.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno.exp
|
||||
@@ -0,0 +1,60 @@
|
||||
+# Copyright 2007 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+set testfile dw2-errno
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+proc prep {} {
|
||||
+ global srcdir subdir binfile
|
||||
+ gdb_exit
|
||||
+ gdb_start
|
||||
+ gdb_reinitialize_dir $srcdir/$subdir
|
||||
+ gdb_load ${binfile}
|
||||
+
|
||||
+ runto_main
|
||||
+
|
||||
+ gdb_breakpoint [gdb_get_line_number "breakpoint"]
|
||||
+ gdb_continue_to_breakpoint "breakpoint"
|
||||
+}
|
||||
+
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=N threads=N"
|
||||
+
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=Y threads=N"
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=N threads=Y"
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep
|
||||
+gdb_test "print errno" ".* = 42" "errno with macros=Y threads=Y"
|
||||
+
|
||||
+# TODO: Test the error on resolving ERRNO with only libc loaded.
|
||||
+# Just how to find the current libc filename?
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno2.c b/gdb/testsuite/gdb.dwarf2/dw2-errno2.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno2.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2005, 2007 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+
|
||||
+int main()
|
||||
+{
|
||||
+ errno = 42;
|
||||
+
|
||||
+ return 0; /* breakpoint */
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-errno2.exp b/gdb/testsuite/gdb.dwarf2/dw2-errno2.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-errno2.exp
|
||||
@@ -0,0 +1,71 @@
|
||||
+# Copyright 2007 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+set testfile dw2-errno2
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+proc prep { message {do_xfail 0} } { with_test_prefix $message {
|
||||
+ global srcdir subdir binfile variant
|
||||
+ gdb_exit
|
||||
+ gdb_start
|
||||
+ gdb_reinitialize_dir $srcdir/$subdir
|
||||
+ gdb_load ${binfile}${variant}
|
||||
+
|
||||
+ runto_main
|
||||
+
|
||||
+ gdb_breakpoint [gdb_get_line_number "breakpoint"]
|
||||
+ gdb_continue_to_breakpoint "breakpoint"
|
||||
+
|
||||
+ gdb_test "gcore ${binfile}${variant}.core" "\r\nSaved corefile .*" "gcore $variant"
|
||||
+
|
||||
+ gdb_test "print errno" ".* = 42"
|
||||
+
|
||||
+ gdb_test "kill" ".*" "kill" {Kill the program being debugged\? \(y or n\) } "y"
|
||||
+ gdb_test "core-file ${binfile}${variant}.core" "\r\nCore was generated by .*" "core-file"
|
||||
+ if $do_xfail {
|
||||
+ setup_xfail "*-*-*"
|
||||
+ }
|
||||
+ gdb_test "print (int) errno" ".* = 42" "print errno for core"
|
||||
+}}
|
||||
+
|
||||
+set variant g2thrN
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g2"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=N threads=N" 1
|
||||
+
|
||||
+set variant g3thrN
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g3"] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=Y threads=N" 1
|
||||
+
|
||||
+set variant g2thrY
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g2"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=N threads=Y"
|
||||
+
|
||||
+set variant g3thrY
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}${variant}" executable "additional_flags=-g3"] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+prep "macros=Y threads=Y" 1
|
||||
+
|
||||
+# TODO: Test the error on resolving ERRNO with only libc loaded.
|
||||
+# Just how to find the current libc filename?
|
@ -1,89 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-bz243845-stale-testing-zombie-test.patch
|
||||
|
||||
;; Test leftover zombie process (BZ 243845).
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/tracefork-zombie.exp b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/tracefork-zombie.exp
|
||||
@@ -0,0 +1,76 @@
|
||||
+# Copyright 2007 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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. */
|
||||
+
|
||||
+# are we on a target board
|
||||
+if {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Start the program running and then wait for a bit, to be sure
|
||||
+# that it can be attached to.
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_load sleep
|
||||
+
|
||||
+set gdb_pid [exp_pid -i [board_info host fileid]]
|
||||
+set test "identified the child GDB"
|
||||
+if {$gdb_pid != "" && $gdb_pid > 0} {
|
||||
+ pass $test
|
||||
+ verbose -log "Child GDB PID $gdb_pid"
|
||||
+} else {
|
||||
+ fail $test
|
||||
+}
|
||||
+
|
||||
+set testpid [eval exec sleep 10 &]
|
||||
+exec sleep 2
|
||||
+
|
||||
+set test "attach"
|
||||
+gdb_test_multiple "attach $testpid" "$test" {
|
||||
+ -re "Attaching to program.*`?.*'?, process $testpid..*$gdb_prompt $" {
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+ -re "Attaching to program.*`?.*\.exe'?, process $testpid.*\[Switching to thread $testpid\..*\].*$gdb_prompt $" {
|
||||
+ # Response expected on Cygwin
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Some time to let GDB spawn its testing child.
|
||||
+exec sleep 2
|
||||
+
|
||||
+set found none
|
||||
+foreach procpid [glob -directory /proc -type d {[0-9]*}] {
|
||||
+ if {[catch {open $procpid/status} statusfi]} {
|
||||
+ continue
|
||||
+ }
|
||||
+ set status [read $statusfi]
|
||||
+ close $statusfi
|
||||
+ if {1
|
||||
+ && [regexp -line {^Name:\tgdb$} $status]
|
||||
+ && [regexp -line {^PPid:\t1$} $status]
|
||||
+ && [regexp -line "^TracerPid:\t$gdb_pid$" $status]} {
|
||||
+ set found $procpid
|
||||
+ verbose -log "Found linux_test_for_tracefork zombie PID $procpid"
|
||||
+ }
|
||||
+}
|
||||
+set test "linux_test_for_tracefork leaves no zombie"
|
||||
+if {$found eq {none}} {
|
||||
+ pass $test
|
||||
+} else {
|
||||
+ fail $test
|
||||
+}
|
@ -1,127 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.5-section-num-fixup-test.patch
|
||||
|
||||
;; Test a crash on libraries missing the .text section.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/datalib-lib.c b/gdb/testsuite/gdb.base/datalib-lib.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/datalib-lib.c
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2008 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+int var;
|
||||
diff --git a/gdb/testsuite/gdb.base/datalib-main.c b/gdb/testsuite/gdb.base/datalib-main.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/datalib-main.c
|
||||
@@ -0,0 +1,26 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2008 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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.
|
||||
+
|
||||
+ Please email any bugs, comments, and/or additions to this file to:
|
||||
+ bug-gdb@prep.ai.mit.edu */
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/datalib.exp b/gdb/testsuite/gdb.base/datalib.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/datalib.exp
|
||||
@@ -0,0 +1,56 @@
|
||||
+# Copyright 2008 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 {[use_gdb_stub]} {
|
||||
+ untested "skipping test because of use_gdb_stub"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set testfile datalib
|
||||
+set srcfilemain ${testfile}-main.c
|
||||
+set srcfilelib ${testfile}-lib.c
|
||||
+set libfile [standard_output_file ${testfile}-lib.so]
|
||||
+set binfile [standard_output_file ${testfile}-main]
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfilelib}" "${libfile}" executable [list debug {additional_flags=-shared -nostdlib}]] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfilemain}" "${binfile} ${libfile}" executable {debug}] != "" } {
|
||||
+ untested "Couldn't compile test program"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Get things started.
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+gdb_load ${binfile}
|
||||
+
|
||||
+# We must use a separate library as the main executable is compiled to the
|
||||
+# address 0 by default and it would get fixed up already at the end of
|
||||
+# INIT_OBJFILE_SECT_INDICES. We also cannot PRELINK it as PRELINK is missing
|
||||
+# on ia64. The library must be NOSTDLIB as otherwise some stub code would
|
||||
+# create the `.text' section there. Also DEBUG option is useful as some of
|
||||
+# the crashes occur in dwarf2read.c.
|
||||
+
|
||||
+# FAIL case:
|
||||
+# ../../gdb/ia64-tdep.c:2838: internal-error: sect_index_text not initialized
|
||||
+# A problem internal to GDB has been detected,
|
||||
+
|
||||
+gdb_test "start" \
|
||||
+ "main \\(\\) at .*${srcfilemain}.*" \
|
||||
+ "start"
|
@ -1,19 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-buildid-locate-rpm-librpm-workaround.patch
|
||||
|
||||
;; Workaround librpm BZ 643031 due to its unexpected exit() calls (BZ 642879).
|
||||
;;=push+jan
|
||||
|
||||
diff --git a/gdb/proc-service.list b/gdb/proc-service.list
|
||||
--- a/gdb/proc-service.list
|
||||
+++ b/gdb/proc-service.list
|
||||
@@ -37,4 +37,7 @@
|
||||
ps_pstop;
|
||||
ps_ptread;
|
||||
ps_ptwrite;
|
||||
+
|
||||
+ /* gdb-6.6-buildid-locate-rpm.patch */
|
||||
+ rpmsqEnable;
|
||||
};
|
@ -1,123 +1,43 @@
|
||||
diff --git a/gdb/build-id.c b/gdb/build-id.c
|
||||
index 059a72fc050..58d73e70bad 100644
|
||||
--- a/gdb/build-id.c
|
||||
+++ b/gdb/build-id.c
|
||||
@@ -863,10 +863,8 @@ missing_rpm_enlist_1 (const char *filename, int verify_vendor)
|
||||
#endif
|
||||
{
|
||||
Header h;
|
||||
- char *debuginfo, **slot, *s, *s2;
|
||||
+ char *debuginfo, **slot;
|
||||
errmsg_t err;
|
||||
- size_t srcrpmlen = sizeof (".src.rpm") - 1;
|
||||
- size_t debuginfolen = sizeof ("-debuginfo") - 1;
|
||||
rpmdbMatchIterator mi_debuginfo;
|
||||
diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
index f52b822c111..da80363ebd2 100644
|
||||
--- a/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
+++ b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
@@ -33,6 +33,8 @@ else:
|
||||
# the prompt is shown.
|
||||
__suggest_rpms = {}
|
||||
|
||||
h = rpmdbNextIterator_p (mi);
|
||||
@@ -875,7 +873,9 @@ missing_rpm_enlist_1 (const char *filename, int verify_vendor)
|
||||
+ __package_to_debug_package = {}
|
||||
+
|
||||
|
||||
/* Verify the debuginfo file is not already installed. */
|
||||
# Lookup RPMs that might provide the debug information for FILENAME,
|
||||
# which is a string containing the path to an object file GDB could
|
||||
@@ -48,6 +50,7 @@ else:
|
||||
for h in mi:
|
||||
# Build the debuginfo package name.
|
||||
obj = h.format("%{name}-debuginfo-%{version}-%{release}.%{arch}")
|
||||
+ debug_rpm_name = str(obj)
|
||||
|
||||
- debuginfo = headerFormat_p (h, "%{sourcerpm}-debuginfo.%{arch}",
|
||||
+ /* The allocated memory gets utilized below for MISSING_RPM_HASH. */
|
||||
+ debuginfo = headerFormat_p (h,
|
||||
+ "%{name}-debuginfo-%{version}-%{release}.%{arch}",
|
||||
&err);
|
||||
if (!debuginfo)
|
||||
{
|
||||
@@ -883,60 +883,19 @@ missing_rpm_enlist_1 (const char *filename, int verify_vendor)
|
||||
err);
|
||||
continue;
|
||||
}
|
||||
- /* s = `.src.rpm-debuginfo.%{arch}' */
|
||||
- s = strrchr (debuginfo, '-') - srcrpmlen;
|
||||
- s2 = NULL;
|
||||
- if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0)
|
||||
- {
|
||||
- /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */
|
||||
- s2 = (char *) memrchr (debuginfo, '-', s - debuginfo);
|
||||
- }
|
||||
- if (s2)
|
||||
- {
|
||||
- /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
|
||||
- s2 = (char *) memrchr (debuginfo, '-', s2 - debuginfo);
|
||||
- }
|
||||
- if (!s2)
|
||||
- {
|
||||
- warning (_("Error querying the rpm file `%s': %s"), filename,
|
||||
- debuginfo);
|
||||
- xfree (debuginfo);
|
||||
- continue;
|
||||
- }
|
||||
- /* s = `.src.rpm-debuginfo.%{arch}' */
|
||||
- /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
|
||||
- memmove (s2 + debuginfolen, s2, s - s2);
|
||||
- memcpy (s2, "-debuginfo", debuginfolen);
|
||||
- /* s = `XXXX.%{arch}' */
|
||||
- /* strlen ("XXXX") == srcrpmlen + debuginfolen */
|
||||
- /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */
|
||||
- /* strlen ("XX") == srcrpmlen */
|
||||
- memmove (s + debuginfolen, s + srcrpmlen + debuginfolen,
|
||||
- strlen (s + srcrpmlen + debuginfolen) + 1);
|
||||
- /* s = `-debuginfo-%{version}-%{release}.%{arch}' */
|
||||
# Check to see if the package is installed.
|
||||
mi2 = ts.dbMatch(rpm.RPMDBI_LABEL, str(obj))
|
||||
@@ -57,6 +60,7 @@ else:
|
||||
# Now build the name of the package FILENAME came from.
|
||||
obj = h.format("%{name}-%{version}-%{release}.%{arch}")
|
||||
rpm_name = str(obj)
|
||||
+ __package_to_debug_package[rpm_name] = debug_rpm_name
|
||||
if not rpm_name in __missing_rpms:
|
||||
__suggest_rpms[rpm_name] = True
|
||||
__missing_rpms[rpm_name] = True
|
||||
@@ -88,10 +92,12 @@ else:
|
||||
# suggests this to the user.
|
||||
def before_prompt():
|
||||
global __suggest_rpms
|
||||
+ global __package_to_debug_package
|
||||
|
||||
+ /* Verify the debuginfo file is not already installed. */
|
||||
/* RPMDBI_PACKAGES requires keylen == sizeof (int). */
|
||||
/* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */
|
||||
mi_debuginfo = rpmtsInitIterator_p (ts, (rpmDbiTagVal) RPMDBI_LABEL, debuginfo, 0);
|
||||
- xfree (debuginfo);
|
||||
if (mi_debuginfo)
|
||||
{
|
||||
+ xfree (debuginfo);
|
||||
rpmdbFreeIterator_p (mi_debuginfo);
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
if len(__suggest_rpms) > 0:
|
||||
for p in __suggest_rpms.keys():
|
||||
- print("Missing debuginfo, try: dnf debuginfo-install " + p)
|
||||
+ dp = __package_to_debug_package[p]
|
||||
+ print("Missing separate debuginfos, use: zypper install " + dp)
|
||||
__suggest_rpms = {}
|
||||
|
||||
- /* The allocated memory gets utilized below for MISSING_RPM_HASH. */
|
||||
- debuginfo = headerFormat_p (h,
|
||||
- "%{name}-%{version}-%{release}.%{arch}",
|
||||
- &err);
|
||||
- if (!debuginfo)
|
||||
- {
|
||||
- warning (_("Error querying the rpm file `%s': %s"), filename,
|
||||
- err);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
/* Base package name for `debuginfo-install'. We do not use the
|
||||
`yum' command directly as the line
|
||||
yum --enablerepo='*debug*' install NAME-debuginfo.ARCH
|
||||
@@ -1085,10 +1044,7 @@ missing_rpm_list_print (void)
|
||||
missing_rpm_list_entries = 0;
|
||||
|
||||
gdb_printf (_("Missing separate debuginfos, use: %s"),
|
||||
-#ifdef DNF_DEBUGINFO_INSTALL
|
||||
- "dnf "
|
||||
-#endif
|
||||
- "debuginfo-install");
|
||||
+ "zypper install");
|
||||
for (const char *el : array)
|
||||
{
|
||||
gdb_printf (" %s", el);
|
||||
@@ -1296,14 +1252,15 @@ debug_print_missing (const char *binary, const char *debug)
|
||||
_("Missing separate debuginfo for %s.\n"), binary);
|
||||
if (debug != NULL)
|
||||
{
|
||||
+#ifdef HAVE_LIBRPM
|
||||
if (access (debug, F_OK) == 0) {
|
||||
- gdb_printf (gdb_stdlog, _("Try: %s %s\n"),
|
||||
-#ifdef DNF_DEBUGINFO_INSTALL
|
||||
- "dnf"
|
||||
#else
|
||||
- "yum"
|
||||
+ if (1) {
|
||||
#endif
|
||||
- " --enablerepo='*debug*' install", debug);
|
||||
+ const char *p = strrchr (debug, '/');
|
||||
+ gdb_printf (gdb_stdlog, _("Try: %s%.2s%.38s\"\n"),
|
||||
+ "zypper install -C \"debuginfo(build-id)=",
|
||||
+ p - 2, p + 1);
|
||||
} else
|
||||
gdb_printf (gdb_stdlog, _("The debuginfo package for this file is probably broken.\n"));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,26 +14,48 @@ https://bugzilla.redhat.com/show_bug.cgi?id=1339862
|
||||
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
--- a/gdb/solib-svr4.c
|
||||
+++ b/gdb/solib-svr4.c
|
||||
@@ -1320,14 +1320,28 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
@@ -347,11 +347,13 @@ lm_addr_check (const solib &so, bfd *abfd)
|
||||
|
||||
struct svr4_so
|
||||
{
|
||||
- svr4_so (const char *name, lm_info_svr4_up lm_info)
|
||||
- : name (name), lm_info (std::move (lm_info))
|
||||
+ svr4_so (const char *name, lm_info_svr4_up lm_info, const char *orig_name = nullptr)
|
||||
+ : name (name), original_name (orig_name == nullptr ? name : orig_name),
|
||||
+ lm_info (std::move (lm_info))
|
||||
{}
|
||||
|
||||
std::string name;
|
||||
+ std::string original_name;
|
||||
lm_info_svr4_up lm_info;
|
||||
};
|
||||
|
||||
@@ -1002,6 +1004,7 @@ so_list_from_svr4_sos (const std::vector<svr4_so> &sos)
|
||||
|
||||
newobj->so_name = so.name;
|
||||
newobj->so_original_name = so.name;
|
||||
+ newobj->so_original_name = so.original_name;
|
||||
newobj->lm_info = std::make_unique<lm_info_svr4> (*so.lm_info);
|
||||
|
||||
dst.push_back (*newobj);
|
||||
@@ -1263,11 +1266,28 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
continue;
|
||||
}
|
||||
|
||||
+ /* Preserve original name since name may be changed below. */
|
||||
+ gdb::unique_xmalloc_ptr<char> original_name = make_unique_xstrdup (name.get ());
|
||||
{
|
||||
- struct bfd_build_id *build_id;
|
||||
+ struct bfd_build_id *build_id = NULL;
|
||||
+ struct bfd_build_id *build_id = nullptr;
|
||||
|
||||
strncpy (newobj->so_original_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
|
||||
newobj->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
|
||||
/* May get overwritten below. */
|
||||
strcpy (newobj->so_name, newobj->so_original_name);
|
||||
|
||||
- build_id = build_id_addr_get (((lm_info_svr4 *) newobj->lm_info)->l_ld);
|
||||
- build_id = build_id_addr_get (li->l_ld);
|
||||
- if (build_id != NULL)
|
||||
+ /* In the case the main executable was found according to its build-id
|
||||
+ (from a core file) prevent loading a different build of a library
|
||||
+ with accidentally the same SO_NAME.
|
||||
+
|
||||
+ It suppresses bogus backtraces (and prints "??" there instead) if
|
||||
+ the on-disk files no longer match the running program version.
|
||||
+
|
||||
+ If the main executable was not loaded according to its build-id do
|
||||
+ not do any build-id checking of the libraries. There may be missing
|
||||
+ build-ids dumped in the core file and we would map all the libraries
|
||||
@ -42,15 +64,18 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
+ && (current_program_space->symfile_object_file->flags
|
||||
+ & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
+ build_id = build_id_addr_get (li->l_ld);
|
||||
if (build_id != NULL)
|
||||
+
|
||||
+
|
||||
+ if (build_id != nullptr)
|
||||
{
|
||||
char *name, *build_id_filename;
|
||||
@@ -1342,23 +1356,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
xfree (name);
|
||||
char *bid_name, *build_id_filename;
|
||||
|
||||
@@ -1280,23 +1300,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
|
||||
xfree (bid_name);
|
||||
}
|
||||
else
|
||||
- {
|
||||
- debug_print_missing (newobj->so_name, build_id_filename);
|
||||
- debug_print_missing (name.get (), build_id_filename);
|
||||
-
|
||||
- /* In the case the main executable was found according to
|
||||
- its build-id (from a core file) prevent loading
|
||||
@ -64,9 +89,9 @@ diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
|
||||
- if (current_program_space->symfile_object_file != NULL
|
||||
- && (current_program_space->symfile_object_file->flags
|
||||
- & OBJF_BUILD_ID_CORE_LOADED) != 0)
|
||||
- newobj->so_name[0] = 0;
|
||||
- name = make_unique_xstrdup ("");
|
||||
- }
|
||||
+ debug_print_missing (newobj->so_name, build_id_filename);
|
||||
+ debug_print_missing (name.get (), build_id_filename);
|
||||
|
||||
xfree (build_id_filename);
|
||||
xfree (build_id);
|
||||
@ -130,7 +155,7 @@ diff --git a/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp b/gdb/t
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcore-buildid-exec-but-not-solib.exp
|
||||
@@ -0,0 +1,105 @@
|
||||
@@ -0,0 +1,104 @@
|
||||
+# Copyright 2016 Free Software Foundation, Inc.
|
||||
+
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
@ -146,9 +171,7 @@ new file mode 100644
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+if {[skip_shlib_tests]} {
|
||||
+ return 0
|
||||
+}
|
||||
+require allow_shlib_tests
|
||||
+
|
||||
+set testfile "gcore-buildid-exec-but-not-solib"
|
||||
+set srcmainfile ${testfile}-main.c
|
||||
@ -226,7 +249,8 @@ new file mode 100644
|
||||
+remote_exec build "ln -s /lib64 ${debugdir}/"
|
||||
+# /usr is not needed, all the libs are in /lib64: libm.so.6 libc.so.6 ld-linux-x86-64.so.2
|
||||
+
|
||||
+gdb_test "set solib-absolute-prefix $debugdir"
|
||||
+gdb_test_no_output "set solib-absolute-prefix $debugdir" \
|
||||
+ "set solib-absolute-prefix"
|
||||
+
|
||||
+gdb_test_no_output "set debug-file-directory $debugdir" "set debug-file-directory"
|
||||
+
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,188 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-bz229517-gcore-without-terminal.patch
|
||||
|
||||
;; Allow running `/usr/bin/gcore' with provided but inaccessible tty (BZ 229517).
|
||||
;;=fedoratest
|
||||
|
||||
2007-04-22 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb_gcore.sh: Redirect GDB from `</dev/null'.
|
||||
|
||||
2007-04-22 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.base/gcorebg.exp, gdb.base/gcorebg.c: New files.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gcorebg.c b/gdb/testsuite/gdb.base/gcorebg.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcorebg.c
|
||||
@@ -0,0 +1,49 @@
|
||||
+#include <stdio.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <unistd.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <signal.h>
|
||||
+#include <string.h>
|
||||
+#include <assert.h>
|
||||
+
|
||||
+int main (int argc, char **argv)
|
||||
+{
|
||||
+ pid_t pid = 0;
|
||||
+ pid_t ppid;
|
||||
+ char buf[1024*2 + 500];
|
||||
+ int gotint;
|
||||
+
|
||||
+ if (argc != 4)
|
||||
+ {
|
||||
+ fprintf (stderr, "Syntax: %s {standard|detached} <gcore command> <core output file>\n",
|
||||
+ argv[0]);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ pid = fork ();
|
||||
+
|
||||
+ switch (pid)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ if (strcmp (argv[1], "detached") == 0)
|
||||
+ setpgrp ();
|
||||
+ ppid = getppid ();
|
||||
+ gotint = snprintf (buf, sizeof (buf), "sh %s -o %s %d", argv[2], argv[3], (int) ppid);
|
||||
+ assert (gotint < sizeof (buf));
|
||||
+ system (buf);
|
||||
+ fprintf (stderr, "Killing parent PID %d\n", ppid);
|
||||
+ kill (ppid, SIGTERM);
|
||||
+ break;
|
||||
+
|
||||
+ case -1:
|
||||
+ perror ("fork err\n");
|
||||
+ exit (1);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ fprintf (stderr,"Sleeping as PID %d\n", getpid ());
|
||||
+ sleep (60);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/gcorebg.exp b/gdb/testsuite/gdb.base/gcorebg.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gcorebg.exp
|
||||
@@ -0,0 +1,113 @@
|
||||
+# Copyright 2007 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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.
|
||||
+
|
||||
+# Please email any bugs, comments, and/or additions to this file to:
|
||||
+# bug-gdb@prep.ai.mit.edu
|
||||
+
|
||||
+# This file was written by Jan Kratochvil <jan.kratochvil@redhat.com>.
|
||||
+# This is a test for `gdb_gcore.sh' functionality.
|
||||
+# It also tests a regression with `gdb_gcore.sh' being run without its
|
||||
+# accessible terminal.
|
||||
+
|
||||
+if ![info exists GCORE] {
|
||||
+ set GCORE "[standard_output_file ../../../../gcore]"
|
||||
+}
|
||||
+verbose "using GCORE = $GCORE" 2
|
||||
+
|
||||
+set testfile "gcorebg"
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+set corefile [standard_output_file ${testfile}.test]
|
||||
+
|
||||
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ untested gcorebg.exp
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Cleanup.
|
||||
+
|
||||
+proc core_clean {} {
|
||||
+ global corefile
|
||||
+
|
||||
+ foreach file [glob -nocomplain [join [list $corefile *] ""]] {
|
||||
+ verbose "Delete file $file" 1
|
||||
+ remote_file target delete $file
|
||||
+ }
|
||||
+}
|
||||
+core_clean
|
||||
+remote_file target delete "./gdb"
|
||||
+
|
||||
+# Generate the core file.
|
||||
+
|
||||
+# Provide `./gdb' for `gdb_gcore.sh' running it as a bare `gdb' command.
|
||||
+# Setup also `$PATH' appropriately.
|
||||
+# If GDB was not found let `gdb_gcore.sh' to find the system GDB by `$PATH'.
|
||||
+if {$GDB != "gdb"} {
|
||||
+ file link ./gdb $GDB
|
||||
+}
|
||||
+global env
|
||||
+set oldpath $env(PATH)
|
||||
+set env(PATH) [join [list . $env(PATH)] ":"]
|
||||
+verbose "PATH = $env(PATH)" 2
|
||||
+
|
||||
+# Test file body.
|
||||
+# $detached == "standard" || $detached == "detached"
|
||||
+
|
||||
+proc test_body { detached } {
|
||||
+ global binfile
|
||||
+ global GCORE
|
||||
+ global corefile
|
||||
+
|
||||
+ set res [remote_spawn target "$binfile $detached $GCORE $corefile"]
|
||||
+ if { $res < 0 || $res == "" } {
|
||||
+ fail "Spawning $detached gcore"
|
||||
+ return 1
|
||||
+ }
|
||||
+ pass "Spawning $detached gcore"
|
||||
+ remote_expect target 20 {
|
||||
+ timeout {
|
||||
+ fail "Spawned $detached gcore finished (timeout)"
|
||||
+ remote_exec target "kill -9 -[exp_pid -i $res]"
|
||||
+ return 1
|
||||
+ }
|
||||
+ "Saved corefile .*\r\nKilling parent PID " {
|
||||
+ pass "Spawned $detached gcore finished"
|
||||
+ remote_wait target 20
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if {1 == [llength [glob -nocomplain [join [list $corefile *] ""]]]} {
|
||||
+ pass "Core file generated by $detached gcore"
|
||||
+ } else {
|
||||
+ fail "Core file generated by $detached gcore"
|
||||
+ }
|
||||
+ core_clean
|
||||
+}
|
||||
+
|
||||
+# First a general `gdb_gcore.sh' spawn with its controlling terminal available.
|
||||
+
|
||||
+test_body standard
|
||||
+
|
||||
+# And now `gdb_gcore.sh' spawn without its controlling terminal available.
|
||||
+# It is spawned through `gcorebg.c' using setpgrp ().
|
||||
+
|
||||
+test_body detached
|
||||
+
|
||||
+
|
||||
+# Cleanup.
|
||||
+
|
||||
+set env(PATH) $oldpath
|
||||
+remote_file target delete "./gdb"
|
@ -1,32 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-6.6-testsuite-timeouts.patch
|
||||
|
||||
;; Avoid too long timeouts on failing cases of "annota1.exp annota3.exp".
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/annota1.exp b/gdb/testsuite/gdb.base/annota1.exp
|
||||
--- a/gdb/testsuite/gdb.base/annota1.exp
|
||||
+++ b/gdb/testsuite/gdb.base/annota1.exp
|
||||
@@ -37,6 +37,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
+gdb_test "set breakpoint pending off" "" "Avoid lockup on nonexisting functions"
|
||||
+
|
||||
# The commands we test here produce many lines of output; disable "press
|
||||
# <return> to continue" prompts.
|
||||
gdb_test_no_output "set height 0"
|
||||
diff --git a/gdb/testsuite/gdb.base/annota3.exp b/gdb/testsuite/gdb.base/annota3.exp
|
||||
--- a/gdb/testsuite/gdb.base/annota3.exp
|
||||
+++ b/gdb/testsuite/gdb.base/annota3.exp
|
||||
@@ -36,6 +36,8 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
+gdb_test "set breakpoint pending off" "" "Avoid lockup on nonexisting functions"
|
||||
+
|
||||
# The commands we test here produce many lines of output; disable "press
|
||||
# <return> to continue" prompts.
|
||||
gdb_test_no_output "set height 0"
|
180
gdb-add-rpm-suggestion-script.patch
Normal file
180
gdb-add-rpm-suggestion-script.patch
Normal file
@ -0,0 +1,180 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Thu, 7 Mar 2024 15:14:23 +0000
|
||||
Subject: gdb-add-rpm-suggestion-script.patch
|
||||
|
||||
;; Not a backport. Add a new script which hooks into GDB and suggests
|
||||
;; RPMs to install when GDB finds an objfile with no debug info.
|
||||
|
||||
gdb: add script which will suggest debuginfo RPMs to install
|
||||
|
||||
This script hooks into GDB's missing debug info Python API and
|
||||
suggests debuginfo RPMs to install.
|
||||
|
||||
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
|
||||
--- a/gdb/data-directory/Makefile.in
|
||||
+++ b/gdb/data-directory/Makefile.in
|
||||
@@ -89,6 +89,7 @@ PYTHON_FILE_LIST = \
|
||||
gdb/command/missing_debug.py \
|
||||
gdb/command/pretty_printers.py \
|
||||
gdb/command/prompt.py \
|
||||
+ gdb/command/rpm-suggestions.py \
|
||||
gdb/command/type_printers.py \
|
||||
gdb/command/unwinders.py \
|
||||
gdb/command/xmethods.py \
|
||||
diff --git a/gdb/python/lib/gdb/command/rpm-suggestions.py b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/python/lib/gdb/command/rpm-suggestions.py
|
||||
@@ -0,0 +1,134 @@
|
||||
+# Copyright 2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+import sys
|
||||
+import gdb
|
||||
+import gdb.missing_debug
|
||||
+try:
|
||||
+ import rpm
|
||||
+except ModuleNotFoundError:
|
||||
+ # The "RPM suggestions" mechanism will not work without the (python)
|
||||
+ # rpm module. Inform the user of this, but wait to do so until
|
||||
+ # just prior to printing the GDB prompt. If we do it right away,
|
||||
+ # the message typically appears before the version and copyright
|
||||
+ # info, which is easily missed by many users. Additionally, it
|
||||
+ # seems that several other packages which parse GDB version info
|
||||
+ # are confused by an early error message regarding a missing
|
||||
+ # python3-rpm package, so waiting to print the error allows those
|
||||
+ # applications to work as they used to.
|
||||
+ def before_prompt():
|
||||
+ print(
|
||||
+ ("\nUnable to load the Python 'rpm' module. Lack of this module disables\n"
|
||||
+ "the RPM suggestions mechanism which recommends shell commands for\n"
|
||||
+ "installing missing debuginfo packages. To enable this functionality,\n"
|
||||
+ "please install the python3-rpm package."),
|
||||
+ file=sys.stderr
|
||||
+ )
|
||||
+ gdb.events.before_prompt.disconnect(before_prompt)
|
||||
+
|
||||
+ gdb.events.before_prompt.connect(before_prompt)
|
||||
+else:
|
||||
+ # Track all the RPMs suggested during a single debug session so we
|
||||
+ # don't suggest the same RPM twice. This is only cleared when the
|
||||
+ # main executable is changed.
|
||||
+ __missing_rpms = {}
|
||||
+
|
||||
+ # Track any missing RPMs that have been discovered since the last time
|
||||
+ # the prompt was displayed. RPMs in here are also present in the
|
||||
+ # __MISSING_RPMS dictionary, but this dictionary is cleared each time
|
||||
+ # the prompt is shown.
|
||||
+ __suggest_rpms = {}
|
||||
+
|
||||
+
|
||||
+ # Lookup RPMs that might provide the debug information for FILENAME,
|
||||
+ # which is a string containing the path to an object file GDB could
|
||||
+ # not find any debug information for.
|
||||
+ #
|
||||
+ # If a possible RPM is found then this is added to the globals
|
||||
+ # __MISSING_RPMS and __SUGGEST_RPMS, which are used elsewhere in this
|
||||
+ # script.
|
||||
+ def find_suggestions(filename):
|
||||
+ ts = rpm.TransactionSet()
|
||||
+
|
||||
+ mi = ts.dbMatch(rpm.RPMDBI_BASENAMES, filename)
|
||||
+ for h in mi:
|
||||
+ # Build the debuginfo package name.
|
||||
+ obj = h.format("%{name}-debuginfo-%{version}-%{release}.%{arch}")
|
||||
+
|
||||
+ # Check to see if the package is installed.
|
||||
+ mi2 = ts.dbMatch(rpm.RPMDBI_LABEL, str(obj))
|
||||
+ if len(mi2) > 0:
|
||||
+ continue
|
||||
+
|
||||
+ # Now build the name of the package FILENAME came from.
|
||||
+ obj = h.format("%{name}-%{version}-%{release}.%{arch}")
|
||||
+ rpm_name = str(obj)
|
||||
+ if not rpm_name in __missing_rpms:
|
||||
+ __suggest_rpms[rpm_name] = True
|
||||
+ __missing_rpms[rpm_name] = True
|
||||
+
|
||||
+
|
||||
+ # A missing debug handler class. Just forwards the name of the
|
||||
+ # objfile for which we are missing debug information to
|
||||
+ # find_suggestions.
|
||||
+ class RPMSuggestionHandler(gdb.missing_debug.MissingDebugHandler):
|
||||
+ def __init__(self):
|
||||
+ super().__init__("rpm-suggestions")
|
||||
+
|
||||
+ def __call__(self, objfile):
|
||||
+ # Traditionally the 'build-id-verbose' parameter is what
|
||||
+ # controlled all RPM suggestion. Maybe once all the RPM
|
||||
+ # suggestion is performed via Python extensions then we might
|
||||
+ # consider renaming this parameter to something else, but for
|
||||
+ # now, for backward compatibility, I've retained this name.
|
||||
+ if gdb.parameter("build-id-verbose") > 0:
|
||||
+ find_suggestions(objfile.filename)
|
||||
+ return False
|
||||
+ return None
|
||||
+
|
||||
+
|
||||
+ # Called before GDB displays its prompt. If the global __SUGGEST_RPMS
|
||||
+ # dictionary is not empty, then this hook prints treats the keys of
|
||||
+ # this dictionary as strings which are the names of RPMs. This hook
|
||||
+ # formats each RPM name into a suggested debuginfo-install command and
|
||||
+ # suggests this to the user.
|
||||
+ def before_prompt():
|
||||
+ global __suggest_rpms
|
||||
+
|
||||
+ if len(__suggest_rpms) > 0:
|
||||
+ for p in __suggest_rpms.keys():
|
||||
+ print("Missing debuginfo, try: dnf debuginfo-install " + p)
|
||||
+ __suggest_rpms = {}
|
||||
+
|
||||
+
|
||||
+ # Called when the executable within a progrm space is changed. Clear
|
||||
+ # the lists of RPM suggestions. We only clear the previous suggestion
|
||||
+ # list when the executable really changes. If the user simply
|
||||
+ # recompiles the executable, then we don't both clearing this list.
|
||||
+ def executable_changed_handler(event):
|
||||
+ global __missing_rpms
|
||||
+ global __suggest_rpms
|
||||
+
|
||||
+ if not event.reload:
|
||||
+ __missing_rpms = {}
|
||||
+ __suggest_rpms = {}
|
||||
+
|
||||
+
|
||||
+ # Attach to the required GDB events.
|
||||
+ gdb.events.executable_changed.connect(executable_changed_handler)
|
||||
+ gdb.events.before_prompt.connect(before_prompt)
|
||||
+
|
||||
+ # Register the missing debug handler with GDB.
|
||||
+ gdb.missing_debug.register_handler(None, RPMSuggestionHandler())
|
||||
diff --git a/gdb/testsuite/gdb.python/py-missing-debug.py b/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
--- a/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-missing-debug.py
|
||||
@@ -19,6 +19,13 @@ from enum import Enum
|
||||
import gdb
|
||||
from gdb.missing_debug import MissingDebugHandler
|
||||
|
||||
+# This is a RHEL/Fedora work around: There's already a
|
||||
+# missing-debug-info handler registered for these versions of GDB.
|
||||
+# Discard the handler now so that the tests will pass (the tests
|
||||
+# assume no handler is currently registered).
|
||||
+gdb.missing_debug_handlers = []
|
||||
+
|
||||
+
|
||||
# A global log that is filled in by instances of the LOG_HANDLER class
|
||||
# when they are called.
|
||||
handler_call_log = []
|
@ -59,7 +59,7 @@ new file mode 100644
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+if { [skip_cplus_tests] } { continue }
|
||||
+require allow_cplus_tests
|
||||
+
|
||||
+set testfile cxxexec
|
||||
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.cc {c++ debug}] } {
|
||||
|
@ -1,47 +0,0 @@
|
||||
From 40b2857e42b477832ca7fc2771b6cde910e22f05 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
|
||||
Date: Tue, 23 Jan 2024 14:11:33 -0300
|
||||
Subject: [PATCH 4/7] gdb/arm: Fix epilogue frame id
|
||||
|
||||
arm_epilogue_frame_this_id has a comment saying that it fall backs to using
|
||||
the current PC if the function start address can't be identified, but it
|
||||
actually uses only the PC to make the frame id.
|
||||
|
||||
This patch makes the code match the comment. Another hint that it's what
|
||||
is intended is that arm_prologue_this_id, a function almost identical to
|
||||
it, does that.
|
||||
|
||||
The problem was found by code inspection. It fixes the following testsuite
|
||||
failures:
|
||||
|
||||
FAIL: gdb.base/unwind-on-each-insn.exp: foo: instruction 9: check frame-id matches
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next third shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next second shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next first shr1
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-next generic
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step into solib function one
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step within solib function one
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step into solib function two
|
||||
FAIL: gdb.reverse/solib-reverse.exp: reverse-step within solib function two
|
||||
|
||||
Tested on arm-linux-gnueabi-hf.
|
||||
---
|
||||
gdb/arm-tdep.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
|
||||
index 3b1682a2aea..21dad198dc7 100644
|
||||
--- a/gdb/arm-tdep.c
|
||||
+++ b/gdb/arm-tdep.c
|
||||
@@ -3252,7 +3252,7 @@ arm_epilogue_frame_this_id (frame_info_ptr this_frame,
|
||||
|
||||
arm_gdbarch_tdep *tdep
|
||||
= gdbarch_tdep<arm_gdbarch_tdep> (get_frame_arch (this_frame));
|
||||
- *this_id = frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), pc);
|
||||
+ *this_id = frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), func);
|
||||
}
|
||||
|
||||
/* Implementation of function hook 'prev_register' in
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,77 +0,0 @@
|
||||
From 51a5415b3313470cb62fda7ad6762fc1c41c8cbd Mon Sep 17 00:00:00 2001
|
||||
From: Simon Marchi <simon.marchi@efficios.com>
|
||||
Date: Tue, 7 Nov 2023 11:11:18 -0500
|
||||
Subject: [PATCH] gdb/arm: remove thumb bit in arm_adjust_breakpoint_address
|
||||
|
||||
When compiling gdb with -fsanitize=address on ARM, I get a crash in test
|
||||
gdb.arch/arm-disp-step.exp, reproduced easily with:
|
||||
|
||||
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
|
||||
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
|
||||
=================================================================
|
||||
==23295==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb4a14fd1 at pc 0x01a48871 bp 0xbeab8490 sp 0xbeab8494
|
||||
|
||||
Since it doesn't require running the program, it can be reproduced locally on a
|
||||
dev machine other than ARM, after acquiring the test binary.
|
||||
|
||||
The length of the allocate buffer `buf` is 1, and we try to extract an
|
||||
integer of size 2 from it. The length of 1 comes from the subtraction
|
||||
`bpaddr - boundary`. Normally, on ARM, all instructions are aligned on
|
||||
a multiple of 2, so it's weird for this subtraction to result in 1. In
|
||||
this case, boundary comes from the result of find_pc_partial_function
|
||||
returning 0x549:
|
||||
|
||||
(gdb) p/x bpaddr
|
||||
$2 = 0x54a
|
||||
(gdb) p/x boundary
|
||||
$3 = 0x549
|
||||
(gdb) p/x bpaddr - boundary
|
||||
$4 = 0x1
|
||||
|
||||
0x549 is the address of the test_call_subr label, 0x548, with the thumb
|
||||
bit enabled. Before doing some math with the address, I think we need
|
||||
to strip the thumb bit, like is done elsewhere (for instance for bpaddr
|
||||
earlier in the same function).
|
||||
|
||||
I wonder if find_pc_partial_function should do that itself, in order to
|
||||
return an address that is suitable for arithmetic. In any case, that
|
||||
would be a change with a broad impact, so for now just fix the issue
|
||||
locally.
|
||||
|
||||
After the patch:
|
||||
|
||||
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step -ex "break *test_call_end"
|
||||
Reading symbols from testsuite/outputs/gdb.arch/arm-disp-step/arm-disp-step...
|
||||
Breakpoint 1 at 0x54a: file /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/arm-disp-step.S, line 103.
|
||||
|
||||
Change-Id: I74fc458dbea0d2c1e1f5eadd90755188df089288
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
---
|
||||
gdb/arm-tdep.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
|
||||
index 21dad198dc7..e61342f3ccb 100644
|
||||
--- a/gdb/arm-tdep.c
|
||||
+++ b/gdb/arm-tdep.c
|
||||
@@ -5340,9 +5340,12 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
|
||||
|
||||
bpaddr = gdbarch_addr_bits_remove (gdbarch, bpaddr);
|
||||
|
||||
- if (find_pc_partial_function (bpaddr, NULL, &func_start, NULL)
|
||||
- && func_start > boundary)
|
||||
- boundary = func_start;
|
||||
+ if (find_pc_partial_function (bpaddr, NULL, &func_start, NULL))
|
||||
+ {
|
||||
+ func_start = gdbarch_addr_bits_remove (gdbarch, func_start);
|
||||
+ if (func_start > boundary)
|
||||
+ boundary = func_start;
|
||||
+ }
|
||||
|
||||
/* Search for a candidate IT instruction. We have to do some fancy
|
||||
footwork to distinguish a real IT instruction from the second
|
||||
|
||||
base-commit: eafca1ce3d589c731927e5481199db715bcbeff3
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,219 +0,0 @@
|
||||
From 7973eaf11e33ddd405830b9bd29495991db5901d Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
|
||||
Date: Mon, 26 Feb 2024 19:11:45 -0300
|
||||
Subject: [PATCH 2/7] gdb/arm: Remove tpidruro register from non-FreeBSD target
|
||||
descriptions
|
||||
|
||||
Commit 92d48a1e4eac ("Add an arm-tls feature which includes the tpidruro
|
||||
register from CP15.") introduced the org.gnu.gdb.arm.tls feature, which
|
||||
adds the tpidruro register, and unconditionally enabled it in
|
||||
aarch32_create_target_description.
|
||||
|
||||
In Linux, the tpidruro register isn't available via ptrace in the 32-bit
|
||||
kernel but it is available for an aarch32 program running under an arm64
|
||||
kernel via the ptrace compat interface. This isn't currently implemented
|
||||
however, which causes GDB on arm-linux with 64-bit kernel to list the
|
||||
register but show it as unavailable, as reported by Tom de Vries:
|
||||
|
||||
$ gdb -q -batch a.out -ex start -ex 'p $tpidruro'
|
||||
Temporary breakpoint 1 at 0x512
|
||||
|
||||
Temporary breakpoint 1, 0xaaaaa512 in main ()
|
||||
$1 = <unavailable>
|
||||
|
||||
Simon Marchi then clarified:
|
||||
|
||||
> The only time we should be seeing some "unavailable" registers or memory
|
||||
> is in the context of tracepoints, for things that are not collected.
|
||||
> Seeing an unavailable register here is a sign that something is not
|
||||
> right.
|
||||
|
||||
Therefore, disable the TLS feature in aarch32 target descriptions for Linux
|
||||
and NetBSD targets (the latter also doesn't seem to support accessing
|
||||
tpidruro either, based on a quick look at arm-netbsd-nat.c).
|
||||
|
||||
This patch fixes the following tests:
|
||||
|
||||
Running gdb.base/inline-frame-cycle-unwind.exp ...
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 3: backtrace when the unwind is broken at frame 3
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: backtrace when the unwind is broken at frame 5
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 1: backtrace when the unwind is broken at frame 1
|
||||
|
||||
Tested with Ubuntu 22.04.3 on armv8l-linux-gnueabihf in native,
|
||||
native-gdbserver and native-extended-gdbserver targets with no regressions.
|
||||
|
||||
PR tdep/31418
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31418
|
||||
|
||||
Approved-By: John Baldwin <jhb@FreeBSD.org>
|
||||
---
|
||||
gdb/aarch32-tdep.c | 15 ++++++++++-----
|
||||
gdb/aarch32-tdep.h | 2 +-
|
||||
gdb/aarch64-linux-nat.c | 2 +-
|
||||
gdb/arch/aarch32.c | 5 +++--
|
||||
gdb/arch/aarch32.h | 2 +-
|
||||
gdb/arm-fbsd-tdep.c | 2 +-
|
||||
gdb/arm-linux-nat.c | 2 +-
|
||||
gdb/arm-linux-tdep.c | 2 +-
|
||||
gdb/arm-netbsd-nat.c | 2 +-
|
||||
gdbserver/linux-aarch32-tdesc.cc | 2 +-
|
||||
10 files changed, 21 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/gdb/aarch32-tdep.c b/gdb/aarch32-tdep.c
|
||||
index bfa88a96522..395328936e4 100644
|
||||
--- a/gdb/aarch32-tdep.c
|
||||
+++ b/gdb/aarch32-tdep.c
|
||||
@@ -22,15 +22,20 @@
|
||||
#include "gdbsupport/common-regcache.h"
|
||||
#include "arch/aarch32.h"
|
||||
|
||||
-static struct target_desc *tdesc_aarch32;
|
||||
+static struct target_desc *tdesc_aarch32_list[2];
|
||||
|
||||
/* See aarch32-tdep.h. */
|
||||
|
||||
const target_desc *
|
||||
-aarch32_read_description ()
|
||||
+aarch32_read_description (bool tls)
|
||||
{
|
||||
- if (tdesc_aarch32 == nullptr)
|
||||
- tdesc_aarch32 = aarch32_create_target_description ();
|
||||
+ struct target_desc *tdesc = tdesc_aarch32_list[tls];
|
||||
|
||||
- return tdesc_aarch32;
|
||||
+ if (tdesc == nullptr)
|
||||
+ {
|
||||
+ tdesc = aarch32_create_target_description (tls);
|
||||
+ tdesc_aarch32_list[tls] = tdesc;
|
||||
+ }
|
||||
+
|
||||
+ return tdesc;
|
||||
}
|
||||
diff --git a/gdb/aarch32-tdep.h b/gdb/aarch32-tdep.h
|
||||
index bee4d4e9fc0..efc93351298 100644
|
||||
--- a/gdb/aarch32-tdep.h
|
||||
+++ b/gdb/aarch32-tdep.h
|
||||
@@ -22,6 +22,6 @@ struct target_desc;
|
||||
|
||||
/* Get the AArch32 target description. */
|
||||
|
||||
-const target_desc *aarch32_read_description ();
|
||||
+const target_desc *aarch32_read_description (bool tls);
|
||||
|
||||
#endif /* aarch32-tdep.h. */
|
||||
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
|
||||
index 768748a20db..c680d6de0c9 100644
|
||||
--- a/gdb/aarch64-linux-nat.c
|
||||
+++ b/gdb/aarch64-linux-nat.c
|
||||
@@ -887,7 +887,7 @@ aarch64_linux_nat_target::read_description ()
|
||||
|
||||
ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_VFP, &iovec);
|
||||
if (ret == 0)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
|
||||
CORE_ADDR hwcap = linux_get_hwcap ();
|
||||
CORE_ADDR hwcap2 = linux_get_hwcap2 ();
|
||||
diff --git a/gdb/arch/aarch32.c b/gdb/arch/aarch32.c
|
||||
index 5be2cc0156e..b7510ee41e9 100644
|
||||
--- a/gdb/arch/aarch32.c
|
||||
+++ b/gdb/arch/aarch32.c
|
||||
@@ -25,7 +25,7 @@
|
||||
/* See aarch32.h. */
|
||||
|
||||
target_desc *
|
||||
-aarch32_create_target_description ()
|
||||
+aarch32_create_target_description (bool tls)
|
||||
{
|
||||
target_desc_up tdesc = allocate_target_description ();
|
||||
|
||||
@@ -39,7 +39,8 @@ aarch32_create_target_description ()
|
||||
/* Create a vfpv3 feature, then a blank NEON feature. */
|
||||
regnum = create_feature_arm_arm_vfpv3 (tdesc.get (), regnum);
|
||||
tdesc_create_feature (tdesc.get (), "org.gnu.gdb.arm.neon");
|
||||
- regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
|
||||
+ if (tls)
|
||||
+ regnum = create_feature_arm_arm_tls (tdesc.get (), regnum);
|
||||
|
||||
return tdesc.release ();
|
||||
}
|
||||
diff --git a/gdb/arch/aarch32.h b/gdb/arch/aarch32.h
|
||||
index 6b24ae94335..e06e260e370 100644
|
||||
--- a/gdb/arch/aarch32.h
|
||||
+++ b/gdb/arch/aarch32.h
|
||||
@@ -22,6 +22,6 @@
|
||||
|
||||
/* Create the AArch32 target description. */
|
||||
|
||||
-target_desc *aarch32_create_target_description ();
|
||||
+target_desc *aarch32_create_target_description (bool tls);
|
||||
|
||||
#endif /* aarch32.h. */
|
||||
diff --git a/gdb/arm-fbsd-tdep.c b/gdb/arm-fbsd-tdep.c
|
||||
index b46fa91d0a0..a4cea77f388 100644
|
||||
--- a/gdb/arm-fbsd-tdep.c
|
||||
+++ b/gdb/arm-fbsd-tdep.c
|
||||
@@ -228,7 +228,7 @@ arm_fbsd_read_description_auxv (const gdb::optional<gdb::byte_vector> &auxv,
|
||||
if (arm_hwcap & HWCAP_VFP)
|
||||
{
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (tls);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
== (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, tls);
|
||||
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
|
||||
index 70c6bc684fa..07af23d3881 100644
|
||||
--- a/gdb/arm-linux-nat.c
|
||||
+++ b/gdb/arm-linux-nat.c
|
||||
@@ -568,7 +568,7 @@ arm_linux_nat_target::read_description ()
|
||||
/* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
|
||||
Neon with VFPv3-D32. */
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
|
||||
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
|
||||
index dfa816990ff..33748731cfd 100644
|
||||
--- a/gdb/arm-linux-tdep.c
|
||||
+++ b/gdb/arm-linux-tdep.c
|
||||
@@ -740,7 +740,7 @@ arm_linux_core_read_description (struct gdbarch *gdbarch,
|
||||
/* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
|
||||
Neon with VFPv3-D32. */
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
|
||||
diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c
|
||||
index d83714a46c3..018964b010d 100644
|
||||
--- a/gdb/arm-netbsd-nat.c
|
||||
+++ b/gdb/arm-netbsd-nat.c
|
||||
@@ -350,7 +350,7 @@ arm_netbsd_nat_target::read_description ()
|
||||
|
||||
len = sizeof(flag);
|
||||
if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag)
|
||||
- return aarch32_read_description ();
|
||||
+ return aarch32_read_description (false);
|
||||
|
||||
return arm_read_description (ARM_FP_TYPE_VFPV3, false);
|
||||
}
|
||||
diff --git a/gdbserver/linux-aarch32-tdesc.cc b/gdbserver/linux-aarch32-tdesc.cc
|
||||
index e1380fa2a40..443f91e3585 100644
|
||||
--- a/gdbserver/linux-aarch32-tdesc.cc
|
||||
+++ b/gdbserver/linux-aarch32-tdesc.cc
|
||||
@@ -32,7 +32,7 @@ aarch32_linux_read_description ()
|
||||
{
|
||||
if (tdesc_aarch32 == nullptr)
|
||||
{
|
||||
- tdesc_aarch32 = aarch32_create_target_description ();
|
||||
+ tdesc_aarch32 = aarch32_create_target_description (false);
|
||||
|
||||
static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };
|
||||
init_target_desc (tdesc_aarch32, expedite_regs);
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,41 +0,0 @@
|
||||
From 0397481ff25b76d43b123f3d51828982ceb92834 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Wielaard <mark@klomp.org>
|
||||
Date: Fri, 3 May 2024 15:17:42 +0200
|
||||
Subject: [PATCH] [gdb/build] Fix gdbserver/linux-aarch64-low.cc build
|
||||
|
||||
Commit 0ee25f97d21e ("Fix regression on aarch64-linux gdbserver")
|
||||
removed the last use of i in gdbserver/linux-aarch64-low.cc
|
||||
(aarch64_target::low_stopped_data_address). Breaking the build on
|
||||
aarch64 with:
|
||||
|
||||
gdbserver/linux-aarch64-low.cc: In member function ?virtual CORE_ADDR aarch64_target::low_stopped_data_address()?:
|
||||
gdbserver/linux-aarch64-low.cc:557:12: error: unused variable ?i? [-Werror=unused-variable]
|
||||
557 | int pid, i;
|
||||
| ^
|
||||
cc1plus: all warnings being treated as errors
|
||||
|
||||
Fix this by removing the variable i completely.
|
||||
|
||||
Fixes: 0ee25f97d21e ("Fix regression on aarch64-linux gdbserver")
|
||||
---
|
||||
gdbserver/linux-aarch64-low.cc | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
|
||||
index 14346b89822..ce0029b885f 100644
|
||||
--- a/gdbserver/linux-aarch64-low.cc
|
||||
+++ b/gdbserver/linux-aarch64-low.cc
|
||||
@@ -555,7 +555,7 @@ CORE_ADDR
|
||||
aarch64_target::low_stopped_data_address ()
|
||||
{
|
||||
siginfo_t siginfo;
|
||||
- int pid, i;
|
||||
+ int pid;
|
||||
struct aarch64_debug_reg_state *state;
|
||||
|
||||
pid = lwpid_of (current_thread);
|
||||
|
||||
base-commit: b33811a85ff53af77cdad995ad8cb50431c8c362
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,41 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-bz634108-solib_address.patch
|
||||
|
||||
;; Verify GDB Python built-in function gdb.solib_address exists (BZ # 634108).
|
||||
;;=fedoratest
|
||||
|
||||
Fix gdb.solib_address (fix by Phil Muldoon).
|
||||
|
||||
s/solib_address/solib_name/ during upstreaming.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/rh634108-solib_address.exp b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/rh634108-solib_address.exp
|
||||
@@ -0,0 +1,24 @@
|
||||
+# Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# https://bugzilla.redhat.com/show_bug.cgi?id=634108
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+
|
||||
+# Skip all tests if Python scripting is not enabled.
|
||||
+if { [skip_python_tests] } { continue }
|
||||
+
|
||||
+gdb_test "python print (gdb.solib_name(-1))" "None" "gdb.solib_name exists"
|
575
gdb-catchpoint-re-set.patch
Normal file
575
gdb-catchpoint-re-set.patch
Normal file
@ -0,0 +1,575 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Wed, 14 Aug 2024 15:16:46 +0100
|
||||
Subject: gdb-catchpoint-re-set.patch
|
||||
|
||||
;; Backport upstream commit a92e943014f to fix rhbz2304296.
|
||||
|
||||
gdb: implement ::re_set method for catchpoint class
|
||||
|
||||
It is possible to attach a condition to a catchpoint. This can't be
|
||||
done when the catchpoint is created, but can be done with the
|
||||
'condition' command, this is documented in the GDB manual:
|
||||
|
||||
You can also use the 'if' keyword with the 'watch' command. The
|
||||
'catch' command does not recognize the 'if' keyword; 'condition' is the
|
||||
only way to impose a further condition on a catchpoint.
|
||||
|
||||
A GDB crash was reported against Fedora GDB where a user had attached
|
||||
a condition to a catchpoint and then restarted the inferior. When the
|
||||
catchpoint was hit GDB would immediately segfault. I was able to
|
||||
reproduce the failure on upstream GDB:
|
||||
|
||||
(gdb) file ./some/binary
|
||||
(gdb) catch syscall write
|
||||
(gdb) run
|
||||
...
|
||||
Catchpoint 1 (returned from syscall write), 0x00007ffff7b594a7 in write () from /lib64/libc.so.6
|
||||
(gdb) condition 1 $_streq((char *) $rsi, "foobar") == 0
|
||||
(gdb) run
|
||||
...
|
||||
Fatal signal: Segmentation fault
|
||||
...
|
||||
|
||||
What happened here is that on the system in question we had debug
|
||||
information available for both the main application and also for
|
||||
libc.
|
||||
|
||||
When the condition was attached GDB was stopped inside libc and as the
|
||||
debug information was available GDB found a reference to the 'char'
|
||||
type (for the cast) inside libc's debug information.
|
||||
|
||||
When the inferior is restarted GDB discards all of the objfiles
|
||||
associated with shared libraries, and this includes libc. As such the
|
||||
'char' type, which is objfile owned, is discarded and the reference to
|
||||
it from the catchpoint's condition expression becomes invalid.
|
||||
|
||||
Now, if it were a breakpoint instead of a catchpoint, what would
|
||||
happen is that after the shared library objfiles had been discarded
|
||||
we'd call the virtual breakpoint::re_set method on the breakpoint, and
|
||||
this would update the breakpoint's condition expression. This is
|
||||
because user breakpoints are actually instances of the code_breakpoint
|
||||
class and the code_breakpoint::re_set method contains the code to
|
||||
recompute the breakpoint's condition expression.
|
||||
|
||||
However, catchpoints are instances of the catchpoint class which
|
||||
inherits from the base breakpoint class. The catchpoint class does
|
||||
not override breakpoint::re_set, and breakpoint::re_set is empty!
|
||||
|
||||
The consequence of this is that catchpoint condition expressions are
|
||||
never recomputed, and the dangling pointer to the now deleted, objfile
|
||||
owned type 'char' is left around, and, when the catchpoint is hit, the
|
||||
invalid pointer is used when GDB tries to evaluate the condition
|
||||
expression.
|
||||
|
||||
In this commit I have implemented catchpoint::re_set. This is pretty
|
||||
simple and just recomputes the condition expression as you'd expect.
|
||||
If the condition doesn't evaluate then the catchpoint is marked as
|
||||
disabled_by_cond.
|
||||
|
||||
I have also made breakpoint::re_set pure virtual. With the addition
|
||||
of catchpoint::re_set every sub-class of breakpoint now implements the
|
||||
::re_set method, and if new sub-classes are added in the future I
|
||||
think that they _must_ implement ::re_set in order to avoid this
|
||||
problem. As such falling back to an empty breakpoint::re_set doesn't
|
||||
seem helpful.
|
||||
|
||||
For testing I have not relied on stopping in libc and having libc
|
||||
debug information available, this doesn't seem like a good idea for
|
||||
the GDB testsuite. Instead I create a (rather pointless) condition
|
||||
check that uses a type defined only within a shared library. When the
|
||||
inferior is restarted the catchpoint will temporarily be marked as
|
||||
disabled_by_cond (due to the type not being available), but once the
|
||||
shared library is loaded again the catchpoint will be re-enabled.
|
||||
Without the fixes above then the same crashing behaviour can be
|
||||
observed.
|
||||
|
||||
One point of note: the dangling pointer of course exposes undefined
|
||||
behaviour, with no guarantee of a crash. Though a crash is what I
|
||||
usually see I have see GDB throw random errors from the expression
|
||||
evaluation code, and once, I saw no problem at all! If you recompile
|
||||
GDB with the address sanitizer, or run under valgrind, then the bug
|
||||
will be exposed every time.
|
||||
|
||||
After fixing this bug I checked bugzilla and found PR gdb/29960 which
|
||||
is the same bug. I was able to reproduce the bug before this commit,
|
||||
and after this commit GDB is no longer crashing.
|
||||
|
||||
Before:
|
||||
|
||||
(gdb) file /tmp/hello.x
|
||||
Reading symbols from /tmp/hello.x...
|
||||
(gdb) run
|
||||
Starting program: /tmp/hello.x
|
||||
Hello World
|
||||
[Inferior 1 (process 1101855) exited normally]
|
||||
(gdb) catch syscall 1
|
||||
Catchpoint 1 (syscall 'write' [1])
|
||||
(gdb) condition 1 write.fd == 1
|
||||
(gdb) run
|
||||
Starting program: /tmp/hello.x
|
||||
|
||||
Fatal signal: Segmentation fault
|
||||
...
|
||||
|
||||
And after:
|
||||
|
||||
(gdb) file /tmp/hello.x
|
||||
Reading symbols from /tmp/hello.x...
|
||||
(gdb) run
|
||||
Starting program: /tmp/hello.x
|
||||
Hello World
|
||||
Args: ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 )
|
||||
[Inferior 1 (process 1102373) exited normally]
|
||||
(gdb) catch syscall 1
|
||||
Catchpoint 1 (syscall 'write' [1])
|
||||
(gdb) condition 1 write.fd == 1
|
||||
(gdb) r
|
||||
Starting program: /tmp/hello.x
|
||||
Error in testing condition for breakpoint 1:
|
||||
Attempt to extract a component of a value that is not a structure.
|
||||
|
||||
Catchpoint 1 (call to syscall write), 0x00007ffff7eb94a7 in write ()
|
||||
from /lib64/libc.so.6
|
||||
(gdb) ptype write
|
||||
type = <unknown return type> ()
|
||||
(gdb)
|
||||
|
||||
Notice we get the error now when the condition fails to evaluate.
|
||||
This seems reasonable given that 'write' will be a function, and
|
||||
indeed the final 'ptype' shows that it's a function, not a struct.
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29960
|
||||
|
||||
Reviewed-By: Tom de Vries <tdevries@suse.de>
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -8146,6 +8146,60 @@ catchpoint::catchpoint (struct gdbarch *gdbarch, bool temp,
|
||||
pspace = current_program_space;
|
||||
}
|
||||
|
||||
+/* See breakpoint.h. */
|
||||
+
|
||||
+void
|
||||
+catchpoint::re_set ()
|
||||
+{
|
||||
+ /* All catchpoints are associated with a specific program_space. */
|
||||
+ gdb_assert (pspace != nullptr);
|
||||
+
|
||||
+ /* Catchpoints have a single dummy location. */
|
||||
+ gdb_assert (locations ().size () == 1);
|
||||
+ bp_location &bl = m_locations.front ();
|
||||
+
|
||||
+ if (cond_string == nullptr)
|
||||
+ {
|
||||
+ /* It shouldn't be possible to have a parsed condition expression
|
||||
+ cached on this location if the catchpoint doesn't have a condition
|
||||
+ string set. */
|
||||
+ gdb_assert (bl.cond == nullptr);
|
||||
+
|
||||
+ /* Nothing to re-compute, and the catchpoint cannot change. */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bool previous_disabled_by_cond = bl.disabled_by_cond;
|
||||
+
|
||||
+ /* Start by marking the location disabled and discarding the previously
|
||||
+ computed condition expression. Now if we get an exception, even if
|
||||
+ it's a quit exception, we'll leave the location disabled and there
|
||||
+ will be no (possibly invalid) expression cached. */
|
||||
+ bl.disabled_by_cond = true;
|
||||
+ bl.cond = nullptr;
|
||||
+
|
||||
+ const char *s = cond_string.get ();
|
||||
+ try
|
||||
+ {
|
||||
+ switch_to_program_space_and_thread (pspace);
|
||||
+
|
||||
+ bl.cond = parse_exp_1 (&s, bl.address, block_for_pc (bl.address),
|
||||
+ nullptr);
|
||||
+ bl.disabled_by_cond = false;
|
||||
+ }
|
||||
+ catch (const gdb_exception_error &e)
|
||||
+ {
|
||||
+ /* Any exception thrown must be from either the parse_exp_1 or
|
||||
+ earlier in the try block. As such the following two asserts
|
||||
+ should be true. */
|
||||
+ gdb_assert (bl.disabled_by_cond);
|
||||
+ gdb_assert (bl.cond == nullptr);
|
||||
+ }
|
||||
+
|
||||
+ if (previous_disabled_by_cond != bl.disabled_by_cond)
|
||||
+ notify_breakpoint_modified (this);
|
||||
+}
|
||||
+
|
||||
/* Notify interpreters and observers that breakpoint B was created. */
|
||||
|
||||
static void
|
||||
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
|
||||
--- a/gdb/breakpoint.h
|
||||
+++ b/gdb/breakpoint.h
|
||||
@@ -702,11 +702,10 @@ struct breakpoint : public intrusive_list_node<breakpoint>
|
||||
|
||||
/* Reevaluate a breakpoint. This is necessary after symbols change
|
||||
(e.g., an executable or DSO was loaded, or the inferior just
|
||||
- started). */
|
||||
- virtual void re_set ()
|
||||
- {
|
||||
- /* Nothing to re-set. */
|
||||
- }
|
||||
+ started). This is pure virtual as, at a minimum, each sub-class must
|
||||
+ recompute any cached condition expressions based off of the
|
||||
+ cond_string member variable. */
|
||||
+ virtual void re_set () = 0;
|
||||
|
||||
/* Insert the breakpoint or watchpoint or activate the catchpoint.
|
||||
Return 0 for success, 1 if the breakpoint, watchpoint or
|
||||
@@ -1120,6 +1119,10 @@ struct catchpoint : public breakpoint
|
||||
catchpoint (struct gdbarch *gdbarch, bool temp, const char *cond_string);
|
||||
|
||||
~catchpoint () override = 0;
|
||||
+
|
||||
+ /* If the catchpoint has a condition set then recompute the cached
|
||||
+ expression within the single dummy location. */
|
||||
+ void re_set () override;
|
||||
};
|
||||
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c b/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond-lib.c
|
||||
@@ -0,0 +1,76 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <signal.h>
|
||||
+#include <unistd.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <unistd.h>
|
||||
+#include <assert.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+/* This type is used by GDB. */
|
||||
+struct lib_type
|
||||
+{
|
||||
+ int a;
|
||||
+ int b;
|
||||
+ int c;
|
||||
+};
|
||||
+
|
||||
+/* Ensure the type above is used. */
|
||||
+volatile struct lib_type global_lib_object = { 1, 2, 3 };
|
||||
+
|
||||
+/* This pointer is checked by GDB. */
|
||||
+volatile void *opaque_ptr = 0;
|
||||
+
|
||||
+void
|
||||
+lib_func_test_syscall (void)
|
||||
+{
|
||||
+ puts ("Inside library\n");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sig_handler (int signo)
|
||||
+{
|
||||
+ /* Nothing. */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+lib_func_test_signal (void)
|
||||
+{
|
||||
+ signal (SIGUSR1, sig_handler);
|
||||
+
|
||||
+ kill (getpid (), SIGUSR1);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+lib_func_test_fork (void)
|
||||
+{
|
||||
+ pid_t pid = fork ();
|
||||
+ assert (pid != -1);
|
||||
+
|
||||
+ if (pid == 0)
|
||||
+ {
|
||||
+ /* Child: just exit. */
|
||||
+ exit (0);
|
||||
+ }
|
||||
+
|
||||
+ /* Parent. */
|
||||
+ waitpid (pid, NULL, 0);
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.c b/gdb/testsuite/gdb.base/reset-catchpoint-cond.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+extern void lib_func_test_syscall (void);
|
||||
+extern void lib_func_test_signal (void);
|
||||
+extern void lib_func_test_fork (void);
|
||||
+
|
||||
+/* We use this to perform some filler work. */
|
||||
+volatile int global_var = 0;
|
||||
+
|
||||
+/* Just somewhere for GDB to put a breakpoint. */
|
||||
+void
|
||||
+breakpt_before_exit (void)
|
||||
+{
|
||||
+ /* Nothing. */
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+#if defined TEST_SYSCALL
|
||||
+ lib_func_test_syscall ();
|
||||
+#elif defined TEST_SIGNAL
|
||||
+ lib_func_test_signal ();
|
||||
+#elif defined TEST_FORK
|
||||
+ lib_func_test_fork ();
|
||||
+#else
|
||||
+# error compile with suitable -DTEST_xxx macro defined
|
||||
+#endif
|
||||
+
|
||||
+ ++global_var;
|
||||
+
|
||||
+ breakpt_before_exit ();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.exp
|
||||
@@ -0,0 +1,169 @@
|
||||
+# Copyright 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Test that the condition for a catchpoint is correctly reset after
|
||||
+# shared libraries are unloaded, as happens when an inferior is
|
||||
+# restarted.
|
||||
+#
|
||||
+# If this is not done then, when the catchpoint is hit on the second
|
||||
+# run, we'll evaluate the parsed expression from the first run, which
|
||||
+# might include references to types owned by the now deleted objfile
|
||||
+# (for the shared library loaded in the first run).
|
||||
+#
|
||||
+# This scripts tests a number of different catchpoint types. Inside
|
||||
+# GDB these are all sub-classes of the 'catchpoint' type, which is
|
||||
+# where the fix for the above issue resides, so all catchpoint types
|
||||
+# should work correctly.
|
||||
+
|
||||
+standard_testfile .c -lib.c
|
||||
+
|
||||
+set libfile $binfile-lib.so
|
||||
+
|
||||
+set pyfile [gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
||||
+
|
||||
+if {[build_executable "build shared library" $libfile $srcfile2 \
|
||||
+ {debug shlib}] == -1} {
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+# Depending on whether or not libc debug info is installed, when we
|
||||
+# hit a syscall catchpoint inside libc there might be a source line
|
||||
+# included in the output.
|
||||
+#
|
||||
+# This regexp will match an optional line and can be added to the
|
||||
+# expected catchpoint output to ignore the (possibly missing) source
|
||||
+# line.
|
||||
+set libc_src_line_re "(?:\r\n\[^\r\n\]+)?"
|
||||
+
|
||||
+# Check the Python bp_modified_list and then reset the list back to
|
||||
+# empty. TESTNAME is just a string. BP_NUM is a list of breakpoint
|
||||
+# numbers that are expected to appear (in the given order) in the
|
||||
+# bp_modified_list.
|
||||
+
|
||||
+proc check_modified_bp_list { testname bp_num } {
|
||||
+ if { [allow_python_tests] } {
|
||||
+ set expected [join $bp_num ", "]
|
||||
+
|
||||
+ gdb_test "python print(bp_modified_list)" "\\\[$expected\\\]" \
|
||||
+ $testname
|
||||
+ gdb_test_no_output -nopass "python bp_modified_list=\[\]" \
|
||||
+ "reset bp_modified_list after $testname"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Build an executable and run tests on 'catch MODE'.
|
||||
+
|
||||
+proc run_test { mode } {
|
||||
+ set exec_name ${::binfile}-${mode}
|
||||
+
|
||||
+ set macro TEST_[string toupper $mode]
|
||||
+
|
||||
+ if {[build_executable "build test executable" $exec_name $::srcfile \
|
||||
+ [list debug shlib=$::libfile additional_flags=-D${macro}]] == -1} {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ clean_restart $exec_name
|
||||
+ gdb_load_shlib $::libfile
|
||||
+
|
||||
+ if {![runto_main]} {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ if { $mode eq "syscall" } {
|
||||
+ gdb_test "catch syscall write" \
|
||||
+ "Catchpoint $::decimal \\(syscall 'write' \[^)\]+\\)"
|
||||
+ set catch_re "call to syscall write"
|
||||
+ } elseif { $mode eq "signal" } {
|
||||
+ gdb_test "catch signal SIGUSR1" \
|
||||
+ "Catchpoint $::decimal \\(signal SIGUSR1\\)"
|
||||
+ set catch_re "signal SIGUSR1"
|
||||
+ } elseif { $mode eq "fork" } {
|
||||
+ gdb_test "catch fork" \
|
||||
+ "Catchpoint $::decimal \\(fork\\)"
|
||||
+ set catch_re "forked process $::decimal"
|
||||
+ } else {
|
||||
+ error "unknown mode $mode"
|
||||
+ }
|
||||
+ set cp_num [get_integer_valueof "\$bpnum" "*UNKNOWN*"]
|
||||
+
|
||||
+ gdb_breakpoint "breakpt_before_exit"
|
||||
+
|
||||
+ gdb_test "continue" \
|
||||
+ "Catchpoint ${cp_num} \[^\r\n\]+$::libc_src_line_re"
|
||||
+
|
||||
+ if { [allow_python_tests] } {
|
||||
+ gdb_test_no_output "source $::pyfile" "import python scripts"
|
||||
+ check_modified_bp_list \
|
||||
+ "check b/p modified observer has not yet triggered" {}
|
||||
+ }
|
||||
+
|
||||
+ with_test_prefix "with false condition" {
|
||||
+ gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) != 0" \
|
||||
+ "set catchpoint condition"
|
||||
+
|
||||
+ check_modified_bp_list \
|
||||
+ "catchpoint modified once by setting condition" \
|
||||
+ [list $cp_num]
|
||||
+
|
||||
+ gdb_run_cmd
|
||||
+ gdb_test "" [multi_line \
|
||||
+ "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
|
||||
+ "$::decimal\\s+\[^\r\n\]+"]
|
||||
+
|
||||
+ check_modified_bp_list "catchpoint modified twice at startup" \
|
||||
+ [list $cp_num $cp_num "$::decimal"]
|
||||
+
|
||||
+ gdb_test "continue" \
|
||||
+ [multi_line \
|
||||
+ "Breakpoint $::decimal, breakpt_before_exit \\(\\) at \[^\r\n\]+" \
|
||||
+ "$::decimal\\s+\[^\r\n\]+"] \
|
||||
+ "continue to breakpt_before_exit"
|
||||
+ }
|
||||
+
|
||||
+ # Check the bp_modified_list against '.*'. We don't care at this
|
||||
+ # point what's in the list (nothing relevant has happened since we
|
||||
+ # last checked), but this has the side effect of clearing the list.
|
||||
+ check_modified_bp_list "clear bp modified list" { .* }
|
||||
+
|
||||
+ with_test_prefix "with true condition" {
|
||||
+ gdb_test_no_output "condition $cp_num ((struct lib_type *) opaque_ptr) == 0" \
|
||||
+ "set catchpoint condition"
|
||||
+
|
||||
+ check_modified_bp_list \
|
||||
+ "catchpoint modified once by setting condition" \
|
||||
+ [list $cp_num]
|
||||
+
|
||||
+ gdb_run_cmd
|
||||
+ gdb_test "" [multi_line \
|
||||
+ "Breakpoint $::decimal, main \\(\\) \[^\r\n\]+" \
|
||||
+ "$::decimal\\s+\[^\r\n\]+"]
|
||||
+
|
||||
+ check_modified_bp_list "catchpoint modified twice at startup" \
|
||||
+ [list $cp_num $cp_num "$::decimal"]
|
||||
+
|
||||
+ gdb_test "continue" \
|
||||
+ "Catchpoint $cp_num \\($catch_re\\), \[^\r\n\]+$::libc_src_line_re" \
|
||||
+ "continue until catchpoint hit"
|
||||
+
|
||||
+ check_modified_bp_list "catchpoint modified again when hit" \
|
||||
+ [list $cp_num]
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Run the tests.
|
||||
+foreach_with_prefix mode { syscall signal fork } {
|
||||
+ run_test $mode
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/reset-catchpoint-cond.py b/gdb/testsuite/gdb.base/reset-catchpoint-cond.py
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/reset-catchpoint-cond.py
|
||||
@@ -0,0 +1,21 @@
|
||||
+# Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+bp_modified_list = []
|
||||
+
|
||||
+def bp_modified(bp):
|
||||
+ bp_modified_list.append (bp.number)
|
||||
+
|
||||
+gdb.events.breakpoint_modified.connect(bp_modified)
|
41
gdb-cli-print-at_hwcap3-and-at_hwcap4.patch
Normal file
41
gdb-cli-print-at_hwcap3-and-at_hwcap4.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From 442c996a4de355459eeabd280649ddb282d7de41 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 25 Jan 2025 10:08:53 +0100
|
||||
Subject: [PATCH 2/2] [gdb/cli] Print AT_HWCAP3 and AT_HWCAP4
|
||||
|
||||
PR cli/32590
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32590
|
||||
---
|
||||
gdb/auxv.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/gdb/auxv.c b/gdb/auxv.c
|
||||
index 8cda0b687b4..bb4c7ea70a0 100644
|
||||
--- a/gdb/auxv.c
|
||||
+++ b/gdb/auxv.c
|
||||
@@ -453,6 +453,13 @@ fprint_auxv_entry (struct ui_file *file, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifndef AT_HWCAP3
|
||||
+#define AT_HWCAP3 29
|
||||
+#endif
|
||||
+#ifndef AT_HWCAP4
|
||||
+#define AT_HWCAP4 30
|
||||
+#endif
|
||||
+
|
||||
/* The default implementation of gdbarch_print_auxv_entry. */
|
||||
|
||||
void
|
||||
@@ -495,6 +502,8 @@ default_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file,
|
||||
AUXV_FORMAT_STR);
|
||||
TAG (AT_RANDOM, _("Address of 16 random bytes"), AUXV_FORMAT_HEX);
|
||||
TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), AUXV_FORMAT_HEX);
|
||||
+ TAG (AT_HWCAP3, _("Extension of AT_HWCAP"), AUXV_FORMAT_HEX);
|
||||
+ TAG (AT_HWCAP4, _("Extension of AT_HWCAP"), AUXV_FORMAT_HEX);
|
||||
TAG (AT_RSEQ_FEATURE_SIZE, _("rseq supported feature size"),
|
||||
AUXV_FORMAT_DEC);
|
||||
TAG (AT_RSEQ_ALIGN, _("rseq allocation alignment"),
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,58 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-core-open-vdso-warning.patch
|
||||
|
||||
;; Fix GNU/Linux core open: Can't read pathname for load map: Input/output error.
|
||||
;; Fix regression of undisplayed missing shared libraries caused by a fix for.
|
||||
;;=fedoratest: It should be in glibc: libc-alpha: <20091004161706.GA27450@.*>
|
||||
|
||||
http://sourceware.org/ml/gdb-patches/2009-10/msg00142.html
|
||||
Subject: [patch] Fix GNU/Linux core open: Can't read pathname for load map: Input/output error.
|
||||
|
||||
[ New patch variant. ]
|
||||
|
||||
commit 7d760051ffb8a23cdc51342d4e6243fbc462f73f
|
||||
Author: Ulrich Weigand <uweigand@de.ibm.com>
|
||||
Date: Wed Sep 25 11:52:50 2013 +0000
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/solib-symbol.exp b/gdb/testsuite/gdb.base/solib-symbol.exp
|
||||
--- a/gdb/testsuite/gdb.base/solib-symbol.exp
|
||||
+++ b/gdb/testsuite/gdb.base/solib-symbol.exp
|
||||
@@ -27,6 +27,7 @@ set testfile "solib-symbol-main"
|
||||
set srcfile ${srcdir}/${subdir}/${testfile}.c
|
||||
set binfile [standard_output_file ${testfile}]
|
||||
set bin_flags [list debug shlib=${binfile_lib}]
|
||||
+set executable ${testfile}
|
||||
|
||||
if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
|
||||
|| [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
|
||||
@@ -61,4 +62,28 @@ gdb_test "br foo2" \
|
||||
"Breakpoint.*: foo2. .2 locations..*" \
|
||||
"foo2 in mdlib"
|
||||
|
||||
+# Test GDB warns for shared libraris which have not been found.
|
||||
+
|
||||
+gdb_test "info sharedlibrary" "/${libname}.*"
|
||||
+
|
||||
+clean_restart ${executable}
|
||||
+gdb_breakpoint "main"
|
||||
+gdb_run_cmd
|
||||
+set test "no warning for missing libraries"
|
||||
+gdb_test_multiple "" $test {
|
||||
+ -re "warning: Could not load shared library symbols for \[0-9\]+ libraries,.*\r\n$gdb_prompt $" {
|
||||
+ fail $test
|
||||
+ }
|
||||
+ -re "Breakpoint \[0-9\]+, main .*\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+clean_restart ${executable}
|
||||
+gdb_test_no_output "set solib-absolute-prefix /doESnotEXIST"
|
||||
+gdb_breakpoint "main"
|
||||
+gdb_run_cmd
|
||||
+gdb_test "" "warning: Could not load shared library symbols for \[0-9\]+ libraries,.*\r\nBreakpoint \[0-9\]+, main .*" \
|
||||
+ "warning for missing libraries"
|
||||
+
|
||||
gdb_exit
|
61
gdb-doc-fix-gdb.unwinder-docs.patch
Normal file
61
gdb-doc-fix-gdb.unwinder-docs.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From b57066d1eaafab3100a8d7d788feba5802c409b7 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 10:33:28 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix gdb.unwinder docs
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/python.texi:3015: warning: `(' follows defined name \
|
||||
`gdb.unwinder.Unwinder.__init__' instead of whitespace.
|
||||
gdb/doc/python.texi:3041: warning: `(' follows defined name \
|
||||
`gdb.unwinder.FrameId.__init__' instead of whitespace.
|
||||
...
|
||||
|
||||
The warnings are related to these two lines:
|
||||
...
|
||||
@defun gdb.unwinder.Unwinder.__init__(name)
|
||||
...
|
||||
@defun gdb.unwinder.FrameId.__init__(sp, pc, special = @code{None})
|
||||
...
|
||||
|
||||
Indeed, when checking the command and variable index, we can see that it
|
||||
contains an incorrect entry:
|
||||
...
|
||||
gdb.unwinder.FrameId.__init__(sp,: Unwinding Frames in Python
|
||||
...
|
||||
|
||||
Fix this by adding a space before the left parenthesis.
|
||||
|
||||
Tested by rebuilding the documentation and checking the command and variable
|
||||
index.
|
||||
---
|
||||
gdb/doc/python.texi | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
|
||||
index e49cc580b1b..58904298c71 100644
|
||||
--- a/gdb/doc/python.texi
|
||||
+++ b/gdb/doc/python.texi
|
||||
@@ -3011,7 +3011,7 @@ unwinders can derive, though it is not required that unwinders derive
|
||||
from this class, so long as any user created unwinder has the required
|
||||
@code{name} and @code{enabled} attributes.
|
||||
|
||||
-@defun gdb.unwinder.Unwinder.__init__(name)
|
||||
+@defun gdb.unwinder.Unwinder.__init__ (name)
|
||||
The @var{name} is a string used to reference this unwinder within some
|
||||
@value{GDBN} commands (@pxref{Managing Registered Unwinders}).
|
||||
@end defun
|
||||
@@ -3037,7 +3037,7 @@ most cases this class will be sufficient.
|
||||
|
||||
@code{gdb.unwinder.FrameId} has the following method:
|
||||
|
||||
-@defun gdb.unwinder.FrameId.__init__(sp, pc, special = @code{None})
|
||||
+@defun gdb.unwinder.FrameId.__init__ (sp, pc, special = @code{None})
|
||||
The @var{sp} and @var{pc} arguments are required and should be either
|
||||
a @code{gdb.Value} object, or an integer.
|
||||
|
||||
|
||||
base-commit: fe0e6edbcb65ab5eca50c1a0ad8ddc9844f8ea98
|
||||
--
|
||||
2.43.0
|
||||
|
41
gdb-doc-fix-qisaddresstagged-anchor.patch
Normal file
41
gdb-doc-fix-qisaddresstagged-anchor.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From c23182d85ad9b5b6a45ba74993de55eac00a71bc Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 11:22:12 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix qIsAddressTagged anchor
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/gdb.texinfo:44159: @anchor expected braces.
|
||||
gdb/doc/gdb.texinfo:44159: ` {qIsAddressTagged}
|
||||
...
|
||||
|
||||
This is related to this line:
|
||||
...
|
||||
@anchor {qIsAddressTagged}
|
||||
...
|
||||
|
||||
Fix this by removing the space before the left brace.
|
||||
|
||||
Tested by rebuilding the documentation.
|
||||
---
|
||||
gdb/doc/gdb.texinfo | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
index 6b08838862c..97508863776 100644
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -44156,7 +44156,7 @@ tags found in the requested memory range.
|
||||
@cindex check if a given address is in a memory tagged region
|
||||
@cindex @samp{qIsAddressTagged} packet
|
||||
@item qIsAddressTagged:@var{address}
|
||||
-@anchor {qIsAddressTagged}
|
||||
+@anchor{qIsAddressTagged}
|
||||
Check if address @var{address} is in a memory tagged region; if it is, it's
|
||||
said to be @dfn{tagged}. The target is responsible for checking it, as this
|
||||
is architecture-specific.
|
||||
|
||||
base-commit: 3e2d8d7edd244dd5a82588c3e7145c47c7b539ab
|
||||
--
|
||||
2.43.0
|
||||
|
44
gdb-doc-fix-standard-replies-xref.patch
Normal file
44
gdb-doc-fix-standard-replies-xref.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From 2004e74e0e28ed0b762d98380972b1e6984b9c46 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 28 Jan 2025 08:01:46 +0100
|
||||
Subject: [PATCH] [gdb/doc] Fix "Standard Replies" xref
|
||||
|
||||
When building gdb with an older makeinfo (4.13), I run into:
|
||||
...
|
||||
gdb/doc/gdb.texinfo:42613: warning: `.' or `,' must follow @xref, not `f'.
|
||||
...
|
||||
|
||||
This is related to this line:
|
||||
...
|
||||
@xref{Standard Replies} for standard error responses, and how to
|
||||
respond indicating a command is not supported.
|
||||
...
|
||||
|
||||
Fix this by adding a comma.
|
||||
|
||||
Tested by rebuilding the docs.
|
||||
|
||||
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
|
||||
Co-Authored-By: Eli Zaretskii <eliz@gnu.org>
|
||||
---
|
||||
gdb/doc/gdb.texinfo | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
|
||||
index e5d562c00b4..0bfe6be6126 100644
|
||||
--- a/gdb/doc/gdb.texinfo
|
||||
+++ b/gdb/doc/gdb.texinfo
|
||||
@@ -42610,7 +42610,7 @@ seven repeats (@samp{$}) can be expanded using a repeat count of only
|
||||
five (@samp{"}). For example, @samp{00000000} can be encoded as
|
||||
@samp{0*"00}.
|
||||
|
||||
-@xref{Standard Replies} for standard error responses, and how to
|
||||
+@xref{Standard Replies}, for standard error responses, and how to
|
||||
respond indicating a command is not supported.
|
||||
|
||||
In describing packets (commands and responses), each description has a
|
||||
|
||||
base-commit: 7992b582e5a55bf2fd64f2f94b854d335c36c6a5
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,150 +0,0 @@
|
||||
From b96d3adafdb636898913710ec40ee86647665ae8 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 3 May 2024 09:37:19 +0200
|
||||
Subject: [PATCH 24/48] [gdb/exp] Fix cast handling for indirection
|
||||
|
||||
Consider a test-case compiled without debug info, containing:
|
||||
...
|
||||
char a = 'a';
|
||||
|
||||
char *
|
||||
a_loc (void)
|
||||
{
|
||||
return &a;
|
||||
}
|
||||
...
|
||||
|
||||
We get:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
Cannot access memory at address 0x10
|
||||
...
|
||||
|
||||
There's a bug in unop_ind_base_operation::evaluate that evaluates
|
||||
"(char)*a_loc ()" the same as:
|
||||
...
|
||||
(gdb) p (char)*(char)a_loc ()
|
||||
Cannot access memory at address 0x10
|
||||
...
|
||||
|
||||
Fix this by instead doing:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR exp/31693
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31693
|
||||
---
|
||||
gdb/expop.h | 5 +--
|
||||
gdb/testsuite/gdb.base/cast-indirection.c | 31 ++++++++++++++++
|
||||
gdb/testsuite/gdb.base/cast-indirection.exp | 41 +++++++++++++++++++++
|
||||
3 files changed, 74 insertions(+), 3 deletions(-)
|
||||
create mode 100644 gdb/testsuite/gdb.base/cast-indirection.c
|
||||
create mode 100644 gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
|
||||
diff --git a/gdb/expop.h b/gdb/expop.h
|
||||
index 25769d5b810..25d50fe00d0 100644
|
||||
--- a/gdb/expop.h
|
||||
+++ b/gdb/expop.h
|
||||
@@ -1513,9 +1513,8 @@ class unop_ind_base_operation
|
||||
struct expression *exp,
|
||||
enum noside noside) override
|
||||
{
|
||||
- if (expect_type != nullptr && expect_type->code () == TYPE_CODE_PTR)
|
||||
- expect_type = check_typedef (expect_type)->target_type ();
|
||||
- value *val = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
|
||||
+ value *val
|
||||
+ = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
|
||||
return eval_op_ind (expect_type, exp, noside, val);
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.c b/gdb/testsuite/gdb.base/cast-indirection.c
|
||||
new file mode 100644
|
||||
index 00000000000..d59c66ead35
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.c
|
||||
@@ -0,0 +1,31 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+char a = 'a';
|
||||
+
|
||||
+char *
|
||||
+a_loc (void)
|
||||
+{
|
||||
+ return &a;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ int res = *a_loc () == 'a';
|
||||
+ return !res;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.exp b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
new file mode 100644
|
||||
index 00000000000..f1fe4302d27
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
@@ -0,0 +1,41 @@
|
||||
+# Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Check that "p (char)*a_loc ()" is handled as "p (char)*(char *)a_loc ()".
|
||||
+
|
||||
+standard_testfile
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
|
||||
+ {nodebug}] == -1} {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if ![runto_main] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_test "p a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
+
|
||||
+gdb_test "p *a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
+
|
||||
+gdb_test "p *(char *)a_loc ()" " = 97 'a'"
|
||||
+
|
||||
+gdb_test "p (char)*(char *)a_loc ()" " = 97 'a'"
|
||||
+
|
||||
+# Regression test for PR31693.
|
||||
+gdb_test "p (char)*a_loc ()" \
|
||||
+ "'a_loc' has unknown return type; cast the call to its declared return type"
|
||||
--
|
||||
2.35.3
|
||||
|
232
gdb-exp-fix-gdb.fortran-intrinsics.exp-fail-on-arm.patch
Normal file
232
gdb-exp-fix-gdb.fortran-intrinsics.exp-fail-on-arm.patch
Normal file
@ -0,0 +1,232 @@
|
||||
From 1e295ef5fa3a5a89e9ee08d6e60d971ddb9e6e46 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 31 Jul 2024 13:11:48 +0200
|
||||
Subject: [PATCH 13/46] [gdb/exp] Fix gdb.fortran/intrinsics.exp fail on arm
|
||||
|
||||
When running test-case gdb.fortran/intrinsics.exp on arm-linux, I get:
|
||||
...
|
||||
(gdb) p cmplx (4,4,16)^M
|
||||
/home/linux/gdb/src/gdb/f-lang.c:1002: internal-error: eval_op_f_cmplx: \
|
||||
Assertion `kind_arg->code () == TYPE_CODE_COMPLEX' failed.^M
|
||||
A problem internal to GDB has been detected,^M
|
||||
further debugging may prove unreliable.^M
|
||||
----- Backtrace -----^M
|
||||
FAIL: gdb.fortran/intrinsics.exp: p cmplx (4,4,16) (GDB internal error)
|
||||
...
|
||||
|
||||
The problem is that 16-byte floats are unsupported:
|
||||
...
|
||||
$ gfortran test.f90
|
||||
test.f90:2:17:
|
||||
|
||||
2 | REAL(kind=16) :: foo = 1
|
||||
| 1
|
||||
Error: Kind 16 not supported for type REAL at (1)
|
||||
...
|
||||
and consequently we end up with a builtin_real_s16 and builtin_complex_s16 with
|
||||
code TYPE_CODE_ERROR.
|
||||
|
||||
Fix this by bailing out asap when encountering such a type.
|
||||
|
||||
Without this patch we're able to do the rather useless:
|
||||
...
|
||||
(gdb) ptype real*16
|
||||
type = real*16
|
||||
(gdb) ptype real_16
|
||||
type = real*16
|
||||
...
|
||||
but with this patch we get:
|
||||
...
|
||||
(gdb) ptype real*16
|
||||
unsupported kind 16 for type real*4
|
||||
(gdb) ptype real_16
|
||||
unsupported type real*16
|
||||
...
|
||||
|
||||
Tested on arm-linux.
|
||||
|
||||
PR fortran/30537
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30537
|
||||
---
|
||||
gdb/f-exp.y | 39 +++++++++++++++++-------
|
||||
gdb/testsuite/gdb.fortran/intrinsics.exp | 8 +++--
|
||||
gdb/testsuite/gdb.fortran/type-kinds.exp | 22 ++++++++++---
|
||||
gdb/testsuite/gdb.fortran/types.exp | 19 +++++++++++-
|
||||
4 files changed, 70 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
|
||||
index bdf9c32a81b..259f274d341 100644
|
||||
--- a/gdb/f-exp.y
|
||||
+++ b/gdb/f-exp.y
|
||||
@@ -754,7 +754,11 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
||||
| REAL_S8_KEYWORD
|
||||
{ $$ = parse_f_type (pstate)->builtin_real_s8; }
|
||||
| REAL_S16_KEYWORD
|
||||
- { $$ = parse_f_type (pstate)->builtin_real_s16; }
|
||||
+ { $$ = parse_f_type (pstate)->builtin_real_s16;
|
||||
+ if ($$->code () == TYPE_CODE_ERROR)
|
||||
+ error (_("unsupported type %s"),
|
||||
+ TYPE_SAFE_NAME ($$));
|
||||
+ }
|
||||
| COMPLEX_KEYWORD
|
||||
{ $$ = parse_f_type (pstate)->builtin_complex; }
|
||||
| COMPLEX_S4_KEYWORD
|
||||
@@ -762,7 +766,11 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
||||
| COMPLEX_S8_KEYWORD
|
||||
{ $$ = parse_f_type (pstate)->builtin_complex_s8; }
|
||||
| COMPLEX_S16_KEYWORD
|
||||
- { $$ = parse_f_type (pstate)->builtin_complex_s16; }
|
||||
+ { $$ = parse_f_type (pstate)->builtin_complex_s16;
|
||||
+ if ($$->code () == TYPE_CODE_ERROR)
|
||||
+ error (_("unsupported type %s"),
|
||||
+ TYPE_SAFE_NAME ($$));
|
||||
+ }
|
||||
| SINGLE PRECISION
|
||||
{ $$ = parse_f_type (pstate)->builtin_real;}
|
||||
| DOUBLE PRECISION
|
||||
@@ -1156,12 +1164,9 @@ push_kind_type (LONGEST val, struct type *type)
|
||||
type_stack->push (tp_kind);
|
||||
}
|
||||
|
||||
-/* Called when a type has a '(kind=N)' modifier after it, for example
|
||||
- 'character(kind=1)'. The BASETYPE is the type described by 'character'
|
||||
- in our example, and KIND is the integer '1'. This function returns a
|
||||
- new type that represents the basetype of a specific kind. */
|
||||
+/* Helper function for convert_to_kind_type. */
|
||||
static struct type *
|
||||
-convert_to_kind_type (struct type *basetype, int kind)
|
||||
+convert_to_kind_type_1 (struct type *basetype, int kind)
|
||||
{
|
||||
if (basetype == parse_f_type (pstate)->builtin_character)
|
||||
{
|
||||
@@ -1211,13 +1216,25 @@ convert_to_kind_type (struct type *basetype, int kind)
|
||||
return parse_f_type (pstate)->builtin_integer_s8;
|
||||
}
|
||||
|
||||
- error (_("unsupported kind %d for type %s"),
|
||||
- kind, TYPE_SAFE_NAME (basetype));
|
||||
-
|
||||
- /* Should never get here. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+/* Called when a type has a '(kind=N)' modifier after it, for example
|
||||
+ 'character(kind=1)'. The BASETYPE is the type described by 'character'
|
||||
+ in our example, and KIND is the integer '1'. This function returns a
|
||||
+ new type that represents the basetype of a specific kind. */
|
||||
+static struct type *
|
||||
+convert_to_kind_type (struct type *basetype, int kind)
|
||||
+{
|
||||
+ struct type *res = convert_to_kind_type_1 (basetype, kind);
|
||||
+
|
||||
+ if (res == nullptr || res->code () == TYPE_CODE_ERROR)
|
||||
+ error (_("unsupported kind %d for type %s"),
|
||||
+ kind, TYPE_SAFE_NAME (basetype));
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
struct f_token
|
||||
{
|
||||
/* The string to match against. */
|
||||
diff --git a/gdb/testsuite/gdb.fortran/intrinsics.exp b/gdb/testsuite/gdb.fortran/intrinsics.exp
|
||||
index 60c79f956dc..060bb53db97 100644
|
||||
--- a/gdb/testsuite/gdb.fortran/intrinsics.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/intrinsics.exp
|
||||
@@ -112,10 +112,14 @@ gdb_test "ptype cmplx (4,4)" "= complex\\*4"
|
||||
gdb_test "p cmplx (-14,-4)" "= \\(-14,-4\\)"
|
||||
gdb_test "p cmplx (4,4,4)" "\\(4,4\\)"
|
||||
gdb_test "p cmplx (4,4,8)" "\\(4,4\\)"
|
||||
-gdb_test "p cmplx (4,4,16)" "\\(4,4\\)"
|
||||
+set re_unsupported_kind_16 \
|
||||
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
|
||||
+gdb_test "p cmplx (4,4,16)" \
|
||||
+ ([string_to_regexp " = (4,4)"]|$re_unsupported_kind_16)
|
||||
gdb_test "ptype cmplx (4,4,4)" "= complex\\*4"
|
||||
gdb_test "ptype cmplx (4,4,8)" "= complex\\*8"
|
||||
-gdb_test "ptype cmplx (4,4,16)" "= complex\\*16"
|
||||
+gdb_test "ptype cmplx (4,4,16)" \
|
||||
+ ([string_to_regexp " = complex*16"]|$re_unsupported_kind_16)
|
||||
|
||||
gdb_test "p cmplx (4,4,1)" "unsupported kind 1 for type complex\\*4"
|
||||
gdb_test "p cmplx (4,4,-1)" "unsupported kind -1 for type complex\\*4"
|
||||
diff --git a/gdb/testsuite/gdb.fortran/type-kinds.exp b/gdb/testsuite/gdb.fortran/type-kinds.exp
|
||||
index ab5f19f97a4..a6f2aa4e870 100644
|
||||
--- a/gdb/testsuite/gdb.fortran/type-kinds.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/type-kinds.exp
|
||||
@@ -43,12 +43,20 @@ proc test_basic_parsing_of_type_kinds {} {
|
||||
test_cast_1_to_type_kind "complex" "" "\\(1,0\\)" "8"
|
||||
test_cast_1_to_type_kind "complex" "4" "\\(1,0\\)" "8"
|
||||
test_cast_1_to_type_kind "complex" "8" "\\(1,0\\)" "16"
|
||||
- test_cast_1_to_type_kind "complex" "16" "\\(1,0\\)" "32"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
|
||||
+ test_cast_1_to_type_kind "complex" "16" \
|
||||
+ [string_to_regexp (1,0)]|$re_unsupported_kind \
|
||||
+ 32|$re_unsupported_kind
|
||||
|
||||
test_cast_1_to_type_kind "real" "" "1" "4"
|
||||
test_cast_1_to_type_kind "real" "4" "1" "4"
|
||||
test_cast_1_to_type_kind "real" "8" "1" "8"
|
||||
- test_cast_1_to_type_kind "real" "16" "1" "16"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type real*4"]
|
||||
+ test_cast_1_to_type_kind "real" "16" \
|
||||
+ 1|$re_unsupported_kind \
|
||||
+ 16|$re_unsupported_kind
|
||||
|
||||
test_cast_1_to_type_kind "logical" "" "\\.TRUE\\." "4"
|
||||
test_cast_1_to_type_kind "logical" "1" "\\.TRUE\\." "1"
|
||||
@@ -83,11 +91,17 @@ proc test_old_star_type_sizes {} {
|
||||
|
||||
gdb_test "p ((complex*4) 1)" " = \\(1,0\\)"
|
||||
gdb_test "p ((complex*8) 1)" " = \\(1,0\\)"
|
||||
- gdb_test "p ((complex*16) 1)" " = \\(1,0\\)"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type complex*4"]
|
||||
+ gdb_test "p ((complex*16) 1)" \
|
||||
+ [string_to_regexp " = (1,0)"]|$re_unsupported_kind
|
||||
|
||||
gdb_test "p ((real*4) 1)" " = 1"
|
||||
gdb_test "p ((real*8) 1)" " = 1"
|
||||
- gdb_test "p ((real*16) 1)" " = 1"
|
||||
+ set re_unsupported_kind \
|
||||
+ [string_to_regexp "unsupported kind 16 for type real*4"]
|
||||
+ gdb_test "p ((real*16) 1)" \
|
||||
+ "( = 1|$re_unsupported_kind)"
|
||||
|
||||
gdb_test "p ((logical*1) 1)" " = \\.TRUE\\."
|
||||
gdb_test "p ((logical*4) 1)" " = \\.TRUE\\."
|
||||
diff --git a/gdb/testsuite/gdb.fortran/types.exp b/gdb/testsuite/gdb.fortran/types.exp
|
||||
index 83b109869e6..edbf5abee97 100644
|
||||
--- a/gdb/testsuite/gdb.fortran/types.exp
|
||||
+++ b/gdb/testsuite/gdb.fortran/types.exp
|
||||
@@ -94,7 +94,24 @@ proc test_primitive_types_known {} {
|
||||
# While TYPE_KIND is allowed as input, GDB will always return the
|
||||
# Fortran notation TYPE*KIND
|
||||
regsub -all "_" $type "\*" type_res
|
||||
- gdb_test "ptype $type" [string_to_regexp "type = $type_res"]
|
||||
+ set re [string_to_regexp "type = $type_res"]
|
||||
+ switch $type {
|
||||
+ real*16 - complex*16 {
|
||||
+ regexp {^[^*_]*} $type base
|
||||
+ set re_unsupported \
|
||||
+ [string_to_regexp \
|
||||
+ "unsupported kind 16 for type $base*4"]
|
||||
+ set re ($re|$re_unsupported)
|
||||
+ }
|
||||
+ real_16 - complex_16 {
|
||||
+ set re_unsupported \
|
||||
+ [string_to_regexp \
|
||||
+ "unsupported type $type_res"]
|
||||
+ set re ($re|$re_unsupported)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ gdb_test "ptype $type" $re
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,365 +0,0 @@
|
||||
From 86e379aa22ba5e77ba0c6fa26588c5fd1d9e6abe Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 19 Feb 2024 09:59:15 +0100
|
||||
Subject: [PATCH 13/48] [gdb/exp] Fix printing of out of bounds struct members
|
||||
|
||||
When building gdb with -O0 -fsanitize=address, and running test-case
|
||||
gdb.ada/uninitialized_vars.exp, I run into:
|
||||
...
|
||||
(gdb) info locals
|
||||
a = 0
|
||||
z = (a => 1, b => false, c => 2.0)
|
||||
=================================================================
|
||||
==66372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000097f58 at pc 0xffff52c0da1c bp 0xffffc90a1d40 sp 0xffffc90a1d80
|
||||
READ of size 4 at 0x602000097f58 thread T0
|
||||
#0 0xffff52c0da18 in memmove (/lib64/libasan.so.8+0x6da18)
|
||||
#1 0xbcab24 in unsigned char* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<unsigned char const, unsigned char>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:748
|
||||
#2 0xbc9bf4 in unsigned char* std::__copy_move_backward_a2<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:769
|
||||
#3 0xbc898c in unsigned char* std::__copy_move_backward_a1<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:778
|
||||
#4 0xbc715c in unsigned char* std::__copy_move_backward_a<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:807
|
||||
#5 0xbc4e6c in unsigned char* std::copy_backward<unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:867
|
||||
#6 0xbc2934 in void gdb::copy<unsigned char const, unsigned char>(gdb::array_view<unsigned char const>, gdb::array_view<unsigned char>) gdb/../gdbsupport/array-view.h:223
|
||||
#7 0x20e0100 in value::contents_copy_raw(value*, long, long, long) gdb/value.c:1239
|
||||
#8 0x20e9830 in value::primitive_field(long, int, type*) gdb/value.c:3078
|
||||
#9 0x20e98f8 in value_field(value*, int) gdb/value.c:3095
|
||||
#10 0xcafd64 in print_field_values gdb/ada-valprint.c:658
|
||||
#11 0xcb0fa0 in ada_val_print_struct_union gdb/ada-valprint.c:857
|
||||
#12 0xcb1bb4 in ada_value_print_inner(value*, ui_file*, int, value_print_options const*) gdb/ada-valprint.c:1042
|
||||
#13 0xc66e04 in ada_language::value_print_inner(value*, ui_file*, int, value_print_options const*) const (/home/vries/gdb/build/gdb/gdb+0xc66e04)
|
||||
#14 0x20ca1e8 in common_val_print(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1092
|
||||
#15 0x20caabc in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1184
|
||||
#16 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
|
||||
#17 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
|
||||
#18 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
|
||||
#19 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
|
||||
#20 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
|
||||
#21 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
|
||||
#22 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
|
||||
#23 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
|
||||
#24 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
|
||||
#25 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
|
||||
#26 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
|
||||
#27 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
|
||||
#28 0x1384080 in command_handler(char const*) gdb/event-top.c:566
|
||||
#29 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
|
||||
#30 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
|
||||
#31 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
|
||||
#32 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
|
||||
#33 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
|
||||
#34 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
|
||||
#35 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
|
||||
#36 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
|
||||
#37 0x35ff9d8 in gdb_wait_for_event gdbsupport/event-loop.cc:694
|
||||
#38 0x35fd284 in gdb_do_one_event(int) gdbsupport/event-loop.cc:264
|
||||
#39 0x1768080 in start_event_loop gdb/main.c:408
|
||||
#40 0x17684c4 in captured_command_loop gdb/main.c:472
|
||||
#41 0x176cfc8 in captured_main gdb/main.c:1342
|
||||
#42 0x176d088 in gdb_main(captured_main_args*) gdb/main.c:1361
|
||||
#43 0xb73edc in main gdb/gdb.c:39
|
||||
#44 0xffff519b09d8 in __libc_start_call_main (/lib64/libc.so.6+0x309d8)
|
||||
#45 0xffff519b0aac in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x30aac)
|
||||
#46 0xb73c2c in _start (/home/vries/gdb/build/gdb/gdb+0xb73c2c)
|
||||
|
||||
0x602000097f58 is located 0 bytes after 8-byte region [0x602000097f50,0x602000097f58)
|
||||
allocated by thread T0 here:
|
||||
#0 0xffff52c65218 in calloc (/lib64/libasan.so.8+0xc5218)
|
||||
#1 0xcbc278 in xcalloc gdb/alloc.c:97
|
||||
#2 0x35f21e8 in xzalloc(unsigned long) gdbsupport/common-utils.cc:29
|
||||
#3 0x20de270 in value::allocate_contents(bool) gdb/value.c:937
|
||||
#4 0x20edc08 in value::fetch_lazy() gdb/value.c:4033
|
||||
#5 0x20dadc0 in value::entirely_covered_by_range_vector(std::vector<range, std::allocator<range> > const&) gdb/value.c:229
|
||||
#6 0xcb2298 in value::entirely_optimized_out() gdb/value.h:560
|
||||
#7 0x20ca6fc in value_check_printable gdb/valprint.c:1133
|
||||
#8 0x20caa8c in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1182
|
||||
#9 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
|
||||
#10 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
|
||||
#11 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
|
||||
#12 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
|
||||
#13 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
|
||||
#14 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
|
||||
#15 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
|
||||
#16 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
|
||||
#17 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
|
||||
#18 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
|
||||
#19 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
|
||||
#20 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
|
||||
#21 0x1384080 in command_handler(char const*) gdb/event-top.c:566
|
||||
#22 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
|
||||
#23 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
|
||||
#24 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
|
||||
#25 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
|
||||
#26 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
|
||||
#27 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
|
||||
#28 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
|
||||
#29 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
|
||||
|
||||
SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib64/libasan.so.8+0x6da18) in memmove
|
||||
...
|
||||
|
||||
The error happens when trying to print either variable y or y2:
|
||||
...
|
||||
type Variable_Record (A : Boolean := True) is record
|
||||
case A is
|
||||
when True =>
|
||||
B : Integer;
|
||||
when False =>
|
||||
C : Float;
|
||||
D : Integer;
|
||||
end case;
|
||||
end record;
|
||||
Y : Variable_Record := (A => True, B => 1);
|
||||
Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
|
||||
...
|
||||
when the variables are uninitialized.
|
||||
|
||||
The error happens only when printing the entire variable:
|
||||
...
|
||||
(gdb) p y.a
|
||||
$2 = 216
|
||||
(gdb) p y.b
|
||||
There is no member named b.
|
||||
(gdb) p y.c
|
||||
$3 = 9.18340949e-41
|
||||
(gdb) p y.d
|
||||
$4 = 1
|
||||
(gdb) p y
|
||||
<AddressSanitizer: heap-buffer-overflow>
|
||||
...
|
||||
|
||||
The error happens as follows:
|
||||
- field a functions as discriminant, choosing either the b, or c+d variant.
|
||||
- when y.a happens to be set to 216, as above, gdb interprets this as the
|
||||
variable having the c+d variant (which is why trying to print y.b fails).
|
||||
- when printing y, gdb allocates a value, copies the bytes into it from the
|
||||
target, and then prints the value.
|
||||
- gdb allocates the value using the type size, which is 8. It's 8 because
|
||||
that's what the DW_AT_byte_size indicates. Note that for valid values of a,
|
||||
it gives correct results: if a is 0 (c+d variant), size is 12, if a is 1
|
||||
(b variant), size is 8.
|
||||
- gdb tries to print field d, which is at an 8 byte offset, and that results
|
||||
in a out-of-bounds access for the allocated 8-byte value.
|
||||
|
||||
Fix this by handling this case in value::contents_copy_raw, such that we have:
|
||||
...
|
||||
(gdb) p y
|
||||
$1 = (a => 24, c => 9.18340949e-41,
|
||||
d => <error reading variable: access outside bounds of object>)
|
||||
...
|
||||
|
||||
An alternative (additional) fix could be this: in compute_variant_fields_inner
|
||||
gdb reads the discriminant y.a to decide which variant is active. It would be
|
||||
nice to detect that the value (y.a == 24) is not a valid Boolean, and give up
|
||||
on choosing a variant altoghether. However, the situation regarding the
|
||||
internal type CODE_TYPE_BOOL is currently ambiguous (see PR31282) and it's not
|
||||
possible to reliably decide what valid values are.
|
||||
|
||||
The test-case source file gdb.ada/uninitialized-variable-record/parse.adb is
|
||||
a reduced version of gdb.ada/uninitialized_vars/parse.adb, so it copies the
|
||||
copyright years.
|
||||
|
||||
Note that the test-case needs gcc-12 or newer, it's unsupported for older gcc
|
||||
versions. [ So, it would be nice to rewrite it into a dwarf assembly
|
||||
test-case. ]
|
||||
|
||||
The test-case loops over all languages. This is inherited from an earlier
|
||||
attempt to fix this, which had language-specific fixes (in print_field_values,
|
||||
cp_print_value_fields, pascal_object_print_value_fields and
|
||||
f_language::value_print_inner). I've left this in, but I suppose it's not
|
||||
strictly necessary anymore.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR exp/31258
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31258
|
||||
---
|
||||
.../gdb.ada/uninitialized-variable-record.exp | 122 ++++++++++++++++++
|
||||
.../uninitialized-variable-record/parse.adb | 33 +++++
|
||||
gdb/value.c | 3 +
|
||||
3 files changed, 158 insertions(+)
|
||||
create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
new file mode 100644
|
||||
index 00000000000..7fc72395edf
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
|
||||
@@ -0,0 +1,122 @@
|
||||
+# Copyright 2024 Free Software Foundation, Inc.
|
||||
+#
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+load_lib "ada.exp"
|
||||
+
|
||||
+require allow_ada_tests
|
||||
+
|
||||
+standard_ada_testfile parse
|
||||
+
|
||||
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+clean_restart ${testfile}
|
||||
+
|
||||
+set bp_location [gdb_get_line_number "START" ${testdir}/parse.adb]
|
||||
+runto "parse.adb:$bp_location"
|
||||
+
|
||||
+# Check that we have the expected value for variable y2.
|
||||
+
|
||||
+gdb_test "p y2" [string_to_regexp " = (a => false, c => 1.0, d => 2)"]
|
||||
+
|
||||
+# Shorthand.
|
||||
+
|
||||
+proc set_lang { lang } {
|
||||
+ gdb_test_multiple "set language $lang" "" {
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Calculate the offset of y2.d.
|
||||
+
|
||||
+set re_cast [string_to_regexp "(access integer)"]
|
||||
+gdb_test_multiple "print &y2.d - &y2" "" {
|
||||
+ -re -wrap " = $re_cast ($hex)" {
|
||||
+ set offset_d $expect_out(1,string)
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# Try to find a interesting discriminator value, such that at the same time:
|
||||
+# - the d field is part of the variable, and
|
||||
+# - the type size is too small to contain d.
|
||||
+
|
||||
+set interesting_discriminator -1
|
||||
+set_lang c
|
||||
+for { set i 0 } { $i < 256 } { incr i } {
|
||||
+ with_test_prefix $i {
|
||||
+
|
||||
+ # Patch in the discriminator value.
|
||||
+ gdb_test_multiple "set var *(unsigned char *)(&y2.a)=$i" "" {
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ # Check that we have the variant with fields c+d instead of b.
|
||||
+ set have_b 0
|
||||
+ gdb_test_multiple "with language ada -- print y2.b" "" {
|
||||
+ -re -wrap " = $decimal" {
|
||||
+ set have_b 1
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ }
|
||||
+ }
|
||||
+ if { $have_b } {
|
||||
+ # This is the variant with field b.
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ set size 0
|
||||
+ gdb_test_multiple "print sizeof (y2)" "" {
|
||||
+ -re -wrap " = (.*)" {
|
||||
+ set size $expect_out(1,string)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if { ! $size } {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ if { [expr $size > $offset_d] } {
|
||||
+ # Field d fits in the size.
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ set interesting_discriminator $i
|
||||
+ break
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+require {expr $interesting_discriminator != -1}
|
||||
+
|
||||
+foreach lang [gdb_supported_languages] {
|
||||
+ with_test_prefix $lang {
|
||||
+ set_lang $lang
|
||||
+
|
||||
+ gdb_test_multiple "print y2" "" {
|
||||
+ -re -wrap ", d => $decimal.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap ", d = $decimal.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
new file mode 100644
|
||||
index 00000000000..f00c75ca2dc
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
|
||||
@@ -0,0 +1,33 @@
|
||||
+-- Copyright 2009-2024 Free Software Foundation, Inc.
|
||||
+--
|
||||
+-- 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+-- Based on gdb.ada/uninitialized_vars/parse.adb.
|
||||
+
|
||||
+procedure Parse is
|
||||
+
|
||||
+ type Variable_Record (A : Boolean := True) is record
|
||||
+ case A is
|
||||
+ when True =>
|
||||
+ B : Integer;
|
||||
+ when False =>
|
||||
+ C : Float;
|
||||
+ D : Integer;
|
||||
+ end case;
|
||||
+ end record;
|
||||
+ Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
|
||||
+
|
||||
+begin
|
||||
+ null; -- START
|
||||
+end Parse;
|
||||
diff --git a/gdb/value.c b/gdb/value.c
|
||||
index 1cc32625629..56ae9db6603 100644
|
||||
--- a/gdb/value.c
|
||||
+++ b/gdb/value.c
|
||||
@@ -1188,6 +1188,9 @@ value::contents_copy_raw (struct value *dst, LONGEST dst_offset,
|
||||
gdb_assert (!dst->bits_any_optimized_out (TARGET_CHAR_BIT * dst_offset,
|
||||
TARGET_CHAR_BIT * length));
|
||||
|
||||
+ if ((src_offset + copy_length) * unit_size > enclosing_type ()-> length ())
|
||||
+ error (_("access outside bounds of object"));
|
||||
+
|
||||
/* Copy the data. */
|
||||
gdb::array_view<gdb_byte> dst_contents
|
||||
= dst->contents_all_raw ().slice (dst_offset * unit_size,
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,86 +0,0 @@
|
||||
From a6800d9c8145f25001dd39afc3571e3350573e81 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 6 May 2024 14:23:25 +0200
|
||||
Subject: [PATCH] [gdb/exp] Redo cast handling for indirection
|
||||
|
||||
In commit ed8fd0a342f ("[gdb/exp] Fix cast handling for indirection"), I
|
||||
introduced the behaviour that even though we have:
|
||||
...
|
||||
(gdb) p *a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
we get:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
$1 = 97 'a'
|
||||
...
|
||||
|
||||
In other words, the unknown return type of a_loc is inferred from the cast,
|
||||
effectually evaluating:
|
||||
...
|
||||
(gdb) p (char)*(char *)a_loc ()
|
||||
...
|
||||
|
||||
This is convient for the case that errno is defined as:
|
||||
...
|
||||
#define errno (*__errno_location ())
|
||||
...
|
||||
and the return type of __errno_location is unknown but the macro definition is
|
||||
known, such that we can use:
|
||||
...
|
||||
(gdb) p (int)errno
|
||||
...
|
||||
instead of
|
||||
...
|
||||
(gdb) p *(int *)__errno_location ()
|
||||
...
|
||||
|
||||
However, as Pedro has pointed out in post-commit review [1], this makes it
|
||||
harder to reason about the semantics of an expression.
|
||||
|
||||
For instance, this:
|
||||
...
|
||||
(gdb) p (long long)*a_loc ()"
|
||||
...
|
||||
would be evaluated without debug info as:
|
||||
...
|
||||
(gdb) p (long long)*(long long *)a_loc ()"
|
||||
...
|
||||
but with debug info as:
|
||||
...
|
||||
(gdb) p (long long)*(char *)a_loc ()"
|
||||
...
|
||||
|
||||
Fix this by instead simply erroring out for this case:
|
||||
...
|
||||
(gdb) p (char)*a_loc ()
|
||||
'a_loc' has unknown return type; cast the call to its declared return type
|
||||
...
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Pedro Alves <pedro@palves.net>
|
||||
|
||||
[1] https://sourceware.org/pipermail/gdb-patches/2024-May/208821.html
|
||||
---
|
||||
gdb/testsuite/gdb.base/cast-indirection.exp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/cast-indirection.exp b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
index f1fe4302d27..7b9b5a5d677 100644
|
||||
--- a/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
+++ b/gdb/testsuite/gdb.base/cast-indirection.exp
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-# Check that "p (char)*a_loc ()" is handled as "p (char)*(char *)a_loc ()".
|
||||
+# Check that "p (char)*a_loc ()" is handled correctly.
|
||||
|
||||
standard_testfile
|
||||
|
||||
|
||||
base-commit: fc73000faa1798573090994167b7e2d451c211db
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,333 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-fedora-libncursesw.patch
|
||||
|
||||
;; Force libncursesw over libncurses to match the includes (RH BZ 1270534).
|
||||
;;=push+jan
|
||||
|
||||
Fedora: Force libncursesw over libncurses to match the includes.
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1270534
|
||||
|
||||
diff --git a/gdb/configure b/gdb/configure
|
||||
--- a/gdb/configure
|
||||
+++ b/gdb/configure
|
||||
@@ -780,9 +780,6 @@ ENABLE_BFD_64_BIT_TRUE
|
||||
subdirs
|
||||
RPM_LIBS
|
||||
RPM_CFLAGS
|
||||
-PKG_CONFIG_LIBDIR
|
||||
-PKG_CONFIG_PATH
|
||||
-PKG_CONFIG
|
||||
GDB_DATADIR
|
||||
DEBUGDIR
|
||||
MAKEINFO_EXTRA_FLAGS
|
||||
@@ -990,12 +987,12 @@ PKG_CONFIG_PATH
|
||||
PKG_CONFIG_LIBDIR
|
||||
MAKEINFO
|
||||
MAKEINFOFLAGS
|
||||
+RPM_CFLAGS
|
||||
+RPM_LIBS
|
||||
AMD_DBGAPI_CFLAGS
|
||||
AMD_DBGAPI_LIBS
|
||||
DEBUGINFOD_CFLAGS
|
||||
DEBUGINFOD_LIBS
|
||||
-RPM_CFLAGS
|
||||
-RPM_LIBS
|
||||
YACC
|
||||
YFLAGS
|
||||
ZSTD_CFLAGS
|
||||
@@ -1684,11 +1681,11 @@ Optional Packages:
|
||||
[--with-auto-load-dir]
|
||||
--without-auto-load-safe-path
|
||||
do not restrict auto-loaded files locations
|
||||
+ --with-rpm query rpm database for missing debuginfos (yes/no,
|
||||
+ def. auto=librpm.so)
|
||||
--with-amd-dbgapi support for the amd-dbgapi target (yes / no / auto)
|
||||
--with-debuginfod Enable debuginfo lookups with debuginfod
|
||||
(auto/yes/no)
|
||||
- --with-rpm query rpm database for missing debuginfos (yes/no,
|
||||
- def. auto=librpm.so)
|
||||
--with-libunwind-ia64 use libunwind frame unwinding for ia64 targets
|
||||
--with-curses use the curses library instead of the termcap
|
||||
library
|
||||
@@ -1761,6 +1758,8 @@ Some influential environment variables:
|
||||
MAKEINFO Parent configure detects if it is of sufficient version.
|
||||
MAKEINFOFLAGS
|
||||
Parameters for MAKEINFO.
|
||||
+ RPM_CFLAGS C compiler flags for RPM, overriding pkg-config
|
||||
+ RPM_LIBS linker flags for RPM, overriding pkg-config
|
||||
AMD_DBGAPI_CFLAGS
|
||||
C compiler flags for AMD_DBGAPI, overriding pkg-config
|
||||
AMD_DBGAPI_LIBS
|
||||
@@ -1769,8 +1768,6 @@ Some influential environment variables:
|
||||
C compiler flags for DEBUGINFOD, overriding pkg-config
|
||||
DEBUGINFOD_LIBS
|
||||
linker flags for DEBUGINFOD, overriding pkg-config
|
||||
- RPM_CFLAGS C compiler flags for RPM, overriding pkg-config
|
||||
- RPM_LIBS linker flags for RPM, overriding pkg-config
|
||||
YACC The `Yet Another Compiler Compiler' implementation to use.
|
||||
Defaults to the first program found out of: `bison -y', `byacc',
|
||||
`yacc'.
|
||||
@@ -11495,7 +11492,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
-#line 11486 "configure"
|
||||
+#line 11495 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11601,7 +11598,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
-#line 11592 "configure"
|
||||
+#line 11601 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -18102,8 +18099,8 @@ $as_echo_n "checking specific librpm version... " >&6; }
|
||||
if test "$cross_compiling" = yes; then :
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
-as_fn_error "cannot run test program while cross compiling
|
||||
-See \`config.log' for more details." "$LINENO" 5; }
|
||||
+as_fn_error $? "cannot run test program while cross compiling
|
||||
+See \`config.log' for more details" "$LINENO" 5; }
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
@@ -18275,132 +18272,12 @@ $as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
|
||||
$as_echo "no" >&6; }
|
||||
LIBS="$save_LIBS"
|
||||
if $DLOPEN_REQUIRE; then
|
||||
- as_fn_error "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5
|
||||
+ as_fn_error $? "Specific name $LIBRPM was requested but it could not be opened." "$LINENO" 5
|
||||
fi
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
- if test -n "$ac_tool_prefix"; then
|
||||
- # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
|
||||
-set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if test "${ac_cv_path_PKG_CONFIG+set}" = set; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $PKG_CONFIG in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
- ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-PKG_CONFIG=$ac_cv_path_PKG_CONFIG
|
||||
-if test -n "$PKG_CONFIG"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
|
||||
-$as_echo "$PKG_CONFIG" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
-
|
||||
-fi
|
||||
-if test -z "$ac_cv_path_PKG_CONFIG"; then
|
||||
- ac_pt_PKG_CONFIG=$PKG_CONFIG
|
||||
- # Extract the first word of "pkg-config", so it can be a program name with args.
|
||||
-set dummy pkg-config; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $ac_pt_PKG_CONFIG in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
- ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
|
||||
-if test -n "$ac_pt_PKG_CONFIG"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
|
||||
-$as_echo "$ac_pt_PKG_CONFIG" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
- if test "x$ac_pt_PKG_CONFIG" = x; then
|
||||
- PKG_CONFIG=""
|
||||
- else
|
||||
- case $cross_compiling:$ac_tool_warned in
|
||||
-yes:)
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
-ac_tool_warned=yes ;;
|
||||
-esac
|
||||
- PKG_CONFIG=$ac_pt_PKG_CONFIG
|
||||
- fi
|
||||
-else
|
||||
- PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
|
||||
-fi
|
||||
-
|
||||
-fi
|
||||
-if test -n "$PKG_CONFIG"; then
|
||||
- _pkg_min_version=0.9.0
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
|
||||
-$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
|
||||
- if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
-$as_echo "yes" >&6; }
|
||||
- else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
- PKG_CONFIG=""
|
||||
- fi
|
||||
-fi
|
||||
-
|
||||
pkg_failed=no
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RPM" >&5
|
||||
-$as_echo_n "checking for RPM... " >&6; }
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rpm" >&5
|
||||
+$as_echo_n "checking for rpm... " >&6; }
|
||||
|
||||
if test -n "$RPM_CFLAGS"; then
|
||||
pkg_cv_RPM_CFLAGS="$RPM_CFLAGS"
|
||||
@@ -18437,6 +18314,30 @@ fi
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
+if test $pkg_failed = no; then
|
||||
+ pkg_save_LDFLAGS="$LDFLAGS"
|
||||
+ LDFLAGS="$LDFLAGS $pkg_cv_RPM_LIBS"
|
||||
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+
|
||||
+else
|
||||
+ pkg_failed=yes
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+ LDFLAGS=$pkg_save_LDFLAGS
|
||||
+fi
|
||||
+
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
@@ -18531,7 +18432,7 @@ $as_echo "#define HAVE_LIBRPM 1" >>confdefs.h
|
||||
LIBS="$LIBS $RPM_LIBS"
|
||||
else
|
||||
if $RPM_REQUIRE; then
|
||||
- as_fn_error "$RPM_PKG_ERRORS" "$LINENO" 5
|
||||
+ as_fn_error $? "$RPM_PKG_ERRORS" "$LINENO" 5
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $RPM_PKG_ERRORS" >&5
|
||||
$as_echo "$as_me: WARNING: $RPM_PKG_ERRORS" >&2;}
|
||||
@@ -21164,6 +21065,7 @@ if test x"$prefer_curses" = xyes; then
|
||||
# search /usr/local/include, if ncurses is installed in /usr/local. A
|
||||
# default installation of ncurses on alpha*-dec-osf* will lead to such
|
||||
# a situation.
|
||||
+ # Fedora: Force libncursesw over libncurses to match the includes.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing waddstr" >&5
|
||||
$as_echo_n "checking for library containing waddstr... " >&6; }
|
||||
if ${ac_cv_search_waddstr+:} false; then :
|
||||
@@ -21188,7 +21090,7 @@ return waddstr ();
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
-for ac_lib in '' ncursesw ncurses cursesX curses; do
|
||||
+for ac_lib in '' ncursesw; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
@@ -21260,6 +21162,7 @@ case $host_os in
|
||||
esac
|
||||
|
||||
# These are the libraries checked by Readline.
|
||||
+# Fedora: Force libncursesw over libncurses to match the includes.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5
|
||||
$as_echo_n "checking for library containing tgetent... " >&6; }
|
||||
if ${ac_cv_search_tgetent+:} false; then :
|
||||
@@ -21284,7 +21187,7 @@ return tgetent ();
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
-for ac_lib in '' termcap tinfow tinfo curses ncursesw ncurses; do
|
||||
+for ac_lib in '' ncursesw; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
diff --git a/gdb/configure.ac b/gdb/configure.ac
|
||||
--- a/gdb/configure.ac
|
||||
+++ b/gdb/configure.ac
|
||||
@@ -749,7 +749,8 @@ if test x"$prefer_curses" = xyes; then
|
||||
# search /usr/local/include, if ncurses is installed in /usr/local. A
|
||||
# default installation of ncurses on alpha*-dec-osf* will lead to such
|
||||
# a situation.
|
||||
- AC_SEARCH_LIBS(waddstr, [ncursesw ncurses cursesX curses],
|
||||
+ # Fedora: Force libncursesw over libncurses to match the includes.
|
||||
+ AC_SEARCH_LIBS(waddstr, [ncursesw],
|
||||
[curses_found=yes
|
||||
AC_DEFINE([HAVE_LIBCURSES], [1],
|
||||
[Define to 1 if curses is enabled.])
|
||||
@@ -789,7 +790,8 @@ case $host_os in
|
||||
esac
|
||||
|
||||
# These are the libraries checked by Readline.
|
||||
-AC_SEARCH_LIBS(tgetent, [termcap tinfow tinfo curses ncursesw ncurses])
|
||||
+# Fedora: Force libncursesw over libncurses to match the includes.
|
||||
+AC_SEARCH_LIBS(tgetent, [ncursesw])
|
||||
|
||||
if test "$ac_cv_search_tgetent" = no; then
|
||||
CONFIG_OBS="$CONFIG_OBS stub-termcap.o"
|
@ -1,144 +0,0 @@
|
||||
From 350172ea215c7074601e8424ff636563612f91e8 Mon Sep 17 00:00:00 2001
|
||||
From: Pedro Alves <pedro@palves.net>
|
||||
Date: Wed, 21 Feb 2024 16:23:55 +0000
|
||||
Subject: [PATCH 14/48] [gdb] Fix heap-use-after-free in select_event_lwp
|
||||
|
||||
PR gdb/31259 reveals one scenario where we run into a
|
||||
heap-use-after-free reported by thread sanitizer, while running
|
||||
gdb.base/vfork-follow-parent.exp.
|
||||
|
||||
The heap-use-after-free happens during the following scenario:
|
||||
|
||||
- linux_nat_wait_1 is about to return an event for T2. It stops all
|
||||
other threads, and while doing so, stop_wait_callback -> wait_lwp
|
||||
sees T1 exit, and decides to leave the exit event pending. It
|
||||
should have set the lp->stopped flag too, but does not -- this is
|
||||
the bug.
|
||||
|
||||
- The event for T2 is reported, is processed by infrun, and we're
|
||||
back at linux_nat_wait_1.
|
||||
|
||||
- linux_nat_wait_1 selects LWP T1 with the pending exit status to
|
||||
report.
|
||||
|
||||
- it sets variable lp to point to the corresponding lwp_info.
|
||||
|
||||
- it calls stop_callback and stop_wait_callback for all threads
|
||||
(because !target_is_non_stop_p ()).
|
||||
|
||||
- it calls select_event_lwp to maybe pick another thread than T1, to
|
||||
prevent starvation.
|
||||
|
||||
The problem is the following:
|
||||
|
||||
- while calling stop_wait_callback for all threads, it also does this
|
||||
for T1. While doing so, the corresponding lwp_info is deleted
|
||||
(callstack stop_wait_callback -> wait_lwp -> exit_lwp ->
|
||||
delete_lwp), leaving variable lp as a dangling pointer.
|
||||
|
||||
- variable lp is passed to select_event_lwp, which derefences it,
|
||||
which causes the heap-use-after-free.
|
||||
|
||||
Note that the comment here mentions "all other LWP's":
|
||||
...
|
||||
/* Now stop all other LWP's ... */
|
||||
iterate_over_lwps (minus_one_ptid, stop_callback);
|
||||
/* ... and wait until all of them have reported back that
|
||||
they're no longer running. */
|
||||
iterate_over_lwps (minus_one_ptid, stop_wait_callback);
|
||||
...
|
||||
|
||||
The reason the comments say "all other LWP's", and doesn't bother
|
||||
filtering out LP is that lp->stopped should be true at this point, and
|
||||
the callbacks (both stop_callback and stop_wait_callback) check that
|
||||
flag, and do nothing if set. I.e., they skip already-stopped threads,
|
||||
so they should skip LP.
|
||||
|
||||
In this particular scenario, though, we missed setting the stopped
|
||||
flag right in the first step described above, so LP was iterated over
|
||||
incorrectly.
|
||||
|
||||
The fix is to make wait_lwp set the lp->stopped flag when it decides
|
||||
to leave the exit event pending. However, going a bit further,
|
||||
gdbserver has a mark_lwp_dead function to centralize setting up
|
||||
various lwp flags such that the rest of the code doesn't mishandle
|
||||
them, and it seems like a good idea to do a similar thing in gdb as
|
||||
well. That is what this patch does.
|
||||
|
||||
PR gdb/31259
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31259
|
||||
Co-Authored-By: Tom de Vries <tdevries@suse.de>
|
||||
Change-Id: I4a6169976f89bf714c478cbb2b7d4c32365e62a9
|
||||
---
|
||||
gdb/linux-nat.c | 34 +++++++++++++++++++++++++---------
|
||||
1 file changed, 25 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
||||
index 7e36ced6292..ed445c5e5bb 100644
|
||||
--- a/gdb/linux-nat.c
|
||||
+++ b/gdb/linux-nat.c
|
||||
@@ -2029,6 +2029,27 @@ wait_for_signal ()
|
||||
}
|
||||
}
|
||||
|
||||
+/* Mark LWP dead, with STATUS as exit status pending to report
|
||||
+ later. */
|
||||
+
|
||||
+static void
|
||||
+mark_lwp_dead (lwp_info *lp, int status)
|
||||
+{
|
||||
+ /* Store the exit status lp->waitstatus, because lp->status would be
|
||||
+ ambiguous (W_EXITCODE(0,0) == 0). */
|
||||
+ lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+
|
||||
+ /* If we're processing LP's status, there should be no other event
|
||||
+ already recorded as pending. */
|
||||
+ gdb_assert (lp->status == 0);
|
||||
+
|
||||
+ /* Dead LWPs aren't expected to report a pending sigstop. */
|
||||
+ lp->signalled = 0;
|
||||
+
|
||||
+ /* Prevent trying to stop it. */
|
||||
+ lp->stopped = 1;
|
||||
+}
|
||||
+
|
||||
/* Wait for LP to stop. Returns the wait status, or 0 if the LWP has
|
||||
exited. */
|
||||
|
||||
@@ -2114,9 +2135,8 @@ wait_lwp (struct lwp_info *lp)
|
||||
|
||||
/* If this is the leader exiting, it means the whole
|
||||
process is gone. Store the status to report to the
|
||||
- core. Store it in lp->waitstatus, because lp->status
|
||||
- would be ambiguous (W_EXITCODE(0,0) == 0). */
|
||||
- lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+ core. */
|
||||
+ mark_lwp_dead (lp, status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2908,12 +2928,7 @@ linux_nat_filter_event (int lwpid, int status)
|
||||
linux_nat_debug_printf ("LWP %ld exited (resumed=%d)",
|
||||
lp->ptid.lwp (), lp->resumed);
|
||||
|
||||
- /* Dead LWP's aren't expected to reported a pending sigstop. */
|
||||
- lp->signalled = 0;
|
||||
-
|
||||
- /* Store the pending event in the waitstatus, because
|
||||
- W_EXITCODE(0,0) == 0. */
|
||||
- lp->waitstatus = host_status_to_waitstatus (status);
|
||||
+ mark_lwp_dead (lp, status);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3248,6 +3263,7 @@ linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
}
|
||||
|
||||
gdb_assert (lp);
|
||||
+ gdb_assert (lp->stopped);
|
||||
|
||||
status = lp->status;
|
||||
lp->status = 0;
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,636 +0,0 @@
|
||||
From 1d02ba0f4adcba2595a67e88fb1ba6d35c7f8e5b Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 7 May 2024 11:33:57 +0200
|
||||
Subject: [PATCH] [gdb] Fix segfault in for_each_block, part 1
|
||||
|
||||
When running test-case gdb.base/vfork-follow-parent.exp on powerpc64 (likewise
|
||||
on s390x), I run into:
|
||||
...
|
||||
(gdb) PASS: gdb.base/vfork-follow-parent.exp: \
|
||||
exec_file=vfork-follow-parent-exit: target-non-stop=on: non-stop=off: \
|
||||
resolution_method=schedule-multiple: print unblock_parent = 1
|
||||
continue^M
|
||||
Continuing.^M
|
||||
Reading symbols from vfork-follow-parent-exit...^M
|
||||
^M
|
||||
^M
|
||||
Fatal signal: Segmentation fault^M
|
||||
----- Backtrace -----^M
|
||||
0x1027d3e7 gdb_internal_backtrace_1^M
|
||||
src/gdb/bt-utils.c:122^M
|
||||
0x1027d54f _Z22gdb_internal_backtracev^M
|
||||
src/gdb/bt-utils.c:168^M
|
||||
0x1057643f handle_fatal_signal^M
|
||||
src/gdb/event-top.c:889^M
|
||||
0x10576677 handle_sigsegv^M
|
||||
src/gdb/event-top.c:962^M
|
||||
0x3fffa7610477 ???^M
|
||||
0x103f2144 for_each_block^M
|
||||
src/gdb/dcache.c:199^M
|
||||
0x103f235b _Z17dcache_invalidateP13dcache_struct^M
|
||||
src/gdb/dcache.c:251^M
|
||||
0x10bde8c7 _Z24target_dcache_invalidatev^M
|
||||
src/gdb/target-dcache.c:50^M
|
||||
...
|
||||
or similar.
|
||||
|
||||
The root cause for the segmentation fault is that linux_is_uclinux gives an
|
||||
incorrect result: it should always return false, given that we're running on a
|
||||
regular linux system, but instead it returns first true, then false.
|
||||
|
||||
In more detail, the segmentation fault happens as follows:
|
||||
- a program space with an address space is created
|
||||
- a second program space is about to be created. maybe_new_address_space
|
||||
is called, and because linux_is_uclinux returns true, maybe_new_address_space
|
||||
returns false, and no new address space is created
|
||||
- a second program space with the same address space is created
|
||||
- a program space is deleted. Because linux_is_uclinux now returns false,
|
||||
gdbarch_has_shared_address_space (current_inferior ()->arch ()) returns
|
||||
false, and the address space is deleted
|
||||
- when gdb uses the address space of the remaining program space, we run into
|
||||
the segfault, because the address space is deleted.
|
||||
|
||||
Hardcoding linux_is_uclinux to false makes the test-case pass.
|
||||
|
||||
We leave addressing the root cause for the following commit in this series.
|
||||
|
||||
For now, prevent the segmentation fault by making the address space a refcounted
|
||||
object.
|
||||
|
||||
This was already suggested here [1]:
|
||||
...
|
||||
A better solution might be to have the address spaces be reference counted
|
||||
...
|
||||
|
||||
Tested on top of trunk on x86_64-linux and ppc64le-linux.
|
||||
Tested on top of gdb-14-branch on ppc64-linux.
|
||||
|
||||
Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
PR gdb/30547
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547
|
||||
|
||||
[1] https://sourceware.org/pipermail/gdb-patches/2023-October/202928.html
|
||||
---
|
||||
gdb/breakpoint.c | 29 ++++++++-------
|
||||
gdb/inferior.c | 8 ++---
|
||||
gdb/inferior.h | 2 +-
|
||||
gdb/infrun.c | 18 +++++-----
|
||||
gdb/linux-nat.c | 2 +-
|
||||
gdb/process-stratum-target.c | 2 +-
|
||||
gdb/progspace.c | 22 +++++-------
|
||||
gdb/progspace.h | 64 +++++++++++++++++++++-------------
|
||||
gdb/record-btrace.c | 2 +-
|
||||
gdb/regcache.c | 2 +-
|
||||
gdb/scoped-mock-context.h | 2 +-
|
||||
gdb/target-dcache.c | 11 +++---
|
||||
gdbsupport/refcounted-object.h | 17 +++++++++
|
||||
13 files changed, 102 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
index 01f187ca4fe..a22bdb091cd 100644
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -1723,7 +1723,7 @@ one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
|
||||
int bptoffset = 0;
|
||||
|
||||
if (!breakpoint_address_match (target_info->placed_address_space, 0,
|
||||
- current_program_space->aspace, 0))
|
||||
+ current_program_space->aspace.get (), 0))
|
||||
{
|
||||
/* The breakpoint is inserted in a different address space. */
|
||||
return;
|
||||
@@ -2409,7 +2409,7 @@ should_be_inserted (struct bp_location *bl)
|
||||
a breakpoint. */
|
||||
if ((bl->loc_type == bp_loc_software_breakpoint
|
||||
|| bl->loc_type == bp_loc_hardware_breakpoint)
|
||||
- && stepping_past_instruction_at (bl->pspace->aspace,
|
||||
+ && stepping_past_instruction_at (bl->pspace->aspace.get (),
|
||||
bl->address)
|
||||
/* The single-step breakpoint may be inserted at the location
|
||||
we're trying to step if the instruction branches to itself.
|
||||
@@ -2847,7 +2847,7 @@ insert_bp_location (struct bp_location *bl,
|
||||
read the breakpoint instead of returning the data saved in
|
||||
the breakpoint location's shadow contents. */
|
||||
bl->target_info.reqstd_address = bl->address;
|
||||
- bl->target_info.placed_address_space = bl->pspace->aspace;
|
||||
+ bl->target_info.placed_address_space = bl->pspace->aspace.get ();
|
||||
bl->target_info.length = bl->length;
|
||||
|
||||
/* When working with target-side conditions, we must pass all the conditions
|
||||
@@ -4429,7 +4429,7 @@ bp_location_inserted_here_p (const struct bp_location *bl,
|
||||
const address_space *aspace, CORE_ADDR pc)
|
||||
{
|
||||
if (bl->inserted
|
||||
- && breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ && breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, pc))
|
||||
{
|
||||
/* An unmapped overlay can't be a match. */
|
||||
@@ -4508,7 +4508,7 @@ hardware_watchpoint_inserted_in_range (const address_space *aspace,
|
||||
continue;
|
||||
|
||||
for (bp_location &loc : bpt.locations ())
|
||||
- if (loc.pspace->aspace == aspace && loc.inserted)
|
||||
+ if (loc.pspace->aspace.get () == aspace && loc.inserted)
|
||||
{
|
||||
CORE_ADDR l, h;
|
||||
|
||||
@@ -7330,10 +7330,10 @@ breakpoint_location_address_match (struct bp_location *bl,
|
||||
const address_space *aspace,
|
||||
CORE_ADDR addr)
|
||||
{
|
||||
- return (breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ return (breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, addr)
|
||||
|| (bl->length
|
||||
- && breakpoint_address_match_range (bl->pspace->aspace,
|
||||
+ && breakpoint_address_match_range (bl->pspace->aspace.get (),
|
||||
bl->address, bl->length,
|
||||
aspace, addr)));
|
||||
}
|
||||
@@ -7350,7 +7350,7 @@ breakpoint_location_address_range_overlap (struct bp_location *bl,
|
||||
CORE_ADDR addr, int len)
|
||||
{
|
||||
if (gdbarch_has_global_breakpoints (target_gdbarch ())
|
||||
- || bl->pspace->aspace == aspace)
|
||||
+ || bl->pspace->aspace.get () == aspace)
|
||||
{
|
||||
int bl_len = bl->length != 0 ? bl->length : 1;
|
||||
|
||||
@@ -7407,8 +7407,10 @@ breakpoint_locations_match (const struct bp_location *loc1,
|
||||
/* We compare bp_location.length in order to cover ranged
|
||||
breakpoints. Keep this in sync with
|
||||
bp_location_is_less_than. */
|
||||
- return (breakpoint_address_match (loc1->pspace->aspace, loc1->address,
|
||||
- loc2->pspace->aspace, loc2->address)
|
||||
+ return (breakpoint_address_match (loc1->pspace->aspace.get (),
|
||||
+ loc1->address,
|
||||
+ loc2->pspace->aspace.get (),
|
||||
+ loc2->address)
|
||||
&& (loc1->loc_type == loc2->loc_type || sw_hw_bps_match)
|
||||
&& loc1->length == loc2->length);
|
||||
}
|
||||
@@ -9568,8 +9570,9 @@ ranged_breakpoint::breakpoint_hit (const struct bp_location *bl,
|
||||
|| ws.sig () != GDB_SIGNAL_TRAP)
|
||||
return 0;
|
||||
|
||||
- return breakpoint_address_match_range (bl->pspace->aspace, bl->address,
|
||||
- bl->length, aspace, bp_addr);
|
||||
+ return breakpoint_address_match_range (bl->pspace->aspace.get (),
|
||||
+ bl->address, bl->length, aspace,
|
||||
+ bp_addr);
|
||||
}
|
||||
|
||||
/* Implement the "resources_needed" method for ranged breakpoints. */
|
||||
@@ -12018,7 +12021,7 @@ code_breakpoint::breakpoint_hit (const struct bp_location *bl,
|
||||
|| ws.sig () != GDB_SIGNAL_TRAP)
|
||||
return 0;
|
||||
|
||||
- if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
+ if (!breakpoint_address_match (bl->pspace->aspace.get (), bl->address,
|
||||
aspace, bp_addr))
|
||||
return 0;
|
||||
|
||||
diff --git a/gdb/inferior.c b/gdb/inferior.c
|
||||
index 550bbd2827c..461f4fc076a 100644
|
||||
--- a/gdb/inferior.c
|
||||
+++ b/gdb/inferior.c
|
||||
@@ -831,15 +831,13 @@ remove_inferior_command (const char *args, int from_tty)
|
||||
struct inferior *
|
||||
add_inferior_with_spaces (void)
|
||||
{
|
||||
- struct address_space *aspace;
|
||||
struct program_space *pspace;
|
||||
struct inferior *inf;
|
||||
|
||||
/* If all inferiors share an address space on this system, this
|
||||
doesn't really return a new address space; otherwise, it
|
||||
really does. */
|
||||
- aspace = maybe_new_address_space ();
|
||||
- pspace = new program_space (aspace);
|
||||
+ pspace = new program_space (maybe_new_address_space ());
|
||||
inf = add_inferior (0);
|
||||
inf->pspace = pspace;
|
||||
inf->aspace = pspace->aspace;
|
||||
@@ -1002,15 +1000,13 @@ clone_inferior_command (const char *args, int from_tty)
|
||||
|
||||
for (i = 0; i < copies; ++i)
|
||||
{
|
||||
- struct address_space *aspace;
|
||||
struct program_space *pspace;
|
||||
struct inferior *inf;
|
||||
|
||||
/* If all inferiors share an address space on this system, this
|
||||
doesn't really return a new address space; otherwise, it
|
||||
really does. */
|
||||
- aspace = maybe_new_address_space ();
|
||||
- pspace = new program_space (aspace);
|
||||
+ pspace = new program_space (maybe_new_address_space ());
|
||||
inf = add_inferior (0);
|
||||
inf->pspace = pspace;
|
||||
inf->aspace = pspace->aspace;
|
||||
diff --git a/gdb/inferior.h b/gdb/inferior.h
|
||||
index 29c90d15efa..4139791740f 100644
|
||||
--- a/gdb/inferior.h
|
||||
+++ b/gdb/inferior.h
|
||||
@@ -577,7 +577,7 @@ class inferior : public refcounted_object,
|
||||
bool removable = false;
|
||||
|
||||
/* The address space bound to this inferior. */
|
||||
- struct address_space *aspace = NULL;
|
||||
+ address_space_ref_ptr aspace;
|
||||
|
||||
/* The program space bound to this inferior. */
|
||||
struct program_space *pspace = NULL;
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 7be98cfc252..3854c66bf6c 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -531,8 +531,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
}
|
||||
else
|
||||
{
|
||||
- child_inf->aspace = new address_space ();
|
||||
- child_inf->pspace = new program_space (child_inf->aspace);
|
||||
+ child_inf->pspace = new program_space (new_address_space ());
|
||||
+ child_inf->aspace = child_inf->pspace->aspace;
|
||||
child_inf->removable = true;
|
||||
clone_program_space (child_inf->pspace, parent_inf->pspace);
|
||||
}
|
||||
@@ -610,8 +610,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
|
||||
child_inf->aspace = parent_inf->aspace;
|
||||
child_inf->pspace = parent_inf->pspace;
|
||||
- parent_inf->aspace = new address_space ();
|
||||
- parent_inf->pspace = new program_space (parent_inf->aspace);
|
||||
+ parent_inf->pspace = new program_space (new_address_space ());
|
||||
+ parent_inf->aspace = parent_inf->pspace->aspace;
|
||||
clone_program_space (parent_inf->pspace, child_inf->pspace);
|
||||
|
||||
/* The parent inferior is still the current one, so keep things
|
||||
@@ -620,8 +620,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
|
||||
}
|
||||
else
|
||||
{
|
||||
- child_inf->aspace = new address_space ();
|
||||
- child_inf->pspace = new program_space (child_inf->aspace);
|
||||
+ child_inf->pspace = new program_space (new_address_space ());
|
||||
+ child_inf->aspace = child_inf->pspace->aspace;
|
||||
child_inf->removable = true;
|
||||
child_inf->symfile_flags = SYMFILE_NO_READ;
|
||||
clone_program_space (child_inf->pspace, parent_inf->pspace);
|
||||
@@ -1031,7 +1031,6 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
if (vfork_parent->pending_detach)
|
||||
{
|
||||
struct program_space *pspace;
|
||||
- struct address_space *aspace;
|
||||
|
||||
/* follow-fork child, detach-on-fork on. */
|
||||
|
||||
@@ -1056,9 +1055,8 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
of" a hack. */
|
||||
|
||||
pspace = inf->pspace;
|
||||
- aspace = inf->aspace;
|
||||
- inf->aspace = nullptr;
|
||||
inf->pspace = nullptr;
|
||||
+ address_space_ref_ptr aspace = std::move (inf->aspace);
|
||||
|
||||
if (print_inferior_events)
|
||||
{
|
||||
@@ -5906,7 +5904,7 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
= get_thread_arch_aspace_regcache (parent_inf,
|
||||
ecs->ws.child_ptid (),
|
||||
gdbarch,
|
||||
- parent_inf->aspace);
|
||||
+ parent_inf->aspace.get ());
|
||||
/* Read PC value of parent process. */
|
||||
parent_pc = regcache_read_pc (regcache);
|
||||
|
||||
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
|
||||
index ed445c5e5bb..c8991cc3da4 100644
|
||||
--- a/gdb/linux-nat.c
|
||||
+++ b/gdb/linux-nat.c
|
||||
@@ -4365,7 +4365,7 @@ linux_nat_target::thread_address_space (ptid_t ptid)
|
||||
|
||||
inf = find_inferior_pid (this, pid);
|
||||
gdb_assert (inf != NULL);
|
||||
- return inf->aspace;
|
||||
+ return inf->aspace.get ();
|
||||
}
|
||||
|
||||
/* Return the cached value of the processor core for thread PTID. */
|
||||
diff --git a/gdb/process-stratum-target.c b/gdb/process-stratum-target.c
|
||||
index 5c031203e89..4bcca4f39c2 100644
|
||||
--- a/gdb/process-stratum-target.c
|
||||
+++ b/gdb/process-stratum-target.c
|
||||
@@ -37,7 +37,7 @@ process_stratum_target::thread_address_space (ptid_t ptid)
|
||||
"address space of thread %s\n"),
|
||||
target_pid_to_str (ptid).c_str ());
|
||||
|
||||
- return inf->aspace;
|
||||
+ return inf->aspace.get ();
|
||||
}
|
||||
|
||||
struct gdbarch *
|
||||
diff --git a/gdb/progspace.c b/gdb/progspace.c
|
||||
index 1dbcd5875dd..b4d25ba6196 100644
|
||||
--- a/gdb/progspace.c
|
||||
+++ b/gdb/progspace.c
|
||||
@@ -55,8 +55,8 @@ address_space::address_space ()
|
||||
return a pointer to an existing address space, in case inferiors
|
||||
share an address space on this target system. */
|
||||
|
||||
-struct address_space *
|
||||
-maybe_new_address_space (void)
|
||||
+address_space_ref_ptr
|
||||
+maybe_new_address_space ()
|
||||
{
|
||||
int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
|
||||
|
||||
@@ -66,7 +66,7 @@ maybe_new_address_space (void)
|
||||
return program_spaces[0]->aspace;
|
||||
}
|
||||
|
||||
- return new address_space ();
|
||||
+ return new_address_space ();
|
||||
}
|
||||
|
||||
/* Start counting over from scratch. */
|
||||
@@ -94,9 +94,9 @@ remove_program_space (program_space *pspace)
|
||||
|
||||
/* See progspace.h. */
|
||||
|
||||
-program_space::program_space (address_space *aspace_)
|
||||
+program_space::program_space (address_space_ref_ptr aspace_)
|
||||
: num (++last_program_space_num),
|
||||
- aspace (aspace_)
|
||||
+ aspace (std::move (aspace_))
|
||||
{
|
||||
program_spaces.push_back (this);
|
||||
gdb::observers::new_program_space.notify (this);
|
||||
@@ -121,8 +121,6 @@ program_space::~program_space ()
|
||||
/* Defer breakpoint re-set because we don't want to create new
|
||||
locations for this pspace which we're tearing down. */
|
||||
clear_symtab_users (SYMFILE_DEFER_BP_RESET);
|
||||
- if (!gdbarch_has_shared_address_space (target_gdbarch ()))
|
||||
- delete this->aspace;
|
||||
}
|
||||
|
||||
/* See progspace.h. */
|
||||
@@ -408,18 +406,14 @@ update_address_spaces (void)
|
||||
|
||||
if (shared_aspace)
|
||||
{
|
||||
- struct address_space *aspace = new address_space ();
|
||||
+ address_space_ref_ptr aspace = new_address_space ();
|
||||
|
||||
- delete current_program_space->aspace;
|
||||
for (struct program_space *pspace : program_spaces)
|
||||
pspace->aspace = aspace;
|
||||
}
|
||||
else
|
||||
for (struct program_space *pspace : program_spaces)
|
||||
- {
|
||||
- delete pspace->aspace;
|
||||
- pspace->aspace = new address_space ();
|
||||
- }
|
||||
+ pspace->aspace = new_address_space ();
|
||||
|
||||
for (inferior *inf : all_inferiors ())
|
||||
if (gdbarch_has_global_solist (target_gdbarch ()))
|
||||
@@ -456,5 +450,5 @@ initialize_progspace (void)
|
||||
modules have done that. Do this before
|
||||
initialize_current_architecture, because that accesses the ebfd
|
||||
of current_program_space. */
|
||||
- current_program_space = new program_space (new address_space ());
|
||||
+ current_program_space = new program_space (new_address_space ());
|
||||
}
|
||||
diff --git a/gdb/progspace.h b/gdb/progspace.h
|
||||
index ee12d89c173..12f113f6d9c 100644
|
||||
--- a/gdb/progspace.h
|
||||
+++ b/gdb/progspace.h
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "solist.h"
|
||||
#include "gdbsupport/next-iterator.h"
|
||||
#include "gdbsupport/safe-iterator.h"
|
||||
+#include "gdbsupport/refcounted-object.h"
|
||||
+#include "gdbsupport/gdb_ref_ptr.h"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
@@ -42,6 +44,40 @@ struct so_list;
|
||||
|
||||
typedef std::list<std::unique_ptr<objfile>> objfile_list;
|
||||
|
||||
+/* An address space. It is used for comparing if
|
||||
+ pspaces/inferior/threads see the same address space and for
|
||||
+ associating caches to each address space. */
|
||||
+struct address_space : public refcounted_object
|
||||
+{
|
||||
+ /* Create a new address space object, and add it to the list. */
|
||||
+ address_space ();
|
||||
+ DISABLE_COPY_AND_ASSIGN (address_space);
|
||||
+
|
||||
+ /* Returns the integer address space id of this address space. */
|
||||
+ int num () const
|
||||
+ {
|
||||
+ return m_num;
|
||||
+ }
|
||||
+
|
||||
+ /* Per aspace data-pointers required by other GDB modules. */
|
||||
+ registry<address_space> registry_fields;
|
||||
+
|
||||
+private:
|
||||
+ int m_num;
|
||||
+};
|
||||
+
|
||||
+using address_space_ref_ptr
|
||||
+ = gdb::ref_ptr<address_space,
|
||||
+ refcounted_object_delete_ref_policy<address_space>>;
|
||||
+
|
||||
+/* Create a new address space. */
|
||||
+
|
||||
+static inline address_space_ref_ptr
|
||||
+new_address_space ()
|
||||
+{
|
||||
+ return address_space_ref_ptr::new_reference (new address_space);
|
||||
+}
|
||||
+
|
||||
/* An iterator that wraps an iterator over std::unique_ptr<objfile>,
|
||||
and dereferences the returned object. This is useful for iterating
|
||||
over a list of shared pointers and returning raw pointers -- which
|
||||
@@ -191,7 +227,7 @@ struct program_space
|
||||
{
|
||||
/* Constructs a new empty program space, binds it to ASPACE, and
|
||||
adds it to the program space list. */
|
||||
- explicit program_space (address_space *aspace);
|
||||
+ explicit program_space (address_space_ref_ptr aspace);
|
||||
|
||||
/* Releases a program space, and all its contents (shared libraries,
|
||||
objfiles, and any other references to the program space in other
|
||||
@@ -336,7 +372,7 @@ struct program_space
|
||||
are global, then this field is ignored (we don't currently
|
||||
support inferiors sharing a program space if the target doesn't
|
||||
make breakpoints global). */
|
||||
- struct address_space *aspace = NULL;
|
||||
+ address_space_ref_ptr aspace;
|
||||
|
||||
/* True if this program space's section offsets don't yet represent
|
||||
the final offsets of the "live" address space (that is, the
|
||||
@@ -383,28 +419,6 @@ struct program_space
|
||||
target_section_table m_target_sections;
|
||||
};
|
||||
|
||||
-/* An address space. It is used for comparing if
|
||||
- pspaces/inferior/threads see the same address space and for
|
||||
- associating caches to each address space. */
|
||||
-struct address_space
|
||||
-{
|
||||
- /* Create a new address space object, and add it to the list. */
|
||||
- address_space ();
|
||||
- DISABLE_COPY_AND_ASSIGN (address_space);
|
||||
-
|
||||
- /* Returns the integer address space id of this address space. */
|
||||
- int num () const
|
||||
- {
|
||||
- return m_num;
|
||||
- }
|
||||
-
|
||||
- /* Per aspace data-pointers required by other GDB modules. */
|
||||
- registry<address_space> registry_fields;
|
||||
-
|
||||
-private:
|
||||
- int m_num;
|
||||
-};
|
||||
-
|
||||
/* The list of all program spaces. There's always at least one. */
|
||||
extern std::vector<struct program_space *>program_spaces;
|
||||
|
||||
@@ -447,7 +461,7 @@ class scoped_restore_current_program_space
|
||||
/* Maybe create a new address space object, and add it to the list, or
|
||||
return a pointer to an existing address space, in case inferiors
|
||||
share an address space. */
|
||||
-extern struct address_space *maybe_new_address_space (void);
|
||||
+extern address_space_ref_ptr maybe_new_address_space ();
|
||||
|
||||
/* Update all program spaces matching to address spaces. The user may
|
||||
have created several program spaces, and loaded executables into
|
||||
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
|
||||
index 97447d3e8f8..a4d6c1b5bf2 100644
|
||||
--- a/gdb/record-btrace.c
|
||||
+++ b/gdb/record-btrace.c
|
||||
@@ -2321,7 +2321,7 @@ record_btrace_replay_at_breakpoint (struct thread_info *tp)
|
||||
if (insn == NULL)
|
||||
return 0;
|
||||
|
||||
- return record_check_stopped_by_breakpoint (tp->inf->aspace, insn->pc,
|
||||
+ return record_check_stopped_by_breakpoint (tp->inf->aspace.get (), insn->pc,
|
||||
&btinfo->stop_reason);
|
||||
}
|
||||
|
||||
diff --git a/gdb/regcache.c b/gdb/regcache.c
|
||||
index 91b20b7a2a2..a78fe0a80e7 100644
|
||||
--- a/gdb/regcache.c
|
||||
+++ b/gdb/regcache.c
|
||||
@@ -1628,7 +1628,7 @@ get_thread_arch_aspace_regcache_and_check (inferior *inf_for_target_calls,
|
||||
the current inferior's gdbarch. Also use the current inferior's address
|
||||
space. */
|
||||
gdbarch *arch = inf_for_target_calls->gdbarch;
|
||||
- address_space *aspace = inf_for_target_calls->aspace;
|
||||
+ address_space *aspace = inf_for_target_calls->aspace.get ();
|
||||
regcache *regcache = get_thread_arch_aspace_regcache (inf_for_target_calls,
|
||||
ptid, arch, aspace);
|
||||
|
||||
diff --git a/gdb/scoped-mock-context.h b/gdb/scoped-mock-context.h
|
||||
index 9ad7ebf5f0c..5f25dc7ed6b 100644
|
||||
--- a/gdb/scoped-mock-context.h
|
||||
+++ b/gdb/scoped-mock-context.h
|
||||
@@ -38,7 +38,7 @@ struct scoped_mock_context
|
||||
|
||||
Target mock_target;
|
||||
ptid_t mock_ptid {1, 1};
|
||||
- program_space mock_pspace {new address_space ()};
|
||||
+ program_space mock_pspace {new_address_space ()};
|
||||
inferior mock_inferior {mock_ptid.pid ()};
|
||||
thread_info mock_thread {&mock_inferior, mock_ptid};
|
||||
|
||||
diff --git a/gdb/target-dcache.c b/gdb/target-dcache.c
|
||||
index 13c2888e7ea..b1b772ab76e 100644
|
||||
--- a/gdb/target-dcache.c
|
||||
+++ b/gdb/target-dcache.c
|
||||
@@ -33,7 +33,7 @@ int
|
||||
target_dcache_init_p (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
return (dcache != NULL);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ void
|
||||
target_dcache_invalidate (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
if (dcache != NULL)
|
||||
dcache_invalidate (dcache);
|
||||
@@ -56,7 +56,7 @@ target_dcache_invalidate (void)
|
||||
DCACHE *
|
||||
target_dcache_get (void)
|
||||
{
|
||||
- return target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ return target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
}
|
||||
|
||||
/* Return the target dcache. If it is not initialized yet, initialize
|
||||
@@ -66,12 +66,13 @@ DCACHE *
|
||||
target_dcache_get_or_init (void)
|
||||
{
|
||||
DCACHE *dcache
|
||||
- = target_dcache_aspace_key.get (current_program_space->aspace);
|
||||
+ = target_dcache_aspace_key.get (current_program_space->aspace.get ());
|
||||
|
||||
if (dcache == NULL)
|
||||
{
|
||||
dcache = dcache_init ();
|
||||
- target_dcache_aspace_key.set (current_program_space->aspace, dcache);
|
||||
+ target_dcache_aspace_key.set (current_program_space->aspace.get (),
|
||||
+ dcache);
|
||||
}
|
||||
|
||||
return dcache;
|
||||
diff --git a/gdbsupport/refcounted-object.h b/gdbsupport/refcounted-object.h
|
||||
index d8fdb950043..294fd873df1 100644
|
||||
--- a/gdbsupport/refcounted-object.h
|
||||
+++ b/gdbsupport/refcounted-object.h
|
||||
@@ -67,4 +67,21 @@ struct refcounted_object_ref_policy
|
||||
}
|
||||
};
|
||||
|
||||
+/* A policy class to interface gdb::ref_ptr with a refcounted_object, that
|
||||
+ deletes the object once the refcount reaches 0.. */
|
||||
+
|
||||
+template<typename T>
|
||||
+struct refcounted_object_delete_ref_policy
|
||||
+{
|
||||
+ static void incref (T *obj)
|
||||
+ { obj->incref (); }
|
||||
+
|
||||
+ static void decref (T *obj)
|
||||
+ {
|
||||
+ obj->decref ();
|
||||
+ if (obj->refcount () == 0)
|
||||
+ delete obj;
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
#endif /* COMMON_REFCOUNTED_OBJECT_H */
|
||||
|
||||
base-commit: 0bb6f49bb9ad577667075550ca2ad4cb49931078
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,168 +0,0 @@
|
||||
From 3490f51a80a10d46dc1885ba672d9390a8221170 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 2 Nov 2023 14:51:02 +0100
|
||||
Subject: [PATCH] Fix segfault in for_each_block, part 2
|
||||
|
||||
The previous commit describes PR gdb/30547, a segfault when running test-case
|
||||
gdb.base/vfork-follow-parent.exp on powerpc64 (likewise on s390x).
|
||||
|
||||
The root cause for the segmentation fault is that linux_is_uclinux gives an
|
||||
incorrect result: it returns true instead of false.
|
||||
|
||||
So, why does linux_is_uclinux:
|
||||
...
|
||||
int
|
||||
linux_is_uclinux (void)
|
||||
{
|
||||
CORE_ADDR dummy;
|
||||
|
||||
return (target_auxv_search (AT_NULL, &dummy) > 0
|
||||
&& target_auxv_search (AT_PAGESZ, &dummy) == 0);
|
||||
...
|
||||
return true?
|
||||
|
||||
This is because ppc_linux_target_wordsize returns 4 instead of 8, causing
|
||||
ppc_linux_nat_target::auxv_parse to misinterpret the auxv vector.
|
||||
|
||||
So, why does ppc_linux_target_wordsize:
|
||||
...
|
||||
int
|
||||
ppc_linux_target_wordsize (int tid)
|
||||
{
|
||||
int wordsize = 4;
|
||||
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
64-bit, and in addition the top bit of the MSR register is set. */
|
||||
long msr;
|
||||
|
||||
errno = 0;
|
||||
msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
|
||||
if (errno == 0 && ppc64_64bit_inferior_p (msr))
|
||||
wordsize = 8;
|
||||
|
||||
return wordsize;
|
||||
}
|
||||
...
|
||||
return 4?
|
||||
|
||||
Specifically, we get this result because because tid == 0, so we get
|
||||
errno == ESRCH.
|
||||
|
||||
The tid == 0 is caused by the switch_to_no_thread in
|
||||
handle_vfork_child_exec_or_exit:
|
||||
...
|
||||
/* Switch to no-thread while running clone_program_space, so
|
||||
that clone_program_space doesn't want to read the
|
||||
selected frame of a dead process. */
|
||||
scoped_restore_current_thread restore_thread;
|
||||
switch_to_no_thread ();
|
||||
|
||||
inf->pspace = new program_space (maybe_new_address_space ());
|
||||
...
|
||||
but moving the maybe_new_address_space call to before that gives us the
|
||||
same result. The tid is no longer 0, but we still get ESRCH because the
|
||||
thread has exited.
|
||||
|
||||
Fix this in handle_vfork_child_exec_or_exit by doing the
|
||||
maybe_new_address_space call in the context of the vfork parent.
|
||||
|
||||
Tested on top of trunk on x86_64-linux and ppc64le-linux.
|
||||
Tested on top of gdb-14-branch on ppc64-linux.
|
||||
|
||||
Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
PR gdb/30547
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547
|
||||
---
|
||||
gdb/infrun.c | 16 +++++++++++-----
|
||||
gdb/nat/ppc-linux.c | 2 ++
|
||||
gdb/ppc-linux-nat.c | 2 ++
|
||||
gdb/s390-linux-nat.c | 5 ++++-
|
||||
4 files changed, 19 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/gdb/infrun.c b/gdb/infrun.c
|
||||
index 3854c66bf6c..d259e81df84 100644
|
||||
--- a/gdb/infrun.c
|
||||
+++ b/gdb/infrun.c
|
||||
@@ -1105,13 +1105,19 @@ handle_vfork_child_exec_or_exit (int exec)
|
||||
go ahead and create a new one for this exiting
|
||||
inferior. */
|
||||
|
||||
- /* Switch to no-thread while running clone_program_space, so
|
||||
- that clone_program_space doesn't want to read the
|
||||
- selected frame of a dead process. */
|
||||
scoped_restore_current_thread restore_thread;
|
||||
- switch_to_no_thread ();
|
||||
|
||||
- inf->pspace = new program_space (maybe_new_address_space ());
|
||||
+ /* Temporarily switch to the vfork parent, to facilitate ptrace
|
||||
+ calls done during maybe_new_address_space. */
|
||||
+ switch_to_thread (any_live_thread_of_inferior (vfork_parent));
|
||||
+ address_space_ref_ptr aspace = maybe_new_address_space ();
|
||||
+
|
||||
+ /* Switch back to the vfork child inferior. Switch to no-thread
|
||||
+ while running clone_program_space, so that clone_program_space
|
||||
+ doesn't want to read the selected frame of a dead process. */
|
||||
+ switch_to_inferior_no_thread (inf);
|
||||
+
|
||||
+ inf->pspace = new program_space (std::move (aspace));
|
||||
inf->aspace = inf->pspace->aspace;
|
||||
set_current_program_space (inf->pspace);
|
||||
inf->removable = true;
|
||||
diff --git a/gdb/nat/ppc-linux.c b/gdb/nat/ppc-linux.c
|
||||
index 0957d1b58a7..74549754806 100644
|
||||
--- a/gdb/nat/ppc-linux.c
|
||||
+++ b/gdb/nat/ppc-linux.c
|
||||
@@ -78,6 +78,8 @@ ppc64_64bit_inferior_p (long msr)
|
||||
int
|
||||
ppc_linux_target_wordsize (int tid)
|
||||
{
|
||||
+ gdb_assert (tid != 0);
|
||||
+
|
||||
int wordsize = 4;
|
||||
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
|
||||
index d14aba694e5..817505ea73e 100644
|
||||
--- a/gdb/ppc-linux-nat.c
|
||||
+++ b/gdb/ppc-linux-nat.c
|
||||
@@ -1914,6 +1914,8 @@ ppc_linux_nat_target::auxv_parse (const gdb_byte **readptr,
|
||||
const gdb_byte *endptr, CORE_ADDR *typep,
|
||||
CORE_ADDR *valp)
|
||||
{
|
||||
+ gdb_assert (inferior_ptid != null_ptid);
|
||||
+
|
||||
int tid = inferior_ptid.lwp ();
|
||||
if (tid == 0)
|
||||
tid = inferior_ptid.pid ();
|
||||
diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
|
||||
index 8f54e9f6322..54167f49480 100644
|
||||
--- a/gdb/s390-linux-nat.c
|
||||
+++ b/gdb/s390-linux-nat.c
|
||||
@@ -949,10 +949,12 @@ s390_target_wordsize (void)
|
||||
/* Check for 64-bit inferior process. This is the case when the host is
|
||||
64-bit, and in addition bit 32 of the PSW mask is set. */
|
||||
#ifdef __s390x__
|
||||
+ int tid = s390_inferior_tid ();
|
||||
+ gdb_assert (tid != 0);
|
||||
long pswm;
|
||||
|
||||
errno = 0;
|
||||
- pswm = (long) ptrace (PTRACE_PEEKUSER, s390_inferior_tid (), PT_PSWMASK, 0);
|
||||
+ pswm = (long) ptrace (PTRACE_PEEKUSER, tid, PT_PSWMASK, 0);
|
||||
if (errno == 0 && (pswm & 0x100000000ul) != 0)
|
||||
wordsize = 8;
|
||||
#endif
|
||||
@@ -965,6 +967,7 @@ s390_linux_nat_target::auxv_parse (const gdb_byte **readptr,
|
||||
const gdb_byte *endptr, CORE_ADDR *typep,
|
||||
CORE_ADDR *valp)
|
||||
{
|
||||
+ gdb_assert (inferior_ptid != null_ptid);
|
||||
int sizeof_auxv_field = s390_target_wordsize ();
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
||||
const gdb_byte *ptr = *readptr;
|
||||
|
||||
base-commit: 1d02ba0f4adcba2595a67e88fb1ba6d35c7f8e5b
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,42 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Wed, 17 Jan 2024 12:53:53 -0700
|
||||
Subject: gdb-ftbs-swapped-calloc-args.patch
|
||||
|
||||
Backport upstream commit 54195469c18ec9873cc5ba6907f768509473fa9b
|
||||
which fixes a build problem in which arguments to calloc were swapped.
|
||||
|
||||
[opcodes] ARC + PPC: Fix -Walloc-size warnings
|
||||
|
||||
Recently, -Walloc-size warnings started to kick in. Fix these two
|
||||
calloc() calls to match the intended usage pattern.
|
||||
|
||||
opcodes/ChangeLog:
|
||||
|
||||
* arc-dis.c (init_arc_disasm_info): Fix calloc() call.
|
||||
* ppc-dis.c (powerpc_init_dialect): Ditto.
|
||||
|
||||
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
|
||||
--- a/opcodes/arc-dis.c
|
||||
+++ b/opcodes/arc-dis.c
|
||||
@@ -147,7 +147,7 @@ static bool
|
||||
init_arc_disasm_info (struct disassemble_info *info)
|
||||
{
|
||||
struct arc_disassemble_info *arc_infop
|
||||
- = calloc (sizeof (*arc_infop), 1);
|
||||
+ = calloc (1, sizeof (*arc_infop));
|
||||
|
||||
if (arc_infop == NULL)
|
||||
return false;
|
||||
diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c
|
||||
--- a/opcodes/ppc-dis.c
|
||||
+++ b/opcodes/ppc-dis.c
|
||||
@@ -348,7 +348,7 @@ powerpc_init_dialect (struct disassemble_info *info)
|
||||
{
|
||||
ppc_cpu_t dialect = 0;
|
||||
ppc_cpu_t sticky = 0;
|
||||
- struct dis_private *priv = calloc (sizeof (*priv), 1);
|
||||
+ struct dis_private *priv = calloc (1, sizeof (*priv));
|
||||
|
||||
if (priv == NULL)
|
||||
return;
|
@ -6,5 +6,5 @@ index b9770ea415..3149f6e1fe 100644
|
||||
-#!/usr/bin/env bash
|
||||
+#!/bin/bash
|
||||
|
||||
# Copyright (C) 2003-2023 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003-2024 Free Software Foundation, Inc.
|
||||
|
||||
|
@ -1,132 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-glibc-strstr-workaround.patch
|
||||
|
||||
;; Workaround PR libc/14166 for inferior calls of strstr.
|
||||
;;=fedoratest: Compatibility with RHELs (unchecked which ones).
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/gnu-ifunc-strstr-workaround.exp
|
||||
@@ -0,0 +1,119 @@
|
||||
+# Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Workaround for:
|
||||
+# invalid IFUNC DW_AT_linkage_name: memmove strstr time
|
||||
+# http://sourceware.org/bugzilla/show_bug.cgi?id=14166
|
||||
+
|
||||
+if {[skip_shlib_tests]} {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+set testfile "gnu-ifunc-strstr-workaround"
|
||||
+set executable ${testfile}
|
||||
+set srcfile start.c
|
||||
+set binfile [standard_output_file ${executable}]
|
||||
+
|
||||
+if [prepare_for_testing ${testfile}.exp $executable $srcfile] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if ![runto_main] {
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+set test "ptype atoi"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re "type = int \\(const char \\*\\)\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "type = int \\(\\)\r\n$gdb_prompt $" {
|
||||
+ untested "$test (no DWARF)"
|
||||
+ return 0
|
||||
+ }
|
||||
+ -re "type = <unknown return type> \\(\\)\r\n$gdb_prompt $" {
|
||||
+ untested "$test (no DWARF)"
|
||||
+ return 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set addr ""
|
||||
+set test "print strstr"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <strstr>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <__strstr>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass "$test (GDB workaround)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <__libc_strstr>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} (0x\[0-9a-f\]+) <__libc_strstr_ifunc>\r\n$gdb_prompt $" {
|
||||
+ set addr $expect_out(1,string)
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ untested "$test (gnu-ifunc not in use by glibc)"
|
||||
+ return 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set test "info sym"
|
||||
+gdb_test_multiple "info sym $addr" $test {
|
||||
+ -re "strstr in section \\.text of /lib\[^/\]*/libc.so.6\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re " = {char \\*\\(const char \\*, const char \\*\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ # unexpected
|
||||
+ xfail "$test (not in libc.so.6)"
|
||||
+ return 0
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set test "info addr strstr"
|
||||
+gdb_test_multiple $test $test {
|
||||
+ -re "Symbol \"strstr\" is a function at address $addr\\.\r\n$gdb_prompt $" {
|
||||
+ fail "$test (DWARF for strstr)"
|
||||
+ }
|
||||
+ -re "Symbol \"strstr\" is at $addr in a file compiled without debugging\\.\r\n$gdb_prompt $" {
|
||||
+ pass "$test"
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+set test "print strstr second time"
|
||||
+gdb_test_multiple "print strstr" $test {
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <strstr>\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <__strstr>\r\n$gdb_prompt $" {
|
||||
+ pass "$test (GDB workaround)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <__libc_strstr>\r\n$gdb_prompt $" {
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {<text gnu-indirect-function variable, no debug info>} $addr <__libc_strstr_ifunc>\r\n$gdb_prompt $" {
|
||||
+ pass "$test (fixed glibc)"
|
||||
+ }
|
||||
+ -re " = {void \\*\\(void\\)} 0x\[0-9a-f\]+ <strstr>\r\n$gdb_prompt $" {
|
||||
+ fail $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_test {print (char *)strstr("abc","b")} { = 0x[0-9a-f]+ "bc"}
|
||||
+gdb_test {print (char *)strstr("def","e")} { = 0x[0-9a-f]+ "ef"}
|
68
gdb-guile-use-scm_debug_typing_strictness-0.patch
Normal file
68
gdb-guile-use-scm_debug_typing_strictness-0.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From fe0e6edbcb65ab5eca50c1a0ad8ddc9844f8ea98 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 27 Jan 2025 09:23:18 +0100
|
||||
Subject: [PATCH] [gdb/guile] Use SCM_DEBUG_TYPING_STRICTNESS 0
|
||||
|
||||
I build gdb with libguile v2.0.9, and ran into:
|
||||
...
|
||||
In file included from /usr/include/guile/2.0/libguile.h:56,
|
||||
from ../../gdb/guile/guile-internal.h:30,
|
||||
from ../../gdb/guile/scm-arch.c:26:
|
||||
/usr/include/guile/2.0/libguile/inline.h: In function 'int scm_is_pair(SCM)':
|
||||
/usr/include/guile/2.0/libguile/tags.h:97:53: error: \
|
||||
operation on '*0' may be undefined [-Werror=sequence-point]
|
||||
# define SCM_UNPACK(x) ((scm_t_bits) (0? (*(SCM*)0=(x)): x))
|
||||
~~~~~~~~~^~~~~
|
||||
...
|
||||
|
||||
Fix this by using SCM_DEBUG_TYPING_STRICTNESS 0.
|
||||
|
||||
We were already using this for c++20 due to a Werror=volatile in SCM_UNPACK
|
||||
when using libguile v2.0.10.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/guile/guile-internal.h | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/guile/guile-internal.h b/gdb/guile/guile-internal.h
|
||||
index be16fee0dd2..6665bfc7813 100644
|
||||
--- a/gdb/guile/guile-internal.h
|
||||
+++ b/gdb/guile/guile-internal.h
|
||||
@@ -27,10 +27,30 @@
|
||||
#include "hashtab.h"
|
||||
#include "extension-priv.h"
|
||||
#include "symtab.h"
|
||||
-#include "libguile.h"
|
||||
#include "objfiles.h"
|
||||
#include "top.h"
|
||||
|
||||
+/* For libguile v2.0.9 and SCM_DEBUG_TYPING_STRICTNESS == 1, SCM_UNPACK(x) is
|
||||
+ defined as:
|
||||
+
|
||||
+ ((scm_t_bits) (0? (*(SCM*)0=(x)): x))
|
||||
+
|
||||
+ and for v2.0.10 it's defined as:
|
||||
+
|
||||
+ ((scm_t_bits) (0? (*(volatile SCM *)0=(x)): x))
|
||||
+
|
||||
+ The volatile was added to avoid a clang warning.
|
||||
+
|
||||
+ The latter form causes a Werror=volatile with C++20.
|
||||
+ This was reported upstream (
|
||||
+ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=65333 ).
|
||||
+
|
||||
+ The former form causes a Werror=sequence-point with gcc 7-14.
|
||||
+
|
||||
+ Work around these problem by using SCM_DEBUG_TYPING_STRICTNESS == 0. */
|
||||
+#define SCM_DEBUG_TYPING_STRICTNESS 0
|
||||
+#include "libguile.h"
|
||||
+
|
||||
struct block;
|
||||
struct frame_info;
|
||||
struct objfile;
|
||||
|
||||
base-commit: 94df6741bbabaa9a51960446b2af4c0bed01b54b
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,226 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-linux_perf-bundle.patch
|
||||
|
||||
;; [dts+el7] [x86*] Bundle linux_perf.h for libipt (RH BZ 1256513).
|
||||
;;=fedora
|
||||
|
||||
diff --git a/gdb/gdb.c b/gdb/gdb.c
|
||||
--- a/gdb/gdb.c
|
||||
+++ b/gdb/gdb.c
|
||||
@@ -21,6 +21,10 @@
|
||||
#include "interps.h"
|
||||
#include "run-on-main-thread.h"
|
||||
|
||||
+#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+extern "C" void __libipt_init(void);
|
||||
+#endif
|
||||
+
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -32,6 +36,10 @@ main (int argc, char **argv)
|
||||
|
||||
struct captured_main_args args;
|
||||
|
||||
+#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+ __libipt_init();
|
||||
+#endif
|
||||
+
|
||||
memset (&args, 0, sizeof args);
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h
|
||||
--- a/gdb/nat/linux-btrace.h
|
||||
+++ b/gdb/nat/linux-btrace.h
|
||||
@@ -28,6 +28,177 @@
|
||||
# include <linux/perf_event.h>
|
||||
#endif
|
||||
|
||||
+#ifdef PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+#ifndef HAVE_LINUX_PERF_EVENT_H
|
||||
+# error "PERF_ATTR_SIZE_VER5_BUNDLE && !HAVE_LINUX_PERF_EVENT_H"
|
||||
+#endif
|
||||
+#ifndef PERF_ATTR_SIZE_VER5
|
||||
+#define PERF_ATTR_SIZE_VER5
|
||||
+#define perf_event_mmap_page perf_event_mmap_page_bundle
|
||||
+// kernel-headers-3.10.0-493.el7.x86_64/usr/include/linux/perf_event.h
|
||||
+/*
|
||||
+ * Structure of the page that can be mapped via mmap
|
||||
+ */
|
||||
+struct perf_event_mmap_page {
|
||||
+ __u32 version; /* version number of this structure */
|
||||
+ __u32 compat_version; /* lowest version this is compat with */
|
||||
+
|
||||
+ /*
|
||||
+ * Bits needed to read the hw events in user-space.
|
||||
+ *
|
||||
+ * u32 seq, time_mult, time_shift, index, width;
|
||||
+ * u64 count, enabled, running;
|
||||
+ * u64 cyc, time_offset;
|
||||
+ * s64 pmc = 0;
|
||||
+ *
|
||||
+ * do {
|
||||
+ * seq = pc->lock;
|
||||
+ * barrier()
|
||||
+ *
|
||||
+ * enabled = pc->time_enabled;
|
||||
+ * running = pc->time_running;
|
||||
+ *
|
||||
+ * if (pc->cap_usr_time && enabled != running) {
|
||||
+ * cyc = rdtsc();
|
||||
+ * time_offset = pc->time_offset;
|
||||
+ * time_mult = pc->time_mult;
|
||||
+ * time_shift = pc->time_shift;
|
||||
+ * }
|
||||
+ *
|
||||
+ * index = pc->index;
|
||||
+ * count = pc->offset;
|
||||
+ * if (pc->cap_user_rdpmc && index) {
|
||||
+ * width = pc->pmc_width;
|
||||
+ * pmc = rdpmc(index - 1);
|
||||
+ * }
|
||||
+ *
|
||||
+ * barrier();
|
||||
+ * } while (pc->lock != seq);
|
||||
+ *
|
||||
+ * NOTE: for obvious reason this only works on self-monitoring
|
||||
+ * processes.
|
||||
+ */
|
||||
+ __u32 lock; /* seqlock for synchronization */
|
||||
+ __u32 index; /* hardware event identifier */
|
||||
+ __s64 offset; /* add to hardware event value */
|
||||
+ __u64 time_enabled; /* time event active */
|
||||
+ __u64 time_running; /* time event on cpu */
|
||||
+ union {
|
||||
+ __u64 capabilities;
|
||||
+ struct {
|
||||
+ __u64 cap_bit0 : 1, /* Always 0, deprecated, see commit 860f085b74e9 */
|
||||
+ cap_bit0_is_deprecated : 1, /* Always 1, signals that bit 0 is zero */
|
||||
+
|
||||
+ cap_user_rdpmc : 1, /* The RDPMC instruction can be used to read counts */
|
||||
+ cap_user_time : 1, /* The time_* fields are used */
|
||||
+ cap_user_time_zero : 1, /* The time_zero field is used */
|
||||
+ cap_____res : 59;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ /*
|
||||
+ * If cap_user_rdpmc this field provides the bit-width of the value
|
||||
+ * read using the rdpmc() or equivalent instruction. This can be used
|
||||
+ * to sign extend the result like:
|
||||
+ *
|
||||
+ * pmc <<= 64 - width;
|
||||
+ * pmc >>= 64 - width; // signed shift right
|
||||
+ * count += pmc;
|
||||
+ */
|
||||
+ __u16 pmc_width;
|
||||
+
|
||||
+ /*
|
||||
+ * If cap_usr_time the below fields can be used to compute the time
|
||||
+ * delta since time_enabled (in ns) using rdtsc or similar.
|
||||
+ *
|
||||
+ * u64 quot, rem;
|
||||
+ * u64 delta;
|
||||
+ *
|
||||
+ * quot = (cyc >> time_shift);
|
||||
+ * rem = cyc & (((u64)1 << time_shift) - 1);
|
||||
+ * delta = time_offset + quot * time_mult +
|
||||
+ * ((rem * time_mult) >> time_shift);
|
||||
+ *
|
||||
+ * Where time_offset,time_mult,time_shift and cyc are read in the
|
||||
+ * seqcount loop described above. This delta can then be added to
|
||||
+ * enabled and possible running (if index), improving the scaling:
|
||||
+ *
|
||||
+ * enabled += delta;
|
||||
+ * if (index)
|
||||
+ * running += delta;
|
||||
+ *
|
||||
+ * quot = count / running;
|
||||
+ * rem = count % running;
|
||||
+ * count = quot * enabled + (rem * enabled) / running;
|
||||
+ */
|
||||
+ __u16 time_shift;
|
||||
+ __u32 time_mult;
|
||||
+ __u64 time_offset;
|
||||
+ /*
|
||||
+ * If cap_usr_time_zero, the hardware clock (e.g. TSC) can be calculated
|
||||
+ * from sample timestamps.
|
||||
+ *
|
||||
+ * time = timestamp - time_zero;
|
||||
+ * quot = time / time_mult;
|
||||
+ * rem = time % time_mult;
|
||||
+ * cyc = (quot << time_shift) + (rem << time_shift) / time_mult;
|
||||
+ *
|
||||
+ * And vice versa:
|
||||
+ *
|
||||
+ * quot = cyc >> time_shift;
|
||||
+ * rem = cyc & (((u64)1 << time_shift) - 1);
|
||||
+ * timestamp = time_zero + quot * time_mult +
|
||||
+ * ((rem * time_mult) >> time_shift);
|
||||
+ */
|
||||
+ __u64 time_zero;
|
||||
+ __u32 size; /* Header size up to __reserved[] fields. */
|
||||
+
|
||||
+ /*
|
||||
+ * Hole for extension of the self monitor capabilities
|
||||
+ */
|
||||
+
|
||||
+ __u8 __reserved[118*8+4]; /* align to 1k. */
|
||||
+
|
||||
+ /*
|
||||
+ * Control data for the mmap() data buffer.
|
||||
+ *
|
||||
+ * User-space reading the @data_head value should issue an smp_rmb(),
|
||||
+ * after reading this value.
|
||||
+ *
|
||||
+ * When the mapping is PROT_WRITE the @data_tail value should be
|
||||
+ * written by userspace to reflect the last read data, after issueing
|
||||
+ * an smp_mb() to separate the data read from the ->data_tail store.
|
||||
+ * In this case the kernel will not over-write unread data.
|
||||
+ *
|
||||
+ * See perf_output_put_handle() for the data ordering.
|
||||
+ *
|
||||
+ * data_{offset,size} indicate the location and size of the perf record
|
||||
+ * buffer within the mmapped area.
|
||||
+ */
|
||||
+ __u64 data_head; /* head in the data section */
|
||||
+ __u64 data_tail; /* user-space written tail */
|
||||
+ __u64 data_offset; /* where the buffer starts */
|
||||
+ __u64 data_size; /* data buffer size */
|
||||
+
|
||||
+ /*
|
||||
+ * AUX area is defined by aux_{offset,size} fields that should be set
|
||||
+ * by the userspace, so that
|
||||
+ *
|
||||
+ * aux_offset >= data_offset + data_size
|
||||
+ *
|
||||
+ * prior to mmap()ing it. Size of the mmap()ed area should be aux_size.
|
||||
+ *
|
||||
+ * Ring buffer pointers aux_{head,tail} have the same semantics as
|
||||
+ * data_{head,tail} and same ordering rules apply.
|
||||
+ */
|
||||
+ __u64 aux_head;
|
||||
+ __u64 aux_tail;
|
||||
+ __u64 aux_offset;
|
||||
+ __u64 aux_size;
|
||||
+};
|
||||
+#endif // PERF_ATTR_SIZE_VER5
|
||||
+#endif // PERF_ATTR_SIZE_VER5_BUNDLE
|
||||
+
|
||||
struct target_ops;
|
||||
|
||||
#if HAVE_LINUX_PERF_EVENT_H
|
||||
diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
|
||||
--- a/gdbsupport/common.m4
|
||||
+++ b/gdbsupport/common.m4
|
||||
@@ -168,7 +168,7 @@ AC_DEFUN([GDB_AC_COMMON], [
|
||||
AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <linux/perf_event.h>
|
||||
#ifndef PERF_ATTR_SIZE_VER5
|
||||
- # error
|
||||
+ // error // PERF_ATTR_SIZE_VER5_BUNDLE is not available here - Fedora+RHEL
|
||||
#endif
|
||||
]])], [perf_event=yes], [perf_event=no])
|
||||
if test "$perf_event" != yes; then
|
130
gdb-prune-inferior-after-switching-inferior.patch
Normal file
130
gdb-prune-inferior-after-switching-inferior.patch
Normal file
@ -0,0 +1,130 @@
|
||||
From 22d05b4879b8608e3768483735140a729952b565 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 18 Aug 2024 20:51:29 +0200
|
||||
Subject: [PATCH 39/46] [gdb] Prune inferior after switching inferior
|
||||
|
||||
Usually with test-case gdb.python/py-progspace-events.exp I get:
|
||||
...
|
||||
(gdb) inferior 1^M
|
||||
[Switching to inferior 1 [process 4116] (py-progspace-events)]^M
|
||||
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 4116))]^M
|
||||
28 { /* Nothing. */ }^M
|
||||
(gdb) PASS: gdb.python/py-progspace-events.exp: inferior 1
|
||||
step^M
|
||||
FreeProgspaceEvent: <gdb.Progspace object at 0xabf4f850>^M
|
||||
do_parent_stuff () at py-progspace-events.c:41^M
|
||||
41 ++global_var;^M
|
||||
(gdb) PASS: gdb.python/py-progspace-events.exp: step
|
||||
...
|
||||
|
||||
But occasionally I run into the following FAIL:
|
||||
...
|
||||
(gdb) inferior 1^M
|
||||
[Switching to inferior 1 [process 5199] (py-progspace-events)]^M
|
||||
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 5199))]^M
|
||||
28 { /* Nothing. */ }^M
|
||||
(gdb) FreeProgspaceEvent: <gdb.Progspace object at 0xabaf03a0>^M
|
||||
FAIL: gdb.python/py-progspace-events.exp: inferior 1 (timeout)
|
||||
...
|
||||
|
||||
This is caused by a race between the handling of an event, and the
|
||||
"inferior 1" command.
|
||||
|
||||
In the passing case, the event is handled first. During which prune_inferiors
|
||||
is called, but it can't remove inferior 2, because it's still the current one.
|
||||
|
||||
In the failing case, the "inferior 1" command is handled first. Then during
|
||||
handling of the event, prune_inferiors is called, and it can remove inferior 2
|
||||
because it's no longer the current one.
|
||||
|
||||
This looks like a test-case issue to me, but ISTM that we can do better: by
|
||||
calling prune_inferiors asap, at the end of the "inferior 1" command, we
|
||||
stabilize the moment when the inferior is removed:
|
||||
...
|
||||
(gdb) inferior 1^M
|
||||
[Switching to inferior 1 [process 5199] (py-progspace-events)]^M
|
||||
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 5199))]^M
|
||||
28 { /* Nothing. */ }^M
|
||||
FreeProgspaceEvent: <gdb.Progspace object at 0xabaf03a0>^M
|
||||
(gdb) PASS: gdb.python/py-progspace-events.exp: inferior 1
|
||||
...
|
||||
|
||||
This also allows us to simplify the test-case by removing the step command,
|
||||
which is no longer required to trigger the pruning of the inferior.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-by: Kevin Buettner <kevinb@redhat.com>
|
||||
|
||||
PR gdb/31440
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31440
|
||||
---
|
||||
gdb/inferior.c | 4 +++
|
||||
.../gdb.python/py-progspace-events.exp | 31 +++----------------
|
||||
2 files changed, 9 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/gdb/inferior.c b/gdb/inferior.c
|
||||
index 0522cb5c14d..2a19c5b19a1 100644
|
||||
--- a/gdb/inferior.c
|
||||
+++ b/gdb/inferior.c
|
||||
@@ -790,6 +790,10 @@ inferior_command (const char *args, int from_tty)
|
||||
notify_user_selected_context_changed
|
||||
(USER_SELECTED_INFERIOR);
|
||||
}
|
||||
+
|
||||
+ /* Switching current inferior may have made one of the inferiors
|
||||
+ prunable, so prune it. */
|
||||
+ prune_inferiors ();
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/py-progspace-events.exp b/gdb/testsuite/gdb.python/py-progspace-events.exp
|
||||
index 95e4ca8da0b..9dfc7573d40 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-progspace-events.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-progspace-events.exp
|
||||
@@ -79,37 +79,16 @@ gdb_test "continue" \
|
||||
"\\\[Inferior $decimal \[^\r\n\]+ exited normally\\\]"] \
|
||||
"continue until inferior 2 exits"
|
||||
|
||||
-gdb_test "inferior 1" "\\\[Switching to inferior 1 .*"
|
||||
-
|
||||
-# Step the inferior. During this process GDB will prune the now
|
||||
+# Switch to inferior 1. During this process GDB will prune the now
|
||||
# defunct inferior, which deletes its program space, which should
|
||||
# trigger the FreeProgspaceEvent.
|
||||
#
|
||||
-# However, there is a slight problem. When the target is remote, and
|
||||
-# GDB is accessing files using remote fileio, then GDB will attempt to
|
||||
-# prune the inferior at a point in time when the remote target is
|
||||
-# waiting for a stop reply. Pruning an inferior causes GDB to close
|
||||
-# files associated with that inferior.
|
||||
-#
|
||||
-# In non-async mode we can't send fileio packets while waiting for a
|
||||
-# stop reply, so the attempts to close files fails, and this shows up
|
||||
-# as an error.
|
||||
-#
|
||||
-# As this error has nothing to do with the feature being tested here,
|
||||
-# we just accept the error message, the important part is the
|
||||
-# 'FreeProgspaceEvent' string, so long as that appears (just once)
|
||||
-# then the test is a success.
|
||||
-set warning_msg \
|
||||
- [multi_line \
|
||||
- "warning: cannot close \"\[^\r\n\]+\": Cannot execute this command while the target is running\\." \
|
||||
- "Use the \"interrupt\" command to stop the target" \
|
||||
- "and then try again\\."]
|
||||
|
||||
-gdb_test "step" \
|
||||
+gdb_test "inferior 1" \
|
||||
[multi_line \
|
||||
- "^FreeProgspaceEvent.*: <gdb.Progspace object at $hex>(?:\r\n$warning_msg)*" \
|
||||
- "do_parent_stuff \\(\\) at \[^\r\n\]+" \
|
||||
- "$decimal\\s+\[^\r\n\]+"]
|
||||
+ "\\\[Switching to inferior 1 .*" \
|
||||
+ ".*" \
|
||||
+ "FreeProgspaceEvent.*: <gdb.Progspace object at $hex>"]
|
||||
|
||||
# Let this inferior run to completion.
|
||||
gdb_continue_to_end
|
||||
--
|
||||
2.43.0
|
||||
|
108
gdb-python-avoid-depending-on-the-curses-library.patch
Normal file
108
gdb-python-avoid-depending-on-the-curses-library.patch
Normal file
@ -0,0 +1,108 @@
|
||||
From a4ebf1e476b56777474584b653485bf3dc7068cc Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Mon, 9 Sep 2024 17:33:54 +0100
|
||||
Subject: [PATCH] gdb/python: avoid depending on the curses library
|
||||
|
||||
The commit:
|
||||
|
||||
commit 29c70787112e01cd52b53bf14bdcacb0a11e0725
|
||||
Date: Sun Sep 8 07:46:09 2024 +0200
|
||||
|
||||
[gdb/testsuite] Handle missing curses in gdb.python/py-missing-debug.exp
|
||||
|
||||
Highlighted that in some cases we might be running on a system with an
|
||||
older version of Python (earlier than 3.7), and on a system for which
|
||||
the curses library has not been installed.
|
||||
|
||||
In these circumstances the gdb.missing_debug module will not load as
|
||||
it uses curses to provide isalnum() and isascii() functions.
|
||||
|
||||
To avoid this problem I propose that we copy the isalnum() and
|
||||
isascii() from the Python curses library. These functions are
|
||||
basically trivial and removing the curses dependency means GDB will
|
||||
work in more cases without increasing its dependencies.
|
||||
|
||||
I did consider keeping the uses of curses and only having the function
|
||||
definitions be a fallback for when the curses library failed to load,
|
||||
but this felt like overkill. The function definitions are both tiny
|
||||
and I think "obvious" given their specifications, so I figure we might
|
||||
as well just use our own definitions if they are not available as
|
||||
builtin methods on the str class.
|
||||
|
||||
For testing I changed this line:
|
||||
|
||||
if sys.version_info >= (3, 7):
|
||||
|
||||
to
|
||||
|
||||
if sys.version_info >= (3, 7) and False:
|
||||
|
||||
then reran gdb.python/py-missing-debug.exp, there were no failures.
|
||||
|
||||
Approved-By: Tom de Vries <tdevries@suse.de>
|
||||
---
|
||||
gdb/python/lib/gdb/missing_debug.py | 30 ++++++++++++++++++++++++++---
|
||||
1 file changed, 27 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/lib/gdb/missing_debug.py b/gdb/python/lib/gdb/missing_debug.py
|
||||
index 4256947ff77..cdeea30256d 100644
|
||||
--- a/gdb/python/lib/gdb/missing_debug.py
|
||||
+++ b/gdb/python/lib/gdb/missing_debug.py
|
||||
@@ -32,9 +32,33 @@ if sys.version_info >= (3, 7):
|
||||
return ch.isalnum()
|
||||
|
||||
else:
|
||||
- # Fall back to curses.ascii.isascii() and curses.ascii.isalnum() for
|
||||
- # earlier versions.
|
||||
- from curses.ascii import isalnum, isascii
|
||||
+ # Older version of Python doesn't have str.isascii() and
|
||||
+ # str.isalnum() so provide our own.
|
||||
+ #
|
||||
+ # We could import isalnum() and isascii() from the curses library,
|
||||
+ # but that adds an extra dependency. Given these functions are
|
||||
+ # both small and trivial lets implement them here.
|
||||
+ #
|
||||
+ # These definitions are based on those in the curses library, but
|
||||
+ # simplified as we know C will always be a single character 'str'.
|
||||
+
|
||||
+ def isdigit(c):
|
||||
+ return 48 <= ord(c) <= 57
|
||||
+
|
||||
+ def islower(c):
|
||||
+ return 97 <= ord(c) <= 122
|
||||
+
|
||||
+ def isupper(c):
|
||||
+ return 65 <= ord(c) <= 90
|
||||
+
|
||||
+ def isalpha(c):
|
||||
+ return isupper(c) or islower(c)
|
||||
+
|
||||
+ def isalnum(c):
|
||||
+ return isalpha(c) or isdigit(c)
|
||||
+
|
||||
+ def isascii(c):
|
||||
+ return 0 <= ord(c) <= 127
|
||||
|
||||
|
||||
def _validate_name(name):
|
||||
|
||||
base-commit: b3f9f8454fe3f83754b130dd7aa26b62d4311bde
|
||||
prerequisite-patch-id: 77507b16457eeed54f9c51f9d3899c91bc6739ca
|
||||
prerequisite-patch-id: aec1fa16069ec9c14b671130354a5006b1739a34
|
||||
prerequisite-patch-id: a02aede530a3b3d0c64cd96ef7c2181e2886c3c5
|
||||
prerequisite-patch-id: 720d8081d37ae4b658b7e82ec96a39a82fdc8015
|
||||
prerequisite-patch-id: de6a537726187fa4b145246307af23449ae8fd3b
|
||||
prerequisite-patch-id: 4c8aa2b7f59cde2aa886b3a8e134b58f58ed92de
|
||||
prerequisite-patch-id: 913a84de7152200996b8bc6c6d241f95b4206294
|
||||
prerequisite-patch-id: af18dce2bc2a8c529dfd4b67c4514d4a94fe1f28
|
||||
prerequisite-patch-id: 07d1b82048ab34b0a037cf1c0ba1cb25bf7ec6eb
|
||||
prerequisite-patch-id: f7311861f758921d385103bcae9d72ccfb12db4d
|
||||
prerequisite-patch-id: 15dbe4af0de7b6c098c38a8c767d7166033e03c1
|
||||
prerequisite-patch-id: d27daff5cb15b862e7b48a41389b219040702c9d
|
||||
prerequisite-patch-id: 581089bf2af1e30e5e1e00d01df5b164cb5794cf
|
||||
prerequisite-patch-id: d2419f88c98cd8c7be804fd246eeb38d18dd0bda
|
||||
prerequisite-patch-id: b1806f9e902e5ceb32f31438cb059843461d78eb
|
||||
prerequisite-patch-id: c73d4526570e04107c3278cb8b5142d4a6665374
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From adfcabe4cc43766996a61bdf08ce1e9db7f18dcc Mon Sep 17 00:00:00 2001
|
||||
From 086a725aa02b1195f63b2df4c2a2b4516788b2c6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 18 Apr 2024 14:27:04 +0200
|
||||
Subject: [PATCH] gdb-python-finishbreakpoint-update
|
||||
Subject: [PATCH 42/46] gdb-python-finishbreakpoint-update
|
||||
|
||||
[gdb/python] FinishBreakPoint update
|
||||
|
||||
@ -337,10 +337,10 @@ and running the test-cases:
|
||||
4 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||
index db7d2e6a8e5..01f187ca4fe 100644
|
||||
index 5653842ce76..6e10914a316 100644
|
||||
--- a/gdb/breakpoint.c
|
||||
+++ b/gdb/breakpoint.c
|
||||
@@ -14683,6 +14683,10 @@ breakpoint_free_objfile (struct objfile *objfile)
|
||||
@@ -14693,6 +14693,10 @@ breakpoint_free_objfile (struct objfile *objfile)
|
||||
|
||||
static struct cmd_list_element *enablebreaklist = NULL;
|
||||
|
||||
@ -351,7 +351,7 @@ index db7d2e6a8e5..01f187ca4fe 100644
|
||||
/* See breakpoint.h. */
|
||||
|
||||
cmd_list_element *commands_cmd_element = nullptr;
|
||||
@@ -15243,8 +15247,14 @@ This is useful for formatted output in user-defined commands."));
|
||||
@@ -15255,8 +15259,14 @@ This is useful for formatted output in user-defined commands."));
|
||||
|
||||
gdb::observers::about_to_proceed.attach (breakpoint_about_to_proceed,
|
||||
"breakpoint");
|
||||
@ -367,10 +367,10 @@ index db7d2e6a8e5..01f187ca4fe 100644
|
||||
"breakpoint");
|
||||
}
|
||||
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
|
||||
index 99670cca025..ba414b4e2c3 100644
|
||||
index 86ccc140c6d..e49cc580b1b 100644
|
||||
--- a/gdb/doc/python.texi
|
||||
+++ b/gdb/doc/python.texi
|
||||
@@ -6648,7 +6648,7 @@ is not writable.
|
||||
@@ -6882,7 +6882,7 @@ is not writable.
|
||||
@tindex gdb.FinishBreakpoint
|
||||
|
||||
A finish breakpoint is a temporary breakpoint set at the return address of
|
||||
@ -379,7 +379,7 @@ index 99670cca025..ba414b4e2c3 100644
|
||||
extends @code{gdb.Breakpoint}. The underlying breakpoint will be disabled
|
||||
and deleted when the execution will run out of the breakpoint scope (i.e.@:
|
||||
@code{Breakpoint.stop} or @code{FinishBreakpoint.out_of_scope} triggered).
|
||||
@@ -6667,7 +6667,9 @@ details about this argument.
|
||||
@@ -6901,7 +6901,9 @@ details about this argument.
|
||||
In some circumstances (e.g.@: @code{longjmp}, C@t{++} exceptions, @value{GDBN}
|
||||
@code{return} command, @dots{}), a function may not properly terminate, and
|
||||
thus never hit the finish breakpoint. When @value{GDBN} notices such a
|
||||
@ -391,7 +391,7 @@ index 99670cca025..ba414b4e2c3 100644
|
||||
You may want to sub-class @code{gdb.FinishBreakpoint} and override this
|
||||
method:
|
||||
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
|
||||
index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
index c74a2473a81..957d4ebc142 100644
|
||||
--- a/gdb/python/py-finishbreakpoint.c
|
||||
+++ b/gdb/python/py-finishbreakpoint.c
|
||||
@@ -433,6 +433,24 @@ bpfinishpy_handle_exit (struct inferior *inf)
|
||||
@ -402,9 +402,9 @@ index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
+ scope notifications. */
|
||||
+
|
||||
+static void
|
||||
+bpfinishpy_handle_thread_exit (struct thread_info *tp, gdb::optional<ULONGEST>, bool)
|
||||
+bpfinishpy_handle_thread_exit (struct thread_info *tp, std::optional<ULONGEST>, bool)
|
||||
+{
|
||||
+ gdbpy_enter enter_py (target_gdbarch (), current_language);
|
||||
+ gdbpy_enter enter_py (target_thread_architecture (tp->ptid), current_language);
|
||||
+
|
||||
+ for (breakpoint &bp : all_breakpoints_safe ())
|
||||
+ {
|
||||
@ -429,7 +429,7 @@ index 42a7e0706d2..fa7ec43fbb4 100644
|
||||
return 0;
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
index 66587b8b9a0..31479a05e6f 100644
|
||||
index b837bb3a108..7d99aad2fd2 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-finish-breakpoint2.exp
|
||||
@@ -87,6 +87,7 @@ if { $need_continue } {
|
||||
@ -440,8 +440,6 @@ index 66587b8b9a0..31479a05e6f 100644
|
||||
gdb_test "python ExceptionFinishBreakpoint(gdb.newest_frame())" \
|
||||
"init ExceptionFinishBreakpoint" "set FinishBP after the exception again"
|
||||
|
||||
|
||||
base-commit: 6de9111c512de99fd8cb3ea89f9890b1d72f6ef0
|
||||
--
|
||||
2.35.3
|
||||
2.43.0
|
||||
|
||||
|
@ -1,125 +0,0 @@
|
||||
From 4c7dab250c3581e691c2da87395e80244074d8bf Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 10 Jun 2024 17:53:30 +0200
|
||||
Subject: [PATCH] [gdb/python] Fix gdb.python/py-disasm.exp on arm-linux
|
||||
|
||||
After fixing test-case gdb.python/py-disasm.exp to recognize the arm nop:
|
||||
...
|
||||
nop {0}
|
||||
...
|
||||
we run into:
|
||||
...
|
||||
disassemble test^M
|
||||
Dump of assembler code for function test:^M
|
||||
0x004004d8 <+0>: push {r11} @ (str r11, [sp, #-4]!)^M
|
||||
0x004004dc <+4>: add r11, sp, #0^M
|
||||
0x004004e0 <+8>: nop {0}^M
|
||||
=> 0x004004e4 <+12>: Python Exception <class 'ValueError'>: Buffer \
|
||||
returned from read_memory is sized 0 instead of the expected 4^M
|
||||
^M
|
||||
unknown disassembler error (error = -1)^M
|
||||
(gdb) FAIL: $exp: global_disassembler=ShowInfoRepr: disassemble test
|
||||
...
|
||||
|
||||
This is caused by this code in gdbpy_disassembler::read_memory_func:
|
||||
...
|
||||
gdbpy_ref<> result_obj (PyObject_CallMethod ((PyObject *) obj,
|
||||
"read_memory",
|
||||
"KL", len, offset));
|
||||
...
|
||||
where len has type "unsigned int", while "K" means "unsigned long long" [1].
|
||||
|
||||
Fix this by using "I" instead, meaning "unsigned int".
|
||||
|
||||
Also, offset has type LONGEST, which is typedef'ed to int64_t, while "L" means
|
||||
"long long".
|
||||
|
||||
Fix this by using type gdb_py_longest for offset, in combination with format
|
||||
character "GDB_PY_LL_ARG". Likewise in disasmpy_info_read_memory.
|
||||
|
||||
Tested on arm-linux.
|
||||
|
||||
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR python/31845
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31845
|
||||
|
||||
[1] https://docs.python.org/3/c-api/arg.html
|
||||
|
||||
(cherry picked from commit 4cd214dce4579f86a85a96c882e0fc8c4d94601c)
|
||||
---
|
||||
gdb/python/py-disasm.c | 12 +++++++-----
|
||||
gdb/testsuite/gdb.python/py-disasm.exp | 2 +-
|
||||
gdb/testsuite/gdb.python/py-disasm.py | 2 +-
|
||||
3 files changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
|
||||
index 6f0fed137e6..b2e95b3cba6 100644
|
||||
--- a/gdb/python/py-disasm.c
|
||||
+++ b/gdb/python/py-disasm.c
|
||||
@@ -668,12 +668,13 @@ disasmpy_info_read_memory (PyObject *self, PyObject *args, PyObject *kw)
|
||||
disasm_info_object *obj = (disasm_info_object *) self;
|
||||
DISASMPY_DISASM_INFO_REQUIRE_VALID (obj);
|
||||
|
||||
- LONGEST length, offset = 0;
|
||||
+ gdb_py_longest length, offset = 0;
|
||||
gdb::unique_xmalloc_ptr<gdb_byte> buffer;
|
||||
static const char *keywords[] = { "length", "offset", nullptr };
|
||||
|
||||
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "L|L", keywords,
|
||||
- &length, &offset))
|
||||
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw,
|
||||
+ GDB_PY_LL_ARG "|" GDB_PY_LL_ARG,
|
||||
+ keywords, &length, &offset))
|
||||
return nullptr;
|
||||
|
||||
/* The apparent address from which we are reading memory. Note that in
|
||||
@@ -850,13 +851,14 @@ gdbpy_disassembler::read_memory_func (bfd_vma memaddr, gdb_byte *buff,
|
||||
/* The DisassembleInfo.read_memory method expects an offset from the
|
||||
address stored within the DisassembleInfo object; calculate that
|
||||
offset here. */
|
||||
- LONGEST offset = (LONGEST) memaddr - (LONGEST) obj->address;
|
||||
+ gdb_py_longest offset
|
||||
+ = (gdb_py_longest) memaddr - (gdb_py_longest) obj->address;
|
||||
|
||||
/* Now call the DisassembleInfo.read_memory method. This might have been
|
||||
overridden by the user. */
|
||||
gdbpy_ref<> result_obj (PyObject_CallMethod ((PyObject *) obj,
|
||||
"read_memory",
|
||||
- "KL", len, offset));
|
||||
+ "I" GDB_PY_LL_ARG, len, offset));
|
||||
|
||||
/* Handle any exceptions. */
|
||||
if (result_obj == nullptr)
|
||||
diff --git a/gdb/testsuite/gdb.python/py-disasm.exp b/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
index f2f9225168a..9d0f6ec1d01 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
+++ b/gdb/testsuite/gdb.python/py-disasm.exp
|
||||
@@ -65,7 +65,7 @@ proc py_remove_all_disassemblers {} {
|
||||
#
|
||||
# Each different disassembler tests some different feature of the
|
||||
# Python disassembler API.
|
||||
-set nop "(nop|nop\t0)"
|
||||
+set nop "(nop|nop\t0|[string_to_regexp nop\t{0}])"
|
||||
set unknown_error_pattern "unknown disassembler error \\(error = -1\\)"
|
||||
set addr_pattern "\r\n=> ${curr_pc_pattern} <\[^>\]+>:\\s+"
|
||||
set base_pattern "${addr_pattern}${nop}"
|
||||
diff --git a/gdb/testsuite/gdb.python/py-disasm.py b/gdb/testsuite/gdb.python/py-disasm.py
|
||||
index 67ba6756ea9..6a39b0764e6 100644
|
||||
--- a/gdb/testsuite/gdb.python/py-disasm.py
|
||||
+++ b/gdb/testsuite/gdb.python/py-disasm.py
|
||||
@@ -46,7 +46,7 @@ def check_building_disassemble_result():
|
||||
|
||||
|
||||
def is_nop(s):
|
||||
- return s == "nop" or s == "nop\t0"
|
||||
+ return s == "nop" or s == "nop\t0" or s == "nop\t{0}"
|
||||
|
||||
|
||||
# Remove all currently registered disassemblers.
|
||||
|
||||
base-commit: 22383ac8031b0e626e8ecd62e4378266065d067c
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,70 +0,0 @@
|
||||
From fc73000faa1798573090994167b7e2d451c211db Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 10 May 2024 08:46:21 +0200
|
||||
Subject: [PATCH] [gdb/python] Make gdb.UnwindInfo.add_saved_register more
|
||||
robust (fixup)
|
||||
|
||||
In commit 2236c5e384d ("[gdb/python] Make gdb.UnwindInfo.add_saved_register
|
||||
more robust") I added this code in unwind_infopy_add_saved_register:
|
||||
...
|
||||
if (value->optimized_out () || !value->entirely_available ())
|
||||
...
|
||||
which may throw c++ exceptions.
|
||||
|
||||
This needs to be caught and transformed into a python exception.
|
||||
|
||||
Fix this by using GDB_PY_HANDLE_EXCEPTION.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
Fixes: 2236c5e384d ("[gdb/python] Make gdb.UnwindInfo.add_saved_register more robust")
|
||||
(cherry picked from commit 408bc9c5fc757bd4b8adb1c3d54ecd672beaedb7)
|
||||
---
|
||||
gdb/python/py-unwind.c | 26 +++++++++++++++++---------
|
||||
1 file changed, 17 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
|
||||
index 471eb851674..e57c8c1adcf 100644
|
||||
--- a/gdb/python/py-unwind.c
|
||||
+++ b/gdb/python/py-unwind.c
|
||||
@@ -354,16 +354,24 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
- if (value->optimized_out () || !value->entirely_available ())
|
||||
+
|
||||
+ try
|
||||
+ {
|
||||
+ if (value->optimized_out () || !value->entirely_available ())
|
||||
+ {
|
||||
+ /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
+ to run into an exception when trying to access its contents.
|
||||
+ Throwing an exception here just puts a burden on the user to
|
||||
+ implement the same checks on the user side. We could return False
|
||||
+ here and True otherwise, but again that might require changes in
|
||||
+ user code. So, handle this with minimal impact for the user, while
|
||||
+ improving robustness: silently ignore the register/value pair. */
|
||||
+ Py_RETURN_NONE;
|
||||
+ }
|
||||
+ }
|
||||
+ catch (const gdb_exception &except)
|
||||
{
|
||||
- /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
- to run into an exception when trying to access its contents.
|
||||
- Throwing an exception here just puts a burden on the user to
|
||||
- implement the same checks on the user side. We could return False
|
||||
- here and True otherwise, but again that might require changes in user
|
||||
- code. So, handle this with minimal impact for the user, while
|
||||
- improving robustness: silently ignore the register/value pair. */
|
||||
- Py_RETURN_NONE;
|
||||
+ GDB_PY_HANDLE_EXCEPTION (except);
|
||||
}
|
||||
|
||||
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
|
||||
|
||||
base-commit: a6f598be3d0477c5c59bd490573a5d457949658e
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,61 +0,0 @@
|
||||
From eafca1ce3d589c731927e5481199db715bcbeff3 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 2 Mar 2024 09:35:22 +0100
|
||||
Subject: [PATCH 2/2] [gdb/python] Make gdb.UnwindInfo.add_saved_register more
|
||||
robust
|
||||
|
||||
On arm-linux, until commit bbb12eb9c84 ("gdb/arm: Remove tpidruro register
|
||||
from non-FreeBSD target descriptions") I ran into:
|
||||
...
|
||||
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: \
|
||||
backtrace when the unwind is broken at frame 5
|
||||
...
|
||||
|
||||
What happens is the following:
|
||||
- the TestUnwinder from inline-frame-cycle-unwind.py calls
|
||||
gdb.UnwindInfo.add_saved_register with reg == tpidruro and value
|
||||
"<unavailable>",
|
||||
- pyuw_sniffer calls value->contents ().data () to access the value of the
|
||||
register, which throws an UNAVAILABLE_ERROR,
|
||||
- this causes the TestUnwinder unwinder to fail, after which another unwinder
|
||||
succeeds and returns the correct frame, and
|
||||
- the test-case fails because it's counting on the TestUnwinder to succeed and
|
||||
return an incorrect frame.
|
||||
|
||||
Fix this by checking for !value::entirely_available as well as
|
||||
valued::optimized_out in unwind_infopy_add_saved_register.
|
||||
|
||||
Tested on x86_64-linux and arm-linux.
|
||||
|
||||
PR python/31437
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31437
|
||||
---
|
||||
gdb/python/py-unwind.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
|
||||
index 1856e41e2a1..471eb851674 100644
|
||||
--- a/gdb/python/py-unwind.c
|
||||
+++ b/gdb/python/py-unwind.c
|
||||
@@ -354,6 +354,18 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+ if (value->optimized_out () || !value->entirely_available ())
|
||||
+ {
|
||||
+ /* If we allow this value to be registered here, pyuw_sniffer is going
|
||||
+ to run into an exception when trying to access its contents.
|
||||
+ Throwing an exception here just puts a burden on the user to
|
||||
+ implement the same checks on the user side. We could return False
|
||||
+ here and True otherwise, but again that might require changes in user
|
||||
+ code. So, handle this with minimal impact for the user, while
|
||||
+ improving robustness: silently ignore the register/value pair. */
|
||||
+ Py_RETURN_NONE;
|
||||
+ }
|
||||
+
|
||||
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
|
||||
bool found = false;
|
||||
for (saved_reg ® : *unwind_info->saved_regs)
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,229 +0,0 @@
|
||||
From 0ad71e3088f345101085a1f72e81a000a100db18 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 27 Apr 2024 17:48:22 +0200
|
||||
Subject: [PATCH 25/48] [gdb/remote] Fix abort on REMOTE_CLOSE_ERROR
|
||||
|
||||
When running test-case gdb.server/connect-with-no-symbol-file.exp on
|
||||
aarch64-linux (specifically, an opensuse leap 15.5 container on a
|
||||
fedora asahi 39 system), I run into:
|
||||
...
|
||||
(gdb) detach^M
|
||||
Detaching from program: target:connect-with-no-symbol-file, process 185104^M
|
||||
Ending remote debugging.^M
|
||||
terminate called after throwing an instance of 'gdb_exception_error'^M
|
||||
...
|
||||
|
||||
The detailed backtrace of the corefile is:
|
||||
...
|
||||
(gdb) bt
|
||||
#0 0x0000ffff75504f54 in raise () from /lib64/libpthread.so.0
|
||||
#1 0x00000000007a86b4 in handle_fatal_signal (sig=6)
|
||||
at gdb/event-top.c:926
|
||||
#2 <signal handler called>
|
||||
#3 0x0000ffff74b977b4 in raise () from /lib64/libc.so.6
|
||||
#4 0x0000ffff74b98c18 in abort () from /lib64/libc.so.6
|
||||
#5 0x0000ffff74ea26f4 in __gnu_cxx::__verbose_terminate_handler() ()
|
||||
from /usr/lib64/libstdc++.so.6
|
||||
#6 0x0000ffff74ea011c in ?? () from /usr/lib64/libstdc++.so.6
|
||||
#7 0x0000ffff74ea0180 in std::terminate() () from /usr/lib64/libstdc++.so.6
|
||||
#8 0x0000ffff74ea0464 in __cxa_throw () from /usr/lib64/libstdc++.so.6
|
||||
#9 0x0000000001548870 in throw_it (reason=RETURN_ERROR,
|
||||
error=TARGET_CLOSE_ERROR, fmt=0x16c7810 "Remote connection closed", ap=...)
|
||||
at gdbsupport/common-exceptions.cc:203
|
||||
#10 0x0000000001548920 in throw_verror (error=TARGET_CLOSE_ERROR,
|
||||
fmt=0x16c7810 "Remote connection closed", ap=...)
|
||||
at gdbsupport/common-exceptions.cc:211
|
||||
#11 0x0000000001548a00 in throw_error (error=TARGET_CLOSE_ERROR,
|
||||
fmt=0x16c7810 "Remote connection closed")
|
||||
at gdbsupport/common-exceptions.cc:226
|
||||
#12 0x0000000000ac8f2c in remote_target::readchar (this=0x233d3d90, timeout=2)
|
||||
at gdb/remote.c:9856
|
||||
#13 0x0000000000ac9f04 in remote_target::getpkt (this=0x233d3d90,
|
||||
buf=0x233d40a8, forever=false, is_notif=0x0) at gdb/remote.c:10326
|
||||
#14 0x0000000000acf3d0 in remote_target::remote_hostio_send_command
|
||||
(this=0x233d3d90, command_bytes=13, which_packet=17,
|
||||
remote_errno=0xfffff1a3cf38, attachment=0xfffff1a3ce88,
|
||||
attachment_len=0xfffff1a3ce90) at gdb/remote.c:12567
|
||||
#15 0x0000000000ad03bc in remote_target::fileio_fstat (this=0x233d3d90, fd=3,
|
||||
st=0xfffff1a3d020, remote_errno=0xfffff1a3cf38)
|
||||
at gdb/remote.c:12979
|
||||
#16 0x0000000000c39878 in target_fileio_fstat (fd=0, sb=0xfffff1a3d020,
|
||||
target_errno=0xfffff1a3cf38) at gdb/target.c:3315
|
||||
#17 0x00000000007eee5c in target_fileio_stream::stat (this=0x233d4400,
|
||||
abfd=0x2323fc40, sb=0xfffff1a3d020) at gdb/gdb_bfd.c:467
|
||||
#18 0x00000000007f012c in <lambda(bfd*, void*, stat*)>::operator()(bfd *,
|
||||
void *, stat *) const (__closure=0x0, abfd=0x2323fc40, stream=0x233d4400,
|
||||
sb=0xfffff1a3d020) at gdb/gdb_bfd.c:955
|
||||
#19 0x00000000007f015c in <lambda(bfd*, void*, stat*)>::_FUN(bfd *, void *,
|
||||
stat *) () at gdb/gdb_bfd.c:956
|
||||
#20 0x0000000000f9b838 in opncls_bstat (abfd=0x2323fc40, sb=0xfffff1a3d020)
|
||||
at bfd/opncls.c:665
|
||||
#21 0x0000000000f90adc in bfd_stat (abfd=0x2323fc40, statbuf=0xfffff1a3d020)
|
||||
at bfd/bfdio.c:431
|
||||
#22 0x000000000065fe20 in reopen_exec_file () at gdb/corefile.c:52
|
||||
#23 0x0000000000c3a3e8 in generic_mourn_inferior ()
|
||||
at gdb/target.c:3642
|
||||
#24 0x0000000000abf3f0 in remote_unpush_target (target=0x233d3d90)
|
||||
at gdb/remote.c:6067
|
||||
#25 0x0000000000aca8b0 in remote_target::mourn_inferior (this=0x233d3d90)
|
||||
at gdb/remote.c:10587
|
||||
#26 0x0000000000c387cc in target_mourn_inferior (
|
||||
ptid=<error reading variable: Cannot access memory at address 0x2d310>)
|
||||
at gdb/target.c:2738
|
||||
#27 0x0000000000abfff0 in remote_target::remote_detach_1 (this=0x233d3d90,
|
||||
inf=0x22fce540, from_tty=1) at gdb/remote.c:6421
|
||||
#28 0x0000000000ac0094 in remote_target::detach (this=0x233d3d90,
|
||||
inf=0x22fce540, from_tty=1) at gdb/remote.c:6436
|
||||
#29 0x0000000000c37c3c in target_detach (inf=0x22fce540, from_tty=1)
|
||||
at gdb/target.c:2526
|
||||
#30 0x0000000000860424 in detach_command (args=0x0, from_tty=1)
|
||||
at gdb/infcmd.c:2817
|
||||
#31 0x000000000060b594 in do_simple_func (args=0x0, from_tty=1, c=0x231431a0)
|
||||
at gdb/cli/cli-decode.c:94
|
||||
#32 0x00000000006108c8 in cmd_func (cmd=0x231431a0, args=0x0, from_tty=1)
|
||||
at gdb/cli/cli-decode.c:2741
|
||||
#33 0x0000000000c65a94 in execute_command (p=0x232e52f6 "", from_tty=1)
|
||||
at gdb/top.c:570
|
||||
#34 0x00000000007a7d2c in command_handler (command=0x232e52f0 "")
|
||||
at gdb/event-top.c:566
|
||||
#35 0x00000000007a8290 in command_line_handler (rl=...)
|
||||
at gdb/event-top.c:802
|
||||
#36 0x0000000000c9092c in tui_command_line_handler (rl=...)
|
||||
at gdb/tui/tui-interp.c:103
|
||||
#37 0x00000000007a750c in gdb_rl_callback_handler (rl=0x23385330 "detach")
|
||||
at gdb/event-top.c:258
|
||||
#38 0x0000000000d910f4 in rl_callback_read_char ()
|
||||
at readline/readline/callback.c:290
|
||||
#39 0x00000000007a7338 in gdb_rl_callback_read_char_wrapper_noexcept ()
|
||||
at gdb/event-top.c:194
|
||||
#40 0x00000000007a73f0 in gdb_rl_callback_read_char_wrapper
|
||||
(client_data=0x22fbf640) at gdb/event-top.c:233
|
||||
#41 0x0000000000cbee1c in stdin_event_handler (error=0, client_data=0x22fbf640)
|
||||
at gdb/ui.c:154
|
||||
#42 0x000000000154ed60 in handle_file_event (file_ptr=0x232be730, ready_mask=1)
|
||||
at gdbsupport/event-loop.cc:572
|
||||
#43 0x000000000154f21c in gdb_wait_for_event (block=1)
|
||||
at gdbsupport/event-loop.cc:693
|
||||
#44 0x000000000154dec4 in gdb_do_one_event (mstimeout=-1)
|
||||
at gdbsupport/event-loop.cc:263
|
||||
#45 0x0000000000910f98 in start_event_loop () at gdb/main.c:400
|
||||
#46 0x0000000000911130 in captured_command_loop () at gdb/main.c:464
|
||||
#47 0x0000000000912b5c in captured_main (data=0xfffff1a3db58)
|
||||
at gdb/main.c:1338
|
||||
#48 0x0000000000912bf4 in gdb_main (args=0xfffff1a3db58)
|
||||
at gdb/main.c:1357
|
||||
#49 0x00000000004170f4 in main (argc=10, argv=0xfffff1a3dcc8)
|
||||
at gdb/gdb.c:38
|
||||
(gdb)
|
||||
...
|
||||
|
||||
The abort happens because a c++ exception escapes to c code, specifically
|
||||
opncls_bstat in bfd/opncls.c. Compiling with -fexceptions works around this.
|
||||
|
||||
Fix this by catching the exception just before it escapes, in stat_trampoline
|
||||
and likewise in few similar spot.
|
||||
|
||||
Add a new template catch_exceptions to do so in a consistent way.
|
||||
|
||||
Tested on aarch64-linux.
|
||||
|
||||
Approved-by: Pedro Alves <pedro@palves.net>
|
||||
|
||||
PR remote/31577
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31577
|
||||
---
|
||||
gdb/gdb_bfd.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 56 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
|
||||
index 217753cf914..3c34cc5693f 100644
|
||||
--- a/gdb/gdb_bfd.c
|
||||
+++ b/gdb/gdb_bfd.c
|
||||
@@ -887,6 +887,29 @@ gdb_bfd_openw (const char *filename, const char *target)
|
||||
return gdb_bfd_ref_ptr::new_reference (result);
|
||||
}
|
||||
|
||||
+/* Wrap f (args) and handle exceptions by:
|
||||
+ - returning val, and
|
||||
+ - calling set_quit_flag or set_force_quit_flag, if needed. */
|
||||
+
|
||||
+template <typename R, R val, typename F, typename... Args>
|
||||
+static R
|
||||
+catch_exceptions (F &&f, Args&&... args)
|
||||
+{
|
||||
+ try
|
||||
+ {
|
||||
+ return f (std::forward<Args> (args)...);
|
||||
+ }
|
||||
+ catch (const gdb_exception &ex)
|
||||
+ {
|
||||
+ if (ex.reason == RETURN_QUIT)
|
||||
+ set_quit_flag ();
|
||||
+ else if (ex.reason == RETURN_FORCED_QUIT)
|
||||
+ set_force_quit_flag ();
|
||||
+ }
|
||||
+
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
/* See gdb_bfd.h. */
|
||||
|
||||
gdb_bfd_ref_ptr
|
||||
@@ -896,21 +919,51 @@ gdb_bfd_openr_iovec (const char *filename, const char *target,
|
||||
auto do_open = [] (bfd *nbfd, void *closure) -> void *
|
||||
{
|
||||
auto real_opener = static_cast<gdb_iovec_opener_ftype *> (closure);
|
||||
- return (*real_opener) (nbfd);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<gdb_bfd_iovec_base *, nullptr> ([&]
|
||||
+ {
|
||||
+ return (*real_opener) (nbfd);
|
||||
+ });
|
||||
+ if (res == nullptr)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto read_trampoline = [] (bfd *nbfd, void *stream, void *buf,
|
||||
file_ptr nbytes, file_ptr offset) -> file_ptr
|
||||
{
|
||||
gdb_bfd_iovec_base *obj = static_cast<gdb_bfd_iovec_base *> (stream);
|
||||
- return obj->read (nbfd, buf, nbytes, offset);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<long int, -1> ([&]
|
||||
+ {
|
||||
+ return obj->read (nbfd, buf, nbytes, offset);
|
||||
+ });
|
||||
+ if (res == -1)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto stat_trampoline = [] (struct bfd *abfd, void *stream,
|
||||
struct stat *sb) -> int
|
||||
{
|
||||
gdb_bfd_iovec_base *obj = static_cast<gdb_bfd_iovec_base *> (stream);
|
||||
- return obj->stat (abfd, sb);
|
||||
+ /* Prevent exceptions from escaping to C code and triggering an abort. */
|
||||
+ auto res = catch_exceptions<int, -1> ([&]
|
||||
+ {
|
||||
+ return obj->stat (abfd, sb);
|
||||
+ });
|
||||
+ if (res == -1)
|
||||
+ {
|
||||
+ errno = EIO;
|
||||
+ bfd_set_error (bfd_error_system_call);
|
||||
+ }
|
||||
+ return res;
|
||||
};
|
||||
|
||||
auto close_trampoline = [] (struct bfd *nbfd, void *stream) -> int
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,264 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Sat, 25 Nov 2023 10:35:37 +0000
|
||||
Subject: gdb-rhbz-2232086-cpp-ify-mapped-symtab.patch
|
||||
|
||||
;; Back-port upstream commit acc117b57f7 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: C++-ify mapped_symtab from dwarf2/index-write.c
|
||||
|
||||
Make static the functions add_index_entry, find_slot, and hash_expand,
|
||||
member functions of the mapped_symtab class.
|
||||
|
||||
Fold an additional snippet of code from write_gdbindex into
|
||||
mapped_symtab::minimize, this code relates to minimisation, so this
|
||||
seems like a good home for it.
|
||||
|
||||
Make the n_elements, data, and m_string_obstack member variables of
|
||||
mapped_symtab private. Provide a new obstack() member function to
|
||||
provide access to the obstack when needed, and also add member
|
||||
functions begin(), end(), cbegin(), and cend() so that the
|
||||
mapped_symtab class can be treated like a contained and iterated
|
||||
over.
|
||||
|
||||
I've also taken this opportunity to split out the logic for whether
|
||||
the hash table (m_data) needs expanding, this is the new function
|
||||
hash_needs_expanding. This will be useful in a later commit.
|
||||
|
||||
There should be no user visible changes after this commit.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -187,86 +187,135 @@ struct mapped_symtab
|
||||
{
|
||||
mapped_symtab ()
|
||||
{
|
||||
- data.resize (1024);
|
||||
+ m_data.resize (1024);
|
||||
}
|
||||
|
||||
- /* Minimize each entry in the symbol table, removing duplicates. */
|
||||
+ /* If there are no elements in the symbol table, then reduce the table
|
||||
+ size to zero. Otherwise call symtab_index_entry::minimize each entry
|
||||
+ in the symbol table. */
|
||||
+
|
||||
void minimize ()
|
||||
{
|
||||
- for (symtab_index_entry &item : data)
|
||||
+ if (m_element_count == 0)
|
||||
+ m_data.resize (0);
|
||||
+
|
||||
+ for (symtab_index_entry &item : m_data)
|
||||
item.minimize ();
|
||||
}
|
||||
|
||||
- offset_type n_elements = 0;
|
||||
- std::vector<symtab_index_entry> data;
|
||||
+ /* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX is
|
||||
+ the index of the CU in which the symbol appears. IS_STATIC is one if
|
||||
+ the symbol is static, otherwise zero (global). */
|
||||
+
|
||||
+ void add_index_entry (const char *name, int is_static,
|
||||
+ gdb_index_symbol_kind kind, offset_type cu_index);
|
||||
+
|
||||
+ /* Access the obstack. */
|
||||
+ struct obstack *obstack ()
|
||||
+ { return &m_string_obstack; }
|
||||
+
|
||||
+private:
|
||||
+
|
||||
+ /* Find a slot in SYMTAB for the symbol NAME. Returns a reference to
|
||||
+ the slot.
|
||||
+
|
||||
+ Function is used only during write_hash_table so no index format
|
||||
+ backward compatibility is needed. */
|
||||
+
|
||||
+ symtab_index_entry &find_slot (const char *name);
|
||||
+
|
||||
+ /* Expand SYMTAB's hash table. */
|
||||
+
|
||||
+ void hash_expand ();
|
||||
+
|
||||
+ /* Return true if the hash table in data needs to grow. */
|
||||
+
|
||||
+ bool hash_needs_expanding () const
|
||||
+ { return 4 * m_element_count / 3 >= m_data.size (); }
|
||||
+
|
||||
+ /* A vector that is used as a hash table. */
|
||||
+ std::vector<symtab_index_entry> m_data;
|
||||
+
|
||||
+ /* The number of elements stored in the m_data hash. */
|
||||
+ offset_type m_element_count = 0;
|
||||
|
||||
/* Temporary storage for names. */
|
||||
auto_obstack m_string_obstack;
|
||||
-};
|
||||
|
||||
-/* Find a slot in SYMTAB for the symbol NAME. Returns a reference to
|
||||
- the slot.
|
||||
+public:
|
||||
+ using iterator = decltype (m_data)::iterator;
|
||||
+ using const_iterator = decltype (m_data)::const_iterator;
|
||||
|
||||
- Function is used only during write_hash_table so no index format backward
|
||||
- compatibility is needed. */
|
||||
+ iterator begin ()
|
||||
+ { return m_data.begin (); }
|
||||
|
||||
-static symtab_index_entry &
|
||||
-find_slot (struct mapped_symtab *symtab, const char *name)
|
||||
+ iterator end ()
|
||||
+ { return m_data.end (); }
|
||||
+
|
||||
+ const_iterator cbegin ()
|
||||
+ { return m_data.cbegin (); }
|
||||
+
|
||||
+ const_iterator cend ()
|
||||
+ { return m_data.cend (); }
|
||||
+};
|
||||
+
|
||||
+/* See class definition. */
|
||||
+
|
||||
+symtab_index_entry &
|
||||
+mapped_symtab::find_slot (const char *name)
|
||||
{
|
||||
offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name);
|
||||
|
||||
- index = hash & (symtab->data.size () - 1);
|
||||
- step = ((hash * 17) & (symtab->data.size () - 1)) | 1;
|
||||
+ index = hash & (m_data.size () - 1);
|
||||
+ step = ((hash * 17) & (m_data.size () - 1)) | 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
- if (symtab->data[index].name == NULL
|
||||
- || strcmp (name, symtab->data[index].name) == 0)
|
||||
- return symtab->data[index];
|
||||
- index = (index + step) & (symtab->data.size () - 1);
|
||||
+ if (m_data[index].name == NULL
|
||||
+ || strcmp (name, m_data[index].name) == 0)
|
||||
+ return m_data[index];
|
||||
+ index = (index + step) & (m_data.size () - 1);
|
||||
}
|
||||
}
|
||||
|
||||
-/* Expand SYMTAB's hash table. */
|
||||
+/* See class definition. */
|
||||
|
||||
-static void
|
||||
-hash_expand (struct mapped_symtab *symtab)
|
||||
+void
|
||||
+mapped_symtab::hash_expand ()
|
||||
{
|
||||
- auto old_entries = std::move (symtab->data);
|
||||
+ auto old_entries = std::move (m_data);
|
||||
|
||||
- symtab->data.clear ();
|
||||
- symtab->data.resize (old_entries.size () * 2);
|
||||
+ gdb_assert (m_data.size () == 0);
|
||||
+ m_data.resize (old_entries.size () * 2);
|
||||
|
||||
for (auto &it : old_entries)
|
||||
if (it.name != NULL)
|
||||
{
|
||||
- auto &ref = find_slot (symtab, it.name);
|
||||
+ auto &ref = this->find_slot (it.name);
|
||||
ref = std::move (it);
|
||||
}
|
||||
}
|
||||
|
||||
-/* Add an entry to SYMTAB. NAME is the name of the symbol.
|
||||
- CU_INDEX is the index of the CU in which the symbol appears.
|
||||
- IS_STATIC is one if the symbol is static, otherwise zero (global). */
|
||||
+/* See class definition. */
|
||||
|
||||
-static void
|
||||
-add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
- int is_static, gdb_index_symbol_kind kind,
|
||||
- offset_type cu_index)
|
||||
+void
|
||||
+mapped_symtab::add_index_entry (const char *name, int is_static,
|
||||
+ gdb_index_symbol_kind kind,
|
||||
+ offset_type cu_index)
|
||||
{
|
||||
- symtab_index_entry *slot = &find_slot (symtab, name);
|
||||
+ symtab_index_entry *slot = &this->find_slot (name);
|
||||
if (slot->name == NULL)
|
||||
{
|
||||
/* This is a new element in the hash table. */
|
||||
- ++symtab->n_elements;
|
||||
+ ++this->m_element_count;
|
||||
|
||||
/* We might need to grow the hash table. */
|
||||
- if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
+ if (this->hash_needs_expanding ())
|
||||
{
|
||||
- hash_expand (symtab);
|
||||
+ this->hash_expand ();
|
||||
|
||||
/* This element will have a different slot in the new table. */
|
||||
- slot = &find_slot (symtab, name);
|
||||
+ slot = &this->find_slot (name);
|
||||
|
||||
/* But it should still be a new element in the hash table. */
|
||||
gdb_assert (slot->name == nullptr);
|
||||
@@ -387,7 +436,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
|
||||
|
||||
/* We add all the index vectors to the constant pool first, to
|
||||
ensure alignment is ok. */
|
||||
- for (symtab_index_entry &entry : symtab->data)
|
||||
+ for (symtab_index_entry &entry : *symtab)
|
||||
{
|
||||
if (entry.name == NULL)
|
||||
continue;
|
||||
@@ -416,7 +465,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
|
||||
|
||||
/* Now write out the hash table. */
|
||||
std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
|
||||
- for (const auto &entry : symtab->data)
|
||||
+ for (const auto &entry : *symtab)
|
||||
{
|
||||
offset_type str_off, vec_off;
|
||||
|
||||
@@ -1151,7 +1200,7 @@ write_cooked_index (cooked_index *table,
|
||||
const auto it = cu_index_htab.find (entry->per_cu);
|
||||
gdb_assert (it != cu_index_htab.cend ());
|
||||
|
||||
- const char *name = entry->full_name (&symtab->m_string_obstack);
|
||||
+ const char *name = entry->full_name (symtab->obstack ());
|
||||
|
||||
if (entry->per_cu->lang () == language_ada)
|
||||
{
|
||||
@@ -1159,7 +1208,7 @@ write_cooked_index (cooked_index *table,
|
||||
gdb, it has to use the encoded name, with any
|
||||
suffixes stripped. */
|
||||
std::string encoded = ada_encode (name, false);
|
||||
- name = obstack_strdup (&symtab->m_string_obstack,
|
||||
+ name = obstack_strdup (symtab->obstack (),
|
||||
encoded.c_str ());
|
||||
}
|
||||
else if (entry->per_cu->lang () == language_cplus
|
||||
@@ -1191,8 +1240,8 @@ write_cooked_index (cooked_index *table,
|
||||
else
|
||||
kind = GDB_INDEX_SYMBOL_KIND_TYPE;
|
||||
|
||||
- add_index_entry (symtab, name, (entry->flags & IS_STATIC) != 0,
|
||||
- kind, it->second);
|
||||
+ symtab->add_index_entry (name, (entry->flags & IS_STATIC) != 0,
|
||||
+ kind, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,8 +1316,6 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
|
||||
symtab.minimize ();
|
||||
|
||||
data_buf symtab_vec, constant_pool;
|
||||
- if (symtab.n_elements == 0)
|
||||
- symtab.data.resize (0);
|
||||
|
||||
write_hash_table (&symtab, symtab_vec, constant_pool);
|
||||
|
@ -1,101 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Mon, 27 Nov 2023 13:19:39 +0000
|
||||
Subject: gdb-rhbz-2232086-generate-dwarf-5-index-consistently.patch
|
||||
|
||||
;; Back-port upstream commit 3644f41dc80 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: generate dwarf-5 index identically as worker-thread count changes
|
||||
|
||||
Similar to the previous commit, this commit ensures that the dwarf-5
|
||||
index files are generated identically as the number of worker-threads
|
||||
changes.
|
||||
|
||||
Building the dwarf-5 index makes use of a closed hash table, the
|
||||
bucket_hash local within debug_names::build(). Entries are added to
|
||||
bucket_hash from m_name_to_value_set, which, in turn, is populated
|
||||
by calls to debug_names::insert() in write_debug_names. The insert
|
||||
calls are ordered based on the entries within the cooked_index, and
|
||||
the ordering within cooked_index depends on the number of worker
|
||||
threads that GDB is using.
|
||||
|
||||
My proposal is to sort each chain within the bucket_hash closed hash
|
||||
table prior to using this to build the dwarf-5 index.
|
||||
|
||||
The buckets within bucket_hash will always have the same ordering (for
|
||||
a given GDB build with a given executable), and by sorting the chains
|
||||
within each bucket, we can be sure that GDB will see each entry in a
|
||||
deterministic order.
|
||||
|
||||
I've extended the index creation test to cover this case.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -452,6 +452,11 @@ class c_str_view
|
||||
return strcmp (m_cstr, other.m_cstr) == 0;
|
||||
}
|
||||
|
||||
+ bool operator< (const c_str_view &other) const
|
||||
+ {
|
||||
+ return strcmp (m_cstr, other.m_cstr) < 0;
|
||||
+ }
|
||||
+
|
||||
/* Return the underlying C string. Note, the returned string is
|
||||
only a reference with lifetime of this object. */
|
||||
const char *c_str () const
|
||||
@@ -771,10 +776,18 @@ class debug_names
|
||||
}
|
||||
for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
|
||||
{
|
||||
- const std::forward_list<hash_it_pair> &hashitlist
|
||||
- = bucket_hash[bucket_ix];
|
||||
+ std::forward_list<hash_it_pair> &hashitlist = bucket_hash[bucket_ix];
|
||||
if (hashitlist.empty ())
|
||||
continue;
|
||||
+
|
||||
+ /* Sort the items within each bucket. This ensures that the
|
||||
+ generated index files will be the same no matter the order in
|
||||
+ which symbols were added into the index. */
|
||||
+ hashitlist.sort ([] (const hash_it_pair &a, const hash_it_pair &b)
|
||||
+ {
|
||||
+ return a.it->first < b.it->first;
|
||||
+ });
|
||||
+
|
||||
uint32_t &bucket_slot = m_bucket_table[bucket_ix];
|
||||
/* The hashes array is indexed starting at 1. */
|
||||
store_unsigned_integer (reinterpret_cast<gdb_byte *> (&bucket_slot),
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
--- a/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -47,6 +47,9 @@ remote_exec host "mkdir -p ${dir1}"
|
||||
with_timeout_factor $timeout_factor {
|
||||
gdb_test_no_output "save gdb-index $dir1" \
|
||||
"create gdb-index file"
|
||||
+
|
||||
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir1" \
|
||||
+ "create dwarf-index files"
|
||||
}
|
||||
|
||||
# Close GDB.
|
||||
@@ -143,13 +146,16 @@ if { $worker_threads > 1 } {
|
||||
with_timeout_factor $timeout_factor {
|
||||
gdb_test_no_output "save gdb-index $dir2" \
|
||||
"create second gdb-index file"
|
||||
+
|
||||
+ gdb_test_no_output "save gdb-index -dwarf-5 $dir2" \
|
||||
+ "create second dwarf-index files"
|
||||
}
|
||||
|
||||
# Close GDB.
|
||||
gdb_exit
|
||||
|
||||
# Now check that the index files are identical.
|
||||
- foreach suffix { gdb-index } {
|
||||
+ foreach suffix { gdb-index debug_names debug_str } {
|
||||
set result \
|
||||
[remote_exec host \
|
||||
"cmp -s \"$dir1/${index_filename_base}.${suffix}\" \"$dir2/${index_filename_base}.${suffix}\""]
|
@ -1,230 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 12:04:36 +0000
|
||||
Subject: gdb-rhbz-2232086-generate-gdb-index-consistently.patch
|
||||
|
||||
;; Back-port upstream commit aff250145af as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: generate gdb-index identically regardless of work thread count
|
||||
|
||||
It was observed that changing the number of worker threads that GDB
|
||||
uses (maintenance set worker-threads NUM) would have an impact on the
|
||||
layout of the generated gdb-index.
|
||||
|
||||
The cause seems to be how the CU are distributed between threads, and
|
||||
then symbols that appear in multiple CU can be encountered earlier or
|
||||
later depending on whether a particular CU moves between threads.
|
||||
|
||||
I certainly found this behaviour was reproducible when generating an
|
||||
index for GDB itself, like:
|
||||
|
||||
gdb -q -nx -nh -batch \
|
||||
-eiex 'maint set worker-threads NUM' \
|
||||
-ex 'save gdb-index /tmp/'
|
||||
|
||||
And then setting different values for NUM will change the generated
|
||||
index.
|
||||
|
||||
Now, the question is: does this matter?
|
||||
|
||||
I would like to suggest that yes, this does matter. At Red Hat we
|
||||
generate a gdb-index as part of the build process, and we would
|
||||
ideally like to have reproducible builds: for the same source,
|
||||
compiled with the same tool-chain, we should get the exact same output
|
||||
binary. And we do .... except for the index.
|
||||
|
||||
Now we could simply force GDB to only use a single worker thread when
|
||||
we build the index, but, I don't think the idea of reproducible builds
|
||||
is that strange, so I think we should ensure that our generated
|
||||
indexes are always reproducible.
|
||||
|
||||
To achieve this, I propose that we add an extra step when building the
|
||||
gdb-index file. After constructing the initial symbol hash table
|
||||
contents, we will pull all the symbols out of the hash, sort them,
|
||||
then re-insert them in sorted order. This will ensure that the
|
||||
structure of the generated hash will remain consistent (given the same
|
||||
set of symbols).
|
||||
|
||||
I've extended the existing index-file test to check that the generated
|
||||
index doesn't change if we adjust the number of worker threads used.
|
||||
Given that this test is already rather slow, I've only made one change
|
||||
to the worker-thread count. Maybe this test should be changed to use
|
||||
a smaller binary, which is quicker to load, and for which we could
|
||||
then try many different worker thread counts.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -210,6 +210,13 @@ struct mapped_symtab
|
||||
void add_index_entry (const char *name, int is_static,
|
||||
gdb_index_symbol_kind kind, offset_type cu_index);
|
||||
|
||||
+ /* When entries are originally added into the data hash the order will
|
||||
+ vary based on the number of worker threads GDB is configured to use.
|
||||
+ This function will rebuild the hash such that the final layout will be
|
||||
+ deterministic regardless of the number of worker threads used. */
|
||||
+
|
||||
+ void sort ();
|
||||
+
|
||||
/* Access the obstack. */
|
||||
struct obstack *obstack ()
|
||||
{ return &m_string_obstack; }
|
||||
@@ -296,6 +303,65 @@ mapped_symtab::hash_expand ()
|
||||
}
|
||||
}
|
||||
|
||||
+/* See mapped_symtab class declaration. */
|
||||
+
|
||||
+void mapped_symtab::sort ()
|
||||
+{
|
||||
+ /* Move contents out of this->data vector. */
|
||||
+ std::vector<symtab_index_entry> original_data = std::move (m_data);
|
||||
+
|
||||
+ /* Restore the size of m_data, this will avoid having to expand the hash
|
||||
+ table (and rehash all elements) when we reinsert after sorting.
|
||||
+ However, we do reset the element count, this allows for some sanity
|
||||
+ checking asserts during the reinsert phase. */
|
||||
+ gdb_assert (m_data.size () == 0);
|
||||
+ m_data.resize (original_data.size ());
|
||||
+ m_element_count = 0;
|
||||
+
|
||||
+ /* Remove empty entries from ORIGINAL_DATA, this makes sorting quicker. */
|
||||
+ auto it = std::remove_if (original_data.begin (), original_data.end (),
|
||||
+ [] (const symtab_index_entry &entry) -> bool
|
||||
+ {
|
||||
+ return entry.name == nullptr;
|
||||
+ });
|
||||
+ original_data.erase (it, original_data.end ());
|
||||
+
|
||||
+ /* Sort the existing contents. */
|
||||
+ std::sort (original_data.begin (), original_data.end (),
|
||||
+ [] (const symtab_index_entry &a,
|
||||
+ const symtab_index_entry &b) -> bool
|
||||
+ {
|
||||
+ /* Return true if A is before B. */
|
||||
+ gdb_assert (a.name != nullptr);
|
||||
+ gdb_assert (b.name != nullptr);
|
||||
+
|
||||
+ return strcmp (a.name, b.name) < 0;
|
||||
+ });
|
||||
+
|
||||
+ /* Re-insert each item from the sorted list. */
|
||||
+ for (auto &entry : original_data)
|
||||
+ {
|
||||
+ /* We know that ORIGINAL_DATA contains no duplicates, this data was
|
||||
+ taken from a hash table that de-duplicated entries for us, so
|
||||
+ count this as a new item.
|
||||
+
|
||||
+ As we retained the original size of m_data (see above) then we
|
||||
+ should never need to grow m_data_ during this re-insertion phase,
|
||||
+ assert that now. */
|
||||
+ ++m_element_count;
|
||||
+ gdb_assert (!this->hash_needs_expanding ());
|
||||
+
|
||||
+ /* Lookup a slot. */
|
||||
+ symtab_index_entry &slot = this->find_slot (entry.name);
|
||||
+
|
||||
+ /* As discussed above, we should not find duplicates. */
|
||||
+ gdb_assert (slot.name == nullptr);
|
||||
+
|
||||
+ /* Move this item into the slot we found. */
|
||||
+ slot = std::move (entry);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* See class definition. */
|
||||
|
||||
void
|
||||
@@ -1311,6 +1377,9 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
|
||||
for (auto map : table->get_addrmaps ())
|
||||
write_address_map (map, addr_vec, cu_index_htab);
|
||||
|
||||
+ /* Ensure symbol hash is built domestically. */
|
||||
+ symtab.sort ();
|
||||
+
|
||||
/* Now that we've processed all symbols we can shrink their cu_indices
|
||||
lists. */
|
||||
symtab.minimize ();
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
--- a/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -38,6 +38,9 @@ with_timeout_factor $timeout_factor {
|
||||
clean_restart $filename
|
||||
}
|
||||
|
||||
+# Record how many worker threads GDB is using.
|
||||
+set worker_threads [gdb_get_worker_threads]
|
||||
+
|
||||
# Generate an index file.
|
||||
set dir1 [standard_output_file "index_1"]
|
||||
remote_exec host "mkdir -p ${dir1}"
|
||||
@@ -116,3 +119,41 @@ proc check_symbol_table_usage { filename } {
|
||||
|
||||
set index_filename_base [file tail $filename]
|
||||
check_symbol_table_usage "$dir1/${index_filename_base}.gdb-index"
|
||||
+
|
||||
+# If GDB is using more than 1 worker thread then reduce the number of
|
||||
+# worker threads, regenerate the index, and check that we get the same
|
||||
+# index file back. At one point the layout of the index would vary
|
||||
+# based on the number of worker threads used.
|
||||
+if { $worker_threads > 1 } {
|
||||
+ # Start GDB, but don't load a file yet.
|
||||
+ clean_restart
|
||||
+
|
||||
+ # Adjust the number of threads to use.
|
||||
+ set reduced_threads [expr $worker_threads / 2]
|
||||
+ gdb_test_no_output "maint set worker-threads $reduced_threads"
|
||||
+
|
||||
+ with_timeout_factor $timeout_factor {
|
||||
+ # Now load the test binary.
|
||||
+ gdb_file_cmd $filename
|
||||
+ }
|
||||
+
|
||||
+ # Generate an index file.
|
||||
+ set dir2 [standard_output_file "index_2"]
|
||||
+ remote_exec host "mkdir -p ${dir2}"
|
||||
+ with_timeout_factor $timeout_factor {
|
||||
+ gdb_test_no_output "save gdb-index $dir2" \
|
||||
+ "create second gdb-index file"
|
||||
+ }
|
||||
+
|
||||
+ # Close GDB.
|
||||
+ gdb_exit
|
||||
+
|
||||
+ # Now check that the index files are identical.
|
||||
+ foreach suffix { gdb-index } {
|
||||
+ set result \
|
||||
+ [remote_exec host \
|
||||
+ "cmp -s \"$dir1/${index_filename_base}.${suffix}\" \"$dir2/${index_filename_base}.${suffix}\""]
|
||||
+ gdb_assert { [lindex $result 0] == 0 } \
|
||||
+ "$suffix files are identical"
|
||||
+ }
|
||||
+}
|
||||
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
|
||||
--- a/gdb/testsuite/lib/gdb.exp
|
||||
+++ b/gdb/testsuite/lib/gdb.exp
|
||||
@@ -10033,6 +10033,21 @@ proc is_target_non_stop { {testname ""} } {
|
||||
return $is_non_stop
|
||||
}
|
||||
|
||||
+# Return the number of worker threads that GDB is currently using.
|
||||
+
|
||||
+proc gdb_get_worker_threads { {testname ""} } {
|
||||
+ set worker_threads "UNKNOWN"
|
||||
+ gdb_test_multiple "maintenance show worker-threads" $testname {
|
||||
+ -wrap -re "The number of worker threads GDB can use is unlimited \\(currently ($::decimal)\\)\\." {
|
||||
+ set worker_threads $expect_out(1,string)
|
||||
+ }
|
||||
+ -wrap -re "The number of worker threads GDB can use is ($::decimal)\\." {
|
||||
+ set worker_threads $expect_out(1,string)
|
||||
+ }
|
||||
+ }
|
||||
+ return $worker_threads
|
||||
+}
|
||||
+
|
||||
# Check if the compiler emits epilogue information associated
|
||||
# with the closing brace or with the last statement line.
|
||||
#
|
@ -1,222 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 11:50:35 +0000
|
||||
Subject: gdb-rhbz-2232086-reduce-size-of-gdb-index.patch
|
||||
|
||||
;; Back-port upstream commit aa19bc1d259 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb: reduce size of generated gdb-index file
|
||||
|
||||
I noticed in passing that out algorithm for generating the gdb-index
|
||||
file is incorrect. When building the hash table in add_index_entry we
|
||||
count every incoming entry rehash when the number of entries gets too
|
||||
large. However, some of the incoming entries will be duplicates,
|
||||
which don't actually result in new items being added to the hash
|
||||
table.
|
||||
|
||||
As a result, we grow the gdb-index hash table far too often.
|
||||
|
||||
With an unmodified GDB, generating a gdb-index for GDB, I see a file
|
||||
size of 90M, with a hash usage (in the generated index file) of just
|
||||
2.6%.
|
||||
|
||||
With a patched GDB, generating a gdb-index for the _same_ GDB binary,
|
||||
I now see a gdb-index file size of 30M, with a hash usage of 41.9%.
|
||||
|
||||
This is a 67% reduction in gdb-index file size.
|
||||
|
||||
Obviously, not every gdb-index file is going to see such big savings,
|
||||
however, the larger a program, and the more symbols that are
|
||||
duplicated between compilation units, the more GDB would over count,
|
||||
and so, over-grow the index.
|
||||
|
||||
The gdb-index hash table we create has a minimum size of 1024, and
|
||||
then we grow the hash when it is 75% full, doubling the hash table at
|
||||
that time. Given this, then we expect that either:
|
||||
|
||||
a. The hash table is size 1024, and less than 75% full, or
|
||||
b. The hash table is between 37.5% and 75% full.
|
||||
|
||||
I've include a test that checks some of these constraints -- I've not
|
||||
bothered to check the upper limit, and over full hash table isn't
|
||||
really a problem here, but if the fill percentage is less than 37.5%
|
||||
then this indicates that we've done something wrong (obviously, I also
|
||||
check for the 1024 minimum size).
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
|
||||
--- a/gdb/dwarf2/index-write.c
|
||||
+++ b/gdb/dwarf2/index-write.c
|
||||
@@ -254,20 +254,29 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
int is_static, gdb_index_symbol_kind kind,
|
||||
offset_type cu_index)
|
||||
{
|
||||
- offset_type cu_index_and_attrs;
|
||||
+ symtab_index_entry *slot = &find_slot (symtab, name);
|
||||
+ if (slot->name == NULL)
|
||||
+ {
|
||||
+ /* This is a new element in the hash table. */
|
||||
+ ++symtab->n_elements;
|
||||
|
||||
- ++symtab->n_elements;
|
||||
- if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
- hash_expand (symtab);
|
||||
+ /* We might need to grow the hash table. */
|
||||
+ if (4 * symtab->n_elements / 3 >= symtab->data.size ())
|
||||
+ {
|
||||
+ hash_expand (symtab);
|
||||
|
||||
- symtab_index_entry &slot = find_slot (symtab, name);
|
||||
- if (slot.name == NULL)
|
||||
- {
|
||||
- slot.name = name;
|
||||
+ /* This element will have a different slot in the new table. */
|
||||
+ slot = &find_slot (symtab, name);
|
||||
+
|
||||
+ /* But it should still be a new element in the hash table. */
|
||||
+ gdb_assert (slot->name == nullptr);
|
||||
+ }
|
||||
+
|
||||
+ slot->name = name;
|
||||
/* index_offset is set later. */
|
||||
}
|
||||
|
||||
- cu_index_and_attrs = 0;
|
||||
+ offset_type cu_index_and_attrs = 0;
|
||||
DW2_GDB_INDEX_CU_SET_VALUE (cu_index_and_attrs, cu_index);
|
||||
DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE (cu_index_and_attrs, is_static);
|
||||
DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (cu_index_and_attrs, kind);
|
||||
@@ -279,7 +288,7 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
|
||||
the last entry pushed), but a symbol could have multiple kinds in one CU.
|
||||
To keep things simple we don't worry about the duplication here and
|
||||
sort and uniquify the list after we've processed all symbols. */
|
||||
- slot.cu_indices.push_back (cu_index_and_attrs);
|
||||
+ slot->cu_indices.push_back (cu_index_and_attrs);
|
||||
}
|
||||
|
||||
/* See symtab_index_entry. */
|
||||
diff --git a/gdb/testsuite/gdb.gdb/index-file.exp b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.gdb/index-file.exp
|
||||
@@ -0,0 +1,118 @@
|
||||
+# Copyright 2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Load the GDB executable, and then 'save gdb-index', and make some
|
||||
+# checks of the generated index file.
|
||||
+
|
||||
+load_lib selftest-support.exp
|
||||
+
|
||||
+# Can't save an index with readnow.
|
||||
+if {[readnow]} {
|
||||
+ untested "cannot create an index when readnow is in use"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# A multiplier used to ensure slow tasks are less likely to timeout.
|
||||
+set timeout_factor 20
|
||||
+
|
||||
+set filename [selftest_prepare]
|
||||
+if { $filename eq "" } {
|
||||
+ unsupported "${gdb_test_file_name}.exp"
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+with_timeout_factor $timeout_factor {
|
||||
+ # Start GDB, load FILENAME.
|
||||
+ clean_restart $filename
|
||||
+}
|
||||
+
|
||||
+# Generate an index file.
|
||||
+set dir1 [standard_output_file "index_1"]
|
||||
+remote_exec host "mkdir -p ${dir1}"
|
||||
+with_timeout_factor $timeout_factor {
|
||||
+ gdb_test_no_output "save gdb-index $dir1" \
|
||||
+ "create gdb-index file"
|
||||
+}
|
||||
+
|
||||
+# Close GDB.
|
||||
+gdb_exit
|
||||
+
|
||||
+# Validate that the index-file FILENAME has made efficient use of its
|
||||
+# symbol hash table. Calculate the number of symbols in the hash
|
||||
+# table and the total hash table size. The hash table starts with
|
||||
+# 1024 entries, and then doubles each time it is filled to 75%. At
|
||||
+# 75% filled, doubling the size takes it to 37.5% filled.
|
||||
+#
|
||||
+# Thus, the hash table is correctly filled if:
|
||||
+# 1. Its size is 1024 (i.e. it has not yet had its first doubling), or
|
||||
+# 2. Its filled percentage is over 37%
|
||||
+#
|
||||
+# We could check that it is not over filled, but I don't as that's not
|
||||
+# really an issue. But we did once have a bug where the table was
|
||||
+# doubled incorrectly, in which case we'd see a filled percentage of
|
||||
+# around 2% in some cases, which is a huge waste of disk space.
|
||||
+proc check_symbol_table_usage { filename } {
|
||||
+ # Open the file in binary mode and read-only mode.
|
||||
+ set fp [open $filename rb]
|
||||
+
|
||||
+ # Configure the channel to use binary translation.
|
||||
+ fconfigure $fp -translation binary
|
||||
+
|
||||
+ # Read the first 8 bytes of the file, which contain the header of
|
||||
+ # the index section.
|
||||
+ set header [read $fp [expr 7 * 4]]
|
||||
+
|
||||
+ # Scan the header to get the version, the CU list offset, and the
|
||||
+ # types CU list offset.
|
||||
+ binary scan $header iiiiii version \
|
||||
+ _ _ _ symbol_table_offset shortcut_offset
|
||||
+
|
||||
+ # The length of the symbol hash table (in entries).
|
||||
+ set len [expr ($shortcut_offset - $symbol_table_offset) / 8]
|
||||
+
|
||||
+ # Now walk the hash table and count how many entries are in use.
|
||||
+ set offset $symbol_table_offset
|
||||
+ set count 0
|
||||
+ while { $offset < $shortcut_offset } {
|
||||
+ seek $fp $offset
|
||||
+ set entry [read $fp 8]
|
||||
+ binary scan $entry ii name_ptr flags
|
||||
+ if { $name_ptr != 0 } {
|
||||
+ incr count
|
||||
+ }
|
||||
+
|
||||
+ incr offset 8
|
||||
+ }
|
||||
+
|
||||
+ # Close the file.
|
||||
+ close $fp
|
||||
+
|
||||
+ # Calculate how full the cache is.
|
||||
+ set pct [expr (100 * double($count)) / $len]
|
||||
+
|
||||
+ # Write our results out to the gdb.log.
|
||||
+ verbose -log "Hash table size: $len"
|
||||
+ verbose -log "Hash table entries: $count"
|
||||
+ verbose -log "Percentage usage: $pct%"
|
||||
+
|
||||
+ # The minimum fill percentage is actually 37.5%, but we give TCL a
|
||||
+ # little flexibility in case the FP maths give a result a little
|
||||
+ # off.
|
||||
+ gdb_assert { $len == 1024 || $pct > 37 } \
|
||||
+ "symbol hash table usage"
|
||||
+}
|
||||
+
|
||||
+set index_filename_base [file tail $filename]
|
||||
+check_symbol_table_usage "$dir1/${index_filename_base}.gdb-index"
|
@ -1,170 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz1007614-memleak-infpy_read_memory-test.patch
|
||||
|
||||
;; Fix 'memory leak in infpy_read_memory()' (RH BZ 1007614)
|
||||
;;=fedoratest
|
||||
|
||||
Original message by Tom Tromey:
|
||||
|
||||
<https://sourceware.org/ml/gdb-patches/2012-03/msg00955.html>
|
||||
Message-ID: <871uoc1va3.fsf@fleche.redhat.com>
|
||||
|
||||
Comment from Sergio Durigan Junior:
|
||||
|
||||
In order to correctly test this patch, I wrote a testcase based on Jan
|
||||
Kratochvil's <gdb/testsuite/gdb.base/gcore-excessive-memory.exp>. The
|
||||
testcase, which can be seen below, tests GDB in order to see if the
|
||||
amount of memory being leaked is minimal, as requested in the bugzilla.
|
||||
It is hard to define what "minimum" is, so I ran the testcase on all
|
||||
supported RHEL architectures and came up with an average.
|
||||
|
||||
commit cc0265cdda9dc7e8665e8bfcf5b4477489daf27c
|
||||
Author: Tom Tromey <tromey@redhat.com>
|
||||
Date: Wed Mar 28 17:38:08 2012 +0000
|
||||
|
||||
* python/py-inferior.c (infpy_read_memory): Remove cleanups and
|
||||
explicitly free 'buffer' on exit paths. Decref 'membuf_object'
|
||||
before returning.
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.c b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.c
|
||||
@@ -0,0 +1,27 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2014 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+static struct x
|
||||
+ {
|
||||
+ char unsigned u[4096];
|
||||
+ } x, *px = &x;
|
||||
+
|
||||
+int
|
||||
+main (int argc, char *argv[])
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.exp
|
||||
@@ -0,0 +1,68 @@
|
||||
+# Copyright 2014 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+set testfile py-gdb-rhbz1007614-memleak-infpy_read_memory
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if { [skip_python_tests] } { continue }
|
||||
+
|
||||
+set pid_of_gdb [exp_pid -i [board_info host fileid]]
|
||||
+
|
||||
+proc memory_v_pages_get {} {
|
||||
+ global pid_of_gdb
|
||||
+ set fd [open "/proc/$pid_of_gdb/statm"]
|
||||
+ gets $fd line
|
||||
+ close $fd
|
||||
+ # number of pages of virtual memory
|
||||
+ scan $line "%d" drs
|
||||
+ return $drs
|
||||
+}
|
||||
+
|
||||
+if { ![runto_main] } {
|
||||
+ untested $testfile.exp
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set remote_python_file [remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
||||
+
|
||||
+gdb_test "source ${remote_python_file}" ""
|
||||
+
|
||||
+gdb_test "hello-world" ""
|
||||
+
|
||||
+set kbytes_before [memory_v_pages_get]
|
||||
+verbose -log "kbytes_before = $kbytes_before"
|
||||
+
|
||||
+gdb_test "hello-world" ""
|
||||
+
|
||||
+set kbytes_after [memory_v_pages_get]
|
||||
+verbose -log "kbytes_after = $kbytes_after"
|
||||
+
|
||||
+set kbytes_diff [expr $kbytes_after - $kbytes_before]
|
||||
+verbose -log "kbytes_diff = $kbytes_diff"
|
||||
+
|
||||
+# The value "1000" was calculated by running a few GDB sessions with this
|
||||
+# testcase, and seeing how much (in average) the memory consumption
|
||||
+# increased after the "hello-world" command issued above. The average
|
||||
+# was around 500 bytes, so I chose 1000 as a high estimate.
|
||||
+if { $kbytes_diff > 1000 } {
|
||||
+ fail "there is a memory leak on GDB (RHBZ 1007614)"
|
||||
+} else {
|
||||
+ pass "there is not a memory leak on GDB (RHBZ 1007614)"
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.py b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.py
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.python/py-gdb-rhbz1007614-memleak-infpy_read_memory.py
|
||||
@@ -0,0 +1,30 @@
|
||||
+# Copyright (C) 2014 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+class HelloWorld (gdb.Command):
|
||||
+ """Greet the whole world."""
|
||||
+
|
||||
+ def __init__ (self):
|
||||
+ super (HelloWorld, self).__init__ ("hello-world",
|
||||
+ gdb.COMMAND_OBSCURE)
|
||||
+
|
||||
+ def invoke (self, arg, from_tty):
|
||||
+ px = gdb.parse_and_eval("px")
|
||||
+ core = gdb.inferiors()[0]
|
||||
+ for i in range(256 * 1024):
|
||||
+ chunk = core.read_memory(px, 4096)
|
||||
+ print "Hello, World!"
|
||||
+
|
||||
+HelloWorld ()
|
@ -1,104 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz1261564-aarch64-hw-watchpoint-test.patch
|
||||
|
||||
;; [aarch64] Fix hardware watchpoints (RH BZ 1261564).
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.c b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.c
|
||||
@@ -0,0 +1,33 @@
|
||||
+/* This testcase is part of GDB, the GNU debugger.
|
||||
+
|
||||
+ Copyright 2016 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+__attribute__((aligned(16))) struct
|
||||
+{
|
||||
+ int var0, var4, var8;
|
||||
+} aligned;
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ aligned.var0 = 1;
|
||||
+ aligned.var4 = 2;
|
||||
+ aligned.var8 = 3;
|
||||
+
|
||||
+ aligned.var4 = aligned.var0;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.base/rhbz1261564-aarch64-watchpoint.exp
|
||||
@@ -0,0 +1,53 @@
|
||||
+# Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+if { [prepare_for_testing rhbz1261564-aarch64-watchpoint.exp "rhbz1261564-aarch64-watchpoint"] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if { ! [ runto main ] } then { return 0 }
|
||||
+
|
||||
+set test "rwatch aligned.var4"
|
||||
+if [istarget "s390*-*-*"] {
|
||||
+ gdb_test $test {Target does not support this type of hardware watchpoint\.}
|
||||
+ untested "s390* does not support hw read watchpoint"
|
||||
+ return
|
||||
+}
|
||||
+gdb_test $test "Hardware read watchpoint \[0-9\]+: aligned.var4"
|
||||
+
|
||||
+proc checkvar { address } {
|
||||
+ global gdb_prompt
|
||||
+
|
||||
+ set test "p &aligned.var$address"
|
||||
+ gdb_test_multiple $test $test {
|
||||
+ -re " = \\(int \\*\\) 0x\[0-9a-f\]+$address <aligned(\\+\[0-9\]+)?>\r\n$gdb_prompt $" {
|
||||
+ pass $test
|
||||
+ }
|
||||
+ -re "\r\n$gdb_prompt $" {
|
||||
+ untested "$test (unexpected ELF layout)"
|
||||
+ return 0
|
||||
+ }
|
||||
+ }
|
||||
+ return 1
|
||||
+}
|
||||
+if ![checkvar "0"] { return }
|
||||
+if ![checkvar "4"] { return }
|
||||
+if ![checkvar "8"] { return }
|
||||
+
|
||||
+# Assumes: PPC_PTRACE_GETHWDBGINFO::data_bp_alignment == 8
|
||||
+# 'lwz' does read only 4 bytes but the hw watchpoint is 8 bytes wide.
|
||||
+setup_xfail "powerpc*-*-*"
|
||||
+
|
||||
+gdb_continue_to_end
|
@ -1,77 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Burgess <aburgess@redhat.com>
|
||||
Date: Fri, 24 Nov 2023 11:10:08 +0000
|
||||
Subject: gdb-rhbz2232086-refactor-selftest-support.patch
|
||||
|
||||
;; Back-port upstream commit 1f0fab7ff86 as part of a fix for
|
||||
;; non-deterministic gdb-index generation (RH BZ 2232086).
|
||||
|
||||
gdb/testsuite: small refactor in selftest-support.exp
|
||||
|
||||
Split out the code that makes a copy of the GDB executable ready for
|
||||
self testing into a new proc. A later commit in this series wants to
|
||||
load the GDB executable into GDB (for creating an on-disk debug
|
||||
index), but doesn't need to make use of the full do_self_tests proc.
|
||||
|
||||
There should be no changes in what is tested after this commit.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/testsuite/lib/selftest-support.exp b/gdb/testsuite/lib/selftest-support.exp
|
||||
--- a/gdb/testsuite/lib/selftest-support.exp
|
||||
+++ b/gdb/testsuite/lib/selftest-support.exp
|
||||
@@ -92,11 +92,13 @@ proc selftest_setup { executable function } {
|
||||
return 0
|
||||
}
|
||||
|
||||
-# A simple way to run some self-tests.
|
||||
-
|
||||
-proc do_self_tests {function body} {
|
||||
- global GDB tool
|
||||
-
|
||||
+# Prepare for running a self-test by moving the GDB executable to a
|
||||
+# location where we can use it as the inferior. Return the filename
|
||||
+# of the new location.
|
||||
+#
|
||||
+# If the current testing setup is not suitable for running a
|
||||
+# self-test, then return an empty string.
|
||||
+proc selftest_prepare {} {
|
||||
# Are we testing with a remote board? In that case, the target
|
||||
# won't have access to the GDB's auxilliary data files
|
||||
# (data-directory, etc.). It's simpler to just skip.
|
||||
@@ -120,19 +122,31 @@ proc do_self_tests {function body} {
|
||||
# Run the test with self. Copy the file executable file in case
|
||||
# this OS doesn't like to edit its own text space.
|
||||
|
||||
- set GDB_FULLPATH [find_gdb $GDB]
|
||||
+ set gdb_fullpath [find_gdb $::GDB]
|
||||
|
||||
if {[is_remote host]} {
|
||||
- set xgdb x$tool
|
||||
+ set xgdb x$::tool
|
||||
} else {
|
||||
- set xgdb [standard_output_file x$tool]
|
||||
+ set xgdb [standard_output_file x$::tool]
|
||||
}
|
||||
|
||||
# Remove any old copy lying around.
|
||||
remote_file host delete $xgdb
|
||||
|
||||
+ set filename [remote_download host $gdb_fullpath $xgdb]
|
||||
+
|
||||
+ return $filename
|
||||
+}
|
||||
+
|
||||
+# A simple way to run some self-tests.
|
||||
+
|
||||
+proc do_self_tests {function body} {
|
||||
+ set file [selftest_prepare]
|
||||
+ if { $file eq "" } {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
gdb_start
|
||||
- set file [remote_download host $GDB_FULLPATH $xgdb]
|
||||
|
||||
# When debugging GDB with GDB, some operations can take a relatively long
|
||||
# time, especially if the build is non-optimized. Bump the timeout for the
|
@ -1,48 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= <ahajkova@redhat.com>
|
||||
Date: Mon, 8 Jan 2024 13:24:05 +0100
|
||||
Subject: gdb-rhbz2250652-avoid-PyOS_ReadlineTState.patch
|
||||
|
||||
gdb/python: avoid use of _PyOS_ReadlineTState
|
||||
|
||||
In python/py-gdb-readline.c we make use of _PyOS_ReadlineTState,
|
||||
however, this variable is no longer public in Python 3.13, and so GDB
|
||||
no longer builds.
|
||||
|
||||
We are making use of _PyOS_ReadlineTState in order to re-acquire the
|
||||
Python Global Interpreter Lock (GIL). The _PyOS_ReadlineTState
|
||||
variable is set in Python's outer readline code prior to calling the
|
||||
user (GDB) supplied readline callback function, which for us is
|
||||
gdbpy_readline_wrapper. The gdbpy_readline_wrapper function is called
|
||||
without the GIL held.
|
||||
|
||||
Instead of using _PyOS_ReadlineTState, I propose that we switch to
|
||||
calling PyGILState_Ensure() and PyGILState_Release(). These functions
|
||||
will acquire the GIL based on the current thread. I think this should
|
||||
be sufficient; I can't imagine why we'd be running
|
||||
gdbpy_readline_wrapper on one thread on behalf of a different Python
|
||||
thread.... that would be unexpected I think.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/python/py-gdb-readline.c b/gdb/python/py-gdb-readline.c
|
||||
--- a/gdb/python/py-gdb-readline.c
|
||||
+++ b/gdb/python/py-gdb-readline.c
|
||||
@@ -56,13 +56,11 @@ gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout,
|
||||
if (except.reason == RETURN_QUIT)
|
||||
return NULL;
|
||||
|
||||
- /* The thread state is nulled during gdbpy_readline_wrapper,
|
||||
- with the original value saved in the following undocumented
|
||||
- variable (see Python's Parser/myreadline.c and
|
||||
- Modules/readline.c). */
|
||||
- PyEval_RestoreThread (_PyOS_ReadlineTState);
|
||||
+
|
||||
+ /* This readline callback is called without the GIL held. */
|
||||
+ gdbpy_gil gil;
|
||||
+
|
||||
gdbpy_convert_exception (except);
|
||||
- PyEval_SaveThread ();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,81 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Alexandra=20H=C3=A1jkov=C3=A1?= <ahajkova@redhat.com>
|
||||
Date: Mon, 8 Jan 2024 13:12:15 +0100
|
||||
Subject: gdb-rhbz2250652-gdbpy_gil.patch
|
||||
|
||||
gdb: move gdbpy_gil into python-internal.h
|
||||
|
||||
Move gdbpy_gil class into python-internal.h, the next
|
||||
commit wants to make use of this class from a file other
|
||||
than python.c.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
|
||||
--- a/gdb/python/python-internal.h
|
||||
+++ b/gdb/python/python-internal.h
|
||||
@@ -754,6 +754,30 @@ class gdbpy_allow_threads
|
||||
PyThreadState *m_save;
|
||||
};
|
||||
|
||||
+/* A helper class to save and restore the GIL, but without touching
|
||||
+ the other globals that are handled by gdbpy_enter. */
|
||||
+
|
||||
+class gdbpy_gil
|
||||
+{
|
||||
+public:
|
||||
+
|
||||
+ gdbpy_gil ()
|
||||
+ : m_state (PyGILState_Ensure ())
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ ~gdbpy_gil ()
|
||||
+ {
|
||||
+ PyGILState_Release (m_state);
|
||||
+ }
|
||||
+
|
||||
+ DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
|
||||
+
|
||||
+private:
|
||||
+
|
||||
+ PyGILState_STATE m_state;
|
||||
+};
|
||||
+
|
||||
/* Use this after a TRY_EXCEPT to throw the appropriate Python
|
||||
exception. */
|
||||
#define GDB_PY_HANDLE_EXCEPTION(Exception) \
|
||||
diff --git a/gdb/python/python.c b/gdb/python/python.c
|
||||
--- a/gdb/python/python.c
|
||||
+++ b/gdb/python/python.c
|
||||
@@ -257,30 +257,6 @@ gdbpy_enter::finalize ()
|
||||
python_gdbarch = target_gdbarch ();
|
||||
}
|
||||
|
||||
-/* A helper class to save and restore the GIL, but without touching
|
||||
- the other globals that are handled by gdbpy_enter. */
|
||||
-
|
||||
-class gdbpy_gil
|
||||
-{
|
||||
-public:
|
||||
-
|
||||
- gdbpy_gil ()
|
||||
- : m_state (PyGILState_Ensure ())
|
||||
- {
|
||||
- }
|
||||
-
|
||||
- ~gdbpy_gil ()
|
||||
- {
|
||||
- PyGILState_Release (m_state);
|
||||
- }
|
||||
-
|
||||
- DISABLE_COPY_AND_ASSIGN (gdbpy_gil);
|
||||
-
|
||||
-private:
|
||||
-
|
||||
- PyGILState_STATE m_state;
|
||||
-};
|
||||
-
|
||||
/* Set the quit flag. */
|
||||
|
||||
static void
|
@ -1,55 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Buettner <kevinb@redhat.com>
|
||||
Date: Mon, 29 Jan 2024 14:51:22 -0700
|
||||
Subject: gdb-rhbz2261580-intrusive_list-assertion-fix.patch
|
||||
|
||||
;; Backport upstream workaround for GCC 14 problem which cause assertion
|
||||
;; failures in GDB.
|
||||
|
||||
[gdb/build] Workaround gcc PR113599
|
||||
|
||||
Since gcc commit d3f48f68227 ("c++: non-dependent .* operand folding
|
||||
[PR112427]"), with gdb we run into PR gcc/113599 [1], a wrong-code bug, as
|
||||
reported in PR build/31281.
|
||||
|
||||
Work around this by flipping inherit order:
|
||||
...
|
||||
-class thread_info : public refcounted_object,
|
||||
- public intrusive_list_node<thread_info>
|
||||
+class thread_info : public intrusive_list_node<thread_info>,
|
||||
+ public refcounted_object
|
||||
...
|
||||
|
||||
An argument could be made that this isn't necessary, because this occurred in
|
||||
an unreleased gcc version.
|
||||
|
||||
However, I think it could be useful when bisecting gcc for other problems in
|
||||
building gdb. Having this workaround means the bisect won't reintroduce the
|
||||
problem. Furthermore, the workaround is harmless.
|
||||
|
||||
Tested on Fedora rawhide x86_64.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31281
|
||||
|
||||
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113599
|
||||
|
||||
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
|
||||
--- a/gdb/gdbthread.h
|
||||
+++ b/gdb/gdbthread.h
|
||||
@@ -242,10 +242,11 @@ using private_thread_info_up = std::unique_ptr<private_thread_info>;
|
||||
strong reference, and is thus not accounted for in the thread's
|
||||
refcount.
|
||||
|
||||
- The intrusive_list_node base links threads in a per-inferior list. */
|
||||
+ The intrusive_list_node base links threads in a per-inferior list.
|
||||
+ We place it first in the inherit order to work around PR gcc/113599. */
|
||||
|
||||
-class thread_info : public refcounted_object,
|
||||
- public intrusive_list_node<thread_info>
|
||||
+class thread_info : public intrusive_list_node<thread_info>,
|
||||
+ public refcounted_object
|
||||
{
|
||||
public:
|
||||
explicit thread_info (inferior *inf, ptid_t ptid);
|
@ -1,147 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-rhbz947564-findvar-assertion-frame-failed-testcase.patch
|
||||
|
||||
;; Import regression test for `gdb/findvar.c:417: internal-error:
|
||||
;; read_var_value: Assertion `frame' failed.' (RH BZ 947564) from RHEL 6.5.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.threads/tls-rhbz947564.cc b/gdb/testsuite/gdb.threads/tls-rhbz947564.cc
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/tls-rhbz947564.cc
|
||||
@@ -0,0 +1,53 @@
|
||||
+#include <iostream>
|
||||
+#include <pthread.h>
|
||||
+
|
||||
+class x
|
||||
+ {
|
||||
+ public:
|
||||
+ int n;
|
||||
+
|
||||
+ x() : n(0) {}
|
||||
+ };
|
||||
+
|
||||
+class y
|
||||
+ {
|
||||
+ public:
|
||||
+ int v;
|
||||
+
|
||||
+ y() : v(0) {}
|
||||
+ static __thread x *xp;
|
||||
+ };
|
||||
+
|
||||
+__thread x *y::xp;
|
||||
+
|
||||
+static void
|
||||
+foo (y *yp)
|
||||
+{
|
||||
+ yp->v = 1; /* foo_marker */
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+bar (void *unused)
|
||||
+{
|
||||
+ x xinst;
|
||||
+ y::xp= &xinst;
|
||||
+
|
||||
+ y yy;
|
||||
+ foo(&yy);
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main(int argc, char *argv[])
|
||||
+{
|
||||
+ pthread_t t[2];
|
||||
+
|
||||
+ pthread_create (&t[0], NULL, bar, NULL);
|
||||
+ pthread_create (&t[1], NULL, bar, NULL);
|
||||
+
|
||||
+ pthread_join (t[0], NULL);
|
||||
+ pthread_join (t[1], NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.threads/tls-rhbz947564.exp b/gdb/testsuite/gdb.threads/tls-rhbz947564.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/tls-rhbz947564.exp
|
||||
@@ -0,0 +1,75 @@
|
||||
+# Copyright (C) 2013 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+set testfile tls-rhbz947564
|
||||
+set srcfile ${testfile}.cc
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+if [istarget "*-*-linux"] then {
|
||||
+ set target_cflags "-D_MIT_POSIX_THREADS"
|
||||
+} else {
|
||||
+ set target_cflags ""
|
||||
+}
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list c++ debug]] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+
|
||||
+gdb_load ${binfile}
|
||||
+
|
||||
+if { ![runto_main] } {
|
||||
+ fail "Can't run to function main"
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+gdb_breakpoint "foo"
|
||||
+gdb_continue_to_breakpoint "foo" ".* foo_marker .*"
|
||||
+
|
||||
+proc get_xp_val {try} {
|
||||
+ global expect_out
|
||||
+ global gdb_prompt
|
||||
+ global hex
|
||||
+
|
||||
+ set xp_val ""
|
||||
+ gdb_test_multiple "print *yp" "print yp value" {
|
||||
+ -re { = \{v = 0, static xp = (0x[0-9a-f]+)\}.* } {
|
||||
+ pass "print $try value of *yp"
|
||||
+ set xp_val $expect_out(1,string)
|
||||
+ }
|
||||
+ -re "$gdb_prompt $" {
|
||||
+ fail "print $try value of *yp"
|
||||
+ }
|
||||
+ timeout {
|
||||
+ fail "print $try value of *yp (timeout)"
|
||||
+ }
|
||||
+ }
|
||||
+ return $xp_val
|
||||
+}
|
||||
+
|
||||
+set first_run [get_xp_val "first"]
|
||||
+
|
||||
+gdb_test "continue" "Breakpoint \[0-9\]+, foo \\\(yp=$hex\\\) at.*"
|
||||
+
|
||||
+set second_run [get_xp_val "second"]
|
||||
+
|
||||
+if { $first_run != $second_run } {
|
||||
+ pass "different values for TLS variable"
|
||||
+} else {
|
||||
+ fail "different values for TLS variable"
|
||||
+}
|
@ -1,50 +0,0 @@
|
||||
From 6cfb7bf81be3ab6f131dbc6a27eefca516cf7517 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Arnez <arnez@linux.ibm.com>
|
||||
Date: Tue, 13 Feb 2024 18:55:29 +0100
|
||||
Subject: [PATCH 2/2] gdb: s390: Add arch14 record/replay support
|
||||
|
||||
Enable recording of the new "arch14" instructions on z/Architecture
|
||||
targets, except for the specialized-function-assist instruction NNPA.
|
||||
---
|
||||
gdb/s390-tdep.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
|
||||
index 54b5c89e5e3..dcac407caef 100644
|
||||
--- a/gdb/s390-tdep.c
|
||||
+++ b/gdb/s390-tdep.c
|
||||
@@ -5534,6 +5534,14 @@ s390_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
|
||||
case 0xe635: /* VLRL - vector load rightmost with immed. length */
|
||||
case 0xe637: /* VLRLR - vector load rightmost with length */
|
||||
case 0xe649: /* VLIP - vector load immediate decimal */
|
||||
+ case 0xe656: /* VCLFNH - vector fp convert and lengthen from NNP high */
|
||||
+ case 0xe65e: /* VCLFNL - vector fp convert and lengthen from NNP low */
|
||||
+ case 0xe655: /* VCNF - vector fp convert to NNP */
|
||||
+ case 0xe65d: /* VCFN - vector fp convert from NNP */
|
||||
+ case 0xe674: /* VSCHP - decimal scale and convert to HFP */
|
||||
+ case 0xe675: /* VCRNF - vector fp convert and round to NNP */
|
||||
+ case 0xe67c: /* VSCSHP - decimal scale and convert and split to HFP */
|
||||
+ case 0xe67d: /* VCSPH - vector convert HFP to scaled decimal */
|
||||
case 0xe700: /* VLEB - vector load element */
|
||||
case 0xe701: /* VLEH - vector load element */
|
||||
case 0xe702: /* VLEG - vector load element */
|
||||
@@ -5791,11 +5799,16 @@ s390_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
|
||||
|
||||
/* 0xe747-0xe749 undefined */
|
||||
|
||||
+ case 0xe651: /* VCLZDP - vector count leading zero digits */
|
||||
+ case 0xe654: /* VUPKZH - vector unpack zoned high */
|
||||
case 0xe658: /* VCVD - vector convert to decimal 32 bit */
|
||||
case 0xe659: /* VSRP - vector shift and round decimal */
|
||||
case 0xe65a: /* VCVDG - vector convert to decimal 64 bit*/
|
||||
case 0xe65b: /* VPSOP - vector perform sign operation decimal */
|
||||
+ case 0xe65c: /* VUPKZL - vector unpack zoned low */
|
||||
+ case 0xe670: /* VPKZR - vector pack zoned register */
|
||||
case 0xe671: /* VAP - vector add decimal */
|
||||
+ case 0xe672: /* VSRPR - vector shift and round decimal register */
|
||||
case 0xe673: /* VSP - vector subtract decimal */
|
||||
case 0xe678: /* VMP - vector multiply decimal */
|
||||
case 0xe679: /* VMSP - vector multiply decimal */
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,162 +0,0 @@
|
||||
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
|
||||
From: Fedora GDB patches <invalid@email.com>
|
||||
Date: Fri, 27 Oct 2017 21:07:50 +0200
|
||||
Subject: gdb-simultaneous-step-resume-breakpoint-test.patch
|
||||
|
||||
;; New test for step-resume breakpoint placed in multiple threads at once.
|
||||
;;=fedoratest
|
||||
|
||||
diff --git a/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.c b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.c
|
||||
@@ -0,0 +1,79 @@
|
||||
+/* Copyright 2009 Free Software Foundation, Inc.
|
||||
+
|
||||
+ Written by Fred Fish of Cygnus Support
|
||||
+ Contributed by Cygnus Support
|
||||
+
|
||||
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Test multiple threads stepping into a .debug_line-less function with
|
||||
+ a breakpoint placed on its return-to-caller point. */
|
||||
+
|
||||
+#include <pthread.h>
|
||||
+#include <assert.h>
|
||||
+#include <unistd.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+#define THREADS 3
|
||||
+
|
||||
+static void *
|
||||
+func (void *unused)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ i = 0xdeadf00d;
|
||||
+ i = sleep (THREADS); /* sleep-call */
|
||||
+ if (errno != 0) /* sleep-after */
|
||||
+ perror ("sleep");
|
||||
+
|
||||
+ /* The GDB bug with forgotten step-resume breakpoint could leave stale
|
||||
+ breakpoint on the I assignment making it a nop. */
|
||||
+ if (i == 0xdeadf00d)
|
||||
+ assert (0);
|
||||
+
|
||||
+ assert (i == 0);
|
||||
+
|
||||
+ pthread_exit (NULL);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ pthread_t threads[THREADS];
|
||||
+ int threadi;
|
||||
+
|
||||
+ for (threadi = 0; threadi < THREADS; threadi++)
|
||||
+ {
|
||||
+ int i;
|
||||
+
|
||||
+ i = pthread_create (&threads[threadi], NULL, func, NULL);
|
||||
+ assert (i == 0);
|
||||
+
|
||||
+ i = sleep (1);
|
||||
+ assert (i == 0);
|
||||
+ }
|
||||
+
|
||||
+ for (threadi = 0; threadi < THREADS; threadi++)
|
||||
+ {
|
||||
+ int i;
|
||||
+
|
||||
+ i = pthread_join (threads[threadi], NULL);
|
||||
+ assert (i == 0);
|
||||
+ }
|
||||
+
|
||||
+ return 0; /* final-exit */
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.exp b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.exp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.threads/simultaneous-step-resume-breakpoint.exp
|
||||
@@ -0,0 +1,65 @@
|
||||
+# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+# Test multiple threads stepping into a .debug_line-less function with
|
||||
+# a breakpoint placed on its return-to-caller point.
|
||||
+
|
||||
+set testfile simultaneous-step-resume-breakpoint
|
||||
+set srcfile ${testfile}.c
|
||||
+set binfile [standard_output_file ${testfile}]
|
||||
+
|
||||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_exit
|
||||
+gdb_start
|
||||
+gdb_reinitialize_dir $srcdir/$subdir
|
||||
+
|
||||
+# Ensure we have no debuginfo for the `sleep' call itself (=for libc).
|
||||
+gdb_test "set debug-file-directory /DoesNotExist"
|
||||
+
|
||||
+gdb_load ${binfile}
|
||||
+if ![runto_main] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+# Red Hat vendor patch does set it to "step" by default.
|
||||
+gdb_test "set scheduler-locking off"
|
||||
+
|
||||
+gdb_breakpoint [gdb_get_line_number "final-exit"]
|
||||
+
|
||||
+gdb_breakpoint [gdb_get_line_number "sleep-call"]
|
||||
+gdb_continue_to_breakpoint "sleep-call"
|
||||
+
|
||||
+gdb_test "step" "sleep-call.*" "step thread 1"
|
||||
+gdb_test "step" "sleep-call.*" "step thread 2"
|
||||
+gdb_test "step" "sleep-after.*" "step thread 3"
|
||||
+
|
||||
+set test "first continue"
|
||||
+gdb_test_multiple "continue" $test {
|
||||
+ -re "final-exit.*$gdb_prompt $" {
|
||||
+ # gdb-7.0.
|
||||
+ pass $test
|
||||
+ return
|
||||
+ }
|
||||
+ -re "sleep-after.*$gdb_prompt $" {
|
||||
+ # Fedora/RHEL branch.
|
||||
+ pass $test
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+gdb_test "continue" "sleep-after.*" "second continue"
|
||||
+gdb_test "continue" "final-exit.*" "third continue"
|
@ -1,125 +0,0 @@
|
||||
From aa8ba17b9a3fdfeeb65df4c3e0731a0e9e96cbf7 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 Nov 2023 00:33:12 +0100
|
||||
Subject: [PATCH 1/2] [gdb/symtab] Add producer_is_gas
|
||||
|
||||
Add producer_is_gas, a generic way to get the gas version from the
|
||||
producer string.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 4 ++--
|
||||
gdb/producer.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
gdb/producer.h | 5 +++++
|
||||
3 files changed, 63 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 970dd54c7a5..472684a5817 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -13376,8 +13376,8 @@ check_producer (struct dwarf2_cu *cu)
|
||||
cu->producer_is_codewarrior = true;
|
||||
else if (producer_is_clang (cu->producer, &major, &minor))
|
||||
cu->producer_is_clang = true;
|
||||
- else if (startswith (cu->producer, "GNU AS 2.39.0"))
|
||||
- cu->producer_is_gas_2_39 = true;
|
||||
+ else if (producer_is_gas (cu->producer, &major, &minor))
|
||||
+ cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
else
|
||||
{
|
||||
/* For other non-GCC compilers, expect their behavior is DWARF version
|
||||
diff --git a/gdb/producer.c b/gdb/producer.c
|
||||
index 9fcf749e3d4..cd83dfce128 100644
|
||||
--- a/gdb/producer.c
|
||||
+++ b/gdb/producer.c
|
||||
@@ -81,6 +81,45 @@ producer_is_gcc (const char *producer, int *major, int *minor)
|
||||
|
||||
/* See producer.h. */
|
||||
|
||||
+bool
|
||||
+producer_is_gas (const char *producer, int *major, int *minor)
|
||||
+{
|
||||
+ if (producer == nullptr)
|
||||
+ {
|
||||
+ /* No producer, don't know. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Detect prefix. */
|
||||
+ const char prefix[] = "GNU AS ";
|
||||
+ if (!startswith (producer, prefix))
|
||||
+ {
|
||||
+ /* Producer is not gas. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Skip prefix. */
|
||||
+ const char *cs = &producer[strlen (prefix)];
|
||||
+
|
||||
+ /* Ensure that major/minor are not nullptrs. */
|
||||
+ int maj, min;
|
||||
+ if (major == nullptr)
|
||||
+ major = &maj;
|
||||
+ if (minor == nullptr)
|
||||
+ minor = &min;
|
||||
+
|
||||
+ int scanned = sscanf (cs, "%d.%d", major, minor);
|
||||
+ if (scanned != 2)
|
||||
+ {
|
||||
+ /* Unable to scan major/minor version. */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+ /* See producer.h. */
|
||||
+
|
||||
bool
|
||||
producer_is_icc_ge_19 (const char *producer)
|
||||
{
|
||||
@@ -251,6 +290,23 @@ Version 18.0 Beta";
|
||||
SELF_CHECK (!producer_is_gcc (flang_llvm_exp, &major, &minor));
|
||||
SELF_CHECK (producer_is_llvm (flang_llvm_exp));
|
||||
}
|
||||
+
|
||||
+ {
|
||||
+ static const char gas_exp[] = "GNU AS 2.39.0";
|
||||
+ int major = 0, minor = 0;
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_exp, &major, &minor));
|
||||
+ SELF_CHECK (producer_is_gas (gas_exp, &major, &minor));
|
||||
+ SELF_CHECK (major == 2 && minor == 39);
|
||||
+
|
||||
+ static const char gas_incomplete_exp[] = "GNU AS ";
|
||||
+ SELF_CHECK (!producer_is_gas (gas_incomplete_exp, &major, &minor));
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_incomplete_exp, &major, &minor));
|
||||
+
|
||||
+ static const char gas_incomplete_exp_2[] = "GNU AS 2";
|
||||
+ SELF_CHECK (!producer_is_gas (gas_incomplete_exp_2, &major, &minor));
|
||||
+ SELF_CHECK (!producer_is_gcc (gas_incomplete_exp_2, &major, &minor));
|
||||
+ }
|
||||
+
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/gdb/producer.h b/gdb/producer.h
|
||||
index c915979b122..00718511775 100644
|
||||
--- a/gdb/producer.h
|
||||
+++ b/gdb/producer.h
|
||||
@@ -30,6 +30,11 @@ extern int producer_is_gcc_ge_4 (const char *producer);
|
||||
is NULL or it isn't GCC. */
|
||||
extern int producer_is_gcc (const char *producer, int *major, int *minor);
|
||||
|
||||
+/* Returns nonzero if the given PRODUCER string is GAS and sets the MAJOR
|
||||
+ and MINOR versions when not NULL. Returns zero if the given PRODUCER
|
||||
+ is NULL or it isn't GAS. */
|
||||
+bool producer_is_gas (const char *producer, int *major, int *minor);
|
||||
+
|
||||
/* Check for Intel compilers >= 19.0. */
|
||||
extern bool producer_is_icc_ge_19 (const char *producer);
|
||||
|
||||
|
||||
base-commit: 39553c1e285c426946188ec2a890c1c1cb933060
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,74 +0,0 @@
|
||||
From 0218e033b415df76be0a14871447bbd94dce62a3 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 16 Sep 2023 04:07:22 +0200
|
||||
Subject: [PATCH 10/13] [gdb/symtab] Don't defer backward refs, inter-cu
|
||||
intra-shard case
|
||||
|
||||
In patch "[gdb/symtab] Resolve deferred entries, inter-shard case" we've
|
||||
solved the generic case of handling deferred entries.
|
||||
|
||||
Add an optimization that doesn't defer inter-CU intra-shard dependencies that
|
||||
are present in the shard's parent map.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 29 ++++++++++++++++++++++++++++-
|
||||
1 file changed, 28 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index a97f738a54e..e7904532434 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4709,6 +4709,12 @@ class cooked_index_storage
|
||||
m_index->set_parent_valid (start, end);
|
||||
}
|
||||
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_index->parent_valid (addr);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Hash function for a cutu_reader. */
|
||||
@@ -4857,6 +4863,12 @@ class cooked_indexer
|
||||
{
|
||||
m_index_storage->set_parent_valid (start, end);
|
||||
}
|
||||
+
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_index_storage->parent_valid (addr);
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16482,7 +16494,22 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
else
|
||||
{
|
||||
/* Inter-CU case. */
|
||||
- *maybe_defer = addr;
|
||||
+ if (parent_valid (addr))
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
+ {
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Defer because origin is in other shard. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,76 +0,0 @@
|
||||
From 8a444a93d4bd78355fc4e6ecb1935cc2b0a6a997 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 15 Sep 2023 08:38:00 +0200
|
||||
Subject: [PATCH 04/13] [gdb/symtab] Factor out m_deferred_entries usage
|
||||
|
||||
Factor out usage of cooked_indexer::m_deferred_entries in new member
|
||||
functions defer_entry, handle_deferred_entries and resolve_deferred_entry.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 35 ++++++++++++++++++++++++++++-------
|
||||
1 file changed, 28 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index d48f3010063..afdf9e870a8 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4822,6 +4822,32 @@ class cooked_indexer
|
||||
we'll know the containing context of all the DIEs that we might
|
||||
have scanned. This vector stores these deferred entries. */
|
||||
std::vector<deferred_entry> m_deferred_entries;
|
||||
+
|
||||
+ /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
+ void defer_entry (const deferred_entry &de)
|
||||
+ {
|
||||
+ m_deferred_entries.push_back (de);
|
||||
+ }
|
||||
+
|
||||
+ /* Create a cooked_index_entry corresponding to deferred_entry DE with
|
||||
+ parent PARENT_ENTRY. */
|
||||
+ const cooked_index_entry *resolve_deferred_entry
|
||||
+ (const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ return m_index_storage->add (de.die_offset, de.tag, de.flags, de.name,
|
||||
+ parent_entry, m_per_cu);
|
||||
+ }
|
||||
+
|
||||
+ /* Create cooked_index_entries for the deferred entries. */
|
||||
+ void handle_deferred_entries ()
|
||||
+ {
|
||||
+ for (const auto &entry : m_deferred_entries)
|
||||
+ {
|
||||
+ const cooked_index_entry *parent_entry
|
||||
+ = find_parent (entry.spec_offset);
|
||||
+ resolve_deferred_entry (entry, parent_entry);
|
||||
+ }
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16611,7 +16637,7 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
if (name != nullptr)
|
||||
{
|
||||
if (defer != 0)
|
||||
- m_deferred_entries.push_back ({
|
||||
+ defer_entry ({
|
||||
this_die, name, defer, abbrev->tag, flags
|
||||
});
|
||||
else
|
||||
@@ -16716,12 +16742,7 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
return;
|
||||
index_dies (reader, reader->info_ptr, nullptr, false);
|
||||
|
||||
- for (const auto &entry : m_deferred_entries)
|
||||
- {
|
||||
- const cooked_index_entry *parent = find_parent (entry.spec_offset);
|
||||
- m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
||||
- entry.name, parent, m_per_cu);
|
||||
- }
|
||||
+ handle_deferred_entries ();
|
||||
}
|
||||
|
||||
/* An implementation of quick_symbol_functions for the cooked DWARF
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,151 +0,0 @@
|
||||
From b2f260d117dc11b8e90d4e9bf7f4b2cbd63d1d49 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 22 Aug 2023 13:17:47 +0200
|
||||
Subject: [PATCH 02/13] [gdb/symtab] Factor out m_die_range_map usage
|
||||
|
||||
Factor out usage of cooked_indexer::m_die_range_map into new class parent_map
|
||||
with member functions find_parent and set_parent, and static member function
|
||||
form_addr.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.h | 32 +++++++++++++++++++++++++++
|
||||
gdb/dwarf2/read.c | 46 ++++++++++++++++++++-------------------
|
||||
2 files changed, 56 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 5aacb321c91..979541fbf60 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -239,6 +239,38 @@ struct cooked_index_entry : public allocate_on_obstack
|
||||
bool for_name) const;
|
||||
};
|
||||
|
||||
+class parent_map
|
||||
+{
|
||||
+public:
|
||||
+ /* A helper function to turn a section offset into an address that
|
||||
+ can be used in a parent_map. */
|
||||
+ static CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
+ {
|
||||
+ CORE_ADDR value = to_underlying (offset);
|
||||
+ if (is_dwz)
|
||||
+ value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ const void *obj = m_parent_map.find (lookup);
|
||||
+ return static_cast<const cooked_index_entry *> (obj);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ }
|
||||
+
|
||||
+private:
|
||||
+ /* An addrmap that maps from section offsets to cooked_index_entry *. */
|
||||
+ addrmap_mutable m_parent_map;
|
||||
+};
|
||||
+
|
||||
class cooked_index;
|
||||
|
||||
/* An index of interesting DIEs. This is "cooked", in contrast to a
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 466d3e59878..d48f3010063 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4722,16 +4722,6 @@ class cooked_indexer
|
||||
|
||||
private:
|
||||
|
||||
- /* A helper function to turn a section offset into an address that
|
||||
- can be used in an addrmap. */
|
||||
- CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
- {
|
||||
- CORE_ADDR value = to_underlying (offset);
|
||||
- if (is_dwz)
|
||||
- value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
- return value;
|
||||
- }
|
||||
-
|
||||
/* A helper function to scan the PC bounds of READER and record them
|
||||
in the storage's addrmap. */
|
||||
void check_bounds (cutu_reader *reader);
|
||||
@@ -4799,7 +4789,20 @@ class cooked_indexer
|
||||
/* An addrmap that maps from section offsets (see the form_addr
|
||||
method) to newly-created entries. See m_deferred_entries to
|
||||
understand this. */
|
||||
- addrmap_mutable m_die_range_map;
|
||||
+ parent_map m_die_range_map;
|
||||
+
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ return m_die_range_map.find_parent (lookup);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_die_range_map.set_parent (start, end, parent_entry);
|
||||
+ }
|
||||
|
||||
/* A single deferred entry. */
|
||||
struct deferred_entry
|
||||
@@ -16412,15 +16415,13 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
|
||||
if (*parent_entry == nullptr)
|
||||
{
|
||||
- CORE_ADDR addr = form_addr (origin_offset, origin_is_dwz);
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz);
|
||||
if (new_reader->cu == reader->cu
|
||||
&& new_info_ptr > watermark_ptr)
|
||||
*maybe_defer = addr;
|
||||
else
|
||||
- {
|
||||
- void *obj = m_die_range_map.find (addr);
|
||||
- *parent_entry = static_cast <cooked_index_entry *> (obj);
|
||||
- }
|
||||
+ *parent_entry = find_parent (addr);
|
||||
}
|
||||
|
||||
unsigned int bytes_read;
|
||||
@@ -16538,11 +16539,13 @@ cooked_indexer::recurse (cutu_reader *reader,
|
||||
{
|
||||
/* Both start and end are inclusive, so use both "+ 1" and "- 1" to
|
||||
limit the range to the children of parent_entry. */
|
||||
- CORE_ADDR start = form_addr (parent_entry->die_offset + 1,
|
||||
- reader->cu->per_cu->is_dwz);
|
||||
- CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
+ CORE_ADDR start
|
||||
+ = parent_map::form_addr (parent_entry->die_offset + 1,
|
||||
+ reader->cu->per_cu->is_dwz);
|
||||
+ CORE_ADDR end
|
||||
+ = parent_map::form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
reader->cu->per_cu->is_dwz);
|
||||
- m_die_range_map.set_empty (start, end, (void *) parent_entry);
|
||||
+ set_parent (start, end, parent_entry);
|
||||
}
|
||||
|
||||
return info_ptr;
|
||||
@@ -16715,8 +16718,7 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
|
||||
for (const auto &entry : m_deferred_entries)
|
||||
{
|
||||
- void *obj = m_die_range_map.find (entry.spec_offset);
|
||||
- cooked_index_entry *parent = static_cast<cooked_index_entry *> (obj);
|
||||
+ const cooked_index_entry *parent = find_parent (entry.spec_offset);
|
||||
m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
|
||||
entry.name, parent, m_per_cu);
|
||||
}
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,112 +0,0 @@
|
||||
From c79ecacd3f75cfb0ec1a3afc49ca3f30b1759009 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 11 Aug 2023 01:36:50 +0200
|
||||
Subject: [PATCH 13/13] [gdb/symtab] Fix DW_TAG_inlined_subroutine entries in
|
||||
the cooked index
|
||||
|
||||
We get incorrect qualified names in the cooked index for
|
||||
DW_TAG_inlined_subroutine DIEs with abstract origin, due to the fact that the
|
||||
DIE parent is used instead of the abstract origin.
|
||||
|
||||
Fix this by preferring the abstract origin parent, if available.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/30728
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30728
|
||||
---
|
||||
gdb/dwarf2/read.c | 67 ++++++++++++++++++++++-------------------------
|
||||
1 file changed, 32 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 93708ef11b9..a4f982962ae 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16464,52 +16464,49 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
const gdb_byte *new_info_ptr = (new_reader->buffer
|
||||
+ to_underlying (origin_offset));
|
||||
|
||||
- if (*parent_entry == nullptr)
|
||||
+ gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
+ == new_reader->cu->per_cu->is_debug_types);
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ if (new_reader->cu == reader->cu)
|
||||
{
|
||||
- gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
- == new_reader->cu->per_cu->is_debug_types);
|
||||
- CORE_ADDR addr
|
||||
- = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
- reader->cu->per_cu->is_debug_types);
|
||||
- if (new_reader->cu == reader->cu)
|
||||
+ /* Intra-CU case. */
|
||||
+ if (new_info_ptr > watermark_ptr)
|
||||
{
|
||||
- /* Intra-CU case. */
|
||||
- if (new_info_ptr > watermark_ptr)
|
||||
- {
|
||||
- /* Defer because origin is not read yet. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- auto tmp = find_parent (addr);
|
||||
- if (tmp == &parent_map::deferred)
|
||||
- {
|
||||
- /* Defer because origin is deferred. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- *parent_entry = tmp;
|
||||
- }
|
||||
+ /* Defer because origin is not read yet. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
- /* Inter-CU case. */
|
||||
- if (parent_valid (addr))
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
{
|
||||
- auto tmp = find_parent (addr);
|
||||
- if (tmp == &parent_map::deferred)
|
||||
- {
|
||||
- /* Defer because origin is deferred. */
|
||||
- *maybe_defer = addr;
|
||||
- }
|
||||
- else
|
||||
- *parent_entry = tmp;
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Inter-CU case. */
|
||||
+ if (parent_valid (addr))
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
{
|
||||
- /* Defer because origin is in other shard. */
|
||||
+ /* Defer because origin is deferred. */
|
||||
*maybe_defer = addr;
|
||||
}
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Defer because origin is in other shard. */
|
||||
+ *maybe_defer = addr;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
337
gdb-symtab-fix-target-type-of-complex-long-double-on.patch
Normal file
337
gdb-symtab-fix-target-type-of-complex-long-double-on.patch
Normal file
@ -0,0 +1,337 @@
|
||||
From e485fec626c14303a31bf7eab35c4288f9710c9d Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 19 Jun 2024 17:32:55 +0200
|
||||
Subject: [PATCH 07/46] [gdb/symtab] Fix target type of complex long double on
|
||||
arm
|
||||
|
||||
When running test-case gdb.base/complex-parts.exp on arm-linux, I get:
|
||||
...
|
||||
(gdb) p $_cimag (z3)^M
|
||||
$6 = 6.5^M
|
||||
(gdb) PASS: gdb.base/complex-parts.exp: long double imaginary: p $_cimag (z3)
|
||||
ptype $^M
|
||||
type = double^M
|
||||
(gdb) FAIL: gdb.base/complex-parts.exp: long double imaginary: ptype $
|
||||
...
|
||||
|
||||
Given that z3 is a complex long double, the test-case expects the type of the
|
||||
imaginary part of z3 to be long double, but it's double instead.
|
||||
|
||||
This is due to the fact that the dwarf info doesn't specify an explicit target
|
||||
type:
|
||||
...
|
||||
<5b> DW_AT_name : z3
|
||||
<60> DW_AT_type : <0xa4>
|
||||
...
|
||||
<1><a4>: Abbrev Number: 2 (DW_TAG_base_type)
|
||||
<a5> DW_AT_byte_size : 16
|
||||
<a6> DW_AT_encoding : 3 (complex float)
|
||||
<a7> DW_AT_name : complex long double
|
||||
...
|
||||
and consequently we're guessing in dwarf2_init_complex_target_type based on
|
||||
the size:
|
||||
...
|
||||
case 64:
|
||||
tt = builtin_type (gdbarch)->builtin_double;
|
||||
break;
|
||||
case 96: /* The x86-32 ABI specifies 96-bit long double. */
|
||||
case 128:
|
||||
tt = builtin_type (gdbarch)->builtin_long_double;
|
||||
break;
|
||||
...
|
||||
|
||||
For arm-linux, complex long double is 16 bytes, so the target type is assumed
|
||||
to be 8 bytes, which is handled by the "case 64", which gets us double
|
||||
instead of long double.
|
||||
|
||||
Fix this by searching for "long" in the name_hint parameter, and using long
|
||||
double instead.
|
||||
|
||||
Note that base types in dwarf are not allowed to contain references to other
|
||||
types, and the complex types are base types, so the missing explicit target
|
||||
type is standard-conformant.
|
||||
|
||||
A gcc PR was filed to add this as a dwarf extension (
|
||||
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115272 ).
|
||||
|
||||
Tested on arm-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 10 +-
|
||||
.../gdb.dwarf2/dw2-complex-parts.exp | 244 ++++++++++++++++++
|
||||
2 files changed, 253 insertions(+), 1 deletion(-)
|
||||
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 7cd1d2b4c4e..18054d0070d 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -15123,7 +15123,15 @@ dwarf2_init_complex_target_type (struct dwarf2_cu *cu,
|
||||
tt = builtin_type (gdbarch)->builtin_float;
|
||||
break;
|
||||
case 64:
|
||||
- tt = builtin_type (gdbarch)->builtin_double;
|
||||
+ if (builtin_type (gdbarch)->builtin_long_double->length () == 8
|
||||
+ && name_hint != nullptr
|
||||
+ && strstr (name_hint, "long") != nullptr)
|
||||
+ {
|
||||
+ /* Use "long double" for "complex long double". */
|
||||
+ tt = builtin_type (gdbarch)->builtin_long_double;
|
||||
+ }
|
||||
+ else
|
||||
+ tt = builtin_type (gdbarch)->builtin_double;
|
||||
break;
|
||||
case 96: /* The x86-32 ABI specifies 96-bit long double. */
|
||||
case 128:
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp b/gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp
|
||||
new file mode 100644
|
||||
index 00000000000..281e87d2fc8
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-complex-parts.exp
|
||||
@@ -0,0 +1,244 @@
|
||||
+# Copyright 2024 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Test complex types, and their parts. Dwarf assembly counterpart of
|
||||
+# gdb.base/complex-parts.exp.
|
||||
+#
|
||||
+# In dwarf, base types are not allowed to have references to other types. And
|
||||
+# because complex types are modeled as base types, gdb has to figure out what
|
||||
+# the part type is.
|
||||
+#
|
||||
+# It would be easier for gdb if compilers would add a dwarf extension and
|
||||
+# supply this information, but that may or may not happen
|
||||
+# ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115272 ).
|
||||
+
|
||||
+load_lib dwarf.exp
|
||||
+
|
||||
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
+require dwarf2_support
|
||||
+
|
||||
+standard_testfile main.c -debug.S
|
||||
+
|
||||
+if [prepare_for_testing "failed to prepare" $testfile \
|
||||
+ "${srcfile}" {}] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+set float_size [get_sizeof float 0]
|
||||
+set double_size [get_sizeof double 0]
|
||||
+set long_double_size [get_sizeof "long double" 0]
|
||||
+
|
||||
+set int_size [get_sizeof int 0]
|
||||
+
|
||||
+# Create the DWARF.
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ cu { version 2 } {
|
||||
+ compile_unit {} {
|
||||
+ # Main.
|
||||
+
|
||||
+ declare_labels int_type
|
||||
+
|
||||
+ int_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size $::int_size DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_signed}
|
||||
+ {DW_AT_name int}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_subprogram {
|
||||
+ {MACRO_AT_func {main}}
|
||||
+ {type :$int_type}
|
||||
+ }
|
||||
+
|
||||
+ # GCC complex float.
|
||||
+
|
||||
+ declare_labels cf_type cd_type cld_type
|
||||
+
|
||||
+ cf_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::float_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex float"}
|
||||
+ }
|
||||
+
|
||||
+ cd_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex double"}
|
||||
+ }
|
||||
+
|
||||
+ cld_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::long_double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex long double"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_float}
|
||||
+ {DW_AT_type :$cf_type}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_double}
|
||||
+ {DW_AT_type :$cd_type}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_long_double}
|
||||
+ {DW_AT_type :$cld_type}
|
||||
+ }
|
||||
+
|
||||
+ # GCC complex int.
|
||||
+ # This is what gcc currently generates, see gcc PR debug/93988.
|
||||
+
|
||||
+ declare_labels ci_type
|
||||
+
|
||||
+ ci_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::int_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_lo_user}
|
||||
+ {DW_AT_name "complex int"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_int}
|
||||
+ {DW_AT_type :$ci_type}
|
||||
+ }
|
||||
+
|
||||
+ # Clang complex float.
|
||||
+ # This is what clang currently generates, see this issue (
|
||||
+ # https://github.com/llvm/llvm-project/issues/52996 ).
|
||||
+
|
||||
+ declare_labels clang_cf_type clang_cd_type clang_cld_type
|
||||
+
|
||||
+ clang_cf_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::float_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_clang_float}
|
||||
+ {DW_AT_type :$clang_cf_type}
|
||||
+ }
|
||||
+
|
||||
+ clang_cd_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_clang_double}
|
||||
+ {DW_AT_type :$clang_cd_type}
|
||||
+ }
|
||||
+
|
||||
+ clang_cld_type: DW_TAG_base_type {
|
||||
+ {DW_AT_byte_size [expr 2 * $::long_double_size] DW_FORM_sdata}
|
||||
+ {DW_AT_encoding @DW_ATE_complex_float}
|
||||
+ {DW_AT_name "complex"}
|
||||
+ }
|
||||
+
|
||||
+ DW_TAG_variable {
|
||||
+ {name var_complex_clang_long_double}
|
||||
+ {DW_AT_type :$clang_cld_type}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if [prepare_for_testing "failed to prepare" $testfile \
|
||||
+ "${asm_file} ${srcfile}" {}] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+if ![runto_main] {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+proc do_test { type {clang 0}} {
|
||||
+ with_test_prefix $type {
|
||||
+ with_test_prefix clang=$clang {
|
||||
+
|
||||
+ if { $clang } {
|
||||
+ set type_id [regsub -all " " $type _]
|
||||
+ set var "var_complex_clang_$type_id"
|
||||
+
|
||||
+ # Gdb could try to synthesize better names, see enhancement
|
||||
+ # PR symtab/31858.
|
||||
+ set ctype "complex"
|
||||
+ set ctype_id "complex"
|
||||
+ } else {
|
||||
+ set ctype "complex $type"
|
||||
+ set type_id [regsub -all " " $type _]
|
||||
+ set ctype_id [regsub -all " " $ctype _]
|
||||
+ set var "var_$ctype_id"
|
||||
+ }
|
||||
+
|
||||
+ gdb_test "ptype '$type'" \
|
||||
+ "type = $type"
|
||||
+
|
||||
+ gdb_test "ptype '$ctype'" \
|
||||
+ "type = $ctype"
|
||||
+
|
||||
+ eval set type_size \$::${type_id}_size
|
||||
+
|
||||
+ gdb_test "p sizeof ('$type')" \
|
||||
+ " = $type_size"
|
||||
+
|
||||
+ if { ! $clang } {
|
||||
+ # With clang, the ctype name does not uniquely map to a type,
|
||||
+ # so the size is unpredictable.
|
||||
+ gdb_test "p sizeof ('$ctype')" \
|
||||
+ " = [expr 2 * $type_size]"
|
||||
+ }
|
||||
+
|
||||
+ set re_kfail \
|
||||
+ [string_to_regexp \
|
||||
+ "'var_complex_int' has unknown type; cast it to its declared type"]
|
||||
+
|
||||
+ foreach f { {$_cimag} {$_creal} } {
|
||||
+ gdb_test_multiple "p $f ($var)" "" {
|
||||
+ -re -wrap " = <optimized out>" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap $re_kfail {
|
||||
+ kfail gdb/31857 $gdb_test_name
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if { $clang } {
|
||||
+ # Without a specific complex type name, it's
|
||||
+ # unpredictable which type name the part will have.
|
||||
+ gdb_test {ptype $} \
|
||||
+ "type = (float|double|long double)" \
|
||||
+ "ptype $f"
|
||||
+ } else {
|
||||
+ gdb_test {ptype $} \
|
||||
+ "type = $type" \
|
||||
+ "ptype $f"
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+do_test "float"
|
||||
+do_test "double"
|
||||
+do_test "long double"
|
||||
+
|
||||
+do_test "int"
|
||||
+
|
||||
+do_test "float" 1
|
||||
+do_test "double" 1
|
||||
+do_test "long double" 1
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,37 +0,0 @@
|
||||
From bc970668f83cf142c4955d1cbeaa24e8bcc4b238 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Fri, 25 Aug 2023 09:30:54 +0200
|
||||
Subject: [PATCH 03/13] [gdb/symtab] Handle nullptr parent in
|
||||
parent_map::set_parent
|
||||
|
||||
Set_parent uses m_die_range_map.set_empty, which doesn't allow
|
||||
parent_entry == nullptr.
|
||||
|
||||
So it may be necessary to guard calls to set_parent with
|
||||
"if (parent_entry != nullptr)".
|
||||
|
||||
Fix this by handling the parent_entry == nullptr case in set_parent.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.h | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 979541fbf60..79fbfe88c03 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -263,7 +263,9 @@ class parent_map
|
||||
void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
const cooked_index_entry *parent_entry)
|
||||
{
|
||||
- m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ /* Calling set_empty with nullptr is currently not allowed. */
|
||||
+ if (parent_entry != nullptr)
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
}
|
||||
|
||||
private:
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,38 +0,0 @@
|
||||
From 0e706742f37ee90629350780263b573f326f1a5f Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 7 Dec 2023 10:38:05 +0100
|
||||
Subject: [PATCH 12/13] [gdb/symtab] Keep track of all parents for cooked index
|
||||
|
||||
Keep track of all parents for cooked index.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index de7b655d26c..93708ef11b9 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16718,9 +16718,15 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
});
|
||||
}
|
||||
else
|
||||
- this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
- name, this_parent_entry,
|
||||
- m_per_cu);
|
||||
+ {
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (this_die, reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ set_parent (addr, addr, this_parent_entry);
|
||||
+ this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
+ name, this_parent_entry,
|
||||
+ m_per_cu);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (linkage_name != nullptr)
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,126 +0,0 @@
|
||||
From e8285c8b37d28033209cad6579db4b9f6a48a01a Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 24 Sep 2023 11:41:39 +0200
|
||||
Subject: [PATCH 08/13] [gdb/symtab] Keep track of processed DIEs in shard
|
||||
|
||||
For optimizations in two following patches, we keep track in each shard which
|
||||
DIEs have been processed.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.c | 1 +
|
||||
gdb/dwarf2/cooked-index.h | 15 +++++++++++++++
|
||||
gdb/dwarf2/read.c | 24 ++++++++++++++++++++++++
|
||||
3 files changed, 40 insertions(+)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
|
||||
index 3231d25db5a..c096da57d62 100644
|
||||
--- a/gdb/dwarf2/cooked-index.c
|
||||
+++ b/gdb/dwarf2/cooked-index.c
|
||||
@@ -723,6 +723,7 @@ cooked_index::handle_deferred_entries ()
|
||||
{
|
||||
shard->m_die_range_map.reset (nullptr);
|
||||
shard->m_deferred_entries.reset (nullptr);
|
||||
+ shard->m_die_range_map_valid.reset (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 66424c37f7c..fa895233035 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -316,6 +316,7 @@ class cooked_index_shard
|
||||
{
|
||||
m_die_range_map.reset (new parent_map);
|
||||
m_deferred_entries.reset (new std::vector<deferred_entry>);
|
||||
+ m_die_range_map_valid.reset (new addrmap_mutable);
|
||||
}
|
||||
|
||||
DISABLE_COPY_AND_ASSIGN (cooked_index_shard);
|
||||
@@ -407,6 +408,18 @@ class cooked_index_shard
|
||||
const cooked_index_entry *resolve_deferred_entry
|
||||
(const deferred_entry &entry, const cooked_index_entry *parent_entry);
|
||||
|
||||
+ /* Mark parents in range [START, END] as valid . */
|
||||
+ void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
+ {
|
||||
+ m_die_range_map_valid->set_empty (start, end, (void *) 1);
|
||||
+ }
|
||||
+
|
||||
+ /* Return true if find_parents can be relied upon. */
|
||||
+ bool parent_valid (CORE_ADDR addr)
|
||||
+ {
|
||||
+ return m_die_range_map_valid->find (addr) != nullptr;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Return the entry that is believed to represent the program's
|
||||
@@ -470,6 +483,8 @@ class cooked_index_shard
|
||||
understand this. */
|
||||
std::unique_ptr<parent_map> m_die_range_map;
|
||||
|
||||
+ std::unique_ptr<addrmap> m_die_range_map_valid;
|
||||
+
|
||||
/* The generated DWARF can sometimes have the declaration for a
|
||||
method in a class (or perhaps namespace) scope, with the
|
||||
definition appearing outside this scope... just one of the many
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 5b7c0969ed7..09598e702bc 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4697,6 +4697,12 @@ class cooked_index_storage
|
||||
m_index->defer_entry (de);
|
||||
}
|
||||
|
||||
+ /* Mark parents in range [START, END] as valid . */
|
||||
+ void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
+ {
|
||||
+ m_index->set_parent_valid (start, end);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Hash function for a cutu_reader. */
|
||||
@@ -4840,6 +4846,11 @@ class cooked_indexer
|
||||
{
|
||||
m_index_storage->defer_entry (de);
|
||||
}
|
||||
+
|
||||
+ void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
+ {
|
||||
+ m_index_storage->set_parent_valid (start, end);
|
||||
+ }
|
||||
};
|
||||
|
||||
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
||||
@@ -16604,6 +16615,11 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
+ to_underlying (reader->cu->header.sect_off)
|
||||
+ reader->cu->header.get_length_with_initial ());
|
||||
|
||||
+ const CORE_ADDR start_cu
|
||||
+ = parent_map::form_addr (sect_offset (info_ptr - reader->buffer),
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+
|
||||
while (info_ptr < end_ptr)
|
||||
{
|
||||
sect_offset this_die = (sect_offset) (info_ptr - reader->buffer);
|
||||
@@ -16754,6 +16770,14 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
}
|
||||
}
|
||||
|
||||
+ {
|
||||
+ CORE_ADDR end_prev_die
|
||||
+ = parent_map::form_addr (sect_offset (info_ptr - reader->buffer - 1),
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ set_parent_valid (start_cu, end_prev_die);
|
||||
+ }
|
||||
+
|
||||
return info_ptr;
|
||||
}
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,70 +0,0 @@
|
||||
From f72f115b4c012e3748a2e702d7b970be19974885 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Mon, 11 Dec 2023 15:41:26 +0100
|
||||
Subject: [PATCH 01/13] [gdb/symtab] Refactor condition in scan_attributes
|
||||
|
||||
In scan_attributes there's code:
|
||||
...
|
||||
if (new_reader->cu == reader->cu
|
||||
&& new_info_ptr > watermark_ptr
|
||||
&& *parent_entry == nullptr)
|
||||
...
|
||||
else if (*parent_entry == nullptr)
|
||||
...
|
||||
...
|
||||
that uses the "*parent_entry == nullptr" condition twice.
|
||||
|
||||
Make this somewhat more readable by factoring out the condition:
|
||||
...
|
||||
if (*parent_entry == nullptr)
|
||||
{
|
||||
if (new_reader->cu == reader->cu
|
||||
&& new_info_ptr > watermark_ptr)
|
||||
...
|
||||
else
|
||||
...
|
||||
}
|
||||
...
|
||||
|
||||
This also allows us to factor out "form_addr (origin_offset, origin_is_dwz)".
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/read.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 50fa302b43a..466d3e59878 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -16410,15 +16410,17 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
const gdb_byte *new_info_ptr = (new_reader->buffer
|
||||
+ to_underlying (origin_offset));
|
||||
|
||||
- if (new_reader->cu == reader->cu
|
||||
- && new_info_ptr > watermark_ptr
|
||||
- && *parent_entry == nullptr)
|
||||
- *maybe_defer = form_addr (origin_offset, origin_is_dwz);
|
||||
- else if (*parent_entry == nullptr)
|
||||
+ if (*parent_entry == nullptr)
|
||||
{
|
||||
- CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz);
|
||||
- void *obj = m_die_range_map.find (lookup);
|
||||
- *parent_entry = static_cast <cooked_index_entry *> (obj);
|
||||
+ CORE_ADDR addr = form_addr (origin_offset, origin_is_dwz);
|
||||
+ if (new_reader->cu == reader->cu
|
||||
+ && new_info_ptr > watermark_ptr)
|
||||
+ *maybe_defer = addr;
|
||||
+ else
|
||||
+ {
|
||||
+ void *obj = m_die_range_map.find (addr);
|
||||
+ *parent_entry = static_cast <cooked_index_entry *> (obj);
|
||||
+ }
|
||||
}
|
||||
|
||||
unsigned int bytes_read;
|
||||
|
||||
base-commit: 3490f51a80a10d46dc1885ba672d9390a8221170
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,500 +0,0 @@
|
||||
From e2d7097cf236c9ea6959785754d067833fc302af Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Tue, 22 Aug 2023 14:24:42 +0200
|
||||
Subject: [PATCH 05/13] [gdb/symtab] Resolve deferred entries, inter-shard case
|
||||
|
||||
Generically solve the case of inter-CU dependencies, including inter-shard
|
||||
dependencies:
|
||||
- mark deferred entries in new data structure m_deferred,
|
||||
- return &parent_map::deferred in find_parent for deferred entries,
|
||||
- defer all intra-CU dependencies that depend on deferred entries,
|
||||
- defer all inter-CU dependencies (note that two subsequent patches implement
|
||||
optimizations to deal with this more optimally),
|
||||
- move m_die_range_map and m_deferred_dies to cooked_index_shard, and
|
||||
- move handle_deferred_dies to the cooked_index, where it is called in the
|
||||
constructor, and update it to handle the intra-shard case.
|
||||
|
||||
Handling units from the .debug_info section alongside units from the
|
||||
.debug_types section requires us to extend form_addr to take is_debug_types
|
||||
into account.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/30846
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30846
|
||||
---
|
||||
gdb/dwarf2/cooked-index.c | 77 +++++++++++++++++++++++
|
||||
gdb/dwarf2/cooked-index.h | 105 ++++++++++++++++++++++++++++++-
|
||||
gdb/dwarf2/read.c | 128 ++++++++++++++++++++++----------------
|
||||
3 files changed, 254 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
|
||||
index 58ea541a5c9..3231d25db5a 100644
|
||||
--- a/gdb/dwarf2/cooked-index.c
|
||||
+++ b/gdb/dwarf2/cooked-index.c
|
||||
@@ -228,6 +228,12 @@ cooked_index_entry::write_scope (struct obstack *storage,
|
||||
|
||||
/* See cooked-index.h. */
|
||||
|
||||
+cooked_index_entry parent_map::deferred((sect_offset)0, (dwarf_tag)0,
|
||||
+ (cooked_index_flag)0, nullptr,
|
||||
+ nullptr, nullptr);
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
const cooked_index_entry *
|
||||
cooked_index_shard::add (sect_offset die_offset, enum dwarf_tag tag,
|
||||
cooked_index_flag flags, const char *name,
|
||||
@@ -446,6 +452,8 @@ cooked_index_shard::wait (bool allow_quit) const
|
||||
cooked_index::cooked_index (vec_type &&vec)
|
||||
: m_vector (std::move (vec))
|
||||
{
|
||||
+ handle_deferred_entries ();
|
||||
+
|
||||
for (auto &idx : m_vector)
|
||||
idx->finalize ();
|
||||
|
||||
@@ -649,6 +657,75 @@ cooked_index::maybe_write_index (dwarf2_per_bfd *per_bfd,
|
||||
global_index_cache.store (per_bfd, ctx);
|
||||
}
|
||||
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+const cooked_index_entry *
|
||||
+cooked_index_shard::resolve_deferred_entry
|
||||
+ (const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
+{
|
||||
+ reset_parent_deferred (parent_map::form_addr (de.die_offset, de.per_cu_2->is_dwz,
|
||||
+ de.per_cu_2->is_debug_types));
|
||||
+ return add (de.die_offset, de.tag, de.flags, de.name,
|
||||
+ parent_entry, de.per_cu);
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+const cooked_index_entry *
|
||||
+cooked_index::find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const
|
||||
+{
|
||||
+ const cooked_index_entry *parent_entry = nullptr;
|
||||
+ for (auto &parent_map_shard : m_vector)
|
||||
+ {
|
||||
+ auto res = parent_map_shard->find_parent (entry.spec_offset);
|
||||
+ if (res != nullptr)
|
||||
+ {
|
||||
+ parent_entry = res;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return parent_entry;
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+void
|
||||
+cooked_index::handle_deferred_entries ()
|
||||
+{
|
||||
+ bool changed;
|
||||
+ bool deferred;
|
||||
+ do
|
||||
+ {
|
||||
+ deferred = false;
|
||||
+ changed = false;
|
||||
+ for (auto &shard : m_vector)
|
||||
+ for (auto it = shard->m_deferred_entries->begin ();
|
||||
+ it != shard->m_deferred_entries->end (); )
|
||||
+ {
|
||||
+ const cooked_index_entry *parent_entry
|
||||
+ = find_parent_deferred_entry (*it);
|
||||
+ if (parent_entry == &parent_map::deferred)
|
||||
+ {
|
||||
+ deferred = true;
|
||||
+ it++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ shard->resolve_deferred_entry (*it, parent_entry);
|
||||
+ it = shard->m_deferred_entries->erase (it);
|
||||
+ changed = true;
|
||||
+ }
|
||||
+ }
|
||||
+ while (changed && deferred);
|
||||
+
|
||||
+ for (auto &shard : m_vector)
|
||||
+ {
|
||||
+ shard->m_die_range_map.reset (nullptr);
|
||||
+ shard->m_deferred_entries.reset (nullptr);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Wait for all the index cache entries to be written before gdb
|
||||
exits. */
|
||||
static void
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index 79fbfe88c03..66424c37f7c 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "dwarf2/mapped-index.h"
|
||||
#include "dwarf2/tag.h"
|
||||
#include "gdbsupport/range-chain.h"
|
||||
+#include <unordered_set>
|
||||
|
||||
struct dwarf2_per_cu_data;
|
||||
struct dwarf2_per_bfd;
|
||||
@@ -242,19 +243,29 @@ struct cooked_index_entry : public allocate_on_obstack
|
||||
class parent_map
|
||||
{
|
||||
public:
|
||||
+ /* A dummy cooked_index_entry to mark that computing the parent has been
|
||||
+ deferred. */
|
||||
+ static cooked_index_entry deferred;
|
||||
+
|
||||
/* A helper function to turn a section offset into an address that
|
||||
can be used in a parent_map. */
|
||||
- static CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
|
||||
+ static CORE_ADDR form_addr (sect_offset offset, bool is_dwz,
|
||||
+ bool is_debug_types)
|
||||
{
|
||||
CORE_ADDR value = to_underlying (offset);
|
||||
if (is_dwz)
|
||||
value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
|
||||
+ if (is_debug_types)
|
||||
+ value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Find the parent of DIE LOOKUP. */
|
||||
const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
{
|
||||
+ if (m_deferred.find (lookup) != m_deferred.end ())
|
||||
+ return &parent_map::deferred;
|
||||
+
|
||||
const void *obj = m_parent_map.find (lookup);
|
||||
return static_cast<const cooked_index_entry *> (obj);
|
||||
}
|
||||
@@ -265,12 +276,28 @@ class parent_map
|
||||
{
|
||||
/* Calling set_empty with nullptr is currently not allowed. */
|
||||
if (parent_entry != nullptr)
|
||||
- m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ {
|
||||
+ gdb_assert (parent_entry != &parent_map::deferred);
|
||||
+ m_parent_map.set_empty (start, end, (void *)parent_entry);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_deferred.emplace (addr);
|
||||
+ }
|
||||
+
|
||||
+ void reset_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_deferred.erase (addr);
|
||||
}
|
||||
|
||||
private:
|
||||
/* An addrmap that maps from section offsets to cooked_index_entry *. */
|
||||
addrmap_mutable m_parent_map;
|
||||
+
|
||||
+ /* DIEs that are deffered. */
|
||||
+ std::unordered_set<CORE_ADDR> m_deferred;
|
||||
};
|
||||
|
||||
class cooked_index;
|
||||
@@ -285,7 +312,12 @@ class cooked_index;
|
||||
class cooked_index_shard
|
||||
{
|
||||
public:
|
||||
- cooked_index_shard () = default;
|
||||
+ cooked_index_shard ()
|
||||
+ {
|
||||
+ m_die_range_map.reset (new parent_map);
|
||||
+ m_deferred_entries.reset (new std::vector<deferred_entry>);
|
||||
+ }
|
||||
+
|
||||
DISABLE_COPY_AND_ASSIGN (cooked_index_shard);
|
||||
|
||||
/* Create a new cooked_index_entry and register it with this object.
|
||||
@@ -329,6 +361,52 @@ class cooked_index_shard
|
||||
for completion, will be returned. */
|
||||
range find (const std::string &name, bool completing) const;
|
||||
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *
|
||||
+ find_parent (CORE_ADDR lookup) const
|
||||
+ {
|
||||
+ return m_die_range_map->find_parent (lookup);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_die_range_map->set_parent (start, end, parent_entry);
|
||||
+ }
|
||||
+
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_die_range_map->set_parent_deferred (addr);
|
||||
+ }
|
||||
+
|
||||
+ void reset_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_die_range_map->reset_parent_deferred (addr);
|
||||
+ }
|
||||
+
|
||||
+ /* A single deferred entry. See m_deferred_entries. */
|
||||
+ struct deferred_entry
|
||||
+ {
|
||||
+ sect_offset die_offset;
|
||||
+ const char *name;
|
||||
+ CORE_ADDR spec_offset;
|
||||
+ dwarf_tag tag;
|
||||
+ cooked_index_flag flags;
|
||||
+ dwarf2_per_cu_data *per_cu;
|
||||
+ dwarf2_per_cu_data *per_cu_2;
|
||||
+ };
|
||||
+
|
||||
+ /* Defer creating a cooked_index_entry corresponding to DEFERRED. */
|
||||
+ void defer_entry (deferred_entry de)
|
||||
+ {
|
||||
+ m_deferred_entries->push_back (de);
|
||||
+ }
|
||||
+
|
||||
+ /* Variant of add that takes a deferred_entry as parameter. */
|
||||
+ const cooked_index_entry *resolve_deferred_entry
|
||||
+ (const deferred_entry &entry, const cooked_index_entry *parent_entry);
|
||||
+
|
||||
private:
|
||||
|
||||
/* Return the entry that is believed to represent the program's
|
||||
@@ -386,6 +464,20 @@ class cooked_index_shard
|
||||
that the 'get' method is never called on this future, only
|
||||
'wait'. */
|
||||
gdb::future<void> m_future;
|
||||
+
|
||||
+ /* An addrmap that maps from section offsets (see the form_addr
|
||||
+ method) to newly-created entries. See m_deferred_entries to
|
||||
+ understand this. */
|
||||
+ std::unique_ptr<parent_map> m_die_range_map;
|
||||
+
|
||||
+ /* The generated DWARF can sometimes have the declaration for a
|
||||
+ method in a class (or perhaps namespace) scope, with the
|
||||
+ definition appearing outside this scope... just one of the many
|
||||
+ bad things about DWARF. In order to handle this situation, we
|
||||
+ defer certain entries until the end of scanning, at which point
|
||||
+ we'll know the containing context of all the DIEs that we might
|
||||
+ have scanned. This vector stores these deferred entries. */
|
||||
+ std::unique_ptr<std::vector<deferred_entry>> m_deferred_entries;
|
||||
};
|
||||
|
||||
/* The main index of DIEs. The parallel DIE indexers create
|
||||
@@ -469,6 +561,13 @@ class cooked_index : public dwarf_scanner_base
|
||||
|
||||
private:
|
||||
|
||||
+ /* Find the parent corresponding to deferred entry ENTRY. */
|
||||
+ const cooked_index_entry *find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const;
|
||||
+
|
||||
+ /* Create cooked_index_entries for the deferred entries. */
|
||||
+ void handle_deferred_entries ();
|
||||
+
|
||||
/* Maybe write the index to the index cache. */
|
||||
void maybe_write_index (dwarf2_per_bfd *per_bfd,
|
||||
const index_cache_store_context &);
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index afdf9e870a8..5b7c0969ed7 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4672,6 +4672,31 @@ class cooked_index_storage
|
||||
return &m_addrmap;
|
||||
}
|
||||
|
||||
+ /* Find the parent of DIE LOOKUP. */
|
||||
+ const cooked_index_entry *find_parent (CORE_ADDR lookup)
|
||||
+ {
|
||||
+ return m_index->find_parent (lookup);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
+ void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
+ const cooked_index_entry *parent_entry)
|
||||
+ {
|
||||
+ m_index->set_parent (start, end, parent_entry);
|
||||
+ }
|
||||
+
|
||||
+ /* Set the parent of DIE at ADDR as deferred. */
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
+ {
|
||||
+ m_index->set_parent_deferred (addr);
|
||||
+ }
|
||||
+
|
||||
+ /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
+ void defer_entry (cooked_index_shard::deferred_entry de)
|
||||
+ {
|
||||
+ m_index->defer_entry (de);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
|
||||
/* Hash function for a cutu_reader. */
|
||||
@@ -4794,59 +4819,26 @@ class cooked_indexer
|
||||
/* Find the parent of DIE LOOKUP. */
|
||||
const cooked_index_entry *find_parent (CORE_ADDR lookup) const
|
||||
{
|
||||
- return m_die_range_map.find_parent (lookup);
|
||||
+ return m_index_storage->find_parent (lookup);
|
||||
}
|
||||
|
||||
/* Set the parent of DIES in range [START, END] to PARENT_ENTRY. */
|
||||
void set_parent (CORE_ADDR start, CORE_ADDR end,
|
||||
const cooked_index_entry *parent_entry)
|
||||
{
|
||||
- m_die_range_map.set_parent (start, end, parent_entry);
|
||||
+ m_index_storage->set_parent (start, end, parent_entry);
|
||||
}
|
||||
|
||||
- /* A single deferred entry. */
|
||||
- struct deferred_entry
|
||||
- {
|
||||
- sect_offset die_offset;
|
||||
- const char *name;
|
||||
- CORE_ADDR spec_offset;
|
||||
- dwarf_tag tag;
|
||||
- cooked_index_flag flags;
|
||||
- };
|
||||
-
|
||||
- /* The generated DWARF can sometimes have the declaration for a
|
||||
- method in a class (or perhaps namespace) scope, with the
|
||||
- definition appearing outside this scope... just one of the many
|
||||
- bad things about DWARF. In order to handle this situation, we
|
||||
- defer certain entries until the end of scanning, at which point
|
||||
- we'll know the containing context of all the DIEs that we might
|
||||
- have scanned. This vector stores these deferred entries. */
|
||||
- std::vector<deferred_entry> m_deferred_entries;
|
||||
-
|
||||
- /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
- void defer_entry (const deferred_entry &de)
|
||||
+ /* Set the parent of DIE at ADDR as deferred. */
|
||||
+ void set_parent_deferred (CORE_ADDR addr)
|
||||
{
|
||||
- m_deferred_entries.push_back (de);
|
||||
+ m_index_storage->set_parent_deferred (addr);
|
||||
}
|
||||
|
||||
- /* Create a cooked_index_entry corresponding to deferred_entry DE with
|
||||
- parent PARENT_ENTRY. */
|
||||
- const cooked_index_entry *resolve_deferred_entry
|
||||
- (const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
- {
|
||||
- return m_index_storage->add (de.die_offset, de.tag, de.flags, de.name,
|
||||
- parent_entry, m_per_cu);
|
||||
- }
|
||||
-
|
||||
- /* Create cooked_index_entries for the deferred entries. */
|
||||
- void handle_deferred_entries ()
|
||||
+ /* Defer creating a cooked_index_entry corresponding to deferred_entry DE. */
|
||||
+ void defer_entry (const cooked_index_shard::deferred_entry &de)
|
||||
{
|
||||
- for (const auto &entry : m_deferred_entries)
|
||||
- {
|
||||
- const cooked_index_entry *parent_entry
|
||||
- = find_parent (entry.spec_offset);
|
||||
- resolve_deferred_entry (entry, parent_entry);
|
||||
- }
|
||||
+ m_index_storage->defer_entry (de);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16441,13 +16433,36 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
|
||||
|
||||
if (*parent_entry == nullptr)
|
||||
{
|
||||
+ gdb_assert (reader->cu->per_cu->is_debug_types
|
||||
+ == new_reader->cu->per_cu->is_debug_types);
|
||||
CORE_ADDR addr
|
||||
- = parent_map::form_addr (origin_offset, origin_is_dwz);
|
||||
- if (new_reader->cu == reader->cu
|
||||
- && new_info_ptr > watermark_ptr)
|
||||
- *maybe_defer = addr;
|
||||
+ = parent_map::form_addr (origin_offset, origin_is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ if (new_reader->cu == reader->cu)
|
||||
+ {
|
||||
+ /* Intra-CU case. */
|
||||
+ if (new_info_ptr > watermark_ptr)
|
||||
+ {
|
||||
+ /* Defer because origin is not read yet. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ auto tmp = find_parent (addr);
|
||||
+ if (tmp == &parent_map::deferred)
|
||||
+ {
|
||||
+ /* Defer because origin is deferred. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
+ else
|
||||
+ *parent_entry = tmp;
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
- *parent_entry = find_parent (addr);
|
||||
+ {
|
||||
+ /* Inter-CU case. */
|
||||
+ *maybe_defer = addr;
|
||||
+ }
|
||||
}
|
||||
|
||||
unsigned int bytes_read;
|
||||
@@ -16567,10 +16582,12 @@ cooked_indexer::recurse (cutu_reader *reader,
|
||||
limit the range to the children of parent_entry. */
|
||||
CORE_ADDR start
|
||||
= parent_map::form_addr (parent_entry->die_offset + 1,
|
||||
- reader->cu->per_cu->is_dwz);
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
CORE_ADDR end
|
||||
= parent_map::form_addr (sect_offset (info_ptr - 1 - reader->buffer),
|
||||
- reader->cu->per_cu->is_dwz);
|
||||
+ reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
set_parent (start, end, parent_entry);
|
||||
}
|
||||
|
||||
@@ -16637,9 +16654,16 @@ cooked_indexer::index_dies (cutu_reader *reader,
|
||||
if (name != nullptr)
|
||||
{
|
||||
if (defer != 0)
|
||||
- defer_entry ({
|
||||
- this_die, name, defer, abbrev->tag, flags
|
||||
- });
|
||||
+ {
|
||||
+ CORE_ADDR addr
|
||||
+ = parent_map::form_addr (this_die, reader->cu->per_cu->is_dwz,
|
||||
+ reader->cu->per_cu->is_debug_types);
|
||||
+ set_parent_deferred (addr);
|
||||
+ defer_entry ({
|
||||
+ this_die, name, defer, abbrev->tag, flags, m_per_cu,
|
||||
+ reader->cu->per_cu
|
||||
+ });
|
||||
+ }
|
||||
else
|
||||
this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
|
||||
name, this_parent_entry,
|
||||
@@ -16741,8 +16765,6 @@ cooked_indexer::make_index (cutu_reader *reader)
|
||||
if (!reader->comp_unit_die->has_children)
|
||||
return;
|
||||
index_dies (reader, reader->info_ptr, nullptr, false);
|
||||
-
|
||||
- handle_deferred_entries ();
|
||||
}
|
||||
|
||||
/* An implementation of quick_symbol_functions for the cooked DWARF
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,120 +0,0 @@
|
||||
From 3b2f2b376bb80edadacc582161c362612947e3a6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sun, 24 Sep 2023 11:43:24 +0200
|
||||
Subject: [PATCH 09/13] [gdb/symtab] Resolve deferred entries, intra-shard case
|
||||
|
||||
In patch "[gdb/symtab] Resolve deferred entries, inter-shard case" we've
|
||||
solved the generic case of handling deferred entries.
|
||||
|
||||
Now add an optimization that handles deferred entries with an intra-shard
|
||||
dependency in the parallel for.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
---
|
||||
gdb/dwarf2/cooked-index.c | 35 +++++++++++++++++++++++++++++++++++
|
||||
gdb/dwarf2/cooked-index.h | 7 +++++++
|
||||
gdb/dwarf2/read.c | 10 ++++++++++
|
||||
3 files changed, 52 insertions(+)
|
||||
|
||||
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
|
||||
index c096da57d62..ebed21d510c 100644
|
||||
--- a/gdb/dwarf2/cooked-index.c
|
||||
+++ b/gdb/dwarf2/cooked-index.c
|
||||
@@ -452,6 +452,7 @@ cooked_index_shard::wait (bool allow_quit) const
|
||||
cooked_index::cooked_index (vec_type &&vec)
|
||||
: m_vector (std::move (vec))
|
||||
{
|
||||
+ /* Handle deferred entries, inter-cu case. */
|
||||
handle_deferred_entries ();
|
||||
|
||||
for (auto &idx : m_vector)
|
||||
@@ -659,6 +660,40 @@ cooked_index::maybe_write_index (dwarf2_per_bfd *per_bfd,
|
||||
|
||||
/* See cooked-index.h. */
|
||||
|
||||
+const cooked_index_entry *
|
||||
+cooked_index_shard::find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const
|
||||
+{
|
||||
+ return find_parent (entry.spec_offset);
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
+void
|
||||
+cooked_index_shard::handle_deferred_entries ()
|
||||
+{
|
||||
+ for (auto it = m_deferred_entries->begin (); it != m_deferred_entries->end (); )
|
||||
+ {
|
||||
+ const deferred_entry & deferred_entry = *it;
|
||||
+ if (!parent_valid (deferred_entry.spec_offset))
|
||||
+ {
|
||||
+ it++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ const cooked_index_entry *parent_entry
|
||||
+ = find_parent_deferred_entry (deferred_entry);
|
||||
+ if (parent_entry == &parent_map::deferred)
|
||||
+ {
|
||||
+ it++;
|
||||
+ continue;
|
||||
+ }
|
||||
+ resolve_deferred_entry (deferred_entry, parent_entry);
|
||||
+ it = m_deferred_entries->erase (it);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* See cooked-index.h. */
|
||||
+
|
||||
const cooked_index_entry *
|
||||
cooked_index_shard::resolve_deferred_entry
|
||||
(const deferred_entry &de, const cooked_index_entry *parent_entry)
|
||||
diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h
|
||||
index fa895233035..106e3091a90 100644
|
||||
--- a/gdb/dwarf2/cooked-index.h
|
||||
+++ b/gdb/dwarf2/cooked-index.h
|
||||
@@ -408,6 +408,13 @@ class cooked_index_shard
|
||||
const cooked_index_entry *resolve_deferred_entry
|
||||
(const deferred_entry &entry, const cooked_index_entry *parent_entry);
|
||||
|
||||
+ /* Find the parent entry for deferred_entry ENTRY. */
|
||||
+ const cooked_index_entry *find_parent_deferred_entry
|
||||
+ (const cooked_index_shard::deferred_entry &entry) const;
|
||||
+
|
||||
+ /* Create cooked_index_entries for the deferred entries. */
|
||||
+ void handle_deferred_entries ();
|
||||
+
|
||||
/* Mark parents in range [START, END] as valid . */
|
||||
void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
{
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 09598e702bc..a97f738a54e 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -4697,6 +4697,12 @@ class cooked_index_storage
|
||||
m_index->defer_entry (de);
|
||||
}
|
||||
|
||||
+ /* Handle deferred entries, intra-cu case. */
|
||||
+ void handle_deferred_entries ()
|
||||
+ {
|
||||
+ m_index->handle_deferred_entries ();
|
||||
+ }
|
||||
+
|
||||
/* Mark parents in range [START, END] as valid . */
|
||||
void set_parent_valid (CORE_ADDR start, CORE_ADDR end)
|
||||
{
|
||||
@@ -5183,6 +5189,10 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
|
||||
errors.push_back (std::move (except));
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* Handle deferred entries, intra-cu case. */
|
||||
+ thread_storage.handle_deferred_entries ();
|
||||
+
|
||||
return result_type (thread_storage.release (), std::move (errors));
|
||||
}, task_size);
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,278 +0,0 @@
|
||||
From 1b878333913343630472f89b4bc42f51b1619308 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 Nov 2023 00:33:12 +0100
|
||||
Subject: [PATCH 1/2] [gdb/symtab] Work around gas PR28629
|
||||
|
||||
When running test-case gdb.tui/tui-layout-asm-short-prog.exp on AlmaLinux 9.2
|
||||
ppc64le, I run into:
|
||||
...
|
||||
FAIL: gdb.tui/tui-layout-asm-short-prog.exp: check asm box contents
|
||||
...
|
||||
|
||||
The problem is that we get:
|
||||
...
|
||||
7 [ No Assembly Available ]
|
||||
...
|
||||
because tui_get_begin_asm_address doesn't succeed.
|
||||
|
||||
In more detail, tui_get_begin_asm_address calls:
|
||||
...
|
||||
find_line_pc (sal.symtab, sal.line, &addr);
|
||||
...
|
||||
with:
|
||||
...
|
||||
(gdb) p *sal.symtab
|
||||
$5 = {next = 0x130393c0, m_compunit = 0x130392f0, m_linetable = 0x0,
|
||||
filename = "tui-layout-asm-short-prog.S",
|
||||
filename_for_id = "$gdb/build/gdb/testsuite/tui-layout-asm-short-prog.S",
|
||||
m_language = language_asm, fullname = 0x0}
|
||||
(gdb) p sal.line
|
||||
$6 = 1
|
||||
...
|
||||
|
||||
The problem is the filename_for_id which is the source file prefixed with the
|
||||
compilation dir rather than the source dir.
|
||||
|
||||
This is due to faulty debug info generated by gas, PR28629:
|
||||
...
|
||||
<1a> DW_AT_name : tui-layout-asm-short-prog.S
|
||||
<1e> DW_AT_comp_dir : $gdb/build/gdb/testsuite
|
||||
<22> DW_AT_producer : GNU AS 2.35.2
|
||||
...
|
||||
|
||||
The DW_AT_name is relative, and it's relative to the DW_AT_comp_dir entry,
|
||||
making the effective name $gdb/build/gdb/testsuite/tui-layout-asm-short-prog.S.
|
||||
|
||||
The bug is fixed starting version 2.38, where we get instead:
|
||||
...
|
||||
<1a> DW_AT_name :
|
||||
$gdb/src/gdb/testsuite/gdb.tui/tui-layout-asm-short-prog.S
|
||||
<1e> DW_AT_comp_dir : $gdb/build/gdb/testsuite
|
||||
<22> DW_AT_producer : GNU AS 2.38
|
||||
...
|
||||
|
||||
Work around the faulty debug info by constructing the filename_for_id using
|
||||
the second directory from the directory table in the .debug_line header:
|
||||
...
|
||||
The Directory Table (offset 0x22, lines 2, columns 1):
|
||||
Entry Name
|
||||
0 $gdb/build/gdb/testsuite
|
||||
1 $gdb/src/gdb/testsuite/gdb.tui
|
||||
...
|
||||
|
||||
Note that the used gas contains a backport of commit 3417bfca676 ("GAS:
|
||||
DWARF-5: Ensure that the 0'th entry in the directory table contains the
|
||||
current working directory."), because directory 0 is correct. With the
|
||||
unpatched 2.35.2 release the directory 0 entry is incorrect: it's a copy of
|
||||
entry 1.
|
||||
|
||||
Add a dwarf assembly test-case that reflects the debug info as generated by
|
||||
unpatched gas 2.35.2.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
Approved-By: Tom Tromey <tom@tromey.com>
|
||||
---
|
||||
gdb/dwarf2/cu.c | 1 +
|
||||
gdb/dwarf2/cu.h | 1 +
|
||||
gdb/dwarf2/read.c | 37 +++++++-
|
||||
.../gdb.dwarf2/dw2-gas-workaround.exp | 92 +++++++++++++++++++
|
||||
4 files changed, 130 insertions(+), 1 deletion(-)
|
||||
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
|
||||
diff --git a/gdb/dwarf2/cu.c b/gdb/dwarf2/cu.c
|
||||
index a908ec908cd..f9b05dfc709 100644
|
||||
--- a/gdb/dwarf2/cu.c
|
||||
+++ b/gdb/dwarf2/cu.c
|
||||
@@ -40,6 +40,7 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
||||
producer_is_icc_lt_14 (false),
|
||||
producer_is_codewarrior (false),
|
||||
producer_is_clang (false),
|
||||
+ producer_is_gas_lt_2_38 (false),
|
||||
producer_is_gas_2_39 (false),
|
||||
processing_has_namespace_info (false),
|
||||
load_all_dies (false)
|
||||
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
|
||||
index 6c611710503..ef8db480e3f 100644
|
||||
--- a/gdb/dwarf2/cu.h
|
||||
+++ b/gdb/dwarf2/cu.h
|
||||
@@ -265,6 +265,7 @@ struct dwarf2_cu
|
||||
bool producer_is_icc_lt_14 : 1;
|
||||
bool producer_is_codewarrior : 1;
|
||||
bool producer_is_clang : 1;
|
||||
+ bool producer_is_gas_lt_2_38 : 1;
|
||||
bool producer_is_gas_2_39 : 1;
|
||||
|
||||
/* When true, the file that we're processing is known to have
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index fc4667b782f..50fa302b43a 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -147,6 +147,8 @@ static int dwarf2_locexpr_block_index;
|
||||
static int dwarf2_loclist_block_index;
|
||||
static int ada_block_index;
|
||||
|
||||
+static bool producer_is_gas_lt_2_38 (struct dwarf2_cu *cu);
|
||||
+
|
||||
/* Size of .debug_loclists section header for 32-bit DWARF format. */
|
||||
#define LOCLIST_HEADER_SIZE32 12
|
||||
|
||||
@@ -7665,6 +7667,27 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
||||
|
||||
file_and_directory &fnd = find_file_and_directory (die, cu);
|
||||
|
||||
+ /* GAS supports generating dwarf-5 info starting version 2.35. Versions
|
||||
+ 2.35-2.37 generate an incorrect CU name attribute: it's relative,
|
||||
+ implicitly prefixing it with the compilation dir. Work around this by
|
||||
+ prefixing it with the source dir instead. */
|
||||
+ if (cu->header.version == 5 && !IS_ABSOLUTE_PATH (fnd.get_name ())
|
||||
+ && producer_is_gas_lt_2_38 (cu))
|
||||
+ {
|
||||
+ attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
|
||||
+ if (attr != nullptr && attr->form_is_unsigned ())
|
||||
+ {
|
||||
+ sect_offset line_offset = (sect_offset) attr->as_unsigned ();
|
||||
+ line_header_up lh = dwarf_decode_line_header (line_offset, cu,
|
||||
+ fnd.get_comp_dir ());
|
||||
+ if (lh->version == 5 && lh->is_valid_file_index (1))
|
||||
+ {
|
||||
+ std::string dir = lh->include_dir_at (1);
|
||||
+ fnd.set_comp_dir (std::move (dir));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
cu->start_compunit_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile),
|
||||
lowpc);
|
||||
|
||||
@@ -11427,7 +11450,10 @@ check_producer (struct dwarf2_cu *cu)
|
||||
else if (producer_is_clang (cu->producer, &major, &minor))
|
||||
cu->producer_is_clang = true;
|
||||
else if (producer_is_gas (cu->producer, &major, &minor))
|
||||
- cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
+ {
|
||||
+ cu->producer_is_gas_lt_2_38 = major < 2 || (major == 2 && minor < 38);
|
||||
+ cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
/* For other non-GCC compilers, expect their behavior is DWARF version
|
||||
@@ -11463,6 +11489,15 @@ producer_is_codewarrior (struct dwarf2_cu *cu)
|
||||
return cu->producer_is_codewarrior;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+producer_is_gas_lt_2_38 (struct dwarf2_cu *cu)
|
||||
+{
|
||||
+ if (!cu->checked_producer)
|
||||
+ check_producer (cu);
|
||||
+
|
||||
+ return cu->producer_is_gas_lt_2_38;
|
||||
+}
|
||||
+
|
||||
static bool
|
||||
producer_is_gas_2_39 (struct dwarf2_cu *cu)
|
||||
{
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp b/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
new file mode 100644
|
||||
index 00000000000..ca2b10f23b3
|
||||
--- /dev/null
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-gas-workaround.exp
|
||||
@@ -0,0 +1,92 @@
|
||||
+# Copyright 2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Test line number information in various configurations.
|
||||
+
|
||||
+load_lib dwarf.exp
|
||||
+
|
||||
+# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
+require dwarf2_support
|
||||
+
|
||||
+standard_testfile dw2-lines.c -dw2.S
|
||||
+
|
||||
+with_shared_gdb {
|
||||
+ set func_info_vars [get_func_info bar]
|
||||
+}
|
||||
+
|
||||
+# Helper function.
|
||||
+proc line_for { l } {
|
||||
+ global srcfile
|
||||
+ set line [gdb_get_line_number "$l:" $srcfile]
|
||||
+ return [expr $line + 1]
|
||||
+}
|
||||
+
|
||||
+set asm_file [standard_output_file $srcfile2]
|
||||
+Dwarf::assemble $asm_file {
|
||||
+ declare_labels Llines
|
||||
+ global srcdir subdir srcfile objdir
|
||||
+ global func_info_vars
|
||||
+ foreach var $func_info_vars {
|
||||
+ global $var
|
||||
+ }
|
||||
+
|
||||
+ cu { version 5 } {
|
||||
+ compile_unit {
|
||||
+ {language @DW_LANG_Mips_Assembler}
|
||||
+ {name $srcfile}
|
||||
+ {comp_dir $objdir}
|
||||
+ {stmt_list $Llines DW_FORM_sec_offset}
|
||||
+ {producer "GNU AS 2.35.2"}
|
||||
+ } {
|
||||
+ subprogram {
|
||||
+ {external 1 flag}
|
||||
+ {name bar}
|
||||
+ {low_pc $bar_start addr}
|
||||
+ {high_pc "$bar_start + $bar_len" addr}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ lines [list version 5] Llines {
|
||||
+ set diridx1 [include_dir "${srcdir}/${subdir}"]
|
||||
+ set diridx2 [include_dir "${srcdir}/${subdir}"]
|
||||
+ file_name "$srcfile" $diridx1
|
||||
+ file_name "$srcfile" $diridx2
|
||||
+
|
||||
+ program {
|
||||
+ DW_LNE_set_address bar_label
|
||||
+ line [line_for bar_label]
|
||||
+ DW_LNS_copy
|
||||
+
|
||||
+ DW_LNE_set_address bar_label_2
|
||||
+ DW_LNE_end_sequence
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+if { [prepare_for_testing "failed to prepare" ${testfile} \
|
||||
+ [list $srcfile $asm_file] {nodebug}] } {
|
||||
+ return -1
|
||||
+}
|
||||
+
|
||||
+gdb_test_no_output "set debug symtab-create 1"
|
||||
+gdb_test_multiple "ptype bar" "" {
|
||||
+ -re -wrap "$objdir.*" {
|
||||
+ fail $gdb_test_name
|
||||
+ }
|
||||
+ -re -wrap "" {
|
||||
+ pass $gdb_test_name
|
||||
+ }
|
||||
+}
|
||||
|
||||
base-commit: d9951c3c9ea2e542d071710e9706ed505046fe36
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,137 +0,0 @@
|
||||
From 582fc35843fdf71b82d645d83d2903e2546cc21a Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 1 May 2024 15:10:50 +0200
|
||||
Subject: [PATCH 2/2] [gdb/symtab] Work around PR gas/29517, dwarf2 case
|
||||
|
||||
In commit 1d45d90934b ("[gdb/symtab] Work around PR gas/29517") we added a
|
||||
workaround for PR gas/29517.
|
||||
|
||||
The problem is present in gas version 2.39, and fixed in 2.40, so the
|
||||
workaround is only active for gas version == 2.39.
|
||||
|
||||
However, the problem in gas is only fixed for dwarf version >= 3, which
|
||||
supports DW_TAG_unspecified_type.
|
||||
|
||||
Fix this by also activating the workaround for dwarf version == 2.
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/31689
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=31689
|
||||
---
|
||||
gdb/dwarf2/read.c | 5 +++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type-foo.c | 7 ++++++
|
||||
.../gdb.dwarf2/dw2-unspecified-type.c | 3 ++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type.exp | 23 ++++++++++++++++++-
|
||||
4 files changed, 35 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index 761437f6631..fc4667b782f 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -14646,10 +14646,13 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||
|
||||
type = die_type (die, cu);
|
||||
|
||||
+ /* PR gas/29517 occurs in 2.39, and is fixed in 2.40, but it's only fixed
|
||||
+ for dwarf version >= 3 which supports DW_TAG_unspecified_type. */
|
||||
if (type->code () == TYPE_CODE_VOID
|
||||
&& !type->is_stub ()
|
||||
&& die->child == nullptr
|
||||
- && producer_is_gas_2_39 (cu))
|
||||
+ && (cu->per_cu->version () == 2
|
||||
+ || producer_is_gas_2_39 (cu)))
|
||||
{
|
||||
/* Work around PR gas/29517, pretend we have an DW_TAG_unspecified_type
|
||||
return type. */
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c
|
||||
index 164e781c9f0..bcf525a4d2e 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type-foo.c
|
||||
@@ -21,3 +21,10 @@ foo (void)
|
||||
asm ("foo_label: .globl foo_label");
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+int
|
||||
+foo2 (void)
|
||||
+{
|
||||
+ asm ("foo2_label: .globl foo2_label");
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
index e07d9517ff2..9e600f9dcce 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
@@ -16,6 +16,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
extern int foo (void);
|
||||
+extern int foo2 (void);
|
||||
|
||||
int
|
||||
bar (void)
|
||||
@@ -27,6 +28,6 @@ bar (void)
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
- int res = foo () + bar ();
|
||||
+ int res = foo () + bar () + foo2 ();
|
||||
return res;
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
index a6f2a57e33e..947246ba44d 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
@@ -34,11 +34,19 @@ lassign $bar_res \
|
||||
bar_start bar_len
|
||||
set bar_end "$bar_start + $bar_len"
|
||||
|
||||
+set foo2_res \
|
||||
+ [function_range foo2 \
|
||||
+ [list ${srcdir}/${subdir}/$srcfile ${srcdir}/${subdir}/$srcfile2]]
|
||||
+lassign $foo2_res \
|
||||
+ foo2_start foo2_len
|
||||
+set foo2_end "$foo2_start + $foo2_len"
|
||||
+
|
||||
# Create the DWARF.
|
||||
set asm_file [standard_output_file $srcfile3]
|
||||
Dwarf::assemble $asm_file {
|
||||
global foo_start foo_end
|
||||
global bar_start bar_end
|
||||
+ global foo2_start foo2_end
|
||||
declare_labels unspecified_type_label
|
||||
|
||||
cu {} {
|
||||
@@ -68,6 +76,19 @@ Dwarf::assemble $asm_file {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ cu { version 2 } {
|
||||
+ compile_unit {
|
||||
+ {language @DW_LANG_Mips_Assembler}
|
||||
+ {producer "GNU AS 2.40.0"}
|
||||
+ } {
|
||||
+ DW_TAG_subprogram {
|
||||
+ {name foo2}
|
||||
+ {low_pc $foo2_start addr}
|
||||
+ {high_pc $foo2_end addr}
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
if [prepare_for_testing "failed to prepare" $testfile \
|
||||
@@ -79,7 +100,7 @@ if ![runto_main] {
|
||||
return -1
|
||||
}
|
||||
|
||||
-foreach f {foo bar} {
|
||||
+foreach f {foo bar foo2} {
|
||||
# Print the function type. Return type should be stub type, which is printed
|
||||
# as void.
|
||||
gdb_test "ptype $f" "type = void \\(void\\)"
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,256 +0,0 @@
|
||||
From 7a2731d9d1c0926d22905b9d07e32a7b63c43b34 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Thu, 28 Sep 2023 13:55:07 +0200
|
||||
Subject: [PATCH 57/65] Work around PR gas/29517
|
||||
|
||||
When using glibc debuginfo generated with gas 2.39, we run into PR gas/29517:
|
||||
...
|
||||
$ gdb -q -batch a.out -ex start -ex "p (char *)strstr (\"haha\", \"ah\")"
|
||||
Temporary breakpoint 1 at 0x40051b: file hello.c, line 6.
|
||||
|
||||
Temporary breakpoint 1, main () at hello.c:6
|
||||
6 printf ("hello\n");
|
||||
Invalid cast.
|
||||
...
|
||||
while without glibc debuginfo installed we get the expected result:
|
||||
...
|
||||
$n = 0x7ffff7daa1b1 "aha"
|
||||
...
|
||||
and likewise with glibc debuginfo generated with gas 2.40.
|
||||
|
||||
The strstr ifunc resolves to __strstr_sse2_unaligned. The problem is that gas
|
||||
generates dwarf that states that the return type is void:
|
||||
...
|
||||
<1><3e1e58>: Abbrev Number: 2 (DW_TAG_subprogram)
|
||||
<3e1e59> DW_AT_name : __strstr_sse2_unaligned
|
||||
<3e1e5d> DW_AT_external : 1
|
||||
<3e1e5e> DW_AT_low_pc : 0xbbd2e
|
||||
<3e1e66> DW_AT_high_pc : 0xbc1c3
|
||||
...
|
||||
while the return type should be a DW_TAG_unspecified_type, as is the case
|
||||
with gas 2.40.
|
||||
|
||||
We can still use the workaround of casting to another function type for both
|
||||
__strstr_sse2_unaligned:
|
||||
...
|
||||
(gdb) p ((char * (*) (const char *, const char *))__strstr_sse2_unaligned) \
|
||||
("haha", "ah")
|
||||
$n = 0x7ffff7daa211 "aha"
|
||||
...
|
||||
and strstr (which requires using *strstr to dereference the ifunc before we
|
||||
cast):
|
||||
...
|
||||
gdb) p ((char * (*) (const char *, const char *))*strstr) ("haha", "ah")
|
||||
$n = 0x7ffff7daa251 "aha"
|
||||
...
|
||||
but that's a bit cumbersome to use.
|
||||
|
||||
Work around this in the dwarf reader, such that we have instead:
|
||||
...
|
||||
(gdb) p (char *)strstr ("haha", "ah")
|
||||
$n = 0x7ffff7daa1b1 "aha"
|
||||
...
|
||||
|
||||
This also requires fixing producer_is_gcc to stop returning true for
|
||||
producer "GNU AS 2.39.0".
|
||||
|
||||
Tested on x86_64-linux.
|
||||
|
||||
PR symtab/30911
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30911
|
||||
---
|
||||
gdb/dwarf2/cu.c | 1 +
|
||||
gdb/dwarf2/cu.h | 1 +
|
||||
gdb/dwarf2/read.c | 23 ++++++++++++
|
||||
gdb/producer.c | 8 ++++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type.c | 9 ++++-
|
||||
.../gdb.dwarf2/dw2-unspecified-type.exp | 36 +++++++++++++++----
|
||||
6 files changed, 69 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/gdb/dwarf2/cu.c b/gdb/dwarf2/cu.c
|
||||
index 89de40daab0..a908ec908cd 100644
|
||||
--- a/gdb/dwarf2/cu.c
|
||||
+++ b/gdb/dwarf2/cu.c
|
||||
@@ -40,6 +40,7 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
||||
producer_is_icc_lt_14 (false),
|
||||
producer_is_codewarrior (false),
|
||||
producer_is_clang (false),
|
||||
+ producer_is_gas_2_39 (false),
|
||||
processing_has_namespace_info (false),
|
||||
load_all_dies (false)
|
||||
{
|
||||
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
|
||||
index 0c15d8b02db..6c611710503 100644
|
||||
--- a/gdb/dwarf2/cu.h
|
||||
+++ b/gdb/dwarf2/cu.h
|
||||
@@ -265,6 +265,7 @@ struct dwarf2_cu
|
||||
bool producer_is_icc_lt_14 : 1;
|
||||
bool producer_is_codewarrior : 1;
|
||||
bool producer_is_clang : 1;
|
||||
+ bool producer_is_gas_2_39 : 1;
|
||||
|
||||
/* When true, the file that we're processing is known to have
|
||||
debugging info for C++ namespaces. GCC 3.3.x did not produce
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index a5c48baa6f8..e5e557c17d3 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -11426,6 +11426,8 @@ check_producer (struct dwarf2_cu *cu)
|
||||
cu->producer_is_codewarrior = true;
|
||||
else if (producer_is_clang (cu->producer, &major, &minor))
|
||||
cu->producer_is_clang = true;
|
||||
+ else if (startswith (cu->producer, "GNU AS 2.39.0"))
|
||||
+ cu->producer_is_gas_2_39 = true;
|
||||
else
|
||||
{
|
||||
/* For other non-GCC compilers, expect their behavior is DWARF version
|
||||
@@ -11461,6 +11463,15 @@ producer_is_codewarrior (struct dwarf2_cu *cu)
|
||||
return cu->producer_is_codewarrior;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+producer_is_gas_2_39 (struct dwarf2_cu *cu)
|
||||
+{
|
||||
+ if (!cu->checked_producer)
|
||||
+ check_producer (cu);
|
||||
+
|
||||
+ return cu->producer_is_gas_2_39;
|
||||
+}
|
||||
+
|
||||
/* Return the accessibility of DIE, as given by DW_AT_accessibility.
|
||||
If that attribute is not available, return the appropriate
|
||||
default. */
|
||||
@@ -14635,6 +14646,18 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
|
||||
|
||||
type = die_type (die, cu);
|
||||
|
||||
+ if (type->code () == TYPE_CODE_VOID
|
||||
+ && !type->is_stub ()
|
||||
+ && die->child == nullptr
|
||||
+ && producer_is_gas_2_39 (cu))
|
||||
+ {
|
||||
+ /* Work around PR gas/29517, pretend we have an DW_TAG_unspecified_type
|
||||
+ return type. */
|
||||
+ type = (type_allocator (cu->per_objfile->objfile, cu->lang ())
|
||||
+ .new_type (TYPE_CODE_VOID, 0, nullptr));
|
||||
+ type->set_is_stub (true);
|
||||
+ }
|
||||
+
|
||||
/* The die_type call above may have already set the type for this DIE. */
|
||||
ftype = get_die_type (die, cu);
|
||||
if (ftype)
|
||||
diff --git a/gdb/producer.c b/gdb/producer.c
|
||||
index 655eb971283..9fcf749e3d4 100644
|
||||
--- a/gdb/producer.c
|
||||
+++ b/gdb/producer.c
|
||||
@@ -54,13 +54,19 @@ producer_is_gcc (const char *producer, int *major, int *minor)
|
||||
if (minor == NULL)
|
||||
minor = &min;
|
||||
|
||||
+ /* Skip GNU. */
|
||||
+ cs = &producer[strlen ("GNU ")];
|
||||
+
|
||||
+ /* Bail out for GNU AS. */
|
||||
+ if (startswith (cs, "AS "))
|
||||
+ return 0;
|
||||
+
|
||||
/* Skip any identifier after "GNU " - such as "C11" "C++" or "Java".
|
||||
A full producer string might look like:
|
||||
"GNU C 4.7.2"
|
||||
"GNU Fortran 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic ..."
|
||||
"GNU C++14 5.0.0 20150123 (experimental)"
|
||||
*/
|
||||
- cs = &producer[strlen ("GNU ")];
|
||||
while (*cs && !isspace (*cs))
|
||||
cs++;
|
||||
if (*cs && isspace (*cs))
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
index 1df09214d4a..e07d9517ff2 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.c
|
||||
@@ -17,9 +17,16 @@
|
||||
|
||||
extern int foo (void);
|
||||
|
||||
+int
|
||||
+bar (void)
|
||||
+{
|
||||
+ asm ("bar_label: .globl bar_label");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
- int res = foo ();
|
||||
+ int res = foo () + bar ();
|
||||
return res;
|
||||
}
|
||||
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
index 5fa6ee544b2..a6f2a57e33e 100644
|
||||
--- a/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unspecified-type.exp
|
||||
@@ -27,10 +27,18 @@ lassign $foo_res \
|
||||
foo_start foo_len
|
||||
set foo_end "$foo_start + $foo_len"
|
||||
|
||||
+set bar_res \
|
||||
+ [function_range bar \
|
||||
+ [list ${srcdir}/${subdir}/$srcfile ${srcdir}/${subdir}/$srcfile2]]
|
||||
+lassign $bar_res \
|
||||
+ bar_start bar_len
|
||||
+set bar_end "$bar_start + $bar_len"
|
||||
+
|
||||
# Create the DWARF.
|
||||
set asm_file [standard_output_file $srcfile3]
|
||||
Dwarf::assemble $asm_file {
|
||||
global foo_start foo_end
|
||||
+ global bar_start bar_end
|
||||
declare_labels unspecified_type_label
|
||||
|
||||
cu {} {
|
||||
@@ -45,7 +53,19 @@ Dwarf::assemble $asm_file {
|
||||
{high_pc $foo_end addr}
|
||||
{type :$unspecified_type_label}
|
||||
}
|
||||
+ }
|
||||
+ }
|
||||
|
||||
+ cu {} {
|
||||
+ compile_unit {
|
||||
+ {language @DW_LANG_Mips_Assembler}
|
||||
+ {producer "GNU AS 2.39.0"}
|
||||
+ } {
|
||||
+ DW_TAG_subprogram {
|
||||
+ {name bar}
|
||||
+ {low_pc $bar_start addr}
|
||||
+ {high_pc $bar_end addr}
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,12 +79,14 @@ if ![runto_main] {
|
||||
return -1
|
||||
}
|
||||
|
||||
-# Print the function type. Return type should be stub type, which is printed
|
||||
-# as void.
|
||||
-gdb_test "ptype foo" "type = void \\(void\\)"
|
||||
+foreach f {foo bar} {
|
||||
+ # Print the function type. Return type should be stub type, which is printed
|
||||
+ # as void.
|
||||
+ gdb_test "ptype $f" "type = void \\(void\\)"
|
||||
|
||||
-# Call the function, casting the function to the correct function type.
|
||||
-gdb_test "p ((int (*) ()) foo) ()" " = 0"
|
||||
+ # Call the function, casting the function to the correct function type.
|
||||
+ gdb_test "p ((int (*) ()) $f) ()" " = 0"
|
||||
|
||||
-# Call the function, casting the function result to the correct type.
|
||||
-gdb_test "p (int) foo ()" " = 0"
|
||||
+ # Call the function, casting the function result to the correct type.
|
||||
+ gdb_test "p (int) $f ()" " = 0"
|
||||
+}
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,122 +0,0 @@
|
||||
From d25e3f4ed05c3a6c207263d7e532f829860b83f0 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Wed, 20 Mar 2024 09:57:49 +0100
|
||||
Subject: [PATCH 1/7] [gdb/symtab] Workaround PR gas/31115
|
||||
|
||||
On arm-linux, with gas 2.40, I run into:
|
||||
...
|
||||
(gdb) x /i main+8^M
|
||||
0x4e1 <main+7>: vrhadd.u16 d14, d14, d31^M
|
||||
(gdb) FAIL: gdb.arch/pr25124.exp: disassemble thumb instruction (1st try)
|
||||
...
|
||||
|
||||
This is a regression due to PR gas/31115, which makes gas produce a low_pc
|
||||
with the thumb bit set (0x4d8 & 0x1):
|
||||
...
|
||||
<1><24>: Abbrev Number: 2 (DW_TAG_subprogram)
|
||||
<25> DW_AT_name : main
|
||||
<29> DW_AT_external : 1
|
||||
<29> DW_AT_type : <0x2f>
|
||||
<2a> DW_AT_low_pc : 0x4d9
|
||||
<2e> DW_AT_high_pc : 12
|
||||
...
|
||||
|
||||
The regression was introduced in 2.39, and is also present in 2.40 and 2.41,
|
||||
and hasn't been fixed yet.
|
||||
|
||||
Work around this in read_func_scope, by using gdbarch_addr_bits_remove on
|
||||
low_pc and high_pc.
|
||||
|
||||
Tested on arm-linux and x86_64-linux.
|
||||
|
||||
PR tdep/31453
|
||||
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31453
|
||||
---
|
||||
gdb/dwarf2/cu.c | 1 +
|
||||
gdb/dwarf2/cu.h | 1 +
|
||||
gdb/dwarf2/read.c | 22 ++++++++++++++++++++++
|
||||
3 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/gdb/dwarf2/cu.c b/gdb/dwarf2/cu.c
|
||||
index f9b05dfc709..7f89500effd 100644
|
||||
--- a/gdb/dwarf2/cu.c
|
||||
+++ b/gdb/dwarf2/cu.c
|
||||
@@ -42,6 +42,7 @@ dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
|
||||
producer_is_clang (false),
|
||||
producer_is_gas_lt_2_38 (false),
|
||||
producer_is_gas_2_39 (false),
|
||||
+ producer_is_gas_ge_2_40 (false),
|
||||
processing_has_namespace_info (false),
|
||||
load_all_dies (false)
|
||||
{
|
||||
diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
|
||||
index ef8db480e3f..1b02f89ed2f 100644
|
||||
--- a/gdb/dwarf2/cu.h
|
||||
+++ b/gdb/dwarf2/cu.h
|
||||
@@ -267,6 +267,7 @@ struct dwarf2_cu
|
||||
bool producer_is_clang : 1;
|
||||
bool producer_is_gas_lt_2_38 : 1;
|
||||
bool producer_is_gas_2_39 : 1;
|
||||
+ bool producer_is_gas_ge_2_40 : 1;
|
||||
|
||||
/* When true, the file that we're processing is known to have
|
||||
debugging info for C++ namespaces. GCC 3.3.x did not produce
|
||||
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
|
||||
index a4f982962ae..8f2d7a34aef 100644
|
||||
--- a/gdb/dwarf2/read.c
|
||||
+++ b/gdb/dwarf2/read.c
|
||||
@@ -148,6 +148,7 @@ static int dwarf2_loclist_block_index;
|
||||
static int ada_block_index;
|
||||
|
||||
static bool producer_is_gas_lt_2_38 (struct dwarf2_cu *cu);
|
||||
+static bool producer_is_gas_ge_2_39 (struct dwarf2_cu *cu);
|
||||
|
||||
/* Size of .debug_loclists section header for 32-bit DWARF format. */
|
||||
#define LOCLIST_HEADER_SIZE32 12
|
||||
@@ -10223,6 +10224,15 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
||||
lowpc = per_objfile->relocate (unrel_low);
|
||||
highpc = per_objfile->relocate (unrel_high);
|
||||
|
||||
+ if (gdbarch_bfd_arch_info (gdbarch)->arch == bfd_arch_arm
|
||||
+ && producer_is_gas_ge_2_39 (cu))
|
||||
+ {
|
||||
+ /* Gas version 2.39 produces DWARF for a Thumb subprogram with a low_pc
|
||||
+ attribute with the thumb bit set (PR gas/31115). Work around this. */
|
||||
+ lowpc = gdbarch_addr_bits_remove (gdbarch, lowpc);
|
||||
+ highpc = gdbarch_addr_bits_remove (gdbarch, highpc);
|
||||
+ }
|
||||
+
|
||||
/* If we have any template arguments, then we must allocate a
|
||||
different sort of symbol. */
|
||||
for (child_die = die->child; child_die; child_die = child_die->sibling)
|
||||
@@ -11507,6 +11517,7 @@ check_producer (struct dwarf2_cu *cu)
|
||||
{
|
||||
cu->producer_is_gas_lt_2_38 = major < 2 || (major == 2 && minor < 38);
|
||||
cu->producer_is_gas_2_39 = major == 2 && minor == 39;
|
||||
+ cu->producer_is_gas_ge_2_40 = major > 2 || (major == 2 && minor >= 40);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -11561,6 +11572,17 @@ producer_is_gas_2_39 (struct dwarf2_cu *cu)
|
||||
return cu->producer_is_gas_2_39;
|
||||
}
|
||||
|
||||
+/* Return true if CU is produced by GAS 2.39 or later. */
|
||||
+
|
||||
+static bool
|
||||
+producer_is_gas_ge_2_39 (struct dwarf2_cu *cu)
|
||||
+{
|
||||
+ if (!cu->checked_producer)
|
||||
+ check_producer (cu);
|
||||
+
|
||||
+ return cu->producer_is_gas_2_39 || cu->producer_is_gas_ge_2_40;
|
||||
+}
|
||||
+
|
||||
/* Return the accessibility of DIE, as given by DW_AT_accessibility.
|
||||
If that attribute is not available, return the appropriate
|
||||
default. */
|
||||
|
||||
base-commit: c79ecacd3f75cfb0ec1a3afc49ca3f30b1759009
|
||||
--
|
||||
2.35.3
|
||||
|
264
gdb-tdep-fix-arm-thumb2-hw-breakpoint.patch
Normal file
264
gdb-tdep-fix-arm-thumb2-hw-breakpoint.patch
Normal file
@ -0,0 +1,264 @@
|
||||
From 64dc13a4571b4092726291f3ee30bf5c2166fa13 Mon Sep 17 00:00:00 2001
|
||||
From: Tom de Vries <tdevries@suse.de>
|
||||
Date: Sat, 27 Jul 2024 10:05:20 +0200
|
||||
Subject: [PATCH 09/46] [gdb/tdep] Fix arm thumb2 hw breakpoint
|
||||
|
||||
On an aarch64-linux system with 32-bit userland running in a chroot, and using
|
||||
target board unix/mthumb I get:
|
||||
...
|
||||
(gdb) hbreak hbreak.c:27^M
|
||||
Hardware assisted breakpoint 2 at 0x4004e2: file hbreak.c, line 27.^M
|
||||
(gdb) PASS: gdb.base/hbreak.exp: hbreak
|
||||
continue^M
|
||||
Continuing.^M
|
||||
Unexpected error setting breakpoint: Invalid argument.^M
|
||||
(gdb) XFAIL: gdb.base/hbreak.exp: continue to break-at-exit after hbreak
|
||||
...
|
||||
due to this call in arm_linux_nat_target::low_prepare_to_resume:
|
||||
...
|
||||
if (ptrace (PTRACE_SETHBPREGS, pid,
|
||||
(PTRACE_TYPE_ARG3) ((i << 1) + 1), &bpts[i].address) < 0)
|
||||
perror_with_name (_("Unexpected error setting breakpoint"));
|
||||
...
|
||||
|
||||
This problem does not happen if instead we use a 4-byte aligned address.
|
||||
|
||||
This may or may not be a kernel bug.
|
||||
|
||||
Work around this by first using an inoffensive address bpts[i].address & ~0x7.
|
||||
|
||||
Likewise in arm_target::low_prepare_to_resume, which fixes the same fail on
|
||||
target board native-gdbserver/mthumb.
|
||||
|
||||
While we're at it:
|
||||
- use arm_hwbp_control_is_initialized in
|
||||
arm_linux_nat_target::low_prepare_to_resume,
|
||||
- handle the !arm_hwbp_control_is_initialized case explicitly,
|
||||
- add missing '_()' in arm_target::low_prepare_to_resume,
|
||||
- make error messages identical between arm_target::low_prepare_to_resume and
|
||||
arm_linux_nat_target::low_prepare_to_resume,
|
||||
- factor out sethbpregs_hwbp_address and sethbpregs_hwbp_control to
|
||||
make the implementation more readable.
|
||||
|
||||
Remove the tentative xfail added in d0af16d5a10 ("[gdb/testsuite] Add xfail in
|
||||
gdb.base/hbreak.exp") by simply reverting the commit.
|
||||
|
||||
Tested on arm-linux.
|
||||
|
||||
Approved-By: Luis Machado <luis.machado@arm.com>
|
||||
Tested-By: Luis Machado <luis.machado@arm.com>
|
||||
---
|
||||
gdb/arm-linux-nat.c | 98 ++++++++++++++++++++++++++++++++++----
|
||||
gdbserver/linux-arm-low.cc | 65 ++++++++++++++++++++-----
|
||||
2 files changed, 141 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
|
||||
index ac53bed72d7..7b4faacd601 100644
|
||||
--- a/gdb/arm-linux-nat.c
|
||||
+++ b/gdb/arm-linux-nat.c
|
||||
@@ -876,6 +876,14 @@ arm_hwbp_control_is_enabled (arm_hwbp_control_t control)
|
||||
return control & 0x1;
|
||||
}
|
||||
|
||||
+/* Is the breakpoint control value CONTROL initialized? */
|
||||
+
|
||||
+static int
|
||||
+arm_hwbp_control_is_initialized (arm_hwbp_control_t control)
|
||||
+{
|
||||
+ return control != 0;
|
||||
+}
|
||||
+
|
||||
/* Change a breakpoint control word so that it is in the disabled state. */
|
||||
static arm_hwbp_control_t
|
||||
arm_hwbp_control_disable (arm_hwbp_control_t control)
|
||||
@@ -1234,6 +1242,34 @@ arm_linux_nat_target::low_delete_thread (struct arch_lwp_info *arch_lwp)
|
||||
xfree (arch_lwp);
|
||||
}
|
||||
|
||||
+/* For PID, set the address register of hardware breakpoint pair I to
|
||||
+ ADDRESS. */
|
||||
+
|
||||
+static void
|
||||
+sethbpregs_hwbp_address (int pid, int i, unsigned int address)
|
||||
+{
|
||||
+ PTRACE_TYPE_ARG3 address_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 1);
|
||||
+
|
||||
+ errno = 0;
|
||||
+
|
||||
+ if (ptrace (PTRACE_SETHBPREGS, pid, address_reg, &address) < 0)
|
||||
+ perror_with_name (_("Unexpected error updating breakpoint address"));
|
||||
+}
|
||||
+
|
||||
+/* For PID, set the control register of hardware breakpoint pair I to
|
||||
+ CONTROL. */
|
||||
+
|
||||
+static void
|
||||
+sethbpregs_hwbp_control (int pid, int i, arm_hwbp_control_t control)
|
||||
+{
|
||||
+ PTRACE_TYPE_ARG3 control_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 2);
|
||||
+
|
||||
+ errno = 0;
|
||||
+
|
||||
+ if (ptrace (PTRACE_SETHBPREGS, pid, control_reg, &control) < 0)
|
||||
+ perror_with_name (_("Unexpected error setting breakpoint control"));
|
||||
+}
|
||||
+
|
||||
/* Called when resuming a thread.
|
||||
The hardware debug registers are updated when there is any change. */
|
||||
|
||||
@@ -1257,16 +1293,58 @@ arm_linux_nat_target::low_prepare_to_resume (struct lwp_info *lwp)
|
||||
for (i = 0; i < arm_linux_get_hw_breakpoint_count (); i++)
|
||||
if (arm_lwp_info->bpts_changed[i])
|
||||
{
|
||||
- errno = 0;
|
||||
- if (arm_hwbp_control_is_enabled (bpts[i].control))
|
||||
- if (ptrace (PTRACE_SETHBPREGS, pid,
|
||||
- (PTRACE_TYPE_ARG3) ((i << 1) + 1), &bpts[i].address) < 0)
|
||||
- perror_with_name (_("Unexpected error setting breakpoint"));
|
||||
-
|
||||
- if (bpts[i].control != 0)
|
||||
- if (ptrace (PTRACE_SETHBPREGS, pid,
|
||||
- (PTRACE_TYPE_ARG3) ((i << 1) + 2), &bpts[i].control) < 0)
|
||||
- perror_with_name (_("Unexpected error setting breakpoint"));
|
||||
+ unsigned int address = bpts[i].address;
|
||||
+ arm_hwbp_control_t control = bpts[i].control;
|
||||
+
|
||||
+ if (!arm_hwbp_control_is_initialized (control))
|
||||
+ {
|
||||
+ /* Nothing to do. */
|
||||
+ }
|
||||
+ else if (!arm_hwbp_control_is_enabled (control))
|
||||
+ {
|
||||
+ /* Disable hardware breakpoint, just write the control
|
||||
+ register. */
|
||||
+ sethbpregs_hwbp_control (pid, i, control);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* We used to do here simply:
|
||||
+ 1. address_reg = address
|
||||
+ 2. control_reg = control
|
||||
+ but the write to address_reg can fail for thumb2 instructions if
|
||||
+ the address is not 4-byte aligned.
|
||||
+
|
||||
+ It's not clear whether this is a kernel bug or not, partly
|
||||
+ because PTRACE_SETHBPREGS is undocumented.
|
||||
+
|
||||
+ The context is that we're using two ptrace calls to set the two
|
||||
+ halves of a register pair. For each ptrace call, the kernel must
|
||||
+ check the arguments, and return -1 and set errno appropriately if
|
||||
+ something is wrong. One of the aspects that needs validation is
|
||||
+ whether, in terms of hw_breakpoint_arch_parse, the breakpoint
|
||||
+ address matches the breakpoint length. This aspect can only be
|
||||
+ checked by looking in both registers, which only makes sense
|
||||
+ once a pair is written in full.
|
||||
+
|
||||
+ The problem is that the kernel checks this aspect after each
|
||||
+ ptrace call, and consequently for the first call it may be
|
||||
+ checking this aspect using a default or previous value for the
|
||||
+ part of the pair not written by the call. A possible fix for
|
||||
+ this would be to only check this aspect when writing the
|
||||
+ control reg.
|
||||
+
|
||||
+ Work around this by first using an inoffensive address, which is
|
||||
+ guaranteed to hit the offset == 0 case in
|
||||
+ hw_breakpoint_arch_parse. */
|
||||
+ unsigned int aligned_address = address & ~0x7U;
|
||||
+ if (aligned_address != address)
|
||||
+ {
|
||||
+ sethbpregs_hwbp_address (pid, i, aligned_address);
|
||||
+ sethbpregs_hwbp_control (pid, i, control);
|
||||
+ }
|
||||
+ sethbpregs_hwbp_address (pid, i, address);
|
||||
+ sethbpregs_hwbp_control (pid, i, control);
|
||||
+ }
|
||||
|
||||
arm_lwp_info->bpts_changed[i] = 0;
|
||||
}
|
||||
diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc
|
||||
index eec4649b235..ee89949a2a2 100644
|
||||
--- a/gdbserver/linux-arm-low.cc
|
||||
+++ b/gdbserver/linux-arm-low.cc
|
||||
@@ -819,6 +819,34 @@ arm_target::low_new_fork (process_info *parent, process_info *child)
|
||||
child_lwp_info->wpts_changed[i] = 1;
|
||||
}
|
||||
|
||||
+/* For PID, set the address register of hardware breakpoint pair I to
|
||||
+ ADDRESS. */
|
||||
+
|
||||
+static void
|
||||
+sethbpregs_hwbp_address (int pid, int i, unsigned int address)
|
||||
+{
|
||||
+ PTRACE_TYPE_ARG3 address_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 1);
|
||||
+
|
||||
+ errno = 0;
|
||||
+
|
||||
+ if (ptrace (PTRACE_SETHBPREGS, pid, address_reg, &address) < 0)
|
||||
+ perror_with_name (_("Unexpected error updating breakpoint address"));
|
||||
+}
|
||||
+
|
||||
+/* For PID, set the control register of hardware breakpoint pair I to
|
||||
+ CONTROL. */
|
||||
+
|
||||
+static void
|
||||
+sethbpregs_hwbp_control (int pid, int i, arm_hwbp_control_t control)
|
||||
+{
|
||||
+ PTRACE_TYPE_ARG3 control_reg = (PTRACE_TYPE_ARG3) ((i << 1) + 2);
|
||||
+
|
||||
+ errno = 0;
|
||||
+
|
||||
+ if (ptrace (PTRACE_SETHBPREGS, pid, control_reg, &control) < 0)
|
||||
+ perror_with_name (_("Unexpected error setting breakpoint control"));
|
||||
+}
|
||||
+
|
||||
/* Called when resuming a thread.
|
||||
If the debug regs have changed, update the thread's copies. */
|
||||
void
|
||||
@@ -834,19 +862,32 @@ arm_target::low_prepare_to_resume (lwp_info *lwp)
|
||||
for (i = 0; i < arm_linux_get_hw_breakpoint_count (); i++)
|
||||
if (lwp_info->bpts_changed[i])
|
||||
{
|
||||
- errno = 0;
|
||||
+ unsigned int address = proc_info->bpts[i].address;
|
||||
+ arm_hwbp_control_t control = proc_info->bpts[i].control;
|
||||
|
||||
- if (arm_hwbp_control_is_enabled (proc_info->bpts[i].control))
|
||||
- if (ptrace (PTRACE_SETHBPREGS, pid,
|
||||
- (PTRACE_TYPE_ARG3) ((i << 1) + 1),
|
||||
- &proc_info->bpts[i].address) < 0)
|
||||
- perror_with_name ("Unexpected error setting breakpoint address");
|
||||
-
|
||||
- if (arm_hwbp_control_is_initialized (proc_info->bpts[i].control))
|
||||
- if (ptrace (PTRACE_SETHBPREGS, pid,
|
||||
- (PTRACE_TYPE_ARG3) ((i << 1) + 2),
|
||||
- &proc_info->bpts[i].control) < 0)
|
||||
- perror_with_name ("Unexpected error setting breakpoint");
|
||||
+ if (!arm_hwbp_control_is_initialized (control))
|
||||
+ {
|
||||
+ /* Nothing to do. */
|
||||
+ }
|
||||
+ else if (!arm_hwbp_control_is_enabled (control))
|
||||
+ {
|
||||
+ /* Disable hardware breakpoint, just write the control
|
||||
+ register. */
|
||||
+ sethbpregs_hwbp_control (pid, i, control);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* See arm_linux_nat_target::low_prepare_to_resume for detailed
|
||||
+ comment. */
|
||||
+ unsigned int aligned_address = address & ~0x7U;
|
||||
+ if (aligned_address != address)
|
||||
+ {
|
||||
+ sethbpregs_hwbp_address (pid, i, aligned_address);
|
||||
+ sethbpregs_hwbp_control (pid, i, control);
|
||||
+ }
|
||||
+ sethbpregs_hwbp_address (pid, i, address);
|
||||
+ sethbpregs_hwbp_control (pid, i, control);
|
||||
+ }
|
||||
|
||||
lwp_info->bpts_changed[i] = 0;
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user