aboutsummaryrefslogtreecommitdiff
path: root/gdb
AgeCommit message (Collapse)AuthorFilesLines
2023-02-08Run clang-format.shusers/simark/clang-formatSimon Marchi1068-101292/+90883
Change-Id: Ia948cc26d534b0dd02702244d52434b1a2093968
2023-02-08Remove block.h includes from some tdep filesTom Tromey5-5/+0
A few tdep files include block.h but do not need to. This patch removes the inclusions. I checked that this worked correctly by examining the resulting .Po file to make sure that block.h was not being included by some other route.
2023-02-08Don't include block.h from expop.hTom Tromey2-6/+8
expop.h needs block.h for a single inline function. However, I don't think most of the check_objfile functions need to be defined in the header (just the templates). This patch moves the one offending function and removes the include.
2023-02-08Simplify interp::exec / interp_exec - let exceptions propagatePedro Alves7-64/+30
This patch implements a simplication that I suggested here: https://sourceware.org/pipermail/gdb-patches/2022-March/186320.html Currently, the interp::exec virtual method interface is such that subclass implementations must catch exceptions and then return them via normal function return. However, higher up the in chain, for the CLI we get to interpreter_exec_cmd, which does: for (i = 1; i < nrules; i++) { struct gdb_exception e = interp_exec (interp_to_use, prules[i]); if (e.reason < 0) { interp_set (old_interp, 0); error (_("error in command: \"%s\"."), prules[i]); } } and for MI we get to mi_cmd_interpreter_exec, which has: void mi_cmd_interpreter_exec (const char *command, char **argv, int argc) { ... for (i = 1; i < argc; i++) { struct gdb_exception e = interp_exec (interp_to_use, argv[i]); if (e.reason < 0) error ("%s", e.what ()); } } Note that if those errors are reached, we lose the original exception's error code. I can't see why we'd want that. And, I can't see why we need to have interp_exec catch the exception and return it via the normal return path. That's normally needed when we need to handle propagating exceptions across C code, like across readline or ncurses, but that's not the case here. It seems to me that we can simplify things by removing some try/catch-ing and just letting exceptions propagate normally. Note, the "error in command" error shown above, which only exists in the CLI interpreter-exec command, is only ever printed AFAICS if you run "interpreter-exec console" when the top level interpreter is already the console/tui. Like: (gdb) interpreter-exec console "foobar" Undefined command: "foobar". Try "help". error in command: "foobar". You won't see it with MI's "-interpreter-exec console" from a top level MI interpreter: (gdb) -interpreter-exec console "foobar" &"Undefined command: \"foobar\". Try \"help\".\n" ^error,msg="Undefined command: \"foobar\". Try \"help\"." (gdb) nor with MI's "-interpreter-exec mi" from a top level MI interpreter: (gdb) -interpreter-exec mi "-foobar" ^error,msg="Undefined MI command: foobar",code="undefined-command" ^done (gdb) in both these cases because MI's -interpreter-exec just does: error ("%s", e.what ()); You won't see it either when running an MI command with the CLI's "interpreter-exec mi": (gdb) interpreter-exec mi "-foobar" ^error,msg="Undefined MI command: foobar",code="undefined-command" (gdb) This last case is because MI's interp::exec implementation never returns an error: gdb_exception mi_interp::exec (const char *command) { mi_execute_command_wrapper (command); return gdb_exception (); } Thus I think that "error in command" error is pretty pointless, and since it simplifies things to not have it, the patch just removes it. The patch also ends up addressing an old FIXME. Change-Id: I5a6432a80496934ac7127594c53bf5221622e393 Approved-By: Tom Tromey <tromey@adacore.com> Approved-By: Kevin Buettner <kevinb@redhat.com>
2023-02-08Avoid FAILs in gdb.compileTom Tromey2-8/+55
Many gdb.compile C++ tests fail for me on Fedora 36. I think these are largely bugs in the plugin, though I didn't investigate too deeply. Once one failure is seen, this often cascades and sometimes there are many timeouts. For example, this can happen: (gdb) compile code var = a->get_var () warning: Could not find symbol "_ZZ9_gdb_exprP10__gdb_regsE1a" for compiled module "/tmp/gdbobj-0xdI6U/out2.o". 1 symbols were missing, cannot continue. I think this is probably a plugin bug because, IIRC, in theory these symbols should be exempt from a lookup via gdb. This patch arranges to catch any catastrophic failure and then simply exit the entire .exp file.
2023-02-08Don't let .gdb_history file cause failuresTom Tromey1-0/+4
I had a .gdb_history file in my testsuite directory in the build tree, and this provoked a failure in gdbhistsize-history.exp. It seems simple to prevent this file from causing a failure.
2023-02-08Merge fixup_section and fixup_symbol_sectionTom Tromey2-70/+45
fixup_symbol_section delegates all its work to fixup_section, so merge the two. Because there is only a single caller to fixup_symbol_section, we can also remove some of the introductory logic. For example, this will never be called with a NULL objfile any more. The LOC_BLOCK case can be removed, because such symbols are handled by the buildsym code now. Finally, a symbol can only appear in a SEC_ALLOC section, so the loop is modified to skip sections that do not have this flag set.
2023-02-08Remove most calls to fixup_symbol_sectionTom Tromey5-36/+10
Nearly every call to fixup_symbol_section in gdb is incorrect, and if any such call has an effect, it's purely by happenstance. fixup_section has a long comment explaining that the call should only be made before runtime section offsets are applied. And, the loop in this code (the fallback loop -- the minsym lookup code is "ok") is careful to remove these offsets before comparing addresses. However, aside from a single call in dwarf2/read.c, every call in gdb is actually done after section offsets have been applied. So, these calls are incorrect. Now, these calls could be made when the symbol is created. I considered this approach, but I reasoned that the code has been this way for many years, seemingly without ill effect. So, instead I chose to simply remove the offending calls.
2023-02-08Set section index when setting a symbol's blockTom Tromey1-0/+1
When a symbol's block is set, the block has the runtime section offset applied. So, it seems to me that the symbol implicitly is in the same section as the block. Therefore, this patch sets the symbol's section index at this same spot.
2023-02-08Remove compunit_symtab::m_block_line_sectionTom Tromey6-29/+6
The previous patch hard-coded SECT_OFF_TEXT into the buildsym code. After this, it's clear that there is only one caller of compunit_symtab::set_block_line_section, and it always passes SECT_OFF_TEXT. So, remove compunit_symtab::m_block_line_section and use SECT_OFF_TEXT instead.
2023-02-08Do not pass section index to end_compunit_symtabTom Tromey10-46/+32
Right now, the section index passed to end_compunit_symtab is always SECT_OFF_TEXT. Remove this parameter and simply always use SECT_OFF_TEXT.
2023-02-08Set section indices when symbols are madeTom Tromey4-11/+43
Most places in gdb that create a new symbol will apply a section offset to the address. It seems to me that the choice of offset here is also an implicit choice of the section. This is particularly true if you examine fixup_section, which notes that it must be called before such offsets are applied -- meaning that if any such call has an effect, it's purely by accident. This patch cleans up this area by tracking the section index and applying it to a symbol when the address is set. This is done for nearly every case -- the remaining cases will be handled in later patches.
2023-02-08Use default section indexes in fixup_symbol_sectionTom Tromey2-8/+17
If fixup_section does not find a matching section, it arbitrarily chooses the first one. However, it seems better to make this default depend on the type of the symbol -- i.e., default data symbols to .data and text symbols to .text. I've also made fixup_section static, as it only has one caller.
2023-02-08Simplify checks of cooked_indexTom Tromey1-12/+14
This changes the cooked_index_functions to avoid an extra null check now that checked_static_cast allows a null argument. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-02-08[gdb/testsuite] Use maint ignore-probes in gdb.base/longjmp.expTom de Vries1-138/+157
Test-case gdb.base/longjmp.exp handles both the case that there is a libc longjmp probe, and the case that there isn't. However, it only tests one of the two cases. Use maint ignore-probes to test both cases, if possible. Tested on x86_64-linux.
2023-02-08[gdb/testsuite] Use maint ignore-probes in gdb.base/solib-corrupted.expTom de Vries1-12/+14
Test-case gdb.base/solib-corrupted.exp only works for a glibc without probes interface, otherwise we run into: ... XFAIL: gdb.base/solib-corrupted.exp: info probes UNTESTED: gdb.base/solib-corrupted.exp: GDB is using probes ... Fix this by using maint ignore-probes to simulate the absence of the relevant probes. Also, it requires glibc debuginfo, and if not present, it produces an XFAIL: ... XFAIL: gdb.base/solib-corrupted.exp: make solibs looping UNTESTED: gdb.base/solib-corrupted.exp: no _r_debug symbol has been found ... This is incorrect, because an XFAIL indicates a known problem in the environment. In this case, there is no problem: the environment is functioning as expected when glibc debuginfo is not installed. Fix this by using UNSUPPORTED instead, and make the message less cryptic: ... UNSUPPORTED: gdb.base/solib-corrupted.exp: make solibs looping \ (glibc debuginfo required) ... Finally, with glibc debuginfo present, we run into: ... (gdb) PASS: gdb.base/solib-corrupted.exp: make solibs looping info sharedlibrary^M warning: Corrupted shared library list: 0x7ffff7ffe750 != 0x0^M From To Syms Read Shared Object Library^M 0x00007ffff7dd4170 0x00007ffff7df4090 Yes /lib64/ld-linux-x86-64.so.2^M (gdb) FAIL: gdb.base/solib-corrupted.exp: corrupted list \ (shared library list corrupted) ... due to commit 44288716537 ("gdb, testsuite: extend gdb_test_multiple checks"). Fix this by rewriting into gdb_test_multiple and using -early. Tested on x86_64-linux, with and without glibc debuginfo installed.
2023-02-07gdb: fix display of thread condition for multi-location breakpointsAndrew Burgess5-22/+136
This commit addresses the issue in PR gdb/30087. If a breakpoint with multiple locations has a thread condition, then the 'info breakpoints' output is a little messed up, here's an example of the current output: (gdb) break foo thread 1 Breakpoint 2 at 0x401114: foo. (3 locations) (gdb) break bar thread 1 Breakpoint 3 at 0x40110a: file /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c, line 32. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y <MULTIPLE> thread 1 stop only in thread 1 2.1 y 0x0000000000401114 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.2 y 0x0000000000401146 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.3 y 0x0000000000401168 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 3 breakpoint keep y 0x000000000040110a in bar at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:32 thread 1 stop only in thread 1 Notice that, at the end of the location for breakpoint 3, the 'thread 1' condition is printed, but this is then repeated on the next line with 'stop only in thread 1'. In contrast, for breakpoint 2, the 'thread 1' appears randomly, in the "What" column, though slightly offset, non of the separate locations have the 'thread 1' information. Additionally for breakpoint 2 we also get a 'stop only in thread 1' line. There's two things going on here. First the randomly placed 'thread 1' for breakpoint 2 is due to a bug in print_one_breakpoint_location, where we check the variable part_of_multiple instead of header_of_multiple. If I fix this oversight, then the output is now: (gdb) break foo thread 1 Breakpoint 2 at 0x401114: foo. (3 locations) (gdb) break bar thread 1 Breakpoint 3 at 0x40110a: file /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c, line 32. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y <MULTIPLE> stop only in thread 1 2.1 y 0x0000000000401114 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 thread 1 2.2 y 0x0000000000401146 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 thread 1 2.3 y 0x0000000000401168 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 thread 1 3 breakpoint keep y 0x000000000040110a in bar at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:32 thread 1 stop only in thread 1 The 'thread 1' condition is now displayed at the end of each location, which makes the output the same for single location breakpoints and multi-location breakpoints. However, there's still some duplication here. Both breakpoints 2 and 3 include a 'stop only in thread 1' line, and it feels like the additional 'thread 1' is redundant. In fact, there's a comment to this very effect in the code: /* FIXME: This seems to be redundant and lost here; see the "stop only in" line a little further down. */ So, lets fix this FIXME. The new plan is to remove all the trailing 'thread 1' markers from the CLI output, we now get this: (gdb) break foo thread 1 Breakpoint 2 at 0x401114: foo. (3 locations) (gdb) break bar thread 1 Breakpoint 3 at 0x40110a: file /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c, line 32. (gdb) info breakpoints Num Type Disp Enb Address What 2 breakpoint keep y <MULTIPLE> stop only in thread 1 2.1 y 0x0000000000401114 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.2 y 0x0000000000401146 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 2.3 y 0x0000000000401168 in foo at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:25 3 breakpoint keep y 0x000000000040110a in bar at /tmp/src/gdb/testsuite/gdb.base/thread-bp-multi-loc.c:32 stop only in thread 1 All of the above points are also true for the Ada 'task' breakpoint condition, and the changes I've made also update how the task information is printed, though in the case of the Ada task there was no 'stop only in task XXX' line printed, so I've added one of those. Obviously it can't be quite that easy. For MI backwards compatibility I've retained the existing code (but now only for MI like outputs), which ensures we should generate backwards compatible output. I've extended an Ada test to cover the new task related output, and updated all the tests I could find that checked for the old output. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30087 Approved-By: Pedro Alves <pedro@palves.net>
2023-02-07[gdb/testsuite] Improve untested message in gdb.ada/finish-var-size.expTom de Vries1-4/+1
I came across: ... UNTESTED: gdb.ada/finish-var-size.exp: GCC too told for this test ... The message only tells us that the compiler version too old, not what compiler version is required. Fix this by rewriting using required: ... UNSUPPORTED: gdb.ada/finish-var-size.exp: require failed: \ expr [gcc_major_version] >= 12 ... Tested on x86_64-linux.
2023-02-06gdb: adjust comment on target_desc_info::from_user_pSimon Marchi1-1/+1
Remove the stale reference to INFO, which is now "this target description info" now. Change-Id: I35dbdb089048ed7cfffe730d3134ee391b176abf
2023-02-06gdb/doc: extend the documentation for the 'handle' commandAndrew Burgess1-7/+8
The documentation for the 'handle' command does not cover all of the features of the command, and in one case, is just wrong. The user can specify 'all' as signal name, the documentation implies that this will change the behaviour of all signals, in reality, this changes all signals except SIGINT and SIGTRAP (the signals used by GDB). I've updated the docs to list this limitation. The 'handle' command also allows the user to specify multiple signals for a single command, e.g. 'handle SIGFPE SIGILL nostop pass print', however the documentation doesn't describe this, so I've updated the docs to describe this feature.
2023-02-06[gdb/testsuite] Fix gdb.threads/schedlock.exp on fast cpuTom de Vries1-4/+7
Occasionally, I run into: ... (gdb) PASS: gdb.threads/schedlock.exp: schedlock=on: cmd=continue: \ set scheduler-locking on continue^M Continuing.^M PASS: gdb.threads/schedlock.exp: schedlock=on: cmd=continue: \ continue (with lock) [Thread 0x7ffff746e700 (LWP 1339) exited]^M No unwaited-for children left.^M (gdb) Quit^M (gdb) FAIL: gdb.threads/schedlock.exp: schedlock=on: cmd=continue: \ stop all threads (with lock) (timeout) ... What happens is that this loop which is supposed to run "just short of forever": ... /* Don't run forever. Run just short of it :) */ while (*myp > 0) { /* schedlock.exp: main loop. */ MAYBE_CALL_SOME_FUNCTION(); (*myp) ++; } ... finishes after 0x7fffffff iterations (when a signed wrap occurs), which on my system takes only about 1.5 seconds. Fix this by: - changing the pointed-at type of myp from signed to unsigned, which makes the wrap defined behaviour (and which also make the loop run twice as long, which is already enough to make it impossible for me to reproduce the FAIL. But let's try to solve this more structurally). - changing the pointed-at type of myp from int to long long, making the wrap unlikely. - making sure the loop runs forever, by setting the loop condition to 1. - making sure the loop still contains different lines (as far as debug info is concerned) by incrementing a volatile counter in the loop. - making sure the program doesn't run forever in case of trouble, by adding an "alarm (30)". Tested on x86_64-linux. PR testsuite/30074 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30074
2023-02-06gdb: error if 'thread' or 'task' keywords are overusedAndrew Burgess6-2/+42
When creating a breakpoint or watchpoint, the 'thread' and 'task' keywords can be used to create a thread or task specific breakpoint or watchpoint. Currently, a thread or task specific breakpoint can only apply for a single thread or task, if multiple threads or tasks are specified when creating the breakpoint (or watchpoint), then the last specified id will be used. The exception to the above is that when the 'thread' keyword is used during the creation of a watchpoint, GDB will give an error if 'thread' is given more than once. In this commit I propose making this behaviour consistent, if the 'thread' or 'task' keywords are used more than once when creating either a breakpoint or watchpoint, then GDB will give an error. I haven't updated the manual, we don't explicitly say that these keywords can be repeated, and (to me), given the keyword takes a single id, I don't think it makes much sense to repeat the keyword. As such, I see this more as adding a missing error to GDB, rather than making some big change. However, I have added an entry to the NEWS file as I guess it is possible that some people might hit this new error with an existing (I claim, badly written) GDB script. I've added some new tests to check for the new error. Just one test needed updating, gdb.linespec/keywords.exp, this test did use the 'thread' keyword twice, and expected the breakpoint to be created. Looking at what this test was for though, it was checking the use of '-force-condition', and I don't think that being able to repeat 'thread' was actually a critical part of this test. As such, I've updated this test to expect the error when 'thread' is repeated.
2023-02-04gdb/testsuite: don't try to set non-stop mode on a running targetAndrew Burgess1-71/+67
The test gdb.threads/thread-specific-bp.exp tries to set non-stop mode on a running target, something which the manual makes clear is not allowed. This commit restructures the test a little, we now set the non-stop mode as part of the GDBFLAGS, so the mode will be set before GDB connects to the target. As a consequence I'm able to move the with_test_prefix out of the check_thread_specific_breakpoint proc. The check_thread_specific_breakpoint proc is now called within a loop. After this commit the gdb.threads/thread-specific-bp.exp test still has some failures, this is because of an issue GDB currently has printing "Thread ... exited" messages. This problem should be addressed by this patch: https://sourceware.org/pipermail/gdb-patches/2022-December/194694.html when it is merged.
2023-02-03gdb: make target_desc_info_from_user_p a method of target_desc_infoSimon Marchi4-17/+6
Move the implementation over to target_desc_info. Remove the target_desc_info forward declaration in target-descriptions.h, it's no longer needed. Change-Id: Ic95060341685afe0b73af591ca6efe32f5e7e892
2023-02-03gdb: remove copy_inferior_target_desc_infoSimon Marchi4-21/+3
This function is now trivial, we can just copy inferior::tdesc_info where needed. Change-Id: I25185e2cd4ba1ef24a822d9e0eebec6e611d54d6
2023-02-03gdb: remove get_tdesc_infoSimon Marchi1-18/+10
Remove this function, since it's now a trivial access to inferior::tdesc_info. Change-Id: I3e88a8214034f1a4163420b434be11f51eef462c
2023-02-03gdb: change inferior::tdesc_info to non-pointerSimon Marchi4-23/+4
I initially made this field a unique pointer, to have automatic memory management. But I then thought that the field didn't really need to be allocated separately from struct inferior. So make it a regular non-pointer field of inferior. Remove target_desc_info_free, as it's no longer needed. Change-Id: Ica2b97071226f31c40e86222a2f6922454df1229
2023-02-03gdb: move target_desc_info to inferior.hSimon Marchi2-26/+23
In preparation for the following patch, where struct inferior needs to "see" struct target_desc_info, move target_desc_info to the header file. I initially moved the structure to target-descriptions.h, and later made inferior.h include target-descriptions.h. This worked, but it then occured to me that target_desc_info is really an inferior property that involves a target description, so I think it makes sense to have it in inferior.h. Change-Id: I3e81d04faafcad431e294357389f3d4c601ee83d
2023-02-03gdb: use assignment to initialize variable in tdesc_parse_xmlSimon Marchi1-1/+1
Since allocate_target_description returns a target_desc_up, use assignment to initialize the description variable. Change-Id: Iab3311642c09b95648984f305936f4a4cde09440
2023-02-02gdb: initial support for ROCm platform (AMDGPU) debuggingSimon Marchi18-138/+5155
This patch adds the foundation for GDB to be able to debug programs offloaded to AMD GPUs using the AMD ROCm platform [1]. The latest public release of the ROCm release at the time of writing is 5.4, so this is what this patch targets. The ROCm platform allows host programs to schedule bits of code for execution on GPUs or similar accelerators. The programs running on GPUs are typically referred to as `kernels` (not related to operating system kernels). Programs offloaded with the AMD ROCm platform can be written in the HIP language [2], OpenCL and OpenMP, but we're going to focus on HIP here. The HIP language consists of a C++ Runtime API and kernel language. Here's an example of a very simple HIP program: #include "hip/hip_runtime.h" #include <cassert> __global__ void do_an_addition (int a, int b, int *out) { *out = a + b; } int main () { int *result_ptr, result; /* Allocate memory for the device to write the result to. */ hipError_t error = hipMalloc (&result_ptr, sizeof (int)); assert (error == hipSuccess); /* Run `do_an_addition` on one workgroup containing one work item. */ do_an_addition<<<dim3(1), dim3(1), 0, 0>>> (1, 2, result_ptr); /* Copy result from device to host. Note that this acts as a synchronization point, waiting for the kernel dispatch to complete. */ error = hipMemcpyDtoH (&result, result_ptr, sizeof (int)); assert (error == hipSuccess); printf ("result is %d\n", result); assert (result == 3); return 0; } This program can be compiled with: $ hipcc simple.cpp -g -O0 -o simple ... where `hipcc` is the HIP compiler, shipped with ROCm releases. This generates an ELF binary for the host architecture, containing another ELF binary with the device code. The ELF for the device can be inspected with: $ roc-obj-ls simple 1 host-x86_64-unknown-linux file://simple#offset=8192&size=0 1 hipv4-amdgcn-amd-amdhsa--gfx906 file://simple#offset=8192&size=34216 $ roc-obj-extract 'file://simple#offset=8192&size=34216' $ file simple-offset8192-size34216.co simple-offset8192-size34216.co: ELF 64-bit LSB shared object, *unknown arch 0xe0* version 1, dynamically linked, with debug_info, not stripped ^ amcgcn architecture that my `file` doesn't know about ----´ Running the program gives the very unimpressive result: $ ./simple result is 3 While running, this host program has copied the device program into the GPU's memory and spawned an execution thread on it. The goal of this GDB port is to let the user debug host threads and these GPU threads simultaneously. Here's a sample session using a GDB with this patch applied: $ ./gdb -q -nx --data-directory=data-directory ./simple Reading symbols from ./simple... (gdb) break do_an_addition Function "do_an_addition" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (do_an_addition) pending. (gdb) r Starting program: /home/smarchi/build/binutils-gdb-amdgpu/gdb/simple [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New Thread 0x7ffff5db7640 (LWP 1082911)] [New Thread 0x7ffef53ff640 (LWP 1082913)] [Thread 0x7ffef53ff640 (LWP 1082913) exited] [New Thread 0x7ffdecb53640 (LWP 1083185)] [New Thread 0x7ffff54bf640 (LWP 1083186)] [Thread 0x7ffdecb53640 (LWP 1083185) exited] [Switching to AMDGPU Wave 2:2:1:1 (0,0,0)/0] Thread 6 hit Breakpoint 1, do_an_addition (a=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>, b=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>, out=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>) at simple.cpp:24 24 *out = a + b; (gdb) info inferiors Num Description Connection Executable * 1 process 1082907 1 (native) /home/smarchi/build/binutils-gdb-amdgpu/gdb/simple (gdb) info threads Id Target Id Frame 1 Thread 0x7ffff5dc9240 (LWP 1082907) "simple" 0x00007ffff5e9410b in ?? () from /opt/rocm-5.4.0/lib/libhsa-runtime64.so.1 2 Thread 0x7ffff5db7640 (LWP 1082911) "simple" __GI___ioctl (fd=3, request=3222817548) at ../sysdeps/unix/sysv/linux/ioctl.c:36 5 Thread 0x7ffff54bf640 (LWP 1083186) "simple" __GI___ioctl (fd=3, request=3222817548) at ../sysdeps/unix/sysv/linux/ioctl.c:36 * 6 AMDGPU Wave 2:2:1:1 (0,0,0)/0 do_an_addition ( a=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>, b=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>, out=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>) at simple.cpp:24 (gdb) bt Python Exception <class 'gdb.error'>: Unhandled dwarf expression opcode 0xe1 #0 do_an_addition (a=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>, b=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>, out=<error reading variable: DWARF-2 expression error: `DW_OP_regx' operations must be used either alone or in conjunction with DW_OP_piece or DW_OP_bit_piece.>) at simple.cpp:24 (gdb) continue Continuing. result is 3 warning: Temporarily disabling breakpoints for unloaded shared library "file:///home/smarchi/build/binutils-gdb-amdgpu/gdb/simple#offset=8192&size=67208" [Thread 0x7ffff54bf640 (LWP 1083186) exited] [Thread 0x7ffff5db7640 (LWP 1082911) exited] [Inferior 1 (process 1082907) exited normally] One thing to notice is the host and GPU threads appearing under the same inferior. This is a design goal for us, as programmers tend to think of the threads running on the GPU as part of the same program as the host threads, so showing them in the same inferior in GDB seems natural. Also, the host and GPU threads share a global memory space, which fits the inferior model. Another thing to notice is the error messages when trying to read variables or printing a backtrace. This is expected for the moment, since the AMD GPU compiler produces some DWARF that uses some non-standard extensions: https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html There were already some patches posted by Zoran Zaric earlier to make GDB support these extensions: https://inbox.sourceware.org/gdb-patches/20211105113849.118800-1-zoran.zaric@amd.com/ We think it's better to get the basic support for AMD GPU in first, which will then give a better justification for GDB to support these extensions. GPU threads are named `AMDGPU Wave`: a wave is essentially a hardware thread using the SIMT (single-instruction, multiple-threads) [3] execution model. GDB uses the amd-dbgapi library [4], included in the ROCm platform, for a few things related to AMD GPU threads debugging. Different components talk to the library, as show on the following diagram: +---------------------------+ +-------------+ +------------------+ | GDB | amd-dbgapi target | <-> | AMD | | Linux kernel | | +-------------------+ | Debugger | +--------+ | | | amdgcn gdbarch | <-> | API | <=> | AMDGPU | | | +-------------------+ | | | driver | | | | solib-rocm | <-> | (dbgapi.so) | +--------+---------+ +---------------------------+ +-------------+ - The amd-dbgapi target is a target_ops implementation used to control execution of GPU threads. While the debugging of host threads works by using the ptrace / wait Linux kernel interface (as usual), control of GPU threads is done through a special interface (dubbed `kfd`) exposed by the `amdgpu` Linux kernel module. GDB doesn't interact directly with `kfd`, but instead goes through the amd-dbgapi library (AMD Debugger API on the diagram). Since it provides execution control, the amd-dbgapi target should normally be a process_stratum_target, not just a target_ops. More on that later. - The amdgcn gdbarch (describing the hardware architecture of the GPU execution units) offloads some requests to the amd-dbgapi library, so that knowledge about the various architectures doesn't need to be duplicated and baked in GDB. This is for example for things like the list of registers. - The solib-rocm component is an solib provider that fetches the list of code objects loaded on the device from the amd-dbgapi library, and makes GDB read their symbols. This is very similar to other solib providers that handle shared libraries, except that here the shared libraries are the pieces of code loaded on the device. Given that Linux host threads are managed by the linux-nat target, and the GPU threads are managed by the amd-dbgapi target, having all threads appear in the same inferior requires the two targets to be in that inferior's target stack. However, there can only be one process_stratum_target in a given target stack, since there can be only one target per slot. To achieve it, we therefore resort the hack^W solution of placing the amd-dbgapi target in the arch_stratum slot of the target stack, on top of the linux-nat target. Doing so allows the amd-dbgapi target to intercept target calls and handle them if they concern GPU threads, and offload to beneath otherwise. See amd_dbgapi_target::fetch_registers for a simple example: void amd_dbgapi_target::fetch_registers (struct regcache *regcache, int regno) { if (!ptid_is_gpu (regcache->ptid ())) { beneath ()->fetch_registers (regcache, regno); return; } // handle it } ptids of GPU threads are crafted with the following pattern: (pid, 1, wave id) Where pid is the inferior's pid and "wave id" is the wave handle handed to us by the amd-dbgapi library (in practice, a monotonically incrementing integer). The idea is that on Linux systems, the combination (pid != 1, lwp == 1) is not possible. lwp == 1 would always belong to the init process, which would also have pid == 1 (and it's improbable for the init process to offload work to the GPU and much less for the user to debug it). We can therefore differentiate GPU and non-GPU ptids this way. See ptid_is_gpu for more details. Note that we believe that this scheme could break down in the context of containers, where the initial process executed in a container has pid 1 (in its own pid namespace). For instance, if you were to execute a ROCm program in a container, then spawn a GDB in that container and attach to the process, it will likely not work. This is a known limitation. A workaround for this is to have a dummy process (like a shell) fork and execute the program of interest. The amd-dbgapi target watches native inferiors, and "attaches" to them using amd_dbgapi_process_attach, which gives it a notifier fd that is registered in the event loop (see enable_amd_dbgapi). Note that this isn't the same "attach" as in PTRACE_ATTACH, but being ptrace-attached is a precondition for amd_dbgapi_process_attach to work. When the debugged process enables the ROCm runtime, the amd-dbgapi target gets notified through that fd, and pushes itself on the target stack of the inferior. The amd-dbgapi target is then able to intercept target_ops calls. If the debugged process disables the ROCm runtime, the amd-dbgapi target unpushes itself from the target stack. This way, the amd-dbgapi target's footprint stays minimal when debugging a process that doesn't use the AMD ROCm platform, it does not intercept target calls. The amd-dbgapi library is found using pkg-config. Since enabling support for the amdgpu architecture (amdgpu-tdep.c) depends on the amd-dbgapi library being present, we have the following logic for the interaction with --target and --enable-targets: - if the user explicitly asks for amdgcn support with --target=amdgcn-*-* or --enable-targets=amdgcn-*-*, we probe for the amd-dbgapi and fail if not found - if the user uses --enable-targets=all, we probe for amd-dbgapi, enable amdgcn support if found, disable amdgcn support if not found - if the user uses --enable-targets=all and --with-amd-dbgapi=yes, we probe for amd-dbgapi, enable amdgcn if found and fail if not found - if the user uses --enable-targets=all and --with-amd-dbgapi=no, we do not probe for amd-dbgapi, disable amdgcn support - otherwise, amd-dbgapi is not probed for and support for amdgcn is not enabled Finally, a simple test is included. It only tests hitting a breakpoint in device code and resuming execution, pretty much like the example shown above. [1] https://docs.amd.com/category/ROCm_v5.4 [2] https://docs.amd.com/bundle/HIP-Programming-Guide-v5.4 [3] https://en.wikipedia.org/wiki/Single_instruction,_multiple_threads [4] https://docs.amd.com/bundle/ROCDebugger-API-Guide-v5.4 Change-Id: I591edca98b8927b1e49e4b0abe4e304765fed9ee Co-Authored-By: Zoran Zaric <zoran.zaric@amd.com> Co-Authored-By: Laurent Morichetti <laurent.morichetti@amd.com> Co-Authored-By: Tony Tye <Tony.Tye@amd.com> Co-Authored-By: Lancelot SIX <lancelot.six@amd.com> Co-Authored-By: Pedro Alves <pedro@palves.net>
2023-02-02gdb: make gdb_printing_disassembler::stream publicSimon Marchi1-2/+2
In the ROCm port, we need to access the underlying stream of a gdb_printing_disassembler, so make it public. The reason we need to access it is to know whether it supports style escape code. We then pass that information to a temporary string_file we use while symbolizing addresses. Change-Id: Ib95755a4a45b8f6478787993e9f904df60dd8dc1 Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-02-02gdb/solib-svr4: don't disable probes interface if probe not foundSimon Marchi1-5/+10
In ROCm-GDB, we install an solib provider for the GPU code objects on top of the svr4 provider for the host, in order to add solibs representing the GPU code objects to the solib list containing the host process' shared libraries. We override the target_so_ops::handle_event function pointer with our own, in which we call svr4_so_ops.handle_event (which contains svr4_handle_solib_event) manually. When the host (un)loads a library, the ROCm part of handle_event is a no-op. When the GPU (un)loads a code object, we want the host side (svr4) to be a no-op. The problem is that when handle_event is called because of a GPU event, svr4_handle_solib_event gets called while not stopped at an svr4 probe. It then assumes this means there's a problem with the probes interface and disables it through the following sequence of events: - solib_event_probe_at return nullptr - svr4_handle_solib_event returns early - the make_scope_exit callback calls disable_probes_interface We could fix that by making the ROCm handle_event callback check if an svr4 probe is that the stop address, and only call svr4_so_ops.handle_event if so. However, it doesn't feel right to include some svr4 implementation detail in the ROCm event handler. Instead, this patch changes svr4_handle_solib_event to not assume it is an error if called while not at an svr4 probe location, and therefore not disable the probes interface. That just means moving the make_scope_exit call below where we lookup the probe by pc. Change-Id: Ie8ddf5beffa2e92b8ebfdd016454546252519244 Co-Authored-By: Lancelot SIX <lancelot.six@amd.com>
2023-02-02gdb: add gdbarch_upSimon Marchi1-0/+8
Add a gdbarch_up unique pointer type, that calls gdbarch_free on deletion. This is used in the ROCm support patch at the end of this series. Change-Id: I4b808892d35d69a590ce83180f41afd91705b2c8 Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-02-02gdb: add inferior_pre_detach observableSimon Marchi3-0/+6
Add an observable notified in target_detach just before calling the detach method on the inferior's target stack. This allows observer to do some work on the inferior while it's still ptrace-attached, in the case of a native Linux inferior. Specifically, the amd-dbgapi target will need it in order to call amd_dbgapi_process_detach before the process gets ptrace-detached. Change-Id: I28b6065e251012a4c2db8a600fe13ba31671e3c9 Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-02-02gdb: make install_breakpoint return a non-owning referencePedro Alves2-4/+8
A following patch will want to install a breakpoint and then keep a non-owning reference to it. Make install_breakpoint return a non-owning reference, to make that easy. Co-Authored-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I2e8106a784021ff276ce251e24708cbdccc2d479 Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-02-02gdb: add supports_arch_info callback to gdbarch_registerLancelot SIX2-3/+10
In the ROCm GDB port, there are some amdgcn architectures known by BFD that we don't actually support in GDB. We don't want gdbarch_printable_names to return these architectures. gdbarch_printable_names is used for a few things: - completion of the "set architecture" command - the gdb.architecture_names function in Python - foreach-arch selftests Add an optional callback to gdbarch_register that is a predicate indicating whether the gdbarch supports the given bfd_arch_info. by default, it is nullptr, meaning that the gdbarch accepts all "mach"s for that architecture known by BFD. Change-Id: I712f94351b0b34ed1f42e5cf7fc7ba051315d860 Co-Authored-By: Simon Marchi <simon.marchi@efficios.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-02-02gdb: remove gdb_indent.shEnze Li1-92/+0
GDB has been converted to a C++ program for many years[1], and the gdb_indent.sh will not be used any more. Therefore, remove the script as obvious. [1] https://sourceware.org/gdb/wiki/cxx-conversion Approved-By: Simon Marchi <simark@simark.ca>
2023-02-01gdb/testsuite: fix fetch_src_and_symbols.exp with native-gdbserver boardAndrew Burgess1-9/+20
I noticed that the gdb.debuginfod/fetch_src_and_symbols.exp script doesn't work with the native-gdbserver board, I see this error: ERROR: tcl error sourcing /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp. ERROR: gdbserver does not support run without extended-remote while executing "error "gdbserver does not support $command without extended-remote"" (procedure "gdb_test_multiple" line 51) invoked from within This was introduced with this commit: commit 7dd38e31d67c2548b52bea313ab18e40824c05da Date: Fri Jan 6 18:45:27 2023 -0500 gdb/linespec.c: Fix missing source file during breakpoint re-set The problem is that the above commit introduces a direct use of the "run" command, which doesn't work with 'target remote' targets, as exercised by the native-gdbserver board. To avoid this, in this commit I switch to using runto_main. However, calling runto_main will, by default, delete all the currently set breakpoints. As the point of the above commit was to check that a breakpoint set before stating an inferior would be correctly re-set, we need to avoid this breakpoint deleting behaviour. To do this I make use of with_override, and override the delete_breakpoints proc with a dummy proc which does nothing. By reverting the GDB changes in commit 7dd38e31d67c I have confirmed that even after my changes in this commit, the test still fails. But with the fixes in commit 7dd38e31d67c, this test now passed using the unix, native-gdbserver, and native-extended-gdbserver boards.
2023-02-01gdb: defer warnings when loading separate debug filesAlexandra Hájková12-42/+419
Currently, when GDB loads debug information from a separate debug file, there are a couple of warnings that could be produced if things go wrong. In find_separate_debug_file_by_buildid (build-id.c) GDB can give a warning if the separate debug file doesn't include any actual debug information, and in separate_debug_file_exists (symfile.c) we can warn if the CRC checksum in the separate debug file doesn't match the checksum in the original executable. The problem here is that, when looking up debug information, GDB will try several different approaches, lookup by build-id, lookup by debug-link, and then a lookup from debuginfod. GDB can potentially give a warning from an earlier attempt, and then succeed with a later attempt. In the cases I have run into this is primarily a warning about some out of date debug information on my machine, but then GDB finds the correct information using debuginfod. This can be confusing to a user, they will see warnings from GDB when really everything is working just fine. For example: warning: the debug information found in "/usr/lib/debug//lib64/ld-2.32.so.debug" \ does not match "/lib64/ld-linux-x86-64.so.2" (CRC mismatch). This diagnostic was printed on Fedora 33 even when the correct debuginfo was downloaded. In this patch I propose that we defer any warnings related to looking up debug information from a separate debug file. If any of the approaches are successful then GDB will not print any of the warnings. As far as the user is concerned, everything "just worked". Only if GDB completely fails to find any suitable debug information will the warnings be printed. The crc_mismatch test compiles two executables: crc_mismatch and crc_mismatch-2 and then strips them of debuginfo creating separate debug files. The test then replaces crc_mismatch-2.debug with crc_mismatch.debug to trigger "CRC mismatch" warning. A local debuginfod server is setup to supply the correct debug file, now when GDB looks up the debug info no warning is given. The build-id-no-debug-warning.exp is similar to the previous test. It triggers the "separate debug info file has no debug info" warning by replacing the build-id based .debug file with the stripped binary and then loading it to GDB. It then also sets up local debuginfod server with the correct debug file to download to make sure no warnings are emitted.
2023-01-31gdb/dwarf: rename cooked_index_vector to cooked_indexSimon Marchi5-38/+35
See previous patch's commit message for rationale. Change-Id: I6b8cdc045dffccc1c01ed690ff258af09f6ff076 Approved-By: Tom Tromey <tom@tromey.com>
2023-01-31gdb/dwarf: rename cooked_index to cooked_index_shardSimon Marchi3-24/+24
I propose to rename cooked_index_vector and cooked_index such that the "main" object, that is the entry point to the index, is called cooked_index. The fact that the cooked index is implemented as a vector of smaller indexes is an implementation detail. This patch renames cooked_index to cooked_index_shard. The following patch renames cooked_index_vector to cooked_index. Change-Id: Id650f97dcb23c48f8409fa0974cd093ca0b75177 Approved-By: Tom Tromey <tom@tromey.com>
2023-01-31gdb: add nullptr check to cooked_index_functions::dumpSimon Marchi1-4/+5
Since commit 7d82b08e9e0a ("gdb/dwarf: dump cooked index contents in cooked_index_functions::dump"), we see: maint print objfiles /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/dw2-error/dw2-error^M ^M Object file /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/dw2-error/dw2-error: Objfile at 0x614000005040, bfd at 0x6120000e08c0, 15 minsyms^M ^M Cooked index in use:^M ^M /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/gdb-checked-static-cast.h:58: internal-error: checked_static_cast: Assertion `result != nullptr' failed.^M A problem internal to GDB has been detected,^M further debugging may prove unreliable.^M ----- Backtrace -----^M FAIL: gdb.dwarf2/dw2-error.exp: maint print objfiles /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/dw2-error/dw2-error (GDB internal error) The problem is that when cooked_index_functions fails to build an index, per_objfile->index_table is nullptr. Therefore, add a nullptr check, like other methods of cooked_index_functions already do. Print the "Cooked index in use" message after the nullptr check, such that if the cooked index failed to build, that message is not printed. Change-Id: Id67aef592e76c41b1e3bde9838a4e36cef873253
2023-01-31gdb/testsuite: adjust ensure_gdb_index to cooked_index_functions::dump changesSimon Marchi1-1/+1
Following 7d82b08e9e0a ("gdb/dwarf: dump cooked index contents in cooked_index_functions::dump"), I see some failures like: (gdb) mt print objfiles with-mf^M ^M Object file /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/with-mf/with-mf: Objfile at 0x614000005040, bfd at 0x6120000e08c0, 18 minsyms ^M ^M Cooked index in use:^M ^M ... (gdb) FAIL: gdb.base/with-mf.exp: check if index present This is because the format of the "Cooked index in use" line changed slightly. Adjust ensure_gdb_index to expect the trailing colon. Change-Id: If0a87575c02d8a0bc0d4b8ead540c234c62760f8
2023-01-31gdb/testsuite: fix xfail in gdb.ada/ptype_tagged_param.expSimon Marchi1-1/+1
I see: ERROR: wrong # args: should be "xfail message" while executing "xfail "no debug info" $gdb_test_name" ("uplevel" body line 3) invoked from within "uplevel { if {!$has_runtime_debug_info} { xfail "no debug info" $gdb_test_name } else { fail $gdb_test_name } }" This is because the xfail takes only one argument, fix that. Change-Id: I2e304d4fd3aa61067c04b5dac2be2ed34dab3190
2023-01-30Remove value_next declarationTom Tromey1-7/+0
value_next is declared but not defined. It's long obsolete. This patch removes the stray declaration.
2023-01-30gdb: fix dwarf2/cooked-index.c compilation on 32-bit systemsSimon Marchi1-1/+1
The i386 builder shows: ../../binutils-gdb/gdb/dwarf2/cooked-index.c: In member function ‘void cooked_index_vector::dump(gdbarch*) const’: ../../binutils-gdb/gdb/dwarf2/cooked-index.c:492:40: error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘std::__underlying_type_impl<sect_offset, true>::type’ {aka ‘long long unsigned int’} [-Werror=format=] 492 | gdb_printf (" DIE offset: 0x%lx\n", | ~~^ | | | long unsigned int | %llx 493 | to_underlying (entry->die_offset)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | std::__underlying_type_impl<sect_offset, true>::type {aka long long unsigned int} The die_offset's underlying type is uint64, so use PRIx64 in the format string. Change-Id: Ibdde4c624ed1bb50eced9a514a4e37aec70a1323
2023-01-30gdb: Replace memcpy with std::copy to avoid some g++ warnings on sparcMark Wielaard1-1/+1
For some reason g++ 12.2.1 on sparc produces spurious warnings for stringop-overread and restrict in fbsd-tdep.c for a memcpy call. Use std::copy to avoid the warnings: In function ‘void* memcpy(void*, const void*, size_t)’, inlined from ‘gdb::optional<std::vector<unsigned char, gdb::default_init_allocator<unsigned char, std::allocator<unsigned char> > > > fbsd_make_note_desc(target_object, uint32_t)’ at ../../binutils-gdb/gdb/fbsd-tdep.c:666:10: /usr/include/bits/string_fortified.h:29:33: error: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ specified bound 18446744073709551612 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=] In function ‘void* memcpy(void*, const void*, size_t)’, inlined from ‘gdb::optional<std::vector<unsigned char, gdb::default_init_allocator<unsigned char, std::allocator<unsigned char> > > > fbsd_make_note_desc(target_object, uint32_t)’ at ../../binutils-gdb/gdb/fbsd-tdep.c:673:10: /usr/include/bits/string_fortified.h:29:33: error: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ accessing 18446744073709551612 bytes at offsets 0 and 0 overlaps 9223372036854775801 bytes at offset -9223372036854775805 [-Werror=restrict] gdb/ChangeLog: * fbsd-tdep.c (fbsd_make_note_desc): Use std::copy instead of memcpy.
2023-01-30gdb/dwarf: dump cooked index contents in cooked_index_functions::dumpSimon Marchi3-1/+109
As I am investigating a crash I see with the cooked index, I thought it would be useful to have a way to dump the index contents. For those not too familiar with it (that includes me), it can help get a feel of what it contains and how it is structured. The cooked_index_functions::dump function is called as part of the "maintenance print objfiles" command. I tried to make the output well structured and indented to help readability, as this prints a lot of text. The dump function first dumps all cooked index entries, like this: [25] ((cooked_index_entry *) 0x621000121220) name: __ioinit canonical: __ioinit DWARF tag: DW_TAG_variable flags: 0x2 [IS_STATIC] DIE offset: 0x21a4 parent: ((cooked_index_entry *) 0x6210000f9610) [std] Then the information about the main symbol: main: ((cooked_index_entry *) 0x621000123b40) [main] And finally the address map contents: [1] ((addrmap *) 0x6210000f7910) [0x0] ((dwarf2_per_cu_data *) 0) [0x118a] ((dwarf2_per_cu_data *) 0x60c000007f00) [0x1cc7] ((dwarf2_per_cu_data *) 0) [0x1cc8] ((dwarf2_per_cu_data *) 0x60c000007f00) [0x1cdf] ((dwarf2_per_cu_data *) 0) [0x1ce0] ((dwarf2_per_cu_data *) 0x60c000007f00) The display of address maps above could probably be improved, to show it more as ranges, but I think this is a reasonable start. Note that this patch depends on Pedro Alves' patch "enum_flags to_string" [1]. If my patch is to be merged before Pedro's series, I will cherry-pick this patch from his series and merge it before mine. [1] https://inbox.sourceware.org/gdb-patches/20221212203101.1034916-8-pedro@palves.net/ Change-Id: Ida13e479fd4c8d21102ddd732241778bc3b6904a
2023-01-30enum_flags to_stringPedro Alves1-6/+63
This commit introduces shared infrastructure that can be used to implement enum_flags -> to_string functions. With this, if we want to support converting a given enum_flags specialization to string, we just need to implement a function that provides the enumerator->string mapping, like so: enum some_flag { SOME_FLAG1 = 1 << 0, SOME_FLAG2 = 1 << 1, SOME_FLAG3 = 1 << 2, }; DEF_ENUM_FLAGS_TYPE (some_flag, some_flags); static std::string to_string (some_flags flags) { static constexpr some_flags::string_mapping mapping[] = { MAP_ENUM_FLAG (SOME_FLAG1), MAP_ENUM_FLAG (SOME_FLAG2), MAP_ENUM_FLAG (SOME_FLAG3), }; return flags.to_string (mapping); } .. and then to_string(SOME_FLAG2 | SOME_FLAG3) produces a string like "0x6 [SOME_FLAG2 SOME_FLAG3]". If we happen to forget to update the mapping array when we introduce a new enumerator, then the string representation will pretty-print the flags it knows about, and then the leftover flags in hex (one single number). For example, if we had missed mapping SOME_FLAG2 above, we'd end up with: to_string(SOME_FLAG2 | SOME_FLAG3) => "0x6 [SOME_FLAG2 0x4]"); Other than in the unit tests included, no actual usage of the functionality is added in this commit. Approved-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I835de43c33d13bc0c95132f42c3f97318b875779
2023-01-30Fix comparator bug in cooked indexTom Tromey2-85/+132
Simon pointed out that the cooked index template-matching patch introduced a failure in libstdc++ debug mode. In particular, the new code violates the assumption of std::lower_bound and std::upper_bound that the range is sorted with respect to the comparison. When I first debugged this, I thought the problem was unfixable as-is and that a second layer of filtering would have to be done. However, on irc, Simon pointed out that it could perhaps be solved if the comparison function were assured that one operand always came from the index, with the other always being the search string. This patch implements this idea. First, a new mode is introduced: a sorting mode for cooked_index_entry::compare. In this mode, strings are compared case-insensitively, but we're careful to always sort '<' before any other printable character. This way, two names like "func" and "func<param>" will be sorted next to each other -- i.e., "func1" will not be seen between them. This is important when searching. Second, the compare function is changed to work in a strcmp-like way. This makes it easier to test and (IMO) understand. Third, the compare function is modified so that in non-sorting modes, the index entry is always the first argument. This allows consistency in compares. I regression tested this in libstdc++ debug mode on x86-64 Fedora 36. It fixes the crash that Simon saw. This is v2. I believe it addresses the review comments, except for the 'enum class' change, as I mentioned in email on the list. Approved-By: Simon Marchi <simon.marchi@efficios.com>