Bug 31005 - "Cannot access memory at address 0x0" for inlined function argument
Summary: "Cannot access memory at address 0x0" for inlined function argument
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: exp (show other bugs)
Version: 13.1
: P2 minor
Target Milestone: 15.1
Assignee: Tom Tromey
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-10-28 19:34 UTC by The Puzzlemaker
Modified: 2023-12-08 15:16 UTC (History)
3 users (show)

See Also:
Host:
Target: riscv64-elf
Build:
Last reconfirmed: 2023-11-28 00:00:00
Project(s) to access:
ssh public key:


Attachments
riscv64gc-unknown-none-elf binary with debuginfo (919.46 KB, application/x-executable)
2023-10-28 19:34 UTC, The Puzzlemaker
Details
Simple, but hacky patch to fix this (758 bytes, patch)
2023-10-28 19:35 UTC, The Puzzlemaker
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description The Puzzlemaker 2023-10-28 19:34:52 UTC
Created attachment 15199 [details]
riscv64gc-unknown-none-elf binary with debuginfo

I'd like to apologize in advance that I don't have an MCVE for this.

Running the attached binary causes some issues with inlined function arguments.

This binary is for my own kernel I'm developing for learning purposes, but can be started with QEMU linux and the bug shows up before it crashes due to invalid syscall args.

Note that due to #29735 this will crash if you use any extension e.g. GEF that will run `info args`

- Download the attached binary, and run `qemu-riscv64 -g 1234 userspace_testing`
- Run in a separate tty `gdb userspace_testing`
- Run `target remote :1234`
- Run `si` twice
- Observe the following:
```
rille::capability::RemoteCaptr<rille::capability::Captbl>::copy_deep<rille::capability::Captbl> (self=..., from_index=<error reading variable: Cannot access memory at address 0x0>, into=..., 
    into_index=<error reading variable: Cannot access memory at address 0x0>) at rille/src/capability/mod.rs:340
340	       syscalls::captbl::copy_deep(
```

This is invalid, as `from_index` is *not* a pointer of any sort, just an integer value in one of the `a` registers (though not yet loaded at this point).

When looking at the DWARF info (with llvm-dwarfdump) it shows the following:
```
0x0000135f:         DW_TAG_inlined_subroutine
                      DW_AT_abstract_origin     (0x0000000000001b84 "rille::capability::RemoteCaptr<rille::capability::Captbl>::copy_deep")
                      DW_AT_low_pc      (0x00000000000120da)
                      DW_AT_high_pc     (0x00000000000120f2)
                      DW_AT_call_file   ("/home/wren/Code/RISCV/river/user/userspace_testing/src/main.rs")
                      DW_AT_call_line   (15)
                      DW_AT_call_column (0x15)

0x00001373:           DW_TAG_formal_parameter
                        DW_AT_location  (0x00000330: 
                           [0x00000000000120d6, 0x00000000000120f2): DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x8, DW_OP_lit1, DW_OP_stack_value, DW_OP_piece 0x8)
                        DW_AT_abstract_origin   (0x0000000000001b93 "self")

0x0000137c:           DW_TAG_formal_parameter
                        DW_AT_const_value       (1)
                        DW_AT_abstract_origin   (0x0000000000001b9f "from_index")

0x00001382:           DW_TAG_formal_parameter
                        DW_AT_location  (0x0000036a: 
                           [0x00000000000120d6, 0x00000000000120f2): DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x8, DW_OP_lit1, DW_OP_stack_value, DW_OP_piece 0x8)
                        DW_AT_abstract_origin   (0x0000000000001bab "into")

0x0000138b:           DW_TAG_formal_parameter
                        DW_AT_const_value       (2)
                        DW_AT_abstract_origin   (0x0000000000001bb7 "into_index")
```

When debugging, I found that this issue stemmed from looking at the discriminant value in `compute_variant_field_inner`. This ultimately was called (skipping a few frames for the sake of brevity, they aren't important here) in this portion of code:
```
 582     case LOC_CONST:
 583       if (is_dynamic_type (type))
 584         {
 585           /* Value is a constant byte-sequence and needs no memory access.  */
 586           type = resolve_dynamic_type (type, {}, /* Unused address.  */ 0);
 587         }
```
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/findvar.c;h=02d498d8c587616a52613fbc3b0ee749eff122ba;hb=662243de0e14a4945555a480dca33c0e677976eb#l582

With `valaddr` in `resolve_dynamic_type`'s `addrstack` empty, and a null address, it tries to read the memory at `0x0` to resolve the discriminant type. This is incorrect as the discriminant field could be resolved from the constant value in the DWARF debuginfo.

I created a simple patch that fixes just this case, but may not fix others. I will attach it. Feel free to change and extend on this, as long as I am a co-author on the final patch if accepted.
Comment 1 The Puzzlemaker 2023-10-28 19:35:25 UTC
Created attachment 15200 [details]
Simple, but hacky patch to fix this
Comment 2 The Puzzlemaker 2023-10-28 21:05:15 UTC
I have tried this as of 934a14fd6b60626512b5a9c61d25df11e073fb0b on the 14.x git and it still occurs.
Comment 3 Tom Tromey 2023-11-26 19:50:33 UTC
I failed in my first attempt at writing a test case for this :(
I guess I will try to debug the original test case.
Comment 4 Tom Tromey 2023-11-28 00:15:47 UTC
The variable has to have a DW_AT_constant_value to trigger this.
Comment 5 Tom Tromey 2023-11-28 00:16:06 UTC
I mean s/constant/const
Comment 6 Tom Tromey 2023-11-28 00:58:55 UTC
Your patch is reasonably close but I think the LOC_CONST part will
fail for big-endian targets.
I've got a patch and a test case.
I'll see if I can dig up a big-endian machine to test it on.
Comment 8 Sourceware Commits 2023-12-08 15:16:02 UTC
The master branch has been updated by Tom Tromey <tromey@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=703adbb1f97db52ed63b2a6a074195b1cee0f132

commit 703adbb1f97db52ed63b2a6a074195b1cee0f132
Author: Tom Tromey <tom@tromey.com>
Date:   Mon Nov 27 16:44:22 2023 -0700

    Fix dynamic type resolution for LOC_CONST and LOC_CONST_BYTES symbols
    
    PR rust/31005 points out that dynamic type resolution of a LOC_CONST
    or LOC_CONST_BYTES symbol will fail, leading to output like:
    
        from_index=<error reading variable: Cannot access memory at address 0x0>
    
    This patch fixes the problem by using the constant value or bytes when
    performing type resolution.
    
    Thanks to tpzker@thepuzzlemaker.info for a first version of this
    patch.
    
    I also tested this on a big-endian PPC system (cfarm203).
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31005
Comment 9 Tom Tromey 2023-12-08 15:16:50 UTC
Fixed.