Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAuth] Emit Dwarf info for implicitly signed pointers #63

Closed
kovdan01 opened this issue Dec 5, 2023 · 4 comments
Closed

[PAuth] Emit Dwarf info for implicitly signed pointers #63

kovdan01 opened this issue Dec 5, 2023 · 4 comments
Assignees
Labels

Comments

@kovdan01
Copy link
Contributor

kovdan01 commented Dec 5, 2023

In f28e8db, DW_TAG_LLVM_ptrauth_type and corresponding attributes were introduced. However, those are only emitted for explicitly signed pointers (those with explicit __ptrauth specifier).

Consider the following code:

typedef void fptr();

fptr a;
fptr *__ptrauth(0, 0, 0) b = &a;

fptr x;
fptr *y = &x;

When building for a Linux target with -mbranch-protection=pauthabi (or for an Apple's arm64e), we get the following Dwarf info (unrelated parts omitted):

0x0000001e:   DW_TAG_variable [2]   (0x0000000c)
                DW_AT_name [DW_FORM_strx1]      (indexed (00000003) string = "b")
                DW_AT_type [DW_FORM_ref4]       (cu + 0x0029 => {0x00000029} "fptr *__ptrauth(0, 1, 0x00)")
                DW_AT_external [DW_FORM_flag_present]   (true)
                DW_AT_decl_file [DW_FORM_data1] ("/home/kovdan01/Work/armpac/dwarf/test.c")
                DW_AT_decl_line [DW_FORM_data1] (52)
                DW_AT_location [DW_FORM_exprloc]        (DW_OP_addrx 0x0)

0x00000029:   DW_TAG_LLVM_ptrauth_type [3]   (0x0000000c)
                DW_AT_type [DW_FORM_ref4]       (cu + 0x0031 => {0x00000031} "fptr *")
                DW_AT_LLVM_ptrauth_key [DW_FORM_data1]  (0x00)
                DW_AT_LLVM_ptrauth_address_discriminated [DW_FORM_flag_present] (true)
                DW_AT_LLVM_ptrauth_extra_discriminator [DW_FORM_data2]  (0x0000)
0x00000031:   DW_TAG_pointer_type [4]   (0x0000000c)
                DW_AT_type [DW_FORM_ref4]       (cu + 0x0036 => {0x00000036} "fptr")
0x00000041:   DW_TAG_variable [2]   (0x0000000c)
                DW_AT_name [DW_FORM_strx1]      (indexed (00000005) string = "y")
                DW_AT_type [DW_FORM_ref4]       (cu + 0x0031 => {0x00000031} "fptr *")
                DW_AT_external [DW_FORM_flag_present]   (true)
                DW_AT_decl_file [DW_FORM_data1] ("/home/kovdan01/Work/armpac/dwarf/test.c")
                DW_AT_decl_line [DW_FORM_data1] (56)
                DW_AT_location [DW_FORM_exprloc]        (DW_OP_addrx 0x1)

So, only pointer b is listed in Dwarf info as signed, while y is not. However, for both b and y signed R_AARCH64_AUTH_ABS64 relocations are emitted, so they are actually both signed (as expected when using -mbranch-protection=pauthabi).

The same issue also applies to other implicitly signed pointers (by implicitly we here mean without explicit __ptrauth specifier): pointers to member functions, vtable pointers, function pointers with are signed at runtime instead of a relocation.

The fix should include changes in functions declared in llvm/include/llvm/IR/DIBuilder.h, such as DIBuilder::createClassType. Now, we have DIBuilder::createPtrAuthQualifiedType which is only applied to pointers with __ptrauth specifier.

@kovdan01 kovdan01 added the pauth label Dec 5, 2023
@kovdan01 kovdan01 self-assigned this Dec 5, 2023
@kovdan01
Copy link
Contributor Author

kovdan01 commented Dec 6, 2023

A question arises here if explicitly and implicitly signed pointers with identical effective signing schemas should have the same Dwarf info. As for now, I suppose that we can use the same info for simplicity, but if it's expected that such types should be treated different, the Dwarf info should be different as well.

@kovdan01
Copy link
Contributor Author

With #64 applied, we have DW_TAG_LLVM_ptrauth_type emitted containing signing schema and reference to the actual pointer type for the following implicitly signed pointers:

  • virtual table pointers;
  • free function pointers;
  • member function pointers.

For virtual function pointers, things are a bit different. We do not have the virtual table as a thing in IR debug metadata nodes and in Dwarf info. Instead, we only have an artificial member of a polymorphic class which holds the pointer to the table, and an attribute for virtual functions holding their position in the table. So, there is no object with DW_TAG_pointer_type which can be wrapped with DW_TAG_LLVM_ptrauth_type to mark underlying function as signed and specify the schema.

A possible solution is to propose a new attribute for DW_TAG_subprogram instances having DW_AT_virtuality other than DW_VIRTUALITY_none. This attribute would hold a reference to a DW_TAG_LLVM_ptrauth_type with the desired signing schema.

For both signed virtual table pointers and signed virtual function pointers in the table, we should teach the debugger to look at the corresponding attributes and apply the requested signing schema when constructing user expressions. For free and member function pointers, this should be transparent since we just changed the type and a __ptrauth specifier with parameters corresponding to the signing schema would be added to the pointer type when construction a user expression.

@asl
Copy link
Contributor

asl commented Dec 11, 2023

Tagging @ahmedbougacha

@kovdan01
Copy link
Contributor Author

Closing with the same reason as related #64 (should have been closed together with that): #64 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants