aboutsummaryrefslogtreecommitdiff
path: root/gdb/value.c
AgeCommit message (Collapse)AuthorFilesLines
40 hoursMark unavailable bytes of limited-length arrays when allocating contentsHannes Domani1-4/+5
Using 'output' to print arrays larger than max-value-size, with only repeating elements, can cause gdb to crash: ``` $ cat a.c: char a[1000000]; int main() { return a[0]; } $ gdb -q a (gdb) print a $1 = {0 '\000' <repeats 65536 times>, <unavailable> <repeats 934464 times>} (gdb) output a This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. ``` Using 'print' works, because value::record_latest sets the unavailable bytes of the value when it's added to the value history. But 'outout' doesn't do that, so the printing tries to access more bytes than are available. The original problem in PR32015 was about using 'print' of a dynamic array in a D program. Here the crash happens because for 'print' the value was a struct with length/ptr fields, which is converted in d-valprint.c into an array. So value::record_latest didn't have a chance to mark the unavailable bytes in this case. To make sure the unavailable bytes always match the contents, this fixes it by marking the unavailable bytes immediately after the contents are allocated. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32015 Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
2024-07-24[gdb/exp] Fix ptype $_creal/$_cimagTom de Vries1-2/+7
Consider test.c, compiled with -g: ... __complex__ float cf = 1 + 2i; int main (void) { return 0; } ... The values of cf and its components are: ... $ gdb -q a.out Reading symbols from a.out... (gdb) p cf $1 = 1 + 2i (gdb) p $_creal(cf) $2 = 1 (gdb) p $_cimag(cf) $3 = 2 ... and their respective types are: ... (gdb) ptype $1 type = complex float (gdb) ptype $2 type = float (gdb) ptype $3 type = float ... Now let's try that again, using ptype directly: ... (gdb) ptype cf type = complex float (gdb) ptype $_creal(cf) type = int (gdb) ptype $_cimag(cf) type = int ... The last two types should have been float, not int. Fix this by extending the internal function handlers creal_internal_fn and cimag_internal_fn with the noside parameter, such that we get instead: ... (gdb) ptype $_creal(cf) type = float (gdb) ptype $_cimag(cf) type = float ... Tested on x86_64-linux. Reviewed-By: Keith Seitz <keiths@redhat.com> PR exp/31816 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31816
2024-07-24[gdb/exp] Allow internal function to indicate return typeTom de Vries1-8/+67
Currently an internal function handler has this prototype: ... struct value *handler (struct gdbarch *gdbarch, const struct language_defn *language, void *cookie, int argc, struct value **argv); ... Also allow an internal function with a handler with an additional "enum noside noside" parameter: ... struct value *handler (struct gdbarch *gdbarch, const struct language_defn *language, void *cookie, int argc, struct value **argv, enum noside noside); ... In case such a handler is called with noside == EVAL_AVOID_SIDE_EFFECTS, it's expected to return some value with the correct return type. At least, provided it can do so without side effects, otherwise it should throw an error. No functional changes. Tested on x86_64-linux and aarch64-linux. Reviewed-By: Keith Seitz <keiths@redhat.com>
2024-04-25gdb: remove gdbcmd.hSimon Marchi1-1/+1
Most files including gdbcmd.h currently rely on it to access things actually declared in cli/cli-cmds.h (setlist, showlist, etc). To make things easy, replace all includes of gdbcmd.h with includes of cli/cli-cmds.h. This might lead to some unused includes of cli/cli-cmds.h, but it's harmless, and much faster than going through the 170 or so files by hand. Change-Id: I11f884d4d616c12c05f395c98bbc2892950fb00f Approved-By: Tom Tromey <tom@tromey.com>
2024-04-22gdb: move store/extract integer functions to extract-store-integer.{c,h}Simon Marchi1-0/+1
Move the declarations out of defs.h, and the implementations out of findvar.c. I opted for a new file, because this functionality of converting integers to bytes and vice-versa seems a bit to generic to live in findvar.c. Change-Id: I524858fca33901ee2150c582bac16042148d2251 Approved-By: John Baldwin <jhb@FreeBSD.org>
2024-03-26gdb, gdbserver, gdbsupport: remove includes of early headersSimon Marchi1-1/+0
Now that defs.h, server.h and common-defs.h are included via the `-include` option, it is no longer necessary for source files to include them. Remove all the inclusions of these files I could find. Update the generation scripts where relevant. Change-Id: Ia026cff269c1b7ae7386dd3619bc9bb6a5332837 Approved-By: Pedro Alves <pedro@palves.net>
2024-03-19[gdb] Further fix "value is not available" with debug frameTom de Vries1-8/+15
In commit 2aaba744467 ("[gdb] Fix "value is not available" with debug frame") I fixed a case in frame_unwind_register_value where using "set debug frame on" caused an "info frame" command to abort, reporting a "value is not available" error, due to the tpidruro register being unavailable. Subsequently, commit bbb12eb9c84 ("gdb/arm: Remove tpidruro register from non-FreeBSD target descriptions") removed the unavailable register, which caused a progression on test-case gdb.base/inline-frame-cycle-unwind.exp. While investigating the progression (see PR python/31437), I found that the "debug frame" output of the test-case (when reverting commit bbb12eb9c84) showed a smilar problem: ... Python Exception <class 'gdb.error'>: value is not available^M ... that was absent without "debug frame". Fix this likewise in fetch_lazy_register, and update the test-case to check for the exception. Furthermore, I realized that there's both value::entirely_available and value::entirely_unavailable, and that commit 2aaba744467 handled the case of !entirely_available by printing unavailable. Instead, print: - "unavailable" for entirely_unavailable, and - "partly unavailable" for !entirely_unavailable && !entirely_available. Tested on x86_64-linux and arm-linux.
2024-02-27Change finalize_values into a final cleanupTom Tromey1-7/+8
This removes finalize_values in favor of adding a new final cleanup. This is safe now that extension languages are explicitly shut down.
2024-02-20gdb: pass frames as `const frame_info_ptr &`Simon Marchi1-11/+12
We currently pass frames to function by value, as `frame_info_ptr`. This is somewhat expensive: - the size of `frame_info_ptr` is 64 bytes, which is a bit big to pass by value - the constructors and destructor link/unlink the object in the global `frame_info_ptr::frame_list` list. This is an `intrusive_list`, so it's not so bad: it's just assigning a few points, there's no memory allocation as if it was `std::list`, but still it's useless to do that over and over. As suggested by Tom Tromey, change many function signatures to accept `const frame_info_ptr &` instead of `frame_info_ptr`. Some functions reassign their `frame_info_ptr` parameter, like: void the_func (frame_info_ptr frame) { for (; frame != nullptr; frame = get_prev_frame (frame)) { ... } } I wondered what to do about them, do I leave them as-is or change them (and need to introduce a separate local variable that can be re-assigned). I opted for the later for consistency. It might not be clear why some functions take `const frame_info_ptr &` while others take `frame_info_ptr`. Also, if a function took a `frame_info_ptr` because it did re-assign its parameter, I doubt that we would think to change it to `const frame_info_ptr &` should the implementation change such that it doesn't need to take `frame_info_ptr` anymore. It seems better to have a simple rule and apply it everywhere. Change-Id: I59d10addef687d157f82ccf4d54f5dde9a963fd0 Approved-By: Andrew Burgess <aburgess@redhat.com>
2024-02-19[gdb/exp] Fix printing of out of bounds struct membersTom de Vries1-0/+3
When building gdb with -O0 -fsanitize=address, and running test-case gdb.ada/uninitialized_vars.exp, I run into: ... (gdb) info locals a = 0 z = (a => 1, b => false, c => 2.0) ================================================================= ==66372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000097f58 at pc 0xffff52c0da1c bp 0xffffc90a1d40 sp 0xffffc90a1d80 READ of size 4 at 0x602000097f58 thread T0 #0 0xffff52c0da18 in memmove (/lib64/libasan.so.8+0x6da18) #1 0xbcab24 in unsigned char* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<unsigned char const, unsigned char>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:748 #2 0xbc9bf4 in unsigned char* std::__copy_move_backward_a2<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:769 #3 0xbc898c in unsigned char* std::__copy_move_backward_a1<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:778 #4 0xbc715c in unsigned char* std::__copy_move_backward_a<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:807 #5 0xbc4e6c in unsigned char* std::copy_backward<unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:867 #6 0xbc2934 in void gdb::copy<unsigned char const, unsigned char>(gdb::array_view<unsigned char const>, gdb::array_view<unsigned char>) gdb/../gdbsupport/array-view.h:223 #7 0x20e0100 in value::contents_copy_raw(value*, long, long, long) gdb/value.c:1239 #8 0x20e9830 in value::primitive_field(long, int, type*) gdb/value.c:3078 #9 0x20e98f8 in value_field(value*, int) gdb/value.c:3095 #10 0xcafd64 in print_field_values gdb/ada-valprint.c:658 #11 0xcb0fa0 in ada_val_print_struct_union gdb/ada-valprint.c:857 #12 0xcb1bb4 in ada_value_print_inner(value*, ui_file*, int, value_print_options const*) gdb/ada-valprint.c:1042 #13 0xc66e04 in ada_language::value_print_inner(value*, ui_file*, int, value_print_options const*) const (/home/vries/gdb/build/gdb/gdb+0xc66e04) #14 0x20ca1e8 in common_val_print(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1092 #15 0x20caabc in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1184 #16 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355 #17 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308 #18 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305 #19 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299 #20 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289 #21 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240 #22 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259 #23 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380 #24 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458 #25 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95 #26 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 #27 0x1f03790 in execute_command(char const*, int) gdb/top.c:575 #28 0x1384080 in command_handler(char const*) gdb/event-top.c:566 #29 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802 #30 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104 #31 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259 #32 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290 #33 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 #34 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 #35 0x1fe9b40 in stdin_event_handler gdb/ui.c:155 #36 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573 #37 0x35ff9d8 in gdb_wait_for_event gdbsupport/event-loop.cc:694 #38 0x35fd284 in gdb_do_one_event(int) gdbsupport/event-loop.cc:264 #39 0x1768080 in start_event_loop gdb/main.c:408 #40 0x17684c4 in captured_command_loop gdb/main.c:472 #41 0x176cfc8 in captured_main gdb/main.c:1342 #42 0x176d088 in gdb_main(captured_main_args*) gdb/main.c:1361 #43 0xb73edc in main gdb/gdb.c:39 #44 0xffff519b09d8 in __libc_start_call_main (/lib64/libc.so.6+0x309d8) #45 0xffff519b0aac in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x30aac) #46 0xb73c2c in _start (/home/vries/gdb/build/gdb/gdb+0xb73c2c) 0x602000097f58 is located 0 bytes after 8-byte region [0x602000097f50,0x602000097f58) allocated by thread T0 here: #0 0xffff52c65218 in calloc (/lib64/libasan.so.8+0xc5218) #1 0xcbc278 in xcalloc gdb/alloc.c:97 #2 0x35f21e8 in xzalloc(unsigned long) gdbsupport/common-utils.cc:29 #3 0x20de270 in value::allocate_contents(bool) gdb/value.c:937 #4 0x20edc08 in value::fetch_lazy() gdb/value.c:4033 #5 0x20dadc0 in value::entirely_covered_by_range_vector(std::vector<range, std::allocator<range> > const&) gdb/value.c:229 #6 0xcb2298 in value::entirely_optimized_out() gdb/value.h:560 #7 0x20ca6fc in value_check_printable gdb/valprint.c:1133 #8 0x20caa8c in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1182 #9 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355 #10 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308 #11 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305 #12 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299 #13 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289 #14 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240 #15 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259 #16 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380 #17 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458 #18 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95 #19 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 #20 0x1f03790 in execute_command(char const*, int) gdb/top.c:575 #21 0x1384080 in command_handler(char const*) gdb/event-top.c:566 #22 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802 #23 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104 #24 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259 #25 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290 #26 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 #27 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 #28 0x1fe9b40 in stdin_event_handler gdb/ui.c:155 #29 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573 SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib64/libasan.so.8+0x6da18) in memmove ... The error happens when trying to print either variable y or y2: ... type Variable_Record (A : Boolean := True) is record case A is when True => B : Integer; when False => C : Float; D : Integer; end case; end record; Y : Variable_Record := (A => True, B => 1); Y2 : Variable_Record := (A => False, C => 1.0, D => 2); ... when the variables are uninitialized. The error happens only when printing the entire variable: ... (gdb) p y.a $2 = 216 (gdb) p y.b There is no member named b. (gdb) p y.c $3 = 9.18340949e-41 (gdb) p y.d $4 = 1 (gdb) p y <AddressSanitizer: heap-buffer-overflow> ... The error happens as follows: - field a functions as discriminant, choosing either the b, or c+d variant. - when y.a happens to be set to 216, as above, gdb interprets this as the variable having the c+d variant (which is why trying to print y.b fails). - when printing y, gdb allocates a value, copies the bytes into it from the target, and then prints the value. - gdb allocates the value using the type size, which is 8. It's 8 because that's what the DW_AT_byte_size indicates. Note that for valid values of a, it gives correct results: if a is 0 (c+d variant), size is 12, if a is 1 (b variant), size is 8. - gdb tries to print field d, which is at an 8 byte offset, and that results in a out-of-bounds access for the allocated 8-byte value. Fix this by handling this case in value::contents_copy_raw, such that we have: ... (gdb) p y $1 = (a => 24, c => 9.18340949e-41, d => <error reading variable: access outside bounds of object>) ... An alternative (additional) fix could be this: in compute_variant_fields_inner gdb reads the discriminant y.a to decide which variant is active. It would be nice to detect that the value (y.a == 24) is not a valid Boolean, and give up on choosing a variant altoghether. However, the situation regarding the internal type CODE_TYPE_BOOL is currently ambiguous (see PR31282) and it's not possible to reliably decide what valid values are. The test-case source file gdb.ada/uninitialized-variable-record/parse.adb is a reduced version of gdb.ada/uninitialized_vars/parse.adb, so it copies the copyright years. Note that the test-case needs gcc-12 or newer, it's unsupported for older gcc versions. [ So, it would be nice to rewrite it into a dwarf assembly test-case. ] The test-case loops over all languages. This is inherited from an earlier attempt to fix this, which had language-specific fixes (in print_field_values, cp_print_value_fields, pascal_object_print_value_fields and f_language::value_print_inner). I've left this in, but I suppose it's not strictly necessary anymore. Tested on x86_64-linux. PR exp/31258 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31258
2024-02-05Handling of arrays with optimized-out boundsTom Tromey1-2/+9
In Ada, sometimes the compiler must emit array bounds by referencing an artificial variable that's created for this purpose. However, with optimization enabled, these variables can be optimized away. Currently this can result in displays like: (gdb) print mumble $1 = (warning: unable to get bounds of array, assuming null array ) This patch changes this to report that the array is optimized-out, instead, which is closer to the truth, and more generally useful. For example, Python pretty-printers can now recognize this situation. In order to accomplish this, I introduced a new PROP_OPTIMIZED_OUT enumerator and changed one place to use it. Reusing the "unknown" state wouldn't work properly, because in C it is normal for array bounds to be unknown.
2024-01-28Use domain_search_flags in lookup_symbol et alTom Tromey1-2/+4
This changes lookup_symbol and associated APIs to accept domain_search_flags rather than a domain_enum. Note that this introduces some new constants to Python and Guile. I chose to break out the documentation patch for this, because the internals here do not change until a later patch, and it seemed simpler to patch the docs just once, rather than twice.
2024-01-12Update copyright year range in header of all files managed by GDBAndrew Burgess1-1/+1
This commit is the result of the following actions: - Running gdb/copyright.py to update all of the copyright headers to include 2024, - Manually updating a few files the copyright.py script told me to update, these files had copyright headers embedded within the file, - Regenerating gdbsupport/Makefile.in to refresh it's copyright date, - Using grep to find other files that still mentioned 2023. If these files were updated last year from 2022 to 2023 then I've updated them this year to 2024. I'm sure I've probably missed some dates. Feel free to fix them up as you spot them.
2023-12-24gdb: make value::allocate_register_lazy store id of next non-inline frameSimon Marchi1-0/+12
Some spots loop on the frame chain to find the first next non-inline frame, and pass that as the "next frame" to value::allocate_register_lazy / value::allocate_register. This is necessary if the value is used in the process of computing the id of "this frame". If the frame next to "this frame" is inlined into "this frame", then you that next frame won't have a computed id yet. You have to go past that to find the next non-inline frame, which will have a computed id. In other cases, it's fine to store the id of an inline frame as the "next frame id" in a register struct value. When trying to unwind a register from it, it will just call inline_frame_prev_register, which will forward the request to the next next frame, until we hit the next physical frame. I think it would make things simpler to just never store the id of an inline frame as the next frame id of register struct values, and go with the first next non-inline frame directly. This way, we don't have to wonder which code paths have to skip inline frames when creating register values and which don't. So, change value::allocate_register_lazy to do that work, and remove the loops for the callers that did it. Change-Id: Ic88115dac49dc14e3053c95f92050062b24b7310
2023-12-24gdb: remove VALUE_REGNUM, add value::regnumSimon Marchi1-15/+4
Remove VALUE_REGNUM, replace it with a method on struct value. Set `m_location.reg.regnum` directly from value::allocate_register_lazy, which is fine because allocate_register_lazy is a static creation function for struct value. Change-Id: Id632502357da971617d9dce1e2eab9b56dbcf52d
2023-12-24gdb: remove VALUE_NEXT_FRAME_ID, add value::next_frame_idSimon Marchi1-24/+8
Remove VALUE_NEXT_FRAME_ID, replace it with a method on struct value. Set `m_location.reg.next_frame_id` directly from value::allocate_register_lazy, which is fine because allocate_register_lazy is a static creation function for struct value. Change-Id: Ic9f0f239c166a88dccfee836f9f51871e67548e6
2023-12-24gdb: add type parameter to value::allocate_register and add ↵Simon Marchi1-4/+18
value::allocate_register_lazy Some places that create register struct values don't use register_type to obtain the value type. This prevents them from using the current version of value::allocate_register. One spot (value_of_register_lazy) also creates a lazy register value. Add a value::allocate_register_lazy method. Add some type parameters to value::allocate_register and value::allocate_register_lazy, to let the caller specify the type to use for the value. The parameters default to nullptr, in which case we use register_type to obtain the type. Change-Id: I640ec0a5a0f4a55eba12d515dbfd25933229f8ec
2023-12-19gdb: use put_frame_register instead of put_frame_register_bytes in ↵Simon Marchi1-10/+10
pseudo_to_concat_raw Here, we write single complete registers, we don't need the functionality of put_frame_register_bytes, use put_frame_register instead. Change-Id: I987867a27249db4f792a694b47ecb21c44f64d08 Approved-By: Tom Tromey <tom@tromey.com>
2023-12-14gdb: add gdbarch_pseudo_register_write that takes a frameSimon Marchi1-0/+68
Add a new variant of gdbarch_pseudo_register_write that takes a frame_info in order to write raw registers. Use this new method when available: - in put_frame_register, when trying to write a pseudo register to a given frame - in regcache::cooked_write No implementation is migrated to use this new method (that will come in subsequent patches), so no behavior change is expected here. The objective is to fix writing pseudo registers to non-current frames. See previous commit "gdb: read pseudo register through frame" for a more detailed explanation. Change-Id: Ie7fe364a15a4d86c2ecb09de2b4baa08c45555ac Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: read pseudo register through frameSimon Marchi1-0/+70
Change gdbarch_pseudo_register_read_value to take a frame instead of a regcache. The frame (and formerly the regcache) is used to read raw registers needed to make up the pseudo register value. The problem with using the regcache is that it always provides raw register values for the current frame (frame 0). Let's say the user wants to read the ebx register on amd64. ebx is a pseudo register, obtained by reading the bottom half (bottom 4 bytes) of the rbx register, which is a raw register. If the currently selected frame is frame 0, it works fine: (gdb) frame 0 #0 break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:36 36 in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S (gdb) p/x $ebx $1 = 0x24252627 (gdb) p/x $rbx $2 = 0x2021222324252627 But if the user is looking at another frame, and the raw register behind the pseudo register has been saved at some point in the call stack, then we get a wrong answer: (gdb) frame 1 #1 0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:56 56 in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S (gdb) p/x $ebx $3 = 0x24252627 (gdb) p/x $rbx $4 = 0x1011121314151617 Here, the value of ebx was computed using the value of rbx in frame 0 (through the regcache), it should have been computed using the value of rbx in frame 1. In other to make this work properly, make the following changes: - Make dwarf2_frame_prev_register return nullptr if it doesn't know how to unwind a register and that register is a pseudo register. Previously, it returned `frame_unwind_got_register`, meaning, in our example, "the value of ebx in frame 1 is the same as the value of ebx in frame 0", which is obviously false. Return nullptr as a way to say "I don't know". - In frame_unwind_register_value, when prev_register (for instance dwarf2_frame_prev_register) returns nullptr, and we are trying to read a pseudo register, try to get the register value through gdbarch_pseudo_register_read_value or gdbarch_pseudo_register_read. If using gdbarch_pseudo_register_read, the behavior is known to be broken. Implementations should be migrated to use gdbarch_pseudo_register_read_value to fix that. - Change gdbarch_pseudo_register_read_value to take a frame_info instead of a regcache, update implementations (aarch64, amd64, i386). In i386-tdep.c, I made a copy of i386_mmx_regnum_to_fp_regnum that uses a frame instead of a regcache. The version using the regcache is still used by i386_pseudo_register_write. It will get removed in a subsequent patch. - Add some helpers in value.{c,h} to implement the common cases of pseudo registers: taking part of a raw register and concatenating multiple raw registers. - Update readable_regcache::{cooked_read,cooked_read_value} to pass the current frame to gdbarch_pseudo_register_read_value. Passing the current frame will give the same behavior as before: for frame 0, raw registers will be read from the current thread's regcache. Notes: - I do not plan on changing gdbarch_pseudo_register_read to receive a frame instead of a regcache. That method is considered deprecated. Instead, we should be working on migrating implementations to use gdbarch_pseudo_register_read_value instead. - In frame_unwind_register_value, we still ask the unwinder to try to unwind pseudo register values. It's apparently possible for the debug info to provide information about [1] pseudo registers, so we want to try that first, before falling back to computing them ourselves. [1] https://inbox.sourceware.org/gdb-patches/20180528174715.A954AD804AD@oc3748833570.ibm.com/ Change-Id: Id6ef1c64e19090a183dec050e4034d8c2394e7ca Reviewed-by: John Baldwin <jhb@FreeBSD.org>
2023-12-14gdb: add value::allocate_registerSimon Marchi1-0/+15
Add value::allocate_register, to facilitate allocating a value representing a register in a given frame (or rather, in the given frame's previous frame). It will be used in a subsequent patch. I changed one relatively obvious spot that could use it, to at least exercise the code path. Change-Id: Icd4960f5e471a74b657bb3596c88d89679ef3772 Reviewed-By: John Baldwin <jhb@FreeBSD.org>
2023-12-12Support dynamically computed convenience variables in get_internalvar_integerHannes Domani1-0/+15
When using $_thread in info threads to showonly the current thread, you get this error: ``` (gdb) info thread $_thread Convenience variable must have integer value. Args must be numbers or '$' variables. ``` It's because $_thread is a dynamically computed convenience variable, which isn't supported yet by get_internalvar_integer. Now the output looks like this: ``` (gdb) info threads $_thread Id Target Id Frame * 1 Thread 10640.0x2680 main () at C:/src/repos/binutils-gdb.git/gdb/testsuite/gdb.base/gdbvars.c:21 ``` Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17600 Approved-By: Tom Tromey <tom@tromey.com>
2023-11-29Remove gdb_static_assertTom Tromey1-1/+1
C++17 makes the second parameter to static_assert optional, so we can remove gdb_static_assert now.
2023-11-29Use C++17 [[fallthrough]] attributeTom Tromey1-1/+1
This changes gdb to use the C++17 [[fallthrough]] attribute rather than special comments. This was mostly done by script, but I neglected a few spellings and so also fixed it up by hand. I suspect this fixes the bug mentioned below, by switching to a standard approach that, presumably, clang supports. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23159 Approved-By: John Baldwin <jhb@FreeBSD.org> Approved-By: Luis Machado <luis.machado@arm.com> Approved-By: Pedro Alves <pedro@palves.net>
2023-11-21gdb: Replace gdb::optional with std::optionalLancelot Six1-1/+1
Since GDB now requires C++17, we don't need the internally maintained gdb::optional implementation. This patch does the following replacing: - gdb::optional -> std::optional - gdb::in_place -> std::in_place - #include "gdbsupport/gdb_optional.h" -> #include <optional> This change has mostly been done automatically. One exception is gdbsupport/thread-pool.* which did not use the gdb:: prefix as it already lives in the gdb namespace. Change-Id: I19a92fa03e89637bab136c72e34fd351524f65e9 Approved-By: Tom Tromey <tom@tromey.com> Approved-By: Pedro Alves <pedro@palves.net>
2023-10-10gdb: remove target_gdbarchSimon Marchi1-1/+1
This function is just a wrapper around the current inferior's gdbarch. I find that having that wrapper just obscures where the arch is coming from, and that it's often used as "I don't know which arch to use so I'll use this magical target_gdbarch function that gets me an arch" when the arch should in fact come from something in the context (a thread, objfile, symbol, etc). I think that removing it and inlining `current_inferior ()->arch ()` everywhere will make it a bit clearer where that arch comes from and will trigger people into reflecting whether this is the right place to get the arch or not. Change-Id: I79f14b4e4934c88f91ca3a3155f5fc3ea2fadf6b Reviewed-By: John Baldwin <jhb@FreeBSD.org> Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-10-10gdb: add inferior::{arch, set_arch}Simon Marchi1-1/+1
Make the inferior's gdbarch field private, and add getters and setters. This helped me by allowing putting breakpoints on set_arch to know when the inferior's arch was set. A subsequent patch in this series also adds more things in set_arch. Change-Id: I0005bd1ef4cd6b612af501201cec44e457998eec Reviewed-By: John Baldwin <jhb@FreeBSD.org> Approved-By: Andrew Burgess <aburgess@redhat.com>
2023-08-31gdb: remove TYPE_FIELD_BITSIZESimon Marchi1-5/+5
Replace with type::field + field::bitsize. Change-Id: I2a24755a33683e4a2775a6d2a7b7a9ae7362e43a Approved-By: Tom Tromey <tom@tromey.com>
2023-07-07gdb: check max-value-size when reading strings for printfAndrew Burgess1-1/+9
I noticed that the printf code for strings, printf_c_string and printf_wide_c_string, don't take max-value-size into account, but do load a complete string from the inferior into a GDB buffer. As such it would be possible for an badly behaved inferior to cause GDB to try and allocate an excessively large buffer, potentially crashing GDB, or at least causing GDB to swap lots, which isn't great. We already have a setting to protect against this sort of thing, the 'max-value-size'. So this commit updates the two function mentioned above to check the max-value-size and give an error if the max-value-size is exceeded. If the max-value-size is exceeded, I chose to continue reading inferior memory to figure out how long the string actually is, we just don't store the results. The benefit of this is that when we give the user an error we can tell the user how big the string actually is, which would allow them to correctly adjust max-value-size, if that's what they choose to do. The default for max-value-size is 64k so there should be no user visible changes after this commit, unless the user was previously printing very large strings. If that is the case then the user will now need to increase max-value-size.
2023-06-09Use scoped_value_mark in two more placesTom Tromey1-5/+3
I found a couple of spots that could use scoped_value_mark. One of them is a spot that didn't consider the possibility that value_mark can return NULL. I tend to doubt this can be seen in this context, but nevertheless this is safer. Regression tested on x86-64 Fedora 36.
2023-06-05gdb: building inferior strings from within GDBAndrew Burgess1-2/+3
History Of This Patch ===================== This commit aims to address PR gdb/21699. There have now been a couple of attempts to fix this issue. Simon originally posted two patches back in 2021: https://sourceware.org/pipermail/gdb-patches/2021-July/180894.html https://sourceware.org/pipermail/gdb-patches/2021-July/180896.html Before Pedro then posted a version of his own: https://sourceware.org/pipermail/gdb-patches/2021-July/180970.html After this the conversation halted. Then in 2023 I (Andrew) also took a look at this bug and posted two versions: https://sourceware.org/pipermail/gdb-patches/2023-April/198570.html https://sourceware.org/pipermail/gdb-patches/2023-April/198680.html The approach taken in my first patch was pretty similar to what Simon originally posted back in 2021. My second attempt was only a slight variation on the first. Pedro then pointed out his older patch, and so we arrive at this patch. The GDB changes here are mostly Pedro's work, but updated by me (Andrew), any mistakes are mine. The tests here are a combinations of everyone's work, and the commit message is new, but copies bits from everyone's earlier work. Problem Description =================== Bug PR gdb/21699 makes the observation that using $_as_string with GDB's printf can cause GDB to print unexpected data from the inferior. The reproducer is pretty simple: #include <stddef.h> static char arena[100]; /* Override malloc() so value_coerce_to_target() gets a known pointer, and we know we"ll see an error if $_as_string() gives a string that isn't null terminated. */ void *malloc (size_t size) { memset (arena, 'x', sizeof (arena)); if (size > sizeof (arena)) return NULL; return arena; } int main () { return 0; } And then in a GDB session: $ gdb -q test Reading symbols from /tmp/test... (gdb) start Temporary breakpoint 1 at 0x4004c8: file test.c, line 17. Starting program: /tmp/test Temporary breakpoint 1, main () at test.c:17 17 return 0; (gdb) printf "%s\n", $_as_string("hello") "hello"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (gdb) quit The problem above is caused by how value_cstring is used within py-value.c, but once we understand the issue then it turns out that value_cstring is used in an unexpected way in many places within GDB. Within py-value.c we have a null-terminated C-style string. We then pass a pointer to this string, along with the length of this string (so not including the null-character) to value_cstring. In value_cstring GDB allocates an array value of the given character type, and copies in requested number of characters. However value_cstring does not add a null-character of its own. This means that the value created by calling value_cstring is only null-terminated if the null-character is included in the passed in length. In py-value.c this is not the case, and indeed, in most uses of value_cstring, this is not the case. When GDB tries to print one of these strings the value contents are pushed to the inferior, and then read back as a C-style string, that is, GDB reads inferior memory until it finds a null-terminator. For the py-value.c case, no null-terminator is pushed into the inferior, so GDB will continue reading inferior memory until a null-terminator is found, with unpredictable results. Patch Description ================= The first thing this patch does is better define what the arguments for the two function value_cstring and value_string should represent. The comments in the header file are updated to describe whether the length argument should, or should not, include a null-character. Also, the data argument is changed to type gdb_byte. The functions as they currently exist will handle wide-characters, in which case more than one 'char' would be needed for each character. As such using gdb_byte seems to make more sense. To avoid adding casts throughout GDB, I've also added an overload that still takes a 'char *', but asserts that the character type being used is of size '1'. The value_cstring function is now responsible for adding a null character at the end of the string value it creates. However, once we start looking at how value_cstring is used, we realise there's another, related, problem. Not every language's strings are null terminated. Fortran and Ada strings, for example, are just an array of characters, GDB already has the function value_string which can be used to create such values. Consider this example using current GDB: (gdb) set language ada (gdb) p $_gdb_setting("arch") $1 = (97, 117, 116, 111) (gdb) ptype $ type = array (1 .. 4) of char (gdb) p $_gdb_maint_setting("test-settings string") $2 = (0) (gdb) ptype $ type = array (1 .. 1) of char This shows two problems, first, the $_gdb_setting and $_gdb_maint_setting functions are calling value_cstring using the builtin_char character, rather than a language appropriate type. In the first call, the 'arch' case, the value_cstring call doesn't include the null character, so the returned array only contains the expected characters. But, in the $_gdb_maint_setting example we do end up including the null-character, even though this is not expected for Ada strings. This commit adds a new language method language_defn::value_string, this function takes a pointer and length and creates a language appropriate value that represents the string. For C, C++, etc this will be a null-terminated string (by calling value_cstring), and for Fortran and Ada this can be a bounded array of characters with no null terminator. Additionally, this new language_defn::value_string function is responsible for selecting a language appropriate character type. After this commit the only calls to value_cstring are from the C expression evaluator and from the default language_defn::value_string. And the only calls to value_string are from Fortan, Ada, and ObjectC related code. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=21699 Co-Authored-By: Simon Marchi <simon.marchi@efficios.com> Co-Authored-By: Andrew Burgess <aburgess@redhat.com> Co-Authored-By: Pedro Alves <pedro@palves.net> Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-05-12Add dynamic_prop::is_constantTom Tromey1-5/+5
I noticed many spots checking whether a dynamic property's kind is PROP_CONST. Some spots, I think, are doing a slightly incorrect check -- checking for != PROP_UNDEFINED where == PROP_CONST is actually required, the key thing being that const_val may only be called for PROP_CONST properties. This patch adds dynamic::is_constant and then updates these checks to use it. Regression tested on x86-64 Fedora 36.
2023-05-01Remove evaluate_expressionTom Tromey1-1/+1
evaluate_expression is just a little wrapper for a method on expression. Removing it also removes a lot of ugly (IMO) calls to get().
2023-03-30gdb: have value_as_address call unpack_pointerAndrew Burgess1-5/+4
While refactoring some other code in gdb/python/* I wanted to merge two code paths. One path calls value_as_address, while the other calls unpack_pointer. I suspect calling value_as_address is the correct choice, but, while examining the code I noticed that value_as_address calls unpack_long rather than unpack_pointer. Under the hood, unpack_pointer does just call unpack_long so there's no real difference here, but it feels like value_as_address should call unpack_pointer. I've updated the code to use unpack_pointer, and changed a related comment to say that we call unpack_pointer. I've also adjusted the header comment on value_as_address. The existing header refers to some code that is now commented out. Rather than trying to describe the whole algorithm of value_as_address, which is already well commented within the function, I've just trimmed the comment on value_as_address to be a brief summary of what the function does. There should be no user visible changes after this commit. Reviewed-By: Tom Tromey <tom@tromey.com>
2023-03-29Pass a frame to value_at_lazy and value_from_contents_and_addressTom Tromey1-2/+4
This patch adds a 'frame' parameter to value_at_lazy and ensures that it is passed down to the call to resolve_dynamic_type. This required also adding a frame parameter to value_from_contents_and_address. Nothing passes this parameter to value_at_lazy yet, so this patch should have no visible effect.
2023-03-27Add value_as_mpz and value_from_mpzTom Tromey1-0/+106
This adds the two new functions, value_as_mpz and value_from_mpz, useful for manipulation values via gdb_mpz.
2023-03-14Add methods and operators to gdb_mpzTom Tromey1-2/+1
This adds various methods and operators to gdb_mpz, as a step toward hiding the implementation. This only adds the operators that were needed. Many more could be added as required.
2023-03-09gdb, gdbserver, gdbsupport: fix whitespace issuesSimon Marchi1-4/+4
Replace spaces with tabs in a bunch of places. Change-Id: If0f87180f1d13028dc178e5a8af7882a067868b0
2023-03-02gdb: fix -Wmaybe-uninitialized warning in value.cSimon Marchi1-1/+1
Since commit 11470e70ea0d ("gdb: store internalvars in an std::map"), bulding with -O2, with g++ 11.3.0 on Ubuntu 22.04, I see: CXX value.o In constructor ‘internalvar::internalvar(internalvar&&)’, inlined from ‘constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = const char*&; _U2 = internalvar; typename std::enable_if<(std::_PCC<true, _T1, _T2>::_MoveConstructiblePair<_U1, _U2>() && std::_PCC<true, _T1, _T2>::_ImplicitlyMoveConvertiblePair<_U1, _U2>()), bool>::type <anonymous> = true; _T1 = const char*; _T2 = internalvar]’ at /usr/include/c++/11/bits/stl_pair.h:353:35, inlined from ‘constexpr std::pair<typename std::__strip_reference_wrapper<typename std::decay<_Tp>::type>::__type, typename std::__strip_reference_wrapper<typename std::decay<_Tp2>::type>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = const char*&; _T2 = internalvar]’ at /usr/include/c++/11/bits/stl_pair.h:572:72, inlined from ‘internalvar* create_internalvar(const char*)’ at /home/smarchi/src/binutils-gdb/gdb/value.c:1933:52: /home/smarchi/src/binutils-gdb/gdb/value.c:1831:8: warning: ‘<unnamed>.internalvar::u’ may be used uninitialized [-Wmaybe-uninitialized] 1831 | struct internalvar | ^~~~~~~~~~~ /home/smarchi/src/binutils-gdb/gdb/value.c: In function ‘internalvar* create_internalvar(const char*)’: /home/smarchi/src/binutils-gdb/gdb/value.c:1933:76: note: ‘<anonymous>’ declared here 1933 | auto pair = internalvars.emplace (std::make_pair (name, internalvar (name))); | ^ This is because the union field internalvar::u is not initialized when constructing the temporary internalvar object above. That object is then used for move-construction, and the (implicit) move constructor copies the uninitialized bytes of field u over from the temporary object to the new internalvar object. The compiler therefore complains that we use uninitialized bytes. I don't think it's really a problem, because the internalvar object is in the `kind == INTERNALVAR_VOID` state, in which the contents of the union is irrelevant. Still, mute the warning by default-initializing the union. Change-Id: I70c392842f35255f50d8e63f4099cb6685366fb7 Reviewed-By: Tom Tromey <tom@tromey.com>
2023-02-24gdb: fix parenthesis position in commentSimon Marchi1-1/+1
Change-Id: I535b597ab4482378910570d8dd69c090419941eb
2023-02-24GDB: Fix out of bounds accesses with limited-length valuesMaciej W. Rozycki1-3/+14
Fix accesses to limited-length values in `contents_copy_raw' and `contents_copy_raw_bitwise' so that they observe the limit of the original allocation. Reported by Simon Marchi as a heap-buffer-overflow AddressSanitizer issue triggered with gdb.ada/limited-length.exp. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-02-20gdb: revert one erroneous bool-ification changeSimon Marchi1-1/+1
Commit 42c13555ff88 ("Change value::m_stack to bool") erroneously changed a `0` to `false` in this call to read_value_memory. This parameter is `LONGEST bit_offset`, it should stay `0`. Change-Id: I128df6834cf8055ec6a7051e237e379978d3d651
2023-02-15Return bool from more value methodsTom Tromey1-15/+15
There are several more value methods that currently return 'int' but that should return 'bool'. This patch updates these. Reviewed-By: Bruno Larsen <blarsen@redhat.com>
2023-02-15Have value::bits_synthetic_pointer return boolTom Tromey1-2/+2
This changes value::bits_synthetic_pointer to return bool and fixes up some fallout from this. Reviewed-By: Bruno Larsen <blarsen@redhat.com>
2023-02-15Change value::m_stack to boolTom Tromey1-1/+1
This changes value::m_stack to be a bool and updates the various uses. Reviewed-By: Bruno Larsen <blarsen@redhat.com>
2023-02-15Change value::m_lazy to boolTom Tromey1-4/+4
This changes value::m_lazy to be a bool and updates the various uses. Reviewed-By: Bruno Larsen <blarsen@redhat.com>
2023-02-15Change value::m_modifiable to boolTom Tromey1-3/+3
This changes value::m_modifiable to be a bool and updates the various uses. Reviewed-By: Bruno Larsen <blarsen@redhat.com>
2023-02-15gdb: store internalvars in an std::mapSimon Marchi1-27/+28
In a test downstream in ROCgdb, we had a test case failing when GDB_REVERSE_INIT_FUNCTIONS was set. The test was assuming a particular order in the output of "show convenience". And the order changes when running with GDB_REVERSE_INIT_FUNCTIONS. I think that a nice way to fix it is to make the output of "show convenience" sorted, and therefore stable. Ideally, I think that the the user-visible behavior of GDB should not change when using GDB_REVERSE_INIT_FUNCTIONS. Plus, it makes the output of "show convenience" look nice, not that it's really important. Implement this by storing the internal vars in an std::map, which is a sorted container. Change-Id: I1fca7e7877cc984a3a3432c7639d45e68d437241 Approved-By: Tom Tromey <tom@tromey.com>
2023-02-15gdb: add constructor to internalvarSimon Marchi1-5/+7
Add a constructor that takes the name as a parameter. Initialize the next and kind fields inline. Change-Id: Ic4db0aba85f1da9f12f3eee0ac62c0e5ef0cfe88 Approved-By: Tom Tromey <tom@tromey.com>
2023-02-15gdb: use std::string for internalvar::nameSimon Marchi1-10/+10
Change internalvar::name to std::string, automating memory management. It becomes necessary to allocate internalvar with new instead of XNEW. I didn't find how to trigger the code in complete_internalvar. It is called from condition_completer, so it should be by using the "condition" command, but I never managed to get in the right code path. Change-Id: I814d61361663e7becb8f3fb5f58c0180cdc414bc Approved-By: Tom Tromey <tom@tromey.com>