recognize DW_AT_address_space and use in pointers - #255
Open
aktemur wants to merge 13 commits into
Open
Conversation
…r-input.exp In gdb.rocm/aspace-user-input.exp there are some tests that convert a pointer-to-address-space to a scalar value. Although today such pointer values are implemented by carrying the address space bits in the core address, the pointer value is in fact a pair: address space id and offset in the target memory. Therefore, it doesn't make sense to cast such pointers to scalar and expect that they will still retain the same meaning. In DWARF, converting a memory location in a non-default address space to a scalar value is not possible. Such a conversion is defined only for memory locations to the default address space. Hence, remove those tests.
Define the DW_AT_address_space attribute (currently still an LLVM extension).
Revise the `dwarf_address_space_to_address_space_id` gdbarch function
as follows:
- update the default implementation to iterate over the existing
`address_spaces` list obtained from the arch, to detect
unrecognized address spaces earlier,
- make it a method to have a handle on the gdbarch object,
- rename the method to `address_space_dwarf_to_id` to match the
existing `address_class_dwarf_to_id` gdbarch function.
- update the address space argument to be of an unsigned type.
…_name_to_id Rename gdbarch_name_to_address_space_id to gdbarch_address_space_name_to_id to match the existing address_class_name_to_id, address_class_id_to_name, address_class_dwarf_to_id, address_space_dwarf_to_id, address_space_id_to_name pattern.
Read DW_AT_address_space attribute of a pointer, reference, or an rvalue reference type. The attribute is then saved in the type instance flags of the type. For this purposes, we allocate a bitfield in type instance flags.
When creating a pointer value with a given address and type, if the address denotes a non-default address space, pass that information to the type, so that newly-formed pointer value's type knows which address space it points to. The practical impact of this change is that we produce a pointer type with address space information when (1) the address-space operator '#' is used, and (2) when we take the address of a variable. E.g.: (gdb) print &tid $1 = (int *) private_lane#0x0 (gdb) maintenance print type $1 type node 0x588d3e19be90 name '<unnamed type>' (0x0) code 0x1 (TYPE_CODE_PTR) ... instance_flags [ TYPE_ADDRESS_SPACE(5)] <<< AS SEEN HERE ... (gdb) print local#0x12 $2 = (void *) local#0x12 (gdb) maintenance print type $2 ... instance_flags [ TYPE_ADDRESS_SPACE(3)] <<< AND HERE. ... (gdb)
In language_defn::watch_location_expression, GDB builds a watchpoint expression that would later be parsed and evaluated to an address. The address received in this method maybe have an address space encoded in it. This is only because GDB currently does not track addresses as a pair of address space and offset. So, do not use that address verbatim in the watchpoint expression; instead, split it apart to the address space and segment address pieces and use the '#' operator. With this change, for example, a watchpoint expression that would previously be built as "(int *) 0x0008800000000018" becomes "(int *) private_lane#0x18". Tested by gdb.rocm/aspace-watchpoint.exp.
Define a new gdbarch method, pointer_to_pointer, so that architectures
can convert one pointer value to another. This is in particular
needed for when pointers may point to different address spaces. For
instance, on AMD GPUs, a pointer to the local data share (LDS) address
space may be converted to a generic pointer value. This would happen,
for example, when the user does the following in a program where 'ptr'
is a generic program and 'lds_var' is a variable that is located in
LDS memory.
(gdb) print ptr = &lds_var
Similarly, it's possible to convert a private lane/wave address to a
generic pointer value or to an address in the default (i.e. global)
address space.
In value_cast_pointers, if the source and destination pointers have
different address spaces, call the gdbarch method to let the
architecture do the conversion of the address value.
A particularly interesting case is when the source of casting is a
pointer to an address space whereas the destination is a pointer with
no address space. This can happen when the user wants to specify the
data type that is being pointed at. A typical usecase would be the
address space operator '#', which gives a pointer to void ('void *'),
so that it can be dereferenced. E.g.
(gdb) p *(int *)local#0x123
# Want to read an int from 'local' memory, offset 0x123.
Because "int *" is a pointer type with no address space annotation,
casting would appear to be from the 'local' address space to the
default 'global' address space, which may not be possible. For user's
convenience, propagate the address space from the operator to the
destination type of casting. With this, we would get, for instance:
(gdb) p local#0x123
$1 = (void *) local#0x123 <<< Pointer to void in 'local' aspace.
(gdb) p (int *)local#0x123
$2 = (int *) local#0x123 <<< Pointer to int in 'local' aspace.
(gdb) p *(int *)local#0x123
$3 = .... <<< Read an int from 'local' memory, offset 0x123.
Similarly, the user can do things like
(gdb) p &an_int_var_in_local_address_space
$3 = (int *) local#0x123 <<< Pointer to int in 'local' aspace.
(gdb) p (short *) &an_int_var_in_local_address_space
$4 = (short *) local#0x123 <<< Pointer to short in 'local' aspace.
If there is more to the expression that requires further conversion,
the existing casting mechanism with gdbarch_pointer_to_pointer would
handle it. For example, if 'ptr' is a generic pointer, then:
(gdb) p ptr = local#0x123
$5 = (int *) generic#0x1000000000123 <<< Pointer to int in 'generic' aspace.
If 'gptr' were a pointer to the global address space to which it is
not possible to convert a pointer to local, GDB would give an error:
(gdb) p gptr = local#0x123
cannot convert pointer-to-'local' to a pointer-to-'global'
Tested by gdb.rocm tests when a subsequent patch implements the
pointer_to_pointer gdbarch method for the amdgpu architecture.
…_aliases Extract a function from amdgpu_get_watchable_aliases into amdgpu_convert_address to convert an address in a particular address space to an address in another address space. This is a refactoring with the goal of making address conversion a reusable function.
Use address space information attached to a pointer type to convert the pointer value to an address. This is done in the 'pointer_to_address' gdbarch method. Before this change, we have, for example: (gdb) print ptr $1 = (short *) 0x2000000000010 (gdb) print *ptr Cannot access memory at address 0x2000000000010 (gdb) After this change, we get: (gdb) print ptr $1 = (short *) generic#0x2000000000010 (gdb) print *ptr $2 = 12 (gdb) We also define the 'address_to_pointer' gdbarch method to convert an address to the corresponding pointer value. This is important in particular when the user assigns new values to pointers. E.g.: Before this change: (gdb) p ptr = generic#0x1234 $2 = (int *) generic#0x1234 (gdb) x/1gx &ptr private_lane#0x20: 0x0000800000001234 (gdb) Note the value 0x0000800000001234 contains address space id bits still encoded. After this change: (gdb) p ptr = generic#0x1234 $2 = (int *) generic#0x1234 (gdb) x/1gx &ptr private_lane#0x20: 0x0000000000001234 (gdb) We also implement the 'pointer_to_pointer' gdbarch method. This is essential to convert addresses according to the address spaces. E.g.: (gdb) p pointer $1 = (int *) generic#0x2000000000000 (gdb) p &loc_int $2 = (int *) local#0x8 (gdb) p pointer = &loc_int $3 = (int *) generic#0x1000000000008 (gdb) p loc_int $4 = 42 (gdb) p *pointer $5 = 42 (gdb) Several tests can now be turned from KFAIL into PASS. There are two testcases in gdb.rocm/finish.exp that demand explanation. Suppose we have a generic pointer that points to a global variable named 'global_var'. Before this change, printing the pointer gives: (gdb) p global_ptr $1 = (int *) 0x7ffff4e6bbf0 <global_var> (gdb) Note the '<global_var>' annotation showing the symbol that is being pointed to. After this change, we get (gdb) p global_ptr $1 = (int *) generic#0x7ffff4e6bbf0 There is no symbol annotation anymore. This is not a regression, though. It is rather a side-effect of taking address space information of a pointer type into account and printing that address space in the pointer value. The same behavior existed before this patch: (gdb) p (int *) 0x7ffff4e6bbf0 $5 = (int *) 0x7ffff4e6bbf0 <global_var> (gdb) p (int *) generic#0x7ffff4e6bbf0 $6 = (int *) generic#0x7ffff4e6bbf0 Bug: AIROCGDB-605
Add new tests to gdb.rocm/generic-address.exp where we check that writing via generic pointers works as expected.
Add a test to check that a generic null pointer is printed without problems. Also check that global_ptr and global_ptr2 have exactly the same contents. This is essentially the same as resuming the program to end, but we prefer to do the check more explicitly in the test by reading pointer values, because in case of a failure debugging becomes easier.
Pointers to address spaces are not necessarily the same size as default pointers. Define a gdbarch method to ask the architecture for the size of a pointer to a particular address space and use that information in make_qualified_type, which is the utility function used by make_type_with_address_space. This is the place where address-spaced pointer type variants are added to the type chain. Ideally DWARF should tell the size of a pointer to an address space with a DW_AT_byte_size attribute and this value should match what the arch says. Complain if there is a mismatch and continue with the size set by the arch. Also update value_cast to do casting from a pointer to a pointer without the strict requirement that they have the same length. Implement the gdbarch method in the amdgpu arch.
Collaborator
|
Is it really DW_AT_address_space? Or DW_LLVM_AT_address_space? |
Contributor
Author
llvm-dwarfdump displays it as |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Recognize the
DW_AT_address_spaceattribute for pointer types. Use this information to dereference, assign, cast, etc. pointers.Technical Details
Add an attribute to pointer types and use it in various pointer-related operations.
Test Plan
Via existing and new tests.
Test Result
No ROCgdb regression. There are a few failures related to a dbgapi issue, which I'll handle separately.