Originally reported by Jan Vrany on the mailing list: https://sourceware.org/pipermail/gdb/2022-March/049966.html TL;DR: I'm experiencing GDB crashes with recent GDB which seem to be caused by commit 5f8ab46. Why is that I do not know (yet). Some details below. Full story: After updating my every-day-use GDB to commit commit c9178f285acf19e066be8367185d52837161b0a2 (HEAD -> master, origin/master) Author: Alan Modra <amodra@gmail.com> Date: Thu Mar 17 20:05:39 2022 +1030 I'm experiencing GDB to crash on assertion failure in value_copy (value.c:1731). This is triggered when I single-step through code while having (my, custom) GDB/MI frontent displaying local variables with python pretty printers enabled. For example: doing this in frontend triggers the assertion failure: file gdb/testsuite/outputs/gdb.python/py-prettyprint/py-prettyprint-cxx source gdb/testsuite/outputs/gdb.python/py-prettyprint/py-prettyprint.py b add_item(container*, int) r dis 1 fin n n (few more times until it crashes) This is the backtrace when it crashes: /home/jv/Proj...atches/gdb/gdb [stopped] Thread 1 [stopped] "gdb" 0 0x0000556077ADABD0 internal_error (errors.cc:51) 1 0x00005560776148A7 value_copy (value.c:1731) 2 0x0000556077360028 gdbpy_get_varobj_pretty_printer (py-prettyprint.c:655) 3 0x0000556077620E60 install_default_visualizer (varobj.c:1056) 4 0x00005560776210E9 install_new_value_visualizer (varobj.c:1127) 5 0x00005560776218B2 install_new_value (varobj.c:1339) 6 0x000055607761F6FB varobj_create (varobj.c:378) 7 0x0000556077245C05 mi_cmd_var_create (mi-cmd-var.c:132) 8 0x0000556077249F2B mi_command_mi::invoke (mi-cmds.c:58) 9 0x0000556077264F15 mi_cmd_execute (mi-main.c:2091) 10 0x000055607726450C captured_mi_execute_command (mi-main.c:1823) 11 0x000055607726498A mi_execute_command (mi-main.c:1947) 12 0x000055607724D21B mi_execute_command_wrapper (mi-interp.c:285) 13 0x000055607724D2A4 mi_execute_command_input_handler (mi-interp.c:314) 14 0x00005560770D7149 gdb_readline_no_editing_callback (event-top.c:878) 15 0x00005560770D6948 stdin_event_handler (event-top.c:524) 16 0x0000556077ADB57E gdb_wait_for_event (event-loop.cc:700) 17 0x0000556077ADB7FB gdb_wait_for_event (event-loop.cc:596) 18 0x0000556077ADB7FB gdb_do_one_event (event-loop.cc:237) 19 0x000055607721BA1B start_event_loop (main.c:421) 20 0x000055607721BB3F captured_command_loop (main.c:481) 21 0x000055607721D535 captured_main (main.c:1351) 22 0x000055607721D59B gdb_main (main.c:1366) 23 0x0000556076DA7E93 main (gdb.c:32) Thread 2 [stopped] "gdb worker" Thread 3 [stopped] "gdb worker" Thread 4 [stopped] "gdb worker" Thread 5 [stopped] "gdb worker" Unfortunately, so far I was unable to reproduce this outside my frontend. I tried to simulate what the frontend does (see attached file), but running GDB like gdb -i mi < crash-in-value_copy-reproducer.txt does not trigger it (arguably, the frontend issues silly / unnecessary MI commands, but still it should not crash GDB - I would think :-). If I revert commit commit 5f8ab46bc6918efb678deb5956c033e466afe301 Author: Simon Marchi <simon.marchi@polymtl.ca> Date: Mon Jan 31 15:57:58 2022 -0500 gdb: constify parameter of value_copy Everything seems to work just fine for me. I'm not at all familiar with this part of the GDB code so I do not know whether this change is the real culprit or not, let alone to explain why. I'll try to investigate further when I find more time, but in case someone brave enough to read through this post has an idea, I'll appreciate it! Thanks, Jan -------------- next part -------------- file /home/jv/Projects/gdb/users_jv_patches/gdb/testsuite/outputs/gdb.python/py-prettyprint/py-prettyprint-cxx source /home/jv/Projects/gdb/users_jv_patches/gdb/testsuite/outputs/gdb.python/py-prettyprint/py-prettyprint.py b add_item(container*, int) r 23-data-list-register-names --thread 1 --frame 0 24-stack-info-depth --thread 1 100 25-data-list-register-values --thread 1 --frame 0 r 26-stack-list-frames --thread 1 0 1 27-stack-list-variables --thread 1 --frame 0 --simple-values 28-thread-info 1 29-var-create --thread 1 --frame 0 - * c 30-var-update --all-values var1 31-var-create --thread 1 --frame 0 - * val 32-var-update --all-values var2 dis 1 fin 33-data-list-register-values --thread 1 --frame 0 r 34-stack-info-depth --thread 1 100 35-stack-list-variables --thread 1 --frame 0 --simple-values 36-stack-list-frames --thread 1 0 0 37-var-create --thread 1 --frame 0 - * ss 38-var-update --all-values var3 39-var-create --thread 1 --frame 0 - * ssa 40-var-update --all-values var4 41-var-create --thread 1 --frame 0 - * arraystruct 42-var-update --all-values var5 43-var-create --thread 1 --frame 0 - * x 44-var-update --all-values var6 45-var-create --thread 1 --frame 0 - * c 46-var-update --all-values var7 47-var-create --thread 1 --frame 0 - * c2 48-var-update --all-values var8 49-var-create --thread 1 --frame 0 - * cstring 50-var-update --all-values var9 51-var-create --thread 1 --frame 0 - * nullstr 52-var-update --all-values var10 53-var-create --thread 1 --frame 0 - * nstype 54-var-update --all-values var11 55-var-create --thread 1 --frame 0 - * nstype2 56-var-update --all-values var12 57-var-create --thread 1 --frame 0 - * me 58-var-update --all-values var13 59-var-create --thread 1 --frame 0 - * ns 60-var-update --all-values var14 61-var-create --thread 1 --frame 0 - * ns2 62-var-update --all-values var15 63-var-create --thread 1 --frame 0 - * estring 64-var-update --all-values var16 65-var-create --thread 1 --frame 0 - * estring2 66-var-update --all-values var17 67-var-create --thread 1 --frame 0 - * estring3 68-var-update --all-values var18 69-exec-next 70-stack-list-variables --thread 1 --frame 0 --simple-values 71-stack-info-depth --thread 1 100 72-stack-list-frames --thread 1 0 0 73-var-create --thread 1 --frame 0 - * ss 74-var-update --all-values var19 75-var-create --thread 1 --frame 0 - * ssa 76-var-update --all-values var20 77-var-create --thread 1 --frame 0 - * arraystruct 78-var-update --all-values var21 79-var-create --thread 1 --frame 0 - * x 80-var-update --all-values var22 81-var-create --thread 1 --frame 0 - * c 82-var-update --all-values var23 83-var-create --thread 1 --frame 0 - * c2 84-var-update --all-values var24 85-var-create --thread 1 --frame 0 - * cstring 86-var-update --all-values var25 87-var-create --thread 1 --frame 0 - * nullstr 88-var-update --all-values var26 89-var-create --thread 1 --frame 0 - * nstype 90-var-update --all-values var27 91-var-create --thread 1 --frame 0 - * nstype2 92-var-update --all-values var28 93-var-create --thread 1 --frame 0 - * me 94-var-update --all-values var29 95-var-create --thread 1 --frame 0 - * ns 96-var-update --all-values var30 97-var-create --thread 1 --frame 0 - * ns2 98-var-update --all-values var31 99-var-create --thread 1 --frame 0 - * estring 100-var-update --all-values var32 101-var-create --thread 1 --frame 0 - * estring2 102-var-update --all-values var33 103-var-create --thread 1 --frame 0 - * estring3 104-var-update --all-values var34 105-exec-next 106-stack-list-variables --thread 1 --frame 0 --simple-values 107-stack-info-depth --thread 1 100 108-stack-list-frames --thread 1 0 0 109-var-create --thread 1 --frame 0 - * ss 110-var-update --all-values var35 111-var-create --thread 1 --frame 0 - * ssa 112-var-update --all-values var36 113-var-create --thread 1 --frame 0 - * arraystruct 114-var-update --all-values var37 115-var-create --thread 1 --frame 0 - * x 116-var-update --all-values var38 117-var-create --thread 1 --frame 0 - * c 118-var-update --all-values var39 119-var-create --thread 1 --frame 0 - * c2 120-var-update --all-values var40 121-var-create --thread 1 --frame 0 - * cstring 122-var-update --all-values var41 123-var-create --thread 1 --frame 0 - * nullstr 124-var-update --all-values var42 125-var-create --thread 1 --frame 0 - * nstype 126-var-update --all-values var43 127-var-create --thread 1 --frame 0 - * nstype2 128-var-update --all-values var44 129-var-create --thread 1 --frame 0 - * me 130-var-update --all-values var45 131-var-create --thread 1 --frame 0 - * ns 132-var-update --all-values var46 133-var-create --thread 1 --frame 0 - * ns2 134-var-update --all-values var47 135-var-create --thread 1 --frame 0 - * estring 136-var-update --all-values var48 137-var-create --thread 1 --frame 0 - * estring2 138-var-update --all-values var49 139-var-create --thread 1 --frame 0 - * estring3 140-var-update --all-values var50 141-exec-next 142-stack-list-variables --thread 1 --frame 0 --simple-values 143-stack-info-depth --thread 1 100 144-stack-list-frames --thread 1 0 0 145-var-create --thread 1 --frame 0 - * ss 146-var-update --all-values var51 147-var-create --thread 1 --frame 0 - * ssa 148-var-update --all-values var52 149-var-create --thread 1 --frame 0 - * arraystruct 150-var-update --all-values var53 151-var-create --thread 1 --frame 0 - * x 152-var-update --all-values var54 153-var-create --thread 1 --frame 0 - * c 154-var-update --all-values var55 155-var-create --thread 1 --frame 0 - * c2 156-var-update --all-values var56 157-var-create --thread 1 --frame 0 - * cstring 158-var-update --all-values var57 159-var-create --thread 1 --frame 0 - * nullstr 160-var-update --all-values var58 161-var-create --thread 1 --frame 0 - * nstype 162-var-update --all-values var59 163-var-create --thread 1 --frame 0 - * nstype2 164-var-update --all-values var60 165-var-create --thread 1 --frame 0 - * me 166-var-update --all-values var61 167-var-create --thread 1 --frame 0 - * ns 168-var-update --all-values var62 169-var-create --thread 1 --frame 0 - * ns2 170-var-update --all-values var63 171-var-create --thread 1 --frame 0 - * estring 172-var-update --all-values var64 173-var-create --thread 1 --frame 0 - * estring2 174-var-update --all-values var65 175-var-create --thread 1 --frame 0 - * estring3 176-var-update --all-values var66 177-exec-next 178-stack-list-variables --thread 1 --frame 0 --simple-values 179-stack-info-depth --thread 1 100 180-stack-list-frames --thread 1 0 0 181-var-create --thread 1 --frame 0 - * ss 182-var-update --all-values var67 183-var-create --thread 1 --frame 0 - * ssa 184-var-update --all-values var68 185-var-create --thread 1 --frame 0 - * arraystruct 186-var-update --all-values var69 187-var-create --thread 1 --frame 0 - * x 188-var-update --all-values var70 189-var-create --thread 1 --frame 0 - * c 190-var-update --all-values var71 191-var-create --thread 1 --frame 0 - * c2 192-var-update --all-values var72 193-var-create --thread 1 --frame 0 - * cstring 194-var-update --all-values var73 195-var-create --thread 1 --frame 0 - * nullstr 196-var-update --all-values var74 197-var-create --thread 1 --frame 0 - * nstype 198-var-update --all-values var75 199-var-create --thread 1 --frame 0 - * nstype2 200-var-update --all-values var76 201-var-create --thread 1 --frame 0 - * me 202-var-update --all-values var77 203-var-create --thread 1 --frame 0 - * ns 204-var-update --all-values var78 205-var-create --thread 1 --frame 0 - * ns2 206-var-update --all-values var79 207-var-create --thread 1 --frame 0 - * estring 208-var-update --all-values var80 209-var-create --thread 1 --frame 0 - * estring2 210-var-update --all-values var81 211-var-create --thread 1 --frame 0 - * estring3 212-var-update --all-values var82 213-exec-next 214-stack-list-variables --thread 1 --frame 0 --simple-values 215-stack-info-depth --thread 1 100 216-stack-list-frames --thread 1 0 0 217-var-create --thread 1 --frame 0 - * ss 218-var-update --all-values var83 219-var-create --thread 1 --frame 0 - * ssa 220-var-update --all-values var84 221-var-create --thread 1 --frame 0 - * arraystruct 222-var-update --all-values var85 223-var-create --thread 1 --frame 0 - * x 224-var-update --all-values var86 225-var-create --thread 1 --frame 0 - * c 226-var-update --all-values var87 227-var-create --thread 1 --frame 0 - * c2 228-var-update --all-values var88 229-var-create --thread 1 --frame 0 - * cstring 230-var-update --all-values var89 231-var-create --thread 1 --frame 0 - * nullstr 232-var-update --all-values var90 233-var-create --thread 1 --frame 0 - * nstype 234-var-update --all-values var91 235-var-create --thread 1 --frame 0 - * nstype2 236-var-update --all-values var92 237-var-create --thread 1 --frame 0 - * me 238-var-update --all-values var93 239-var-create --thread 1 --frame 0 - * ns 240-var-update --all-values var94 241-var-create --thread 1 --frame 0 - * ns2 242-var-update --all-values var95 243-var-create --thread 1 --frame 0 - * estring 244-var-update --all-values var96 245-var-create --thread 1 --frame 0 - * estring2 246-var-update --all-values var97 247-var-create --thread 1 --frame 0 - * estring3 248-var-update --all-values var98 249-exec-next 250-stack-list-variables --thread 1 --frame 0 --simple-values 251-stack-info-depth --thread 1 100 252-stack-list-frames --thread 1 0 0 253-var-create --thread 1 --frame 0 - * ss 254-var-update --all-values var99 255-var-create --thread 1 --frame 0 - * ssa 256-var-update --all-values var100 257-var-create --thread 1 --frame 0 - * arraystruct 258-var-update --all-values var101 259-var-create --thread 1 --frame 0 - * x 260-var-update --all-values var102 261-var-create --thread 1 --frame 0 - * c 262-var-update --all-values var103 263-var-create --thread 1 --frame 0 - * c2 264-var-update --all-values var104 265-var-create --thread 1 --frame 0 - * cstring 266-var-update --all-values var105 267-var-create --thread 1 --frame 0 - * nullstr 268-var-update --all-values var106 269-var-create --thread 1 --frame 0 - * nstype 270-var-update --all-values var107 271-var-create --thread 1 --frame 0 - * nstype2 272-var-update --all-values var108 273-var-create --thread 1 --frame 0 - * me 274-var-update --all-values var109 275-var-create --thread 1 --frame 0 - * ns 276-var-update --all-values var110 277-var-create --thread 1 --frame 0 - * ns2 278-var-update --all-values var111 279-var-create --thread 1 --frame 0 - * estring 280-var-update --all-values var112 281-var-create --thread 1 --frame 0 - * estring2 282-var-update --all-values var113 283-var-create --thread 1 --frame 0 - * estring3 284-var-update --all-values var114 285-exec-next 286-stack-list-variables --thread 1 --frame 0 --simple-values 287-stack-info-depth --thread 1 100 288-stack-list-frames --thread 1 0 0 289-var-create --thread 1 --frame 0 - * ss 290-var-update --all-values var115 291-var-create --thread 1 --frame 0 - * ssa 292-var-update --all-values var116 293-var-create --thread 1 --frame 0 - * arraystruct 294-var-update --all-values var117 295-var-create --thread 1 --frame 0 - * x 296-var-update --all-values var118 297-var-create --thread 1 --frame 0 - * c 298-var-update --all-values var119 299-var-create --thread 1 --frame 0 - * c2 300-var-update --all-values var120 301-var-create --thread 1 --frame 0 - * cstring 302-var-update --all-values var121 303-var-create --thread 1 --frame 0 - * nullstr 304-var-update --all-values var122 305-var-create --thread 1 --frame 0 - * nstype 306-var-update --all-values var123 307-var-create --thread 1 --frame 0 - * nstype2 308-var-update --all-values var124 309-var-create --thread 1 --frame 0 - * me 310-var-update --all-values var125 311-var-create --thread 1 --frame 0 - * ns 312-var-update --all-values var126 313-var-create --thread 1 --frame 0 - * ns2 314-var-update --all-values var127 315-var-create --thread 1 --frame 0 - * estring 316-var-update --all-values var128 317-var-create --thread 1 --frame 0 - * estring2 318-var-update --all-values var129 319-var-create --thread 1 --frame 0 - * estring3 320-var-update --all-values var130 321-exec-next 322-stack-list-variables --thread 1 --frame 0 --simple-values 323-stack-info-depth --thread 1 100 324-stack-list-frames --thread 1 0 0 325-var-create --thread 1 --frame 0 - * ss 326-var-update --all-values var131 327-var-create --thread 1 --frame 0 - * ssa 328-var-update --all-values var132 329-var-create --thread 1 --frame 0 - * arraystruct 330-var-update --all-values var133 331-var-create --thread 1 --frame 0 - * x 332-var-update --all-values var134 333-var-create --thread 1 --frame 0 - * c 334-var-update --all-values var135 335-var-create --thread 1 --frame 0 - * c2 336-var-update --all-values var136 337-var-create --thread 1 --frame 0 - * cstring 338-var-update --all-values var137 339-var-create --thread 1 --frame 0 - * nullstr 340-var-update --all-values var138 341-var-create --thread 1 --frame 0 - * nstype 342-var-update --all-values var139 343-var-create --thread 1 --frame 0 - * nstype2 344-var-update --all-values var140 345-var-create --thread 1 --frame 0 - * me 346-var-update --all-values var141 347-var-create --thread 1 --frame 0 - * ns 348-var-update --all-values var142 349-var-create --thread 1 --frame 0 - * ns2 350-var-update --all-values var143 351-var-create --thread 1 --frame 0 - * estring 352-var-update --all-values var144 353-var-create --thread 1 --frame 0 - * estring2 354-var-update --all-values var145 355-var-create --thread 1 --frame 0 - * estring3 356-var-update --all-values var146 357-exec-next 358-data-list-register-values --thread 1 --frame 0 r 359-gdb-show directories 360-stack-info-depth --thread 1 100 361-stack-list-variables --thread 1 --frame 0 --simple-values 362-stack-list-frames --thread 1 0 1 363-var-create --thread 1 --frame 0 - * main 364-var-update --all-values var147 365-var-create --thread 1 --frame 0 - * argc 366-var-update --all-values var148 367-var-create --thread 1 --frame 0 - * argv 368-var-update --all-values var149 369-var-create --thread 1 --frame 0 - * init -exec-next
Can be easily reproduced with python when copying an optimized-out value: (gdb) py print(gdb.Value(gdb.Value(5).type.optimized_out())) C:/src/repos/binutils-gdb.git/gdb/value.c:1731: internal-error: value* value_copy(value*): Assertion `arg->contents != nullptr' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) n
*** Bug 28988 has been marked as a duplicate of this bug. ***
The master branch has been updated by Simon Marchi <simark@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6d088eb92ee42e05a4fbe797515229cf2acd0d99 commit 6d088eb92ee42e05a4fbe797515229cf2acd0d99 Author: Simon Marchi <simon.marchi@efficios.com> Date: Mon Apr 4 17:45:59 2022 -0400 gdb: don't copy entirely optimized out values in value_copy Bug 28980 shows that trying to value_copy an entirely optimized out value causes an internal error. The original bug report involves MI and some Python pretty printer, and is quite difficult to reproduce, but another easy way to reproduce (that is believed to be equivalent) was proposed: $ ./gdb -q -nx --data-directory=data-directory -ex "py print(gdb.Value(gdb.Value(5).type.optimized_out()))" /home/smarchi/src/binutils-gdb/gdb/value.c:1731: internal-error: value_copy: Assertion `arg->contents != nullptr' failed. This is caused by 5f8ab46bc691 ("gdb: constify parameter of value_copy"). It added an assertion that the contents buffer is allocated if the value is not lazy: if (!value_lazy (val)) { gdb_assert (arg->contents != nullptr); This was based on the comment on value::contents, which suggest that this is the case: /* Actual contents of the value. Target byte-order. NULL or not valid if lazy is nonzero. */ gdb::unique_xmalloc_ptr<gdb_byte> contents; However, it turns out that it can also be nullptr also if the value is entirely optimized out, for example on exit of allocate_optimized_out_value. That function creates a lazy value, marks the entire value as optimized out, and then clears the lazy flag. But contents remains nullptr. This wasn't a problem for value_copy before, because it was calling value_contents_all_raw on the input value, which caused contents to be allocated before doing the copy. This means that the input value to value_copy did not have its contents allocated on entry, but had it allocated on exit. The result value had it allocated on exit. And that we copied bytes for an entirely optimized out value (i.e. meaningless bytes). From here I see two choices: 1. respect the documented invariant that contents is nullptr only and only if the value is lazy, which means making allocate_optimized_out_value allocate contents 2. extend the cases where contents can be nullptr to also include values that are entirely optimized out (note that you could still have some entirely optimized out values that do have contents allocated, it depends on how they were created) and adjust value_copy accordingly Choice #1 is safe, but less efficient: it's not very useful to allocate a buffer for an entirely optimized out value. It's even a bit less efficient than what we had initially, because values coming out of allocate_optimized_out_value would now always get their contents allocated. Choice #2 would be more efficient than what we had before: giving an optimized out value without allocated contents to value_copy would result in an optimized out value without allocated contents (and the input value would still be without allocated contents on exit). But it's more risky, since it's difficult to ensure that all users of the contents (through the various_contents* accessors) are all fine with that new invariant. In this patch, I opt for choice #2, since I think it is a better direction than choice #1. #1 would be a pessimization, and if we go this way, I doubt that it will ever be revisited, it will just stay that way forever. Add a selftest to test this. I initially started to write it as a Python test (since the reproducer is in Python), but a selftest is more straightforward. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28980 Change-Id: I6e2f5c0ea804fafa041fcc4345d47064b5900ed7
The gdb-12-branch branch has been updated by Simon Marchi <simark@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=439385561588f12c1df670aaa92af9babd98f2ac commit 439385561588f12c1df670aaa92af9babd98f2ac Author: Simon Marchi <simon.marchi@efficios.com> Date: Mon Apr 4 17:45:59 2022 -0400 gdb: don't copy entirely optimized out values in value_copy Bug 28980 shows that trying to value_copy an entirely optimized out value causes an internal error. The original bug report involves MI and some Python pretty printer, and is quite difficult to reproduce, but another easy way to reproduce (that is believed to be equivalent) was proposed: $ ./gdb -q -nx --data-directory=data-directory -ex "py print(gdb.Value(gdb.Value(5).type.optimized_out()))" /home/smarchi/src/binutils-gdb/gdb/value.c:1731: internal-error: value_copy: Assertion `arg->contents != nullptr' failed. This is caused by 5f8ab46bc691 ("gdb: constify parameter of value_copy"). It added an assertion that the contents buffer is allocated if the value is not lazy: if (!value_lazy (val)) { gdb_assert (arg->contents != nullptr); This was based on the comment on value::contents, which suggest that this is the case: /* Actual contents of the value. Target byte-order. NULL or not valid if lazy is nonzero. */ gdb::unique_xmalloc_ptr<gdb_byte> contents; However, it turns out that it can also be nullptr also if the value is entirely optimized out, for example on exit of allocate_optimized_out_value. That function creates a lazy value, marks the entire value as optimized out, and then clears the lazy flag. But contents remains nullptr. This wasn't a problem for value_copy before, because it was calling value_contents_all_raw on the input value, which caused contents to be allocated before doing the copy. This means that the input value to value_copy did not have its contents allocated on entry, but had it allocated on exit. The result value had it allocated on exit. And that we copied bytes for an entirely optimized out value (i.e. meaningless bytes). From here I see two choices: 1. respect the documented invariant that contents is nullptr only and only if the value is lazy, which means making allocate_optimized_out_value allocate contents 2. extend the cases where contents can be nullptr to also include values that are entirely optimized out (note that you could still have some entirely optimized out values that do have contents allocated, it depends on how they were created) and adjust value_copy accordingly Choice #1 is safe, but less efficient: it's not very useful to allocate a buffer for an entirely optimized out value. It's even a bit less efficient than what we had initially, because values coming out of allocate_optimized_out_value would now always get their contents allocated. Choice #2 would be more efficient than what we had before: giving an optimized out value without allocated contents to value_copy would result in an optimized out value without allocated contents (and the input value would still be without allocated contents on exit). But it's more risky, since it's difficult to ensure that all users of the contents (through the various_contents* accessors) are all fine with that new invariant. In this patch, I opt for choice #2, since I think it is a better direction than choice #1. #1 would be a pessimization, and if we go this way, I doubt that it will ever be revisited, it will just stay that way forever. Add a selftest to test this. I initially started to write it as a Python test (since the reproducer is in Python), but a selftest is more straightforward. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28980 Change-Id: I6e2f5c0ea804fafa041fcc4345d47064b5900ed7
Pushed to master and gdb-12-branch.