aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbarch_components.py
AgeCommit message (Collapse)AuthorFilesLines
2023-04-21Handle erroneous DW_AT_call_return_pcTom Tromey1-0/+17
On PPC64, with the test case included in an earlier patch, we found that "finish" would still not correctly find the return value via entry values. The issue is simple. The compiler emits: 0x00000000100032b8 <+28>: bl 0x1000320c <pck__create_large> 0x00000000100032bc <+32>: nop 0x00000000100032c0 <+36>: li r9,42 ... but the DWARF says: <162a> DW_AT_call_return_pc: 0x100032c0 That is, the declared return PC is one instruction past the actual return PC. This patch adds a new arch hook to handle this scenario, and implements it for PPC64. Some care is taken so that GDB will continue to work if this compiler bug is fixed. A GCC patch is here: https://gcc.gnu.org/pipermail/gcc-patches/2023-March/613336.html No check for 'nop' is done, as subsequent discussion revealed that the linker might replace this with another instruction.
2023-04-18gdb: re-format Python code with black 23Simon Marchi1-2/+5
Change-Id: I849d10d69c254342bf01e955ffe62a2b60f9de4b
2023-04-18PowerPC: fix _Float128 type output stringCarl Love1-0/+23
PowerPC supports two 128-bit floating point formats, the IBM long double and IEEE 128-bit float. The issue is the DWARF information does not distinguish between the two. There have been proposals of how to extend the DWARF information as discussed in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104194 but has not been fully implemented. GCC introduced the _Float128 internal type as a work around for the issue. The workaround is not transparent to GDB. The internal _Float128 type name is printed rather then the user specified long double type. This patch adds a new gdbarch method to allow PowerPC to detect the GCC workaround. The workaround checks for "_Float128" name when reading the base typedef from the die_info. If the workaround is detected, the type and format fields from the _Float128 typedef are copied to the long double typedef. The same is done for the complex long double typedef. This patch fixes 74 regression test failures in gdb.base/whatis-ptype-typedefs.exp on PowerPC with IEEE float 128 as the default on GCC. It fixes one regression test failure in gdb.base/complex-parts.exp. The patch has been tested on Power 10 where GCC defaults to IEEE Float 128-bit and on Power 10 where GCC defaults to the IBM 128-bit float. The patch as also been tested on X86-64 with no new regression failures.
2023-04-06gdb: run black code formatter on gdbarch_components.pyAndrew Burgess1-1/+1
The following commit changed gdbarch_components.py but failed to format it with black: commit cf141dd8ccd36efe833aae3ccdb060b517cc1112 Date: Wed Feb 22 12:15:34 2023 +0000 gdb: fix reg corruption from displaced stepping on amd64 This commit just runs black on the file and commits the result. The change is just the addition of an extra "," -- there will be no change to the generated source files after this commit. There will be no user visible changes after this commit.
2023-04-06gdb: fix reg corruption from displaced stepping on amd64Andrew Burgess1-6/+16
This commit aims to address a problem that exists with the current approach to displaced stepping, and was identified in PR gdb/22921. Displaced stepping is currently supported on AArch64, ARM, amd64, i386, rs6000 (ppc), and s390. Of these, I believe there is a problem with the current approach which will impact amd64 and ARM, and can lead to random register corruption when the inferior makes use of asynchronous signals and GDB is using displaced stepping. The problem can be found in displaced_step_buffers::finish in displaced-stepping.c, and is this; after GDB tries to perform a displaced step, and the inferior stops, GDB classifies the stop into one of two states, either the displaced step succeeded, or the displaced step failed. If the displaced step succeeded then gdbarch_displaced_step_fixup is called, which has the job of fixing up the state of the current inferior as if the step had not been performed in a displaced manner. This all seems just fine. However, if the displaced step is considered to have not completed then GDB doesn't call gdbarch_displaced_step_fixup, instead GDB remains in displaced_step_buffers::finish and just performs a minimal fixup which involves adjusting the program counter back to its original value. The problem here is that for amd64 and ARM setting up for a displaced step can involve changing the values in some temporary registers. If the displaced step succeeds then this is fine; after the step the temporary registers are restored to their original values in the architecture specific code. But if the displaced step does not succeed then the temporary registers are never restored, and they retain their modified values. In this context a temporary register is simply any register that is not otherwise used by the instruction being stepped that the architecture specific code considers safe to borrow for the lifetime of the instruction being stepped. In the bug PR gdb/22921, the amd64 instruction being stepped is an rip-relative instruction like this: jmp *0x2fe2(%rip) When we displaced step this instruction we borrow a register, and modify the instruction to something like: jmp *0x2fe2(%rcx) with %rcx having its value adjusted to contain the original %rip value. Now if the displaced step does not succeed, then %rcx will be left with a corrupted value. Obviously corrupting any register is bad; in the bug report this problem was spotted because %rcx is used as a function argument register. And finally, why might a displaced step not succeed? Asynchronous signals provides one reason. GDB sets up for the displaced step and, at that precise moment, the OS delivers a signal (SIGALRM in the bug report), the signal stops the inferior at the address of the displaced instruction. GDB cancels the displaced instruction, handles the signal, and then tries again with the displaced step. But it is that first cancellation of the displaced step that causes the problem; in that case GDB (correctly) sees the displaced step as having not completed, and so does not perform the architecture specific fixup, leaving the register corrupted. The reason why I think AArch64, rs600, i386, and s390 are not effected by this problem is that I don't believe these architectures make use of any temporary registers, so when a displaced step is not completed successfully, the minimal fix up is sufficient. On amd64 we use at most one temporary register. On ARM, looking at arm_displaced_step_copy_insn_closure, we could modify up to 16 temporary registers, and the instruction being displaced stepped could be expanded to multiple replacement instructions, which increases the chances of this bug triggering. This commit only aims to address the issue on amd64 for now, though I believe that the approach I'm proposing here might be applicable for ARM too. What I propose is that we always call gdbarch_displaced_step_fixup. We will now pass an extra argument to gdbarch_displaced_step_fixup, this a boolean that indicates whether GDB thinks the displaced step completed successfully or not. When this flag is false this indicates that the displaced step halted for some "other" reason. On ARM GDB can potentially read the inferior's program counter in order figure out how far through the sequence of replacement instructions we got, and from that GDB can figure out what fixup needs to be performed. On targets like amd64 the problem is slightly easier as displaced stepping only uses a single replacement instruction. If the displaced step didn't complete the GDB knows that the single instruction didn't execute. The point is that by always calling gdbarch_displaced_step_fixup, each architecture can now ensure that the inferior state is fixed up correctly in all cases, not just the success case. On amd64 this ensures that we always restore the temporary register value, and so bug PR gdb/22921 is resolved. In order to move all architectures to this new API, I have moved the minimal roll-back version of the code inside the architecture specific fixup functions for AArch64, rs600, s390, and ARM. For all of these except ARM I think this is good enough, as no temporaries are used all that's needed is the program counter restore anyway. For ARM the minimal code is no worse than what we had before, though I do consider this architecture's displaced-stepping broken. I've updated the gdb.arch/amd64-disp-step.exp test to cover the 'jmpq*' instruction that was causing problems in the original bug, and also added support for testing the displaced step in the presence of asynchronous signal delivery. I've also added two new tests (for amd64 and i386) that check that GDB can correctly handle displaced stepping over a single instruction that branches to itself. I added these tests after a first version of this patch relied too much on checking the program-counter value in order to see if the displaced instruction had executed. This works fine in almost all cases, but when an instruction branches to itself a pure program counter check is not sufficient. The new tests expose this problem. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=22921 Approved-By: Pedro Alves <pedro@palves.net>
2023-03-27displaced step: pass down target_waitstatus instead of gdb_signalPedro Alves1-1/+1
This commit tweaks displaced_step_finish & friends to pass down a target_waitstatus instead of a gdb_signal. This is needed because a patch later in the step-over-{thread-exit,clone] series will want to make displaced_step_buffers::finish handle TARGET_WAITKIND_THREAD_EXITED. It also helps with the TARGET_WAITKIND_THREAD_CLONED patch later in that same series. It's also a bit more logical this way, as we don't have to pass down signals when the thread didn't actually stop for a signal. So we can also think of it as a clean up. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=27338 Change-Id: I4c5d338647b028071bc498c4e47063795a2db4c0 Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-03-22gdb: remove gdbarch_displaced_step_fixup_pAndrew Burgess1-1/+2
The comment on the gdbarch_displaced_step_fixup gdbarch method indicates that this method is optional and that GDB will perform some default if this method is not supplied. As such we define a predicate gdbarch_displaced_step_fixup_p. It may have been true at one point that the fixup method was optional, but it is no longer true. If this method is not defined and GDB tries to complete a displaced step, then GDB is going to crash. Additionally the gdbarch_displaced_step_fixup_p predicate is not used anywhere in GDB. In this commit I have removed the gdbarch_displaced_step_fixup_p predicate, and I have updated the validation check for the gdbarch_displaced_step_fixup method; if the gdbarch_displaced_step_copy_insn method is defined then the fixup method must also be defined. I believe I've manually checked all the current places where gdbarch_displaced_step_copy_insn is defined and they all also define the fixup method, so this change should cause no problems for anyone. There should be no user visible changes after this commit. Approved-By: Pedro Alves <pedro@palves.net>
2023-03-13gdb: add gdbarch::displaced_step_buffer_lengthAndrew Burgess1-2/+16
The gdbarch::max_insn_length field is used mostly to support displaced stepping; it controls the size of the buffers allocated for the displaced-step instruction, and is also used when first copying the instruction, and later, when fixing up the instruction, in order to read in and parse the instruction being stepped. However, it has started to be used in other places in GDB, for example, it's used in the Python disassembler API, and it is used on amd64 as part of branch-tracing instruction classification. The problem is that the value assigned to max_insn_length is not always the maximum instruction length, but sometimes is a multiple of that length, as required to support displaced stepping, see rs600, ARM, and AArch64 for examples of this. It seems to me that we are overloading the meaning of the max_insn_length field, and I think that could potentially lead to confusion. I propose that we add a new gdbarch field, gdbarch::displaced_step_buffer_length, this new field will do exactly what it says on the tin; represent the required displaced step buffer size. The max_insn_length field can then do exactly what it claims to do; represent the maximum length of a single instruction. As some architectures (e.g. i386, and amd64) only require their displaced step buffers to be a single instruction in size, I propose that the default for displaced_step_buffer_length will be the value of max_insn_length. Architectures than need more buffer space can then override this default as needed. I've updated all architectures to setup the new field if appropriate, and I've audited all calls to gdbarch_max_insn_length and switched to gdbarch_displaced_step_buffer_length where appropriate. There should be no user visible changes after this commit. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-03-13gdbarch: make invalid=True the default for all ComponentsAndrew Burgess1-12/+15
This commit switches the default value for the 'invalid' field from False to True. All components that previous set the invalid field to True explicitly have had the field removed. I think that True is a good choice for the default, this means that we now get the validity checks by default, and if anyone adds a new Component they need to make a choice to add an 'invalid=False' line and disable the validation. The flip side of this is that 'invalid=False' seems to be far more common than 'invalid=True'. But I don't see a huge problem with this, we shouldn't be aiming to reduce our typing, rather we should choose based on which is least likely to introduce bugs. I think assuming that we should do a validity check will achieve that. Some additional components need to have an 'invalid=False' line added to their definition, these are components that have a predefault value, which is sufficient; the tdep code doesn't need to replace this value if it doesn't want to. Without adding the 'invalid=False' these components would be considered to be invalid if they have not changed from their predefault value -- but the predefault is fine. There's no change in the generated code after this commit, so there will be no user visible changes after this commit. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-03-13gdbarch: remove some unneeded predefault="0" from gdbarch_components.pyAndrew Burgess1-21/+1
I noticed that there are a bunch of 'predefault="0"' lines in gdbarch_components.py, and that some (just some, not all) of these are not needed. The gdbarch is already zero initialized, but these lines seem to exists so that we can know when to compare against "0" and when to compare against "NULL". At least, this seems to be useful in some places in the generated code. Specifically, if we remove the predefault="0" line from the max_insn_length component then we end up generating a line like: gdb_assert (gdbarch->max_insn_length != NULL); which doesn't compile as we compare a ULONGEST to NULL. In this commit I remove all the predefault="0" lines that I claim are obviously not needed. These are lines for components that are not Values (i.e. the component holds a function pointer anyway), or for Value components that hold a pointer type, in which case using NULL is fine. The only changes after this commit are some fields that have nullptr as their initial value, and gcore_bfd_target now compares to NULL not 0 in gdbarch_gcore_bfd_target_p, which, given the field is of type 'const char *', seems like an improvement. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-03-13gdbarch: use predefault for more value components within gdbarchAndrew Burgess1-6/+6
For some reason the following value components of gdbarch: bfloat16_format half_format float_format double_format long_double_format so_ops All use a postdefault but no predefault to set the default value for the component. As the postdefault values for these components are all constant pointers that don't depend on other fields within the gdbarch, then I don't see any reason why we couldn't use a predefault instead. So lets do that. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-03-13gdb/gdbarch: remove the 'invalid=None' state from gdbarch_components.pyAndrew Burgess1-0/+2
This commit ensures that the 'invalid' property of all components is either True, False, or a string. Additionally, this commit allows a component to have both a predicate and for the 'invalid' property to be a string. Removing the option for 'invalid' to be None allows us to simplify the algorithms in gdbarch.py a little. Allowing a component to have both a predicate and an 'invalid' string means that we can validate the value that a tdep sets into a field, but also allow a predicate to ensure that the field has changed from the default. This functionality isn't going to be used in this series, but I have tested it locally and believe that it would work, and this might make it easier for others to add new components in the future. In gdbarch_types.py, I've updated the type annotations to show that the 'invalid' field should not be None, and I've changed the default for this field from None to False. The change to using False as the default is temporary. Later in this series I'm going to change the default to True, but we need more fixes before that can be done. Additionally, in gdbarch_types.py I've removed an assert from Component.get_predicate. This assert ensured that we didn't have the predicate field set to True and the invalid field set to a string. However, no component currently uses this configuration, and after this commit, that combination is now supported, so the assert can be removed. As a consequence of the gdbarch_types.py changes we see some additional comments generated in gdbarch.c about verification being skipped due to the invalid field being False. This comment is inline with plenty of other getters that also have a similar comment. Plenty of the getters do have validation, so I think it is reasonable to have a comment noting that the validation has been skipped for a specific reason, rather than due to some bug. In gdbarch_components.py I've had to add 'invalid=True' for two components: gcore_bfd_target and max_insn_length, without this the validation in the gdbarch getter would disappear. And in gdbarch.py I've reworked the logic for generating the verify_gdbarch function, and for generating the getter functions. The logic for generating the getter functions is still not ideal, I ended up having to add this additional logic block: elif c.postdefault is not None and c.predefault is not None: print(" /* Check variable changed from pre-default. */", file=f) print(f" gdb_assert (gdbarch->{c.name} != {c.predefault});", file=f) which was needed to ensure we continued to generate the same code as before, without this the fact that invalid is now False when it would previously have been None, meant that we dropped the gdb_assert in favour of a comment like: print(f" /* Skip verify of {c.name}, invalid_p == 0 */", file=f) which is clearly not a good change. We could potentially look at improving this in a later commit, but I don't plan to do that in this series. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-03-13gdb/gdbarch: split postdefault setup from invalid check in gdbarch.pyAndrew Burgess1-23/+17
Restructure how gdbarch.py generates the verify_gdbarch function. Previously the postdefault handling was bundled together with the validation. This means that a field can't have both a postdefault, and set its invalid attribute to a string. This doesn't seem reasonable to me, I see no reason why a field can't have both a postdefault (used when the tdep doesn't set the field), and an invalid expression, which can be used to validate the value that a tdep might set. In this commit I restructure the verify_gdbarch generation code to allow the above, there is no change in the actual generated code in this commit, that will come in later commit. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-03-13gdb/gdbarch: remove yet more 'invalid=True' from gdbarch_components.pyAndrew Burgess1-9/+0
Following on from the previous commit, this commit removes yet more 'invalid=True' lines from gdbarch_components.py where the invalid setting has no effect. Due to the algorithm used in gdbarch.py for generated verify_gdbarch, if a component has a postdefault value then no invalid check will ever be generated for the component, as such setting 'invalid=True' on the component is pointless. This commit removes the setting of invalid. There is no change in the generated code after this commit. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-03-13gdb/gdbarch: remove unused 'invalid=True' from gdbarch_components.pyAndrew Burgess1-64/+0
Due to the algorithm used to generate verify_gdbarch in gdbarch.py, if a component has a predicate, then a validation check will never be generated. There are a bunch of components that are declared with both a predicate AND have 'invalid=True' set. The 'invalid=True' has no effect. In this commit I clean things up by removing all these additional 'invalid=True' lines. There's no change in any of the generated files after this commit. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-02-27gdb: gdbarch*.py, copyright.py: add type annotationsSimon Marchi1-2/+3
Add type annotations to gdbarch*.py to fix all errors shown by pyright. There is one change in copyright.py too, to fix this one: /home/simark/src/binutils-gdb/gdb/gdbarch.py /home/simark/src/binutils-gdb/gdb/gdbarch.py:206:13 - error: Type of "copyright" is partially unknown Type of "copyright" is "(tool: Unknown, description: Unknown) -> str" (reportUnknownMemberType) Change-Id: Ia109b53e267f6e2f5bd79a1288d0d5c9508c9ac4 Reviewed-By: Tom Tromey <tom@tromey.com> Reviewed-By: Andrew Burgess <aburgess@redhat.com>
2023-02-27gdb: split gdbarch component types to gdbarch_types.pySimon Marchi1-0/+2748
Editing gdbarch-components.py is not an experience in an editor that is minimally smart about Python. Because gdbarch-components.py is read and exec'd by gdbarch.py, it doesn't import the Info / Method / Function / Value types. And because these types are defined in gdbarch.py, it can't import them, as that would make a cyclic dependency. Solve this by introducing a third file, gdbarch_types.py, to define these types. Make gdbarch.py and gdbarch-components.py import it. Also, replace the read & exec of gdbarch-components.py by a regular import. For this to work though, gdbarch-components.py needs to be renamed to gdbarch_components.py. Change-Id: Ibe994d56ef9efcc0698b3ca9670d4d9bf8bbb853 Reviewed-By: Tom Tromey <tom@tromey.com> Reviewed-By: Andrew Burgess <aburgess@redhat.com>