Age | Commit message (Collapse) | Author | Files | Lines |
|
As observed on a binary compiled on AMD64 Ubuntu 20.04, against glibc
2.31 (I think it's the libc that provides this startup code, right?),
there are enough bytes at the executable's entry point to hold more than
one displaced step buffer. gdbarch_max_insn_length is 16, and the
code at _start looks like:
0000000000001040 <_start>:
1040: f3 0f 1e fa endbr64
1044: 31 ed xor %ebp,%ebp
1046: 49 89 d1 mov %rdx,%r9
1049: 5e pop %rsi
104a: 48 89 e2 mov %rsp,%rdx
104d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1051: 50 push %rax
1052: 54 push %rsp
1053: 4c 8d 05 56 01 00 00 lea 0x156(%rip),%r8 # 11b0 <__libc_csu_fini>
105a: 48 8d 0d df 00 00 00 lea 0xdf(%rip),%rcx # 1140 <__libc_csu_init>
1061: 48 8d 3d c1 00 00 00 lea 0xc1(%rip),%rdi # 1129 <main>
1068: ff 15 72 2f 00 00 callq *0x2f72(%rip) # 3fe0 <__libc_start_main@GLIBC_2.2.5>
106e: f4 hlt
106f: 90 nop
The two buffers would occupy [0x1040, 0x1060).
I checked on Alpine, which uses the musl C library, the startup code
looks like:
0000000000001048 <_start>:
1048: 48 31 ed xor %rbp,%rbp
104b: 48 89 e7 mov %rsp,%rdi
104e: 48 8d 35 e3 2d 00 00 lea 0x2de3(%rip),%rsi # 3e38 <_DYNAMIC>
1055: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1059: e8 00 00 00 00 callq 105e <_start_c>
000000000000105e <_start_c>:
105e: 48 8b 37 mov (%rdi),%rsi
1061: 48 8d 57 08 lea 0x8(%rdi),%rdx
1065: 45 31 c9 xor %r9d,%r9d
1068: 4c 8d 05 47 01 00 00 lea 0x147(%rip),%r8 # 11b6 <_fini>
106f: 48 8d 0d 8a ff ff ff lea -0x76(%rip),%rcx # 1000 <_init>
1076: 48 8d 3d 0c 01 00 00 lea 0x10c(%rip),%rdi # 1189 <main>
107d: e9 9e ff ff ff jmpq 1020 <__libc_start_main@plt>
Even though there's a _start_c symbol, it all appears to be code that
runs once at the very beginning of the program, so it looks fine if the
two buffers occupy [0x1048, 0x1068).
One important thing I discovered while doing this is that when debugging
a dynamically-linked executable, breakpoints in the shared library
loader are hit before executing the _start code, and these breakpoints
may be displaced-stepped. So it's very important that the buffer bytes
are restored properly after doing the displaced steps, otherwise the
_start code will be corrupted once we try to execute it.
Another thing that made me think about is that library constructors (as
in `__attribute__((constructor))`) run before _start. And they are free
to spawn threads. What if one of these threads executes a displaced
step, therefore changing the bytes at _start, while the main thread
executes _start? That doesn't sound good and I don't know how we could
prevent it. But this is a problem that predates the current patch.
Even when stress-testing the implementation, by making many threads do
displaced steps over and over, I didn't see a significant performance (I
confirmed that the two buffers were used by checking the "set debug
displaced" logs though). However, this patch mostly helps make the
feature testable by anybody with an AMD64/Linux machine, so I think it's
useful.
gdb/ChangeLog:
* amd64-linux-tdep.c (amd64_linux_init_abi): Pass 2 as the
number of displaced step buffers.
Change-Id: Ia0c96ea0fcda893f4726df6fdac7be5214620112
|
|
The displaced_step_buffer class, introduced in the previous patch,
manages access to a single displaced step buffer. Change it into
displaced_step_buffers (note the plural), which manages access to
multiple displaced step buffers.
When preparing a displaced step for a thread, it looks for an unused
buffer.
For now, all users still pass a single displaced step buffer, so no real
behavior change is expected here. The following patch makes a user pass
more than one buffer, so the functionality introduced by this patch is
going to be useful in the next one.
gdb/ChangeLog:
* displaced-stepping.h (struct displaced_step_buffer): Rename
to...
(struct displaced_step_buffers): ... this.
<m_addr, m_current_thread, m_copy_insn_closure>: Remove.
<struct displaced_step_buffer>: New inner class.
<m_buffers>: New.
* displaced-stepping.c (displaced_step_buffer::prepare): Rename
to...
(displaced_step_buffers::prepare): ... this, adjust for multiple
buffers.
(displaced_step_buffer::finish): Rename to...
(displaced_step_buffers::finish): ... this, adjust for multiple
buffers.
(displaced_step_buffer::copy_insn_closure_by_addr): Rename to...
(displaced_step_buffers::copy_insn_closure_by_addr): ... this,
adjust for multiple buffers.
(displaced_step_buffer::restore_in_ptid): Rename to...
(displaced_step_buffers::restore_in_ptid): ... this, adjust for
multiple buffers.
* linux-tdep.h (linux_init_abi): Change supports_displaced_step
for num_disp_step_buffers.
* linux-tdep.c (struct linux_gdbarch_data)
<num_disp_step_buffers>: New field.
(struct linux_info) <disp_step_buf>: Rename to...
<disp_step_bufs>: ... this, change type to
displaced_step_buffers.
(linux_displaced_step_prepare): Use
linux_gdbarch_data::num_disp_step_buffers to create that number
of buffers.
(linux_displaced_step_finish): Adjust.
(linux_displaced_step_copy_insn_closure_by_addr): Adjust.
(linux_displaced_step_restore_all_in_ptid): Adjust.
(linux_init_abi): Change supports_displaced_step parameter for
num_disp_step_buffers, save it in linux_gdbarch_data.
* aarch64-linux-tdep.c (aarch64_linux_init_abi): Adjust.
* alpha-linux-tdep.c (alpha_linux_init_abi): Adjust.
* amd64-linux-tdep.c (amd64_linux_init_abi_common): Change
supports_displaced_step parameter for num_disp_step_buffers.
(amd64_linux_init_abi): Adjust.
(amd64_x32_linux_init_abi): Adjust.
* arc-linux-tdep.c (arc_linux_init_osabi): Adjust.
* arm-linux-tdep.c (arm_linux_init_abi): Adjust.
* bfin-linux-tdep.c (bfin_linux_init_abi): Adjust.
* cris-linux-tdep.c (cris_linux_init_abi): Adjust.
* csky-linux-tdep.c (csky_linux_init_abi): Adjust.
* frv-linux-tdep.c (frv_linux_init_abi): Adjust.
* hppa-linux-tdep.c (hppa_linux_init_abi): Adjust.
* i386-linux-tdep.c (i386_linux_init_abi): Adjust.
* ia64-linux-tdep.c (ia64_linux_init_abi): Adjust.
* m32r-linux-tdep.c (m32r_linux_init_abi): Adjust.
* m68k-linux-tdep.c (m68k_linux_init_abi):
* microblaze-linux-tdep.c (microblaze_linux_init_abi):
* mips-linux-tdep.c (mips_linux_init_abi): Adjust.
* mn10300-linux-tdep.c (am33_linux_init_osabi): Adjust.
* nios2-linux-tdep.c (nios2_linux_init_abi): Adjust.
* or1k-linux-tdep.c (or1k_linux_init_abi): Adjust.
* ppc-linux-tdep.c (ppc_linux_init_abi): Adjust.
* riscv-linux-tdep.c (riscv_linux_init_abi): Adjust.
* rs6000-tdep.c (struct ppc_inferior_data) <disp_step_buf>:
Change type to displaced_step_buffers.
* s390-linux-tdep.c (s390_linux_init_abi_any): Adjust.
* sh-linux-tdep.c (sh_linux_init_abi): Adjust.
* sparc-linux-tdep.c (sparc32_linux_init_abi): Adjust.
* sparc64-linux-tdep.c (sparc64_linux_init_abi): Adjust.
* tic6x-linux-tdep.c (tic6x_uclinux_init_abi): Adjust.
* tilegx-linux-tdep.c (tilegx_linux_init_abi): Adjust.
* xtensa-linux-tdep.c (xtensa_linux_init_abi): Adjust.
Change-Id: Ia9c02f207da2c9e1d9188020139619122392bb70
|
|
The following patch will need to fill a field in linux_gdbarch_data
while the gdbarch is being built. linux_gdbarch_data is currently
allocated as a post-init gdbarch data, meaning it's not possible to fill
it before the gdbarch is completely initialized. Change it to a
pre-init gdbarch data to allow this.
The init_linux_gdbarch_data function doesn't use the created gdbarch,
it only allocates the linux_gdbarch_data structure on the gdbarch's
obstack, so the change is trivial.
gdb/ChangeLog:
* linux-tdep.c (init_linux_gdbarch_data): Change parameter to
obkstack.
(_initialize_linux_tdep): Register pre-init gdb data instead of
post-init.
Change-Id: If35ce91b6bb5435680d43b9268d811d95661644f
|
|
displaced steps
Today, GDB only allows a single displaced stepping operation to happen
per inferior at a time. There is a single displaced stepping buffer per
inferior, whose address is fixed (obtained with
gdbarch_displaced_step_location), managed by infrun.c.
In the case of the AMD ROCm target [1] (in the context of which this
work has been done), it is typical to have thousands of threads (or
waves, in SMT terminology) executing the same code, hitting the same
breakpoint (possibly conditional) and needing to to displaced step it at
the same time. The limitation of only one displaced step executing at a
any given time becomes a real bottleneck.
To fix this bottleneck, we want to make it possible for threads of a
same inferior to execute multiple displaced steps in parallel. This
patch builds the foundation for that.
In essence, this patch moves the task of preparing a displaced step and
cleaning up after to gdbarch functions. This allows using different
schemes for allocating and managing displaced stepping buffers for
different platforms. The gdbarch decides how to assign a buffer to a
thread that needs to execute a displaced step.
On the ROCm target, we are able to allocate one displaced stepping
buffer per thread, so a thread will never have to wait to execute a
displaced step.
On Linux, the entry point of the executable if used as the displaced
stepping buffer, since we assume that this code won't get used after
startup. From what I saw (I checked with a binary generated against
glibc and musl), on AMD64 we have enough space there to fit two
displaced stepping buffers. A subsequent patch makes AMD64/Linux use
two buffers.
In addition to having multiple displaced stepping buffers, there is also
the idea of sharing displaced stepping buffers between threads. Two
threads doing displaced steps for the same PC could use the same buffer
at the same time. Two threads stepping over the same instruction (same
opcode) at two different PCs may also be able to share a displaced
stepping buffer. This is an idea for future patches, but the
architecture built by this patch is made to allow this.
Now, the implementation details. The main part of this patch is moving
the responsibility of preparing and finishing a displaced step to the
gdbarch. Before this patch, preparing a displaced step is driven by the
displaced_step_prepare_throw function. It does some calls to the
gdbarch to do some low-level operations, but the high-level logic is
there. The steps are roughly:
- Ask the gdbarch for the displaced step buffer location
- Save the existing bytes in the displaced step buffer
- Ask the gdbarch to copy the instruction into the displaced step buffer
- Set the pc of the thread to the beginning of the displaced step buffer
Similarly, the "fixup" phase, executed after the instruction was
successfully single-stepped, is driven by the infrun code (function
displaced_step_finish). The steps are roughly:
- Restore the original bytes in the displaced stepping buffer
- Ask the gdbarch to fixup the instruction result (adjust the target's
registers or memory to do as if the instruction had been executed in
its original location)
The displaced_step_inferior_state::step_thread field indicates which
thread (if any) is currently using the displaced stepping buffer, so it
is used by displaced_step_prepare_throw to check if the displaced
stepping buffer is free to use or not.
This patch defers the whole task of preparing and cleaning up after a
displaced step to the gdbarch. Two new main gdbarch methods are added,
with the following semantics:
- gdbarch_displaced_step_prepare: Prepare for the given thread to
execute a displaced step of the instruction located at its current PC.
Upon return, everything should be ready for GDB to resume the thread
(with either a single step or continue, as indicated by
gdbarch_displaced_step_hw_singlestep) to make it displaced step the
instruction.
- gdbarch_displaced_step_finish: Called when the thread stopped after
having started a displaced step. Verify if the instruction was
executed, if so apply any fixup required to compensate for the fact
that the instruction was executed at a different place than its
original pc. Release any resources that were allocated for this
displaced step. Upon return, everything should be ready for GDB to
resume the thread in its "normal" code path.
The displaced_step_prepare_throw function now pretty much just offloads
to gdbarch_displaced_step_prepare and the displaced_step_finish function
offloads to gdbarch_displaced_step_finish.
The gdbarch_displaced_step_location method is now unnecessary, so is
removed. Indeed, the core of GDB doesn't know how many displaced step
buffers there are nor where they are.
To keep the existing behavior for existing architectures, the logic that
was previously implemented in infrun.c for preparing and finishing a
displaced step is moved to displaced-stepping.c, to the
displaced_step_buffer class. Architectures are modified to implement
the new gdbarch methods using this class. The behavior is not expected
to change.
The other important change (which arises from the above) is that the
core of GDB no longer prevents concurrent displaced steps. Before this
patch, start_step_over walks the global step over chain and tries to
initiate a step over (whether it is in-line or displaced). It follows
these rules:
- if an in-line step is in progress (in any inferior), don't start any
other step over
- if a displaced step is in progress for an inferior, don't start
another displaced step for that inferior
After starting a displaced step for a given inferior, it won't start
another displaced step for that inferior.
In the new code, start_step_over simply tries to initiate step overs for
all the threads in the list. But because threads may be added back to
the global list as it iterates the global list, trying to initiate step
overs, start_step_over now starts by stealing the global queue into a
local queue and iterates on the local queue. In the typical case, each
thread will either:
- have initiated a displaced step and be resumed
- have been added back by the global step over queue by
displaced_step_prepare_throw, because the gdbarch will have returned
that there aren't enough resources (i.e. buffers) to initiate a
displaced step for that thread
Lastly, if start_step_over initiates an in-line step, it stops
iterating, and moves back whatever remaining threads it had in its local
step over queue to the global step over queue.
Two other gdbarch methods are added, to handle some slightly annoying
corner cases. They feel awkwardly specific to these cases, but I don't
see any way around them:
- gdbarch_displaced_step_copy_insn_closure_by_addr: in
arm_pc_is_thumb, arm-tdep.c wants to get the closure for a given
buffer address.
- gdbarch_displaced_step_restore_all_in_ptid: when a process forks
(at least on Linux), the address space is copied. If some displaced
step buffers were in use at the time of the fork, we need to restore
the original bytes in the child's address space.
These two adjustments are also made in infrun.c:
- prepare_for_detach: there may be multiple threads doing displaced
steps when we detach, so wait until all of them are done
- handle_inferior_event: when we handle a fork event for a given
thread, it's possible that other threads are doing a displaced step at
the same time. Make sure to restore the displaced step buffer
contents in the child for them.
[1] https://github.com/ROCm-Developer-Tools/ROCgdb
gdb/ChangeLog:
* displaced-stepping.h (struct
displaced_step_copy_insn_closure): Adjust comments.
(struct displaced_step_inferior_state) <step_thread,
step_gdbarch, step_closure, step_original, step_copy,
step_saved_copy>: Remove fields.
(struct displaced_step_thread_state): New.
(struct displaced_step_buffer): New.
* displaced-stepping.c (displaced_step_buffer::prepare): New.
(write_memory_ptid): Move from infrun.c.
(displaced_step_instruction_executed_successfully): New,
factored out of displaced_step_finish.
(displaced_step_buffer::finish): New.
(displaced_step_buffer::copy_insn_closure_by_addr): New.
(displaced_step_buffer::restore_in_ptid): New.
* gdbarch.sh (displaced_step_location): Remove.
(displaced_step_prepare, displaced_step_finish,
displaced_step_copy_insn_closure_by_addr,
displaced_step_restore_all_in_ptid): New.
* gdbarch.c: Re-generate.
* gdbarch.h: Re-generate.
* gdbthread.h (class thread_info) <displaced_step_state>: New
field.
(thread_step_over_chain_remove): New declaration.
(thread_step_over_chain_next): New declaration.
(thread_step_over_chain_length): New declaration.
* thread.c (thread_step_over_chain_remove): Make non-static.
(thread_step_over_chain_next): New.
(global_thread_step_over_chain_next): Use
thread_step_over_chain_next.
(thread_step_over_chain_length): New.
(global_thread_step_over_chain_enqueue): Add debug print.
(global_thread_step_over_chain_remove): Add debug print.
* infrun.h (get_displaced_step_copy_insn_closure_by_addr):
Remove.
* infrun.c (get_displaced_stepping_state): New.
(displaced_step_in_progress_any_inferior): Remove.
(displaced_step_in_progress_thread): Adjust.
(displaced_step_in_progress): Adjust.
(displaced_step_in_progress_any_thread): New.
(get_displaced_step_copy_insn_closure_by_addr): Remove.
(gdbarch_supports_displaced_stepping): Use
gdbarch_displaced_step_prepare_p.
(displaced_step_reset): Change parameter from inferior to
thread.
(displaced_step_prepare_throw): Implement using
gdbarch_displaced_step_prepare.
(write_memory_ptid): Move to displaced-step.c.
(displaced_step_restore): Remove.
(displaced_step_finish): Implement using
gdbarch_displaced_step_finish.
(start_step_over): Allow starting more than one displaced step.
(prepare_for_detach): Handle possibly multiple threads doing
displaced steps.
(handle_inferior_event): Handle possibility that fork event
happens while another thread displaced steps.
* linux-tdep.h (linux_displaced_step_prepare): New.
(linux_displaced_step_finish): New.
(linux_displaced_step_copy_insn_closure_by_addr): New.
(linux_displaced_step_restore_all_in_ptid): New.
(linux_init_abi): Add supports_displaced_step parameter.
* linux-tdep.c (struct linux_info) <disp_step_buf>: New field.
(linux_displaced_step_prepare): New.
(linux_displaced_step_finish): New.
(linux_displaced_step_copy_insn_closure_by_addr): New.
(linux_displaced_step_restore_all_in_ptid): New.
(linux_init_abi): Add supports_displaced_step parameter,
register displaced step methods if true.
(_initialize_linux_tdep): Register inferior_execd observer.
* amd64-linux-tdep.c (amd64_linux_init_abi_common): Add
supports_displaced_step parameter, adjust call to
linux_init_abi. Remove call to
set_gdbarch_displaced_step_location.
(amd64_linux_init_abi): Adjust call to
amd64_linux_init_abi_common.
(amd64_x32_linux_init_abi): Likewise.
* aarch64-linux-tdep.c (aarch64_linux_init_abi): Adjust call to
linux_init_abi. Remove call to
set_gdbarch_displaced_step_location.
* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
* i386-linux-tdep.c (i386_linux_init_abi): Likewise.
* alpha-linux-tdep.c (alpha_linux_init_abi): Adjust call to
linux_init_abi.
* arc-linux-tdep.c (arc_linux_init_osabi): Likewise.
* bfin-linux-tdep.c (bfin_linux_init_abi): Likewise.
* cris-linux-tdep.c (cris_linux_init_abi): Likewise.
* csky-linux-tdep.c (csky_linux_init_abi): Likewise.
* frv-linux-tdep.c (frv_linux_init_abi): Likewise.
* hppa-linux-tdep.c (hppa_linux_init_abi): Likewise.
* ia64-linux-tdep.c (ia64_linux_init_abi): Likewise.
* m32r-linux-tdep.c (m32r_linux_init_abi): Likewise.
* m68k-linux-tdep.c (m68k_linux_init_abi): Likewise.
* microblaze-linux-tdep.c (microblaze_linux_init_abi): Likewise.
* mips-linux-tdep.c (mips_linux_init_abi): Likewise.
* mn10300-linux-tdep.c (am33_linux_init_osabi): Likewise.
* nios2-linux-tdep.c (nios2_linux_init_abi): Likewise.
* or1k-linux-tdep.c (or1k_linux_init_abi): Likewise.
* riscv-linux-tdep.c (riscv_linux_init_abi): Likewise.
* s390-linux-tdep.c (s390_linux_init_abi_any): Likewise.
* sh-linux-tdep.c (sh_linux_init_abi): Likewise.
* sparc-linux-tdep.c (sparc32_linux_init_abi): Likewise.
* sparc64-linux-tdep.c (sparc64_linux_init_abi): Likewise.
* tic6x-linux-tdep.c (tic6x_uclinux_init_abi): Likewise.
* tilegx-linux-tdep.c (tilegx_linux_init_abi): Likewise.
* xtensa-linux-tdep.c (xtensa_linux_init_abi): Likewise.
* ppc-linux-tdep.c (ppc_linux_init_abi): Adjust call to
linux_init_abi. Remove call to
set_gdbarch_displaced_step_location.
* arm-tdep.c (arm_pc_is_thumb): Call
gdbarch_displaced_step_copy_insn_closure_by_addr instead of
get_displaced_step_copy_insn_closure_by_addr.
* rs6000-aix-tdep.c (rs6000_aix_init_osabi): Adjust calls to
clear gdbarch methods.
* rs6000-tdep.c (struct ppc_inferior_data): New structure.
(get_ppc_per_inferior): New function.
(ppc_displaced_step_prepare): New function.
(ppc_displaced_step_finish): New function.
(ppc_displaced_step_restore_all_in_ptid): New function.
(rs6000_gdbarch_init): Register new gdbarch methods.
* s390-tdep.c (s390_gdbarch_init): Don't call
set_gdbarch_displaced_step_location, set new gdbarch methods.
gdb/testsuite/ChangeLog:
* gdb.arch/amd64-disp-step-avx.exp: Adjust pattern.
* gdb.threads/forking-threads-plus-breakpoint.exp: Likewise.
* gdb.threads/non-stop-fair-events.exp: Likewise.
Change-Id: I387cd235a442d0620ec43608fd3dc0097fcbf8c8
|
|
Move displaced-stepping related stuff unchanged to displaced-stepping.h
and displaced-stepping.c. This helps make the following patch a bit
smaller and easier to read.
gdb/ChangeLog:
* Makefile.in (COMMON_SFILES): Add displaced-stepping.c.
* aarch64-tdep.h: Include displaced-stepping.h.
* displaced-stepping.h (struct displaced_step_copy_insn_closure):
Move here.
(displaced_step_copy_insn_closure_up): Move here.
(struct buf_displaced_step_copy_insn_closure): Move here.
(struct displaced_step_inferior_state): Move here.
(debug_displaced): Move here.
(displaced_debug_printf_1): Move here.
(displaced_debug_printf): Move here.
* displaced-stepping.c: New file.
* gdbarch.sh: Include displaced-stepping.h in gdbarch.h.
* gdbarch.h: Re-generate.
* inferior.h: Include displaced-stepping.h.
* infrun.h (debug_displaced): Move to displaced-stepping.h.
(displaced_debug_printf_1): Likewise.
(displaced_debug_printf): Likewise.
(struct displaced_step_copy_insn_closure): Likewise.
(displaced_step_copy_insn_closure_up): Likewise.
(struct buf_displaced_step_copy_insn_closure): Likewise.
(struct displaced_step_inferior_state): Likewise.
* infrun.c (show_debug_displaced): Move to displaced-stepping.c.
(displaced_debug_printf_1): Likewise.
(displaced_step_copy_insn_closure::~displaced_step_copy_insn_closure):
Likewise.
(_initialize_infrun): Don't register "set/show debug displaced".
Change-Id: I29935f5959b80425370630a45148fc06cd4227ca
|
|
Pass to get_linux_inferior_data the inferior for which we want to obtain
the linux-specific data, rather than assuming the current inferior.
This helps slightly reduce the diff in the upcoming main patch.
Update the sole caller to pass the current inferior.
gdb/ChangeLog:
* linux-tdep.c (get_linux_inferior_data): Add inferior
parameter.
(linux_vsyscall_range): Pass current inferior.
Change-Id: Ie4b61190e4a2e89b5b55a140cfecd4de66d92393
|
|
This is a preparatory patch to reduce the size of the diff of the
upcoming main patch. It introduces enum types for the return values of
displaced step "prepare" and "finish" operations. I find that this
expresses better the intention of the code, rather than returning
arbitrary integer values (-1, 0 and 1) which are difficult to remember.
That makes the code easier to read.
I put the new enum types in a new displaced-stepping.h file, because I
introduce that file in a later patch anyway. Putting it there avoids
having to move it later.
There is one change in behavior for displaced_step_finish: it currently
returns 0 if the thread wasn't doing a displaced step and 1 if the
thread was doing a displaced step which was executed successfully. It
turns out that this distinction is not needed by any caller, so I've
merged these two cases into "_OK", rather than adding an extra
enumerator.
gdb/ChangeLog:
* infrun.c (displaced_step_prepare_throw): Change return type to
displaced_step_prepare_status.
(displaced_step_prepare): Likewise.
(displaced_step_finish): Change return type to
displaced_step_finish_status.
(resume_1): Adjust.
(stop_all_threads): Adjust.
* displaced-stepping.h: New file.
Change-Id: I5c8fe07212cd398d5b486b5936d9d0807acd3788
|
|
This is a preparatory patch to reduce a little bit the diff size of the
main patch later in this series. It renames the displaced_step_fixup
function in infrun.c to displaced_step_finish.
The rationale is to better differentiate the low and high level
operations.
We first have the low level operation of writing an instruction to a
displaced buffer, called "copy_insn". The mirror low level operation to
fix up the state after having executed the instruction is "fixup". The
high level operation of preparing a thread for a displaced step (which
includes doing the "copy_insn" and some more bookkeeping) is called
"prepare" (as in displaced_step_prepare). The mirror high level
operation to cleaning up after a displaced step (which includes doing
the "fixup" and some more bookkeeping) is currently also called "fixup"
(as in displaced_step_fixup), just like the low level operation.
I think that choosing a different name for the low and high level
cleanup operation makes it clearer, hence "finish".
gdb/ChangeLog:
* infrun.c (displaced_step_fixup): Rename to...
(displaced_step_finish): ... this, update all callers.
Change-Id: Id32f48c1e2091d09854c77fcedcc14d2519957a2
|
|
Since we're going to introduce other "displaced step" functions and
another kind of displaced step closure, make it clear that this is the
return type of the gdbarch_displaced_step_copy_insn function.
gdb/ChangeLog:
* infrun.h (get_displaced_step_closure_by_addr): Rename to...
(get_displaced_step_copy_insn_closure_by_addr): ... this.
Update all users.
(displaced_step_closure): Rename to...
(displaced_step_copy_insn_closure): ... this. Update all users.
(displaced_step_closure_up): Rename to...
(displaced_step_copy_insn_closure_up). ... this. Update all
users.
(buf_displaced_step_closure): Rename to...
(buf_displaced_step_copy_insn_closure): ... this. Update all
users.
* infrun.c (get_displaced_step_closure_by_addr): Rename to...
(get_displaced_step_copy_insn_closure_by_addr): ... this.
Update all users.
* aarch64-tdep.c (aarch64_displaced_step_closure): Rename to...
(aarch64_displaced_step_copy_insn_closure): ... this. Update
all users.
* amd64-tdep.c (amd64_displaced_step_closure): Rename to...
(amd64_displaced_step_copy_insn_closure): ... this. Update all
users.
* arm-tdep.h (arm_displaced_step_closure): Rename to...
(arm_displaced_step_copy_insn_closure): ... this. Update all
users.
* i386-tdep.h (i386_displaced_step_closure): Rename to...
(i386_displaced_step_copy_insn_closure): ... this. Update all
users.
* rs6000-tdep.c (ppc_displaced_step_closure): Rename to...
(ppc_displaced_step_copy_insn_closure): ... this. Update all
users.
* s390-tdep.c (s390_displaced_step_closure): Rename to...
(s390_displaced_step_copy_insn_closure): ... this. Update all
users.
* gdbarch.h: Re-generate.
* gdbarch.c: Re-generate.
Change-Id: I11f56dbcd4c3532fb195a08ba93bccf1d12a03c8
|
|
Rename step_over_queue_head to global_thread_step_over_chain_head, to
make it more obvious when reading code that we are touching the global
queue. Rename all functions that operate on it to have "global" in
their name, to make it clear on which chain they operate on. Also, in a
subsequent patch, we'll need both global and non-global versions of
these functions, so it will be easier to do the distinction if they are
named properly.
Normalize the naming to use "chain" everywhere instead of sometimes
"queue", sometimes "chain".
I also reworded a few comments in gdbthread.h. They implied that the
step over chain is per-inferior, when in reality there is only one
global chain, not one per inferior, as far as I understand.
gdb/ChangeLog:
* gdbthread.h (thread_step_over_chain_enqueue): Rename to...
(global_thread_step_over_chain_enqueue): ... this. Update all
users.
(thread_step_over_chain_remove): Rename to...
(global_thread_step_over_chain_remove): ... this. Update all
users.
(thread_step_over_chain_next): Rename to...
(global_thread_step_over_chain_next): ... this. Update all
users.
* infrun.h (step_over_queue_head): Rename to...
(global_thread_step_over_chain_head): ... this. Update all
users.
* infrun.c (step_over_queue_head): Rename to...
(global_thread_step_over_chain_head): ... this. Update all
users.
* thread.c (step_over_chain_remove): Rename to...
(thread_step_over_chain_remove): ... this. Update all users.
(thread_step_over_chain_next): Rename to...
(global_thread_step_over_chain_next): ... this. Update all
users.
(thread_step_over_chain_enqueue): Rename to...
(global_thread_step_over_chain_enqueue): ... this. Update all
users.
(thread_step_over_chain_remove): Rename to...
(global_thread_step_over_chain_remove): ... this. Update all
users.
Change-Id: Iabbf57d83c01321ca199d83fadb57f5b04e4d6d9
|
|
Remove function get_displaced_stepping_state. When it was introduced,
inferiors' displaced stepping state was kept in a linked list in
infrun.c, so it was handy. Nowadays, the state is kept inside struct
inferior directly, so we can just access it directly instead.
gdb/ChangeLog:
* infrun.c (get_displaced_stepping_state): Remove, change
callers to access the field directly.
Change-Id: I9a733e32e29c7ebf856ab0befe1076bbb8c7af69
|
|
In handle_inferior_event, where we handle forks, we make sure to restore
the bytes of the displaced stepping buffer in the child's address
space. However, we only do it when the forking thread was the one
doing a displaced step. It could happen that a thread forks while
another one is doing a displaced step. In this case, we also need to
restore the bytes in the child.
Move the byte-restoring code outside of the condition that checks
whether the event thread was displaced stepping.
gdb/ChangeLog:
* infrun.c (handle_inferior_event): Restore displaced step
buffer bytes in child process when handling fork, even if fork
happened in another thread than the displaced-stepping one.
Change-Id: Ibb0daaeb123aba03f4fb4b4d820754eb2436bc69
|
|
When a process does an exec, all its program space is replaced with the
newly loaded executable. All non-main threads disappear and the main
thread starts executing at the entry point of the new executable.
Things can go wrong if a displaced step operation is in progress while
we process the exec event.
If the main thread is the one executing the displaced step: when that
thread (now executing in the new executable) stops somewhere (say, at a
breakpoint), displaced_step_fixup will run and clear up the state. We
will execute the "fixup" phase for the instruction we single-stepped in
the old program space. We are now in a completely different context,
so doing the fixup may corrupt the state.
If it is a non-main thread that is doing the displaced step: while
handling the exec event, GDB deletes the thread_info representing that
thread (since the thread doesn't exist in the inferior after the exec).
But inferior::displaced_step_state::step_thread will still point to it.
When handling events later, this condition, in displaced_step_fixup,
will likely never be true:
/* Was this event for the thread we displaced? */
if (displaced->step_thread != event_thread)
return 0;
... since displaced->step_thread points to a deleted thread (unless that
storage gets re-used for a new thread_info, but that wouldn't be good
either). This effectively makes the displaced stepping buffer occupied
for ever. When a thread in the new program space will want to do a
displaced step, it will wait for ever.
I think we simply need to reset the displaced stepping state of the
inferior on exec. Everything execution-related that existed before the
exec is now gone.
Similarly, if a thread does an in-line step over an exec syscall
instruction, nothing clears the in-line step over info when the event is
handled. So it the in-line step over info stays there indefinitely, and
things hang because we can never start another step over. To fix this,
I added a call to clear_step_over_info in infrun_inferior_execd.
Add a test with a program with two threads that does an exec. The test
includes the following axes:
- whether it's the leader thread or the other thread that does the exec.
- whether the exec'r and exec'd program have different text segment
addresses. This is to hopefully catch cases where the displaced
stepping info doesn't get reset, and GDB later tries to restore bytes
of the old address space in the new address space. If the mapped
addresses are different, we should get some memory error. This
happens without the patch applied:
$ ./gdb -q -nx --data-directory=data-directory testsuite/outputs/gdb.threads/step-over-exec/step-over-exec-execr-thread-leader-diff-text-segs-true -ex "b main" -ex r -ex "b my_execve_syscall if 0" -ex "set displaced-stepping on"
...
Breakpoint 1, main (argc=1, argv=0x7fffffffde38) at /home/simark/src/binutils-gdb/gdb/testsuite/gdb.threads/step-over-exec.c:69
69 argv0 = argv[0];
Breakpoint 2 at 0x60133a: file /home/simark/src/binutils-gdb/gdb/testsuite/lib/my-syscalls.S, line 34.
(gdb) c
Continuing.
[New Thread 0x7ffff7c62640 (LWP 1455423)]
Leader going in exec.
Exec-ing /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.threads/step-over-exec/step-over-exec-execr-thread-leader-diff-text-segs-true-execd
[Thread 0x7ffff7c62640 (LWP 1455423) exited]
process 1455418 is executing new program: /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.threads/step-over-exec/step-over-exec-execr-thread-leader-diff-text-segs-true-execd
Error in re-setting breakpoint 2: Function "my_execve_syscall" not defined.
No unwaited-for children left.
(gdb) n
Single stepping until exit from function _start,
which has no line number information.
Cannot access memory at address 0x6010d2
(gdb)
- Whether displaced stepping is allowed or not, so that we end up
testing both displaced stepping and in-line stepping on arches that do
support displaced stepping (otherwise, it just tests in-line stepping
twice I suppose)
To be able to precisely put a breakpoint on the syscall instruction, I
added a small assembly file (lib/my-syscalls.S) that contains minimal
Linux syscall wrappers. I prefer that to the strategy used in
gdb.base/step-over-syscall.exp, which is to stepi into the glibc wrapper
until we find something that looks like a syscall instruction, I find
that more predictable.
gdb/ChangeLog:
* infrun.c (infrun_inferior_execd): New function.
(_initialize_infrun): Attach inferior_execd observer.
gdb/testsuite/ChangeLog:
* gdb.threads/step-over-exec.exp: New.
* gdb.threads/step-over-exec.c: New.
* gdb.threads/step-over-exec-execd.c: New.
* lib/my-syscalls.S: New.
* lib/my-syscalls.h: New.
Change-Id: I1bbc8538e683f53af5b980091849086f4fec5ff9
|
|
I want to add another action (clearing displaced stepping state) that
happens when an inferior execs. I think it would be cleaner to have an
observer for this event, rather than have infrun know about each other
sub-component.
Replace the calls to solib_create_inferior_hook and
jit_inferior_created_hook in follow_exec by observers.
gdb/ChangeLog:
* observable.h (inferior_execd): Declare new observable.
* observable.c (inferior_execd): Declare new observable.
* infrun.c (follow_exec): Notify inferior_execd observer.
* jit.c (jit_inferior_created_hook): Make static.
(_initialize_jit): Register inferior_execd observer.
* jit.h (jit_inferior_created_hook): Remove declaration.
* solib.c (_initialize_solib): Register inferior_execd observer.
Change-Id: I000cce00094e23baa67df693d912646b6ae38e44
|
|
When building gdb with address sanitizer and running test-case
gdb.base/completion.exp, we run into:
...
==5743==ERROR: AddressSanitizer: heap-buffer-overflow on address \
0x60200025c02f at pc 0x000000cd9d64 bp 0x7fff3297da30 sp 0x7fff3297da28
READ of size 1 at 0x60200025c02f thread T0
#0 0xcd9d63 in completion_tracker::build_completion_result(char const*, \
int, int) gdb/completer.c:2258
...
0x60200025c02f is located 1 bytes to the left of 1-byte region \
[0x60200025c030,0x60200025c031)
...
This can be reproduced using just:
...
$ gdb
(gdb) p/d[TAB]
...
The problem is in this code in completion_tracker::build_completion_result:
...
bool completion_suppress_append
= (suppress_append_ws ()
|| match_list[0][strlen (match_list[0]) - 1] == ' ');
...
If strlen (match_list[0]) == 0, then we access match_list[0][-1].
Fix this by testing if the memory access is in bounds before doing the memory
access.
Tested on x86_64-linux.
gdb/ChangeLog:
2020-12-04 Tom de Vries <tdevries@suse.de>
PR gdb/27003
* completer.c (completion_tracker::build_completion_result): Don't
access match_list[0][-1].
|
|
I was inspired by this patch of Simon's:
https://sourceware.org/pipermail/gdb-patches/2020-November/173522.html
... to remove other typedefs that are no longer necessary now that gdb
uses C++.
I didn't remove absolutely every one -- I didn't touch the tdep files.
However, I removed many of them. In some cases, I removed an existing
different struct tag.
2020-12-04 Tom Tromey <tromey@adacore.com>
* linespec.c (struct linespec_token): Rename; remove typedef.
* guile/scm-block.c (struct block_smob): Remove typedef.
(struct block_syms_progress_smob): Likewise.
* guile/scm-symbol.c (struct symbol_smob): Remove typedef.
* guile/scm-symtab.c (symtab_smob): Remove typedef.
(struct sal_smob): Remove typedef.
* guile/scm-param.c (struct param_smob): Remove typedef.
* guile/scm-progspace.c (struct pspace_smob): Rename.
* guile/scm-objfile.c (struct objfile_smob): Rename.
* guile/scm-iterator.c (struct iterator_smob): Rename.
* guile/scm-frame.c (struct frame_smob): Rename.
* guile/scm-arch.c (struct arch_smob): Rename.
* guile/scm-type.c (struct field_smob): Remove typedef.
(struct type_smob): Rename.
* guile/scm-cmd.c (struct command_smob): Remove typedef.
* guile/scm-ports.c (struct ioscm_memory_port): Remove typedef.
* guile/scm-value.c (struct value_smob): Remove typedef.
* guile/scm-lazy-string.c (lazy_string_smob): Remove typedef.
* guile/guile-internal.h (struct scheme_variable)
(struct scheme_function, struct scheme_integer_constant)
(struct gdb_smob, struct chained_gdb_smob)
(struct eqable_gdb_smob, arch_smob, frame_smob, iterator_smob)
(objfile_smob, pspace_smob, type_smob): Remove typedef.
* guile/scm-pretty-print.c (pretty_printer_smob): Remove typedef.
(struct pretty_printer_worker_smob): Remove typedef.
* guile/scm-exception.c (struct exception_smob): Remove typedef.
* python/py-block.c (struct block_object): Remove typedef.
(block_syms_iterator_object): Update.
(set_block): Update.
(block_syms_iterator_object): Remove typedef.
* python/py-inferior.c (struct membuf_object): Remove typedef.
* python/py-symtab.c (struct symtab_object): Remove typedef.
(set_symtab): Update.
(sal_object): Remove typedef.
(set_sal): Update.
* python/py-frame.c (frame_object): Remove typedef.
* python/py-record-btrace.c (struct btpy_list_object): Remove
typedef.
* python/py-arch.c (struct arch_object): Remove typedef.
* python/py-linetable.c (struct linetable_entry_object)
(linetable_object, struct ltpy_iterator_object): Remove typedef.
* python/py-events.h (eventregistry_object): Remove typedef.
(struct events_object): Remove typedef.
* python/python-internal.h (gdbpy_breakpoint_object): Remove
typedef.
(thread_object): Remove typedef.
* python/py-progspace.c (pspace_object): Remove typedef.
* python/py-value.c (struct value_object): Remove typedef.
* python/py-record.h (recpy_record_object): Remove typedef.
(struct recpy_element_object): Remove typedef.
* python/py-lazy-string.c (lazy_string_object): Remove typedef.
* python/py-objfile.c (objfile_object): Remove typedef.
* python/py-cmd.c (struct cmdpy_object): Remove typedef.
* python/py-type.c (type_object): Remove typedef.
(typy_iterator_object): Update.
(set_type): Update.
(field_object): Remove typedef.
(typy_iterator_object): Remove typedef.
* python/py-registers.c (register_descriptor_iterator_object):
Remove typedef.
(struct register_descriptor_object)
(struct reggroup_iterator_object, struct reggroup_object): Remove
typedef.
* python/py-record.c (recpy_gap_object): Remove typedef.
* python/py-symbol.c (symbol_object): Remove typedef.
(set_symbol): Update.
* python/py-event.h (event_object): Remove typedef.
* python/py-param.c (parmpy_object): Remove typedef.
* python/py-instruction.c (struct py_insn_obj): Remove typedef.
* python/py-unwind.c (struct pending_frame_object): Remove typedef.
(unwind_info_object, struct cached_frame_info): Likewise.
|
|
When using the single-element form of argument to declare_labels, the
generated label (in the assembly file) is of the format ".LlabelN",
where N is a number.
I propose making it use the name of the label by default. Calling:
declare_labels foo
will generate the ".LfooN" in the assembly file (again, where N is a
number). When debugging the output of the DWARF assembler, it makes it
easier to map labels to the source. Also, when defining the same label
twice by mistake in the Tcl code (like I d id), it's easier to track the
error from the message to the root cause:
-/home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/implptrpiece/implptrpiece-dw.S:62: Error: symbol `.Llabel5' is already defined
+/home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.dwarf2/implptrpiece/implptrpiece-dw.S:62: Error: symbol `.Lvar_label5' is already defined
This doesn't change anything for the test cases, it just makes the
assembly output a bit nicer.
gdb/testsuite/ChangeLog:
* lib/dwarf.exp (declare_labels): Use name as text if text is
not provided.
Change-Id: I63856c1fa6390498fd5b9d66f471f817ff0a465c
|
|
Add GDBvn.texi and version.subst to the release tar file,
so the gdb.info does not need makeinfo.
This avoids the need for makeinfo to be available.
2020-12-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.in: Delete GDBvn.texi and version.subst only in
the maintainer-clean target.
|
|
This is just an update in the gdb/ChangeLog to reflect a newly
created PR [27015] for a bugfix commit:
10c19fad arc: Write correct "eret" value during register collection
|
|
I noticed that value_internal_function_name should have a const return
type. This patch makes this change.
gdb/ChangeLog
2020-12-04 Tom Tromey <tromey@adacore.com>
* value.c (value_internal_function_name): Make return type const.
* value.h (value_internal_function_name): Make return type const.
|
|
When UBSan is enabled, I noticed runtime errors complaining of shifting
of negative numbers.
This patch fixes this by reusing existing macros from the ARM port.
It also removes unused macros from AArch64's port.
gdb/ChangeLog:
2020-12-04 Luis Machado <luis.machado@linaro.org>
* aarch64-tdep.c (submask, bit, bits): Remove.
* arch/aarch64-insn.c (extract_signed_bitfield): Remove.
(aarch64_decode_adr, aarch64_decode_b aarch64_decode_bcond)
(aarch64_decode_cb, aarch64_decode_tb)
(aarch64_decode_ldr_literal): Use sbits to extract a signed
immediate.
* arch/aarch64-insn.h (submask, bits, bit, sbits): New macros.
|
|
With target board unix/-m32 I run into:
...
(gdb) print /x $fs_base^M
$1 = void^M
(gdb) FAIL: gdb.arch/amd64-gs_base.exp: print fs_base
...
The problem is that the fs_base register is not supported for i386.
Fix this by making the test unsupported if fs_base/gs_base don't show up in
info register sys output.
Tested on x86_64-linux.
gdb/testsuite/ChangeLog:
2020-12-04 Tom de Vries <tdevries@suse.de>
PR testsuite/26990
* gdb.arch/amd64-gs_base.exp: Handle -m32 where fs_base and gs_base
are unsupported.
|
|
When running test-case on gdb.cp/many-args.exp with target board unix/-m32, I
run into:
...
(gdb) p check_val (ref_val, ref_val, ... , ref_val, ref_val)^M
$1 = false^M
(gdb) FAIL: gdb.cp/many-args.exp: check passing many structures
...
The test source contains struct ss:
...
typedef int v4si __attribute__ ((vector_size (16)));
struct ss
{
static v4si static_field;
unsigned char aa;
};
...
and i386_16_byte_align_p returns true for this type.
Fix this by skipping static fields in i386_16_byte_align_p.
Tested on x86_64-linux.
gdb/ChangeLog:
2020-12-04 Tom de Vries <tdevries@suse.de>
PR tdep/27007
* i386-tdep.c (i386_16_byte_align_p): Skip static fields.
|
|
In gdb.reverse/insn-reverse.exp, we have loop containing a call to
gdb_test_multiple, which itself contains a break:
...
for {} {$count < 500} {incr count} {
...
gdb_test_multiple "x/i \$pc" "" {
...
break
}
...
On SLE-11 with:
...
$ runtest --version
Expect version is 5.44.1.11
Tcl version is 8.5
Framework version is 1.4.4
...
the break doesn't seem to have the effect of breaking out of the loop.
The break does have the effect of terminating evaluation of the expect clause,
which means we don't set insn_array, after which we run into:
...
ERROR: tcl error sourcing src/gdb/testsuite/gdb.reverse/insn-reverse.exp.
ERROR: can't read "insn_array(5)": no such element in array
...
gdb/testsuite/ChangeLog:
2020-12-04 Tom de Vries <tdevries@suse.de>
* gdb.reverse/insn-reverse.exp: Don't break inside gdb_test_multiple
clause.
|
|
Consider the test-case gdb.reverse/insn-reverse.exp.
After the loop setting count, the valid entries in various arrays range from 0
to $count - 1 inclusive.
Then $count is decremented:
...
incr count -1
...
after which the valid entries range from 0 to $count inclusive.
The first subsequent loop handles that properly:
...
for {set i $count} {$i >= 0} {incr i -1} {
...
but the following loop does not, because it treats $count as exclusive bound:
...
for {set i 0} {$i < $count} {incr i} {
...
Fix this by removing the incr, and using $count - 1 as starting value in the
first loop.
gdb/testsuite/ChangeLog:
2020-12-04 Tom de Vries <tdevries@suse.de>
* gdb.reverse/insn-reverse.exp: Fix count handling.
|
|
When running test-case gdb.reverse/insn-reverse.exp with target board
unix/-m32, we get:
...
spawn -ignore SIGHUP gcc -fno-stack-protector -fdiagnostics-color=never \
-c -g -m32 -o insn-reverse0.o insn-reverse.c^M
insn-reverse-x86.c: Assembler messages:^M
insn-reverse-x86.c:88: Error: bad register name `%r8w'^M
....
Fix this by guarding x86_64 assembly in insn-reverse-x86.c with #ifdef
__x86_64__.
Tested on x86_64-linux, with native and unix/-m32.
gdb/testsuite/ChangeLog:
2020-12-04 Tom de Vries <tdevries@suse.de>
* gdb.reverse/insn-reverse-x86.c: Guard x86_64 assembly with #ifdef
__x86_64__.
|
|
Consider test-case gdb.reverse/insn-reverse.exp.
It runs a number of subtests, dependent on the architecture, f.i. for
x86_64 it runs subtests rdrand and rdseed.
For each subtest, it checks whether the subtest is supported and otherwise
bails out of that subtest.
However, there may be a problem with the support test or the information it
relies on, and if it states that a subtest is supported while it is actually
not, we may run into a SIGILL, as f.i. described in PR21166, which results in
tcl errors like this:
...
ERROR: tcl error sourcing src/gdb/testsuite/gdb.reverse/insn-reverse.exp.
ERROR: can't read "insn_array(5)": no such element in array
...
We can emulate this by inserting a sigfpe in function rdrand in
insn-reverse-x86.c, like this:
...
volatile int a = 0; volatile int b = 1; volatile int c = b / a;
...
The problem is that the loop in the test-case attempts to stepi over of all
insn in rdrand, but because of the signal it will never get to the last insn.
Handle this by detecting that the stepi made no progress, and bailing out of
the loop.
Furthermore, make running of the subtests independent, such that a SIGILL in
subtest rdrand does not affect running of subtest rdseed.
Tested on x86_64-linux.
gdb/testsuite/ChangeLog:
2020-12-04 Tom de Vries <tdevries@suse.de>
* gdb.reverse/insn-reverse.c (test_nr): New var.
(usage, parse_args): New function.
(main): Call parse_args. Only run test for test_nr.
* gdb.reverse/insn-reverse.exp: Detect lack of progress in stepi loop
and bail out. Run subtests individually, using an inferior arg
specifying the subtest.
|
|
The logic in find_comp_unit and set_comp_unit is reversed. When the BFD
requires relocation, we want to put the comp_unit structure in the
map where the comp_unit objects are not shared, that is the one indexed
by objfile. If the BFD does not require relocation, then, we can share
a single comp_unit structure for all users of that BFD, so we want to
put it in the BFD-indexed map. The comments on top of
dwarf2_frame_bfd_data and dwarf2_frame_objfile_data make that clear.
Fix it by swapping the two in find_comp_unit and set_comp_unit.
I don't have a test for this, because I don't see how to write one in a
reasonable amount of time.
gdb/ChangeLog:
PR gdb/26876
* dwarf2/frame.c (find_comp_unit, set_comp_unit): Reverse use of
dwarf2_frame_bfd_data and dwarf2_frame_objfile_data.
Change-Id: I80c1ee7ad8425fa4947de65b170973d05f5a52ec
|
|
This commit started as adding rv32e support to gdb. The rv32e
architecture is a cut-down rv32i, it only has 16 x-registers compared
to the usual 32, and an rv32e target should not have any floating
point registers.
In order to add this I needed to adjust the target description
validation checks that are performed from riscv_gdbarch_init, and I
finally got fed up with the current scheme of doing these checks and
rewrote this code.
Unfortunately the rv32e changes are currently mixed in with the
rewrite of the validation scheme. I could split these apart if anyone
is really interested in seeing these two ideas as separate patches.
The main idea behind this change is that where previously I tried to
have a purely data driven approach, a set of tables one for each
expected feature, and then a single generic function that would
validate a feature given a table, I have created a new class for each
feature. Each class has its own check member function which allows
the logic for how to check each feature to be different. I think the
new scheme is much easier to follow.
There are some other changes that I made to the validation code as
part of this commit.
I've relaxed some of the checks related to the floating point CSRs.
Previously the 3 CSRs fflags, frm, and fcsr all had to be present in
either the fpu feature or the csr feature. This requirement is now
relaxed, if the CSRs are not present then gdb will not reject the
target description. My thinking here is that there's no gdb
functionality that specifically requires these registers, and so, if a
target offers a description without these registers nothing else in
gdb should stop working.
And as part of the rv32e support targets now only have to provide the
first 16 x-registers and $pc. The second half of the x-registers (x16
-> x31) are now optional.
gdb/ChangeLog:
* arch/riscv.c: Include 'rv32e-xregs.c'.
(riscv_create_target_description): Update to handle rv32e.
* arch/riscv.h (struct riscv_gdbarch_features) <embedded>: New
member variable.
<operator==>: Update to account for new field.
<hash>: Likewise.
* features/Makefile (FEATURE_XMLFILES): Add riscv/rv32e-xregs.xml.
* features/riscv/rv32e-xregs.c: Generated.
* features/riscv/rv32e-xregs.xml: New file.
* riscv-tdep.c (riscv_debug_breakpoints): Move from later in the
file.
(riscv_debug_infcall): Likewise.
(riscv_debug_unwinder): Likewise.
(riscv_debug_gdbarch): Likewise.
(enum riscv_register_required_status): Delete.
(struct riscv_register_feature): Add constructor, delete default
constructor, copy, and assign constructors.
(struct riscv_register_feature::register_info) <required>: Delete.
<check>: Update comment and arguments.
(struct riscv_register_feature) <name>: Change to member function.
<prefer_first_name>: Delete.
<tdesc_feature>: New member function.
<registers>: Rename to...
<m_registers>: ...this.
<m_feature_name>: New member variable.
(riscv_register_feature::register_info::check): Update arguments.
(riscv_xreg_feature): Rewrite as class, create a single static
instance of the class.
(riscv_freg_feature): Likewise.
(riscv_virtual_feature): Likewise.
(riscv_csr_feature): Likewise.
(riscv_create_csr_aliases): Has become a member function inside
riscv_csr_feature class.
(riscv_abi_embedded): New function definition.
(riscv_register_name): Adjust to use new feature objects.
(struct riscv_call_info) <riscv_call_info>: Check for rv32e abi,
and adjust available argument registers.
(riscv_features_from_gdbarch_info): Check for EF_RISCV_RVE flag.
(riscv_check_tdesc_feature): Delete.
(riscv_tdesc_unknown_reg): Adjust to use new feature objects.
(riscv_gdbarch_init): Delete target description checking code, and
instead call to the new feature objects to perform the checks.
Reorder handling of no abi information case, allows small code
simplification.
(_initialize_riscv_tdep): Remove call, this is now done in the
riscv_csr_feature constructor.
* riscv-tdep.h (riscv_abi_embedded): Declare.
|
|
In this commit:
commit 767a879e31ce31179e6135c2f991f670a35709fa
Date: Tue Jun 9 17:38:30 2020 +0100
gdb/riscv: Improved register alias name creation
RISC-V GDB was changed to make use of the DECLARE_CSR_ALIAS macro to
define register aliases for some CSRs. Actually, only one alias was
created 'dscratch' as an alias for 'dscratch0'. All of the other
DECLARE_CSR_ALIAS lines (from include/opcode/riscv-opc.h) were
filtered out.
In this commit:
commit 08ccfccf0ed825be9be2972594d4be4a2207ef13
Date: Mon Jun 8 10:54:53 2020 +0800
RISC-V: Support debug and float CSR as the unprivileged ones.
Changes were made to include/opcode/riscv-opc.h so that GDB no longer
created even the dscratch alias.
This caused a test failure in gdb.arch/riscv-tdesc-regs.exp.
In looking at how to address this failure I think that the best
strategy is, for now at least, to just remove the code that tries to
create aliases with DECLARE_CSR_ALIAS.
My thoughts are that:
1. At least some of the aliases are for CSRs where the register now
has a completely different use. Being able to reference the CSR
using a completely inappropriate name just seems confusing. This
was solved by the filtering added in the first commit referenced
above. But we certainly don't want to blindly add all aliases.
2. Names presented in a target description are always honoured, so
if a user has a legacy target then they should just start sending a
target description with their legacy register names in, this problem
is then solved.
3. It's easy enough to figure out which CSRs a target has with the
info registers command, so missing an alias shouldn't be a big
issue.
4. Allowing users to use names for registers that differ from the
names the target announces doesn't feel like a critical feature. If
in the future targets want multiple names for a register then maybe
we could/should extend target descriptions to allow the target to
send aliases as well as the primary name.... but that can wait for
another day.
So in this commit I remove the use of DECLARE_CSR_ALIAS, and remove
the test that was failing.
gdb/ChangeLog:
* riscv-tdep.c (riscv_create_csr_aliases): Remove use of
DECLARE_CSR_ALIAS.
gdb/testsuite/ChangeLog:
* gdb.arch/riscv-tdesc-regs.exp: Remove unwanted test.
|
|
Unknown riscv CSRs should not be in the 'general' group, but should be
in the system and csr register groups.
To see this in action connect to QEMU, this target advertises two
registers dscratch and mucounteren which are unknown to GDB (these are
legacy CSRs). Before this commit these registers would show up in the
output of:
(gdb) info registers
....
dscratch Could not fetch register "dscratch"; remote failure reply 'E14'
mucounteren Could not fetch register "mucounteren"; remote failure reply 'E14'
Ignore the errors, this is just a QEMU annoyance, it advertises these
CSRs, but doesn't actually let GDB read them. These registers don't
show up in the output of either:
(gdb) info registers csr
(gdb) info registers system
After this commit this situation is reveresed, which makes more sense
to me.
gdb/ChangeLog:
* riscv-tdep.c (riscv_is_unknown_csr): New function,
implementation moved from riscv_register_reggroup_p.
(riscv_register_reggroup_p): Update group handling for unknown
CSRs.
gdb/testsuite/ChangeLog:
* gdb.arch/riscv-tdesc-regs.exp (get_expected_result): New proc,
update test to use this.
|
|
When Debian (and Ubuntu) builds its binaries, it (still) doesn't use
dwz's "--relative" option. This causes their debuginfo files to
carry a .gnu_debugaltlink section containing a full pathname to the
DWZ alt debug file, like this:
$ readelf -wk /usr/bin/cat
Contents of the .gnu_debugaltlink section:
Separate debug info file: /usr/lib/debug/.dwz/x86_64-linux-gnu/coreutils.debug
Build-ID (0x14 bytes):
ee 76 5d 71 97 37 ce 46 99 44 32 bb e8 a9 1a ef 99 96 88 db
Contents of the .gnu_debuglink section:
Separate debug info file: 06d3bee37b8c7e67b31cb2689cb351102ae73b.debug
CRC value: 0x53267655
This usually works OK, because most of the debuginfo files installed
via apt will be present in /usr/lib/debug anyway. However, imagine
the following scenario:
- You are using /usr/bin/cat, it crashes on you and generates a
corefile.
- You don't want/need to "apt install" the debuginfo file for
coreutils from the repositories. Instead, you already have the
debuginfo files in a separate directory (e.g., $HOME/dbgsym).
- You start GDB and "set debug-file-directory $HOME/dbgsym/usr/lib/debug".
You then get the following message:
$ gdb -ex 'set debug-file-directory ./dbgsym/usr/lib/debug' -ex 'file /bin/cat' -ex 'core-file ./cat.core'
GNU gdb (Ubuntu 10.1-0ubuntu1) 10.1
...
Reading symbols from /bin/cat...
Reading symbols from /home/sergio/gdb/dbgsym/usr/lib/debug/.build-id/bc/06d3bee37b8c7e67b31cb2689cb351102ae73b.debug...
could not find '.gnu_debugaltlink' file for /home/sergio/gdb/dbgsym/usr/lib/debug/.build-id/bc/06d3bee37b8c7e67b31cb2689cb351102ae73b.debug
This error happens because GDB is trying to locate the build-id
link (inside /home/sergio/gdb/dbgsym/usr/lib/debug/.build-id) for the
DWZ alt debug file, which doesn't exist. Arguably, this is a problem
with how dh_dwz works in Debian, and it's something I'm also planning
to tackle. But, back at the problem at hand.
Besides not being able to find the build-id link in the directory
mentioned above, GDB also tried to open the DWZ alt file using its
filename. The problem here is that, since we don't have the distro's
debuginfo installed, it can't find anything under /usr/lib/debug that
satisfies it.
It occurred to me that a good way to workaround this problem is to
actually try to locate the DWZ alt debug file inside the
debug-file-directories (that were likely provided by the user). So
this is what the proposed patch does.
The idea here is simple: get the filename extracted from the
.gnu_debugaltlink section, and manipulate it in order to replace the
initial part of the path (everything before "/.dwz/") by whatever
debug-file-directories the user might have provided.
I talked with Mark Wielaard and he agrees this is a sensible approach.
In fact, apparently this is something that eu-readelf also does.
I regtested this code, and no regressions were found.
2020-12-01 Sergio Durigan Junior <sergiodj@sergiodj.net>
* dwarf2/read.c (dwz_search_other_debugdirs): New function.
(dwarf2_get_dwz_file): Convert 'filename' to a
std::string. Use dwz_search_other_debugdirs to search for DWZ
files in the debug-file-directories provided by the user as well.
|
|
In another series I'm working on, it is necessary to manage
"struct expression" with new and delete. Because the patch is
straightforward and could be extracted, I've done so here.
gdb/ChangeLog
2020-12-01 Tom Tromey <tom@tromey.com>
* parse.c (expr_builder::expr_builder): Initialize expout.
(expr_builder::release): Use expression::resize.
(expression::expression, expression::~expression)
(expression::resize): New methods.
(write_exp_elt): Use expression::resize.
(prefixify_expression): Update.
(increase_expout_size): Use expression::resize.
* expression.h (struct expression): Add constructor, destructor.
<resize>: New method.
(expression_up): Change type.
|
|
gdb/testsuite/ChangeLog:
* gdb.threads/non-ldr-exc-1.exp: Fix indentation.
Change-Id: I02ba8a518aae9cb67106d09bef92968a7078e91e
|
|
Replace the manual with_test_prefix in the do_test proc with using
foreach_with_prefix at the top-level. This helps reduce the indentation
level of the code a bit, and makes the test names in sync with the
variable names used in the code.
gdb/testsuite/ChangeLog:
* gdb.threads/non-ldr-exc-1.exp: Use foreach_with_prefix.
(do_test): Don't use with_test_prefix.
* gdb.threads/non-ldr-exc-2.exp: Use foreach_with_prefix.
(do_test): Don't use with_test_prefix.
* gdb.threads/non-ldr-exc-3.exp: Use foreach_with_prefix.
(do_test): Don't use with_test_prefix.
* gdb.threads/non-ldr-exc-4.exp: Use foreach_with_prefix.
(do_test): Don't use with_test_prefix.
Change-Id: I3af1df2eee1a8add427a67b6048bb6dede41cbeb
|
|
Power 10 introduces the 2nd DAWR (second watchpoint) and also removed
a restriction that limit the watch region to 512 bytes.
2020-11-08 Rogerio A. Cardoso <rcardoso@linux.ibm.com>
/gdb
* ppc-linux-nat.c: (PPC_DEBUG_FEATURE_DATA_BP_ARCH_31): New define.
(region_ok_for_hw_watchpoint): Check if 2nd DAWR is avaliable before
set region.
|
|
|
|
Maybe there's something I don't understand in that test, but the comment
seems wrong. It checks what happens when the non-leader thread does an
exit, not the leader.
gdb/testsuite/ChangeLog:
* gdb.threads/non-ldr-exit.exp: Fix comment.
Change-Id: I35c96a70c097fa9529737874f54f3f78036008a4
|
|
Currently when printing an XML description GDB prints enum values like
this:
<enum id="levels_type" size="4">
<field name="low" start="0"/>
<field name="high" start="1"/>
</enum>
This is incorrect, and is most likely a copy and paste error with the
struct and flags printing code. The correct syntax is:
<enum id="levels_type" size="4">
<evalue name="low" value="0"/>
<evalue name="high" value="1"/>
</enum>
A test is included to cover this functionality.
gdb/testsuite/ChangeLog:
* gdb.xml/maint-xml-dump-03.xml: New file.
gdbsupport/ChangeLog:
* tdesc.cc (print_xml_feature::visit): Print enum fields using
'evalue' syntax.
|
|
Revert empty commits:
- "[gdb] Don't return non-existing path in debuginfod_source_query"
commit 59404f827cb1134b68dbf228d380ff86d15c9f01
- "[gdb/testsuite] Fix minimal encodings KPASSes"
commit 61049d1ee59905589b2ad3f8140a2582e01add7a
|
|
Consider test-case gdb.base/vla-optimized-out.exp, compiled using clang-10.
GDB fails to get the size of the vla a:
...
(gdb) p sizeof (a)^M
Cannot access memory at address 0x6^M
(gdb) FAIL: gdb.base/vla-optimized-out.exp: o1: printed size of \
optimized out vla
...
The relevant DWARF looks like this: the variable a:
...
<2><12b>: Abbrev Number: 5 (DW_TAG_variable)
<12c> DW_AT_name : a
<132> DW_AT_type : <0x189>
...
has type:
...
<1><189>: Abbrev Number: 10 (DW_TAG_array_type)
<18a> DW_AT_type : <0x198>
<2><18e>: Abbrev Number: 11 (DW_TAG_subrange_type)
<18f> DW_AT_type : <0x19f>
<193> DW_AT_count : <0x117>
...
with the count attribute equated to the value of this artificial variable:
...
<2><117>: Abbrev Number: 4 (DW_TAG_variable)
<118> DW_AT_location : 10 byte block: 75 1 10 ff ff ff ff f 1a 9f \
(DW_OP_breg5 (rdi): 1;
DW_OP_constu: 4294967295;
DW_OP_and;
DW_OP_stack_value)
<123> DW_AT_name : __vla_expr0
<127> DW_AT_type : <0x182>
<12b> DW_AT_artificial : 1
...
The location description of the variable is terminated with DW_OP_stack_value,
which according to the DWARF spec means that "the DWARF expression represents
the actual value of the object, rather than its location".
However, in attr_to_dynamic_prop, we set is_reference to true:
...
baton->locexpr.is_reference = true;
...
and use it in dwarf2_evaluate_property to dereference the value of the DWARF
expression, which causes the access to memory at address 0x6.
Fix this by ignoring the baton->locexpr.is_reference == true setting if
the expression evaluation has ctx.location == DWARF_VALUE_STACK, such that we
get:
...
(gdb) p sizeof (a)^M
$2 = 6^M
(gdb) PASS: gdb.base/vla-optimized-out.exp: o1: printed size of \
optimized out vla
...
Tested on x86_64-linux, with gcc.
Tested the following test-cases (the ones mentioned in PR26905) on
x86_64-linux with clang-10:
- gdb.base/vla-optimized-out.exp
- gdb.base/vla-ptr.exp
- gdb.mi/mi-vla-c99
gdb/ChangeLog:
2020-11-30 Tom de Vries <tdevries@suse.de>
PR symtab/26905
* dwarf2/loc.c (dwarf2_locexpr_baton_eval): Add and handle
is_reference parameter.
(dwarf2_evaluate_property): Update dwarf2_locexpr_baton_eval call.
gdb/testsuite/ChangeLog:
2020-11-30 Tom de Vries <tdevries@suse.de>
PR symtab/26905
* gdb.dwarf2/count.exp: Remove kfails.
|
|
With current master I see a couple of KPASSes:
...
KPASS: gdb.ada/enum_idx_packed.exp: scenario=minimal: ptype small \
(PRMS minimal encodings)
...
KPASS: gdb.ada/mod_from_name.exp: scenario=minimal: print xp \
(PRMS minimal encodings)
KPASS: gdb.ada/pckd_arr_ren.exp: scenario=minimal: print var \
(PRMS minimal encodings)
...
The corresponding setup_kfail is called for everything before gnat 11.
However, the test-cases also PASS for me with gnat-4.8, gnat-7.5.0 and
gnat-8.4.0.
Fix the KPASSes by limiting the setup_kfail to gnat 9 and 10.
Tested on x86_64-linux.
gdb/testsuite/ChangeLog:
2020-11-16 Tom de Vries <tdevries@suse.de>
* gdb.ada/enum_idx_packed.exp: Limit setup_kfail to gnat 9 and 10.
* gdb.ada/mod_from_name.exp: Same.
* gdb.ada/pckd_arr_ren.exp: Same.
|
|
When setting env var DEBUGINFOD_URLS to " " and running the testsuite, we run
into these regressions:
...
FAIL: gdb.base/list-missing-source.exp: info source
FAIL: gdb.base/source-dir.exp: info source before setting directory search list
...
Setting var DEBUGINFOD_URLS to " " allows the debuginfod query function
debuginfod_source_query to get past its early exit.
The function debuginfod_source_query is documented as: "If the file is
successfully retrieved, its path on the local machine is stored in DESTNAME".
However, in case we get back -ENOENT from libdebuginfod, we still set
DESTNAME:
....
if (fd.get () < 0 && fd.get () != -ENOENT)
printf_filtered (_("Download failed: %s. Continuing without source file %ps.\n"),
safe_strerror (-fd.get ()),
styled_string (file_name_style.style (), srcpath));
else
*destname = make_unique_xstrdup (srcpath);
return fd;
...
Fix this by making debuginfod_source_query fit it's documentation and only
setting DESTNAME when successfully retrieving a file. Likewise in
debuginfod_debuginfo_query.
gdb/ChangeLog:
2020-11-16 Tom de Vries <tdevries@suse.de>
* debuginfod-support.c (debuginfod_source_query)
(debuginfod_debuginfo_query): Only set DESTNAME if successful.
|
|
enum exp_opcode is created from all the .def files, but then each
language is required to implement its own op_name function to turn an
enum value to a string. This seemed over-complicated to me, and this
patch removes the per-language functions in favor of simply using the
.def names for all languages. Note that op_name is only used for
dumping expressions, which is a maintainer/debug feature.
Furthermore, I don't think there was any case where the .def name and
the string name differed.
gdb/ChangeLog
2020-11-30 Tom Tromey <tom@tromey.com>
* rust-lang.c (rust_op_name): Remove.
(exp_descriptor_rust): Update.
* parser-defs.h (op_name_standard): Don't declare.
(struct exp_descriptor) <op_name>: Remove.
* parse.c (exp_descriptor_standard): Update.
* opencl-lang.c (exp_descriptor_opencl): Update.
* m2-lang.c (m2_language::exp_descriptor_modula2): Update.
* f-lang.c (op_name_f): Remove.
(f_language::exp_descriptor_tab): Update.
* expression.h (op_name): Update.
* expprint.c (op_name): Rewrite.
(op_name_standard): Remove.
(dump_raw_expression, dump_subexp): Update.
* c-lang.c (exp_descriptor_c): Update.
* ax-gdb.c (gen_expr): Update.
* ada-lang.c (ada_op_name): Remove.
(ada_exp_descriptor): Update.
|
|
I noticed that in the OP_ARRAY case in evaluate_subexp_standard,
"index_pc" is read but never set. This dead code then guards the only
call to init_array_element, so this can be removed as well.
gdb/ChangeLog
2020-11-30 Tom Tromey <tom@tromey.com>
* eval.c (init_array_element): Remove.
(evaluate_subexp_standard) <OP_ARRAY>: Remove "index_pc".
|
|
The argument is called static_members, not static_fields.
gdb/doc/ChangeLog:
2020-11-29 Hannes Domani <ssbssa@yahoo.de>
PR python/26974
* python.texi: Fix docu for static members argument.
|
|
The locator win info is special because it is static, all the others are
created dynamically.
gdb/ChangeLog:
2020-11-29 Hannes Domani <ssbssa@yahoo.de>
PR tui/26973
* tui/tui-layout.c (tui_apply_current_layout): Don't delete the
static locator win info.
|
|
-Werror=implicit-function-declaration
I am getting
I'm sorry, Dave, I can't do that. Symbol format `elf64-littleriscv' unknown.
errors after updating from GDB 8.3 to 10. Bisecting showed that since
commit 1ff6de031241 ("bfd, ld: add CTF section linking"), bfd.h depends
on strncmp() being present, so configuring with
-Werror=implicit-function-declaration results in the check for ELF
support in BFD failing:
.../gdb/gdb/../bfd/elf-bfd.h: In function 'bfd_section_is_ctf':
.../gdb/gdb/../bfd/elf-bfd.h:3086:10: error: implicit declaration of function 'strncmp' [-Werror=implicit-function-declaration]
return strncmp (name, ".ctf", 4) == 0 && (name[4] == 0 || name[4] == '.');
gdb/ChangeLog:
* acincludde.m4 (GDB_AC_CHECK_BFD): Include string.h in the test
program.
Change-Id: Iec5e21d454c2a544c44d65e23cfde552c424c18e
|
|
In commit:
commit 037d7135de575c9e0c20e9158c105979bfee339c
Date: Mon Nov 16 11:36:56 2020 +0000
gdb: improve command completion for 'print', 'x', and 'display'
A potential use of an uninitialised variable was introduced. This is
fixed in this commit.
Previously when analysing /FMT strings for tab completion we
considered two possibilities, either the user has typed '/', or the
user has typed '/' followed by an alpha-numeric character, as these
are the only valid FMT string characters.
This meant that if the user type, for example '/@' and then tried to
tab complete gdb would use an uninitialised variable.
Currently only the first character after the '/' is checked to see if
it is alpha-numeric, so if a user typed '/x@@' then gdb would be happy
to treat this as a FMT string.
Given the goal of this change was primarily to allow tab completion of
symbols later in the command when a /FMT was used then I decided to
just make the /FMT skipping less smart. Now any characters after the
'/' up to the first white space, will be treated as a FMT string.
gdb/ChangeLog:
* printcmd.c (skip_over_slash_fmt): Reorder code to ensure in_fmt
is always initialized.
|
|
gdb/Changelog
2020-11-26 Rogerio Alves <rcardoso@linux.ibm.com>
* MAINTAINERS (Write After Approval): Add myself.
|