access-softek / llvm-project

Other
0 stars 0 forks source link

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

Closed kovdan01 closed 8 months ago

kovdan01 commented 10 months ago

In f28e8dbbbd445af8ec0c720aa8fe96214e3a9ce7, 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 commented 10 months ago

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 commented 10 months ago

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:

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 commented 10 months ago

Tagging @ahmedbougacha

kovdan01 commented 8 months ago

Closing with the same reason as related #64 (should have been closed together with that): https://github.com/access-softek/llvm-project/pull/64#issuecomment-1909335683