15ffd83dbSDimitry Andric //===-- CXXFunctionPointer.cpp---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/DataFormatters/CXXFunctionPointer.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
120eae32dcSDimitry Andric #include "lldb/Target/ABI.h"
130b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
140b57cec5SDimitry Andric #include "lldb/Target/Target.h"
150b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
16*c9157d92SDimitry Andric #include "lldb/lldb-enumerations.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include <string>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace lldb;
210b57cec5SDimitry Andric using namespace lldb_private;
220b57cec5SDimitry Andric using namespace lldb_private::formatters;
230b57cec5SDimitry Andric 
CXXFunctionPointerSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)240b57cec5SDimitry Andric bool lldb_private::formatters::CXXFunctionPointerSummaryProvider(
250b57cec5SDimitry Andric     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
260b57cec5SDimitry Andric   std::string destination;
270b57cec5SDimitry Andric   StreamString sstr;
280b57cec5SDimitry Andric   AddressType func_ptr_address_type = eAddressTypeInvalid;
290b57cec5SDimitry Andric   addr_t func_ptr_address = valobj.GetPointerValue(&func_ptr_address_type);
300b57cec5SDimitry Andric   if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) {
310b57cec5SDimitry Andric     switch (func_ptr_address_type) {
320b57cec5SDimitry Andric     case eAddressTypeInvalid:
330b57cec5SDimitry Andric     case eAddressTypeFile:
340b57cec5SDimitry Andric     case eAddressTypeHost:
350b57cec5SDimitry Andric       break;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric     case eAddressTypeLoad: {
380b57cec5SDimitry Andric       ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric       Address so_addr;
410b57cec5SDimitry Andric       Target *target = exe_ctx.GetTargetPtr();
420b57cec5SDimitry Andric       if (target && !target->GetSectionLoadList().IsEmpty()) {
430eae32dcSDimitry Andric         target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address,
440eae32dcSDimitry Andric                                                         so_addr);
450eae32dcSDimitry Andric         if (so_addr.GetSection() == nullptr) {
460eae32dcSDimitry Andric           // If we have an address that doesn't correspond to any symbol,
470eae32dcSDimitry Andric           // it might have authentication bits.  Strip them & see if it
480eae32dcSDimitry Andric           // now points to a symbol -- if so, do the SymbolContext lookup
490eae32dcSDimitry Andric           // based on the stripped address.
500eae32dcSDimitry Andric           // If we find a symbol with the ptrauth bits stripped, print the
510eae32dcSDimitry Andric           // raw value into the stream, and replace the Address with the
520eae32dcSDimitry Andric           // one that points to a symbol for a fuller description.
530eae32dcSDimitry Andric           if (Process *process = exe_ctx.GetProcessPtr()) {
540eae32dcSDimitry Andric             if (ABISP abi_sp = process->GetABI()) {
550eae32dcSDimitry Andric               addr_t fixed_addr = abi_sp->FixCodeAddress(func_ptr_address);
560eae32dcSDimitry Andric               if (fixed_addr != func_ptr_address) {
570eae32dcSDimitry Andric                 Address test_address;
580eae32dcSDimitry Andric                 test_address.SetLoadAddress(fixed_addr, target);
590eae32dcSDimitry Andric                 if (test_address.GetSection() != nullptr) {
600eae32dcSDimitry Andric                   int addrsize = target->GetArchitecture().GetAddressByteSize();
610eae32dcSDimitry Andric                   sstr.Printf("actual=0x%*.*" PRIx64 " ", addrsize * 2,
620eae32dcSDimitry Andric                               addrsize * 2, fixed_addr);
630eae32dcSDimitry Andric                   so_addr = test_address;
640eae32dcSDimitry Andric                 }
650eae32dcSDimitry Andric               }
660eae32dcSDimitry Andric             }
670eae32dcSDimitry Andric           }
680eae32dcSDimitry Andric         }
690eae32dcSDimitry Andric 
700eae32dcSDimitry Andric         if (so_addr.IsValid()) {
710b57cec5SDimitry Andric           so_addr.Dump(&sstr, exe_ctx.GetBestExecutionContextScope(),
720b57cec5SDimitry Andric                        Address::DumpStyleResolvedDescription,
730b57cec5SDimitry Andric                        Address::DumpStyleSectionNameOffset);
740b57cec5SDimitry Andric         }
750b57cec5SDimitry Andric       }
760b57cec5SDimitry Andric     } break;
770b57cec5SDimitry Andric     }
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric   if (sstr.GetSize() > 0) {
80*c9157d92SDimitry Andric     if (valobj.GetValueType() == lldb::eValueTypeVTableEntry)
81*c9157d92SDimitry Andric       stream.PutCString(sstr.GetData());
82*c9157d92SDimitry Andric     else
830b57cec5SDimitry Andric       stream.Printf("(%s)", sstr.GetData());
840b57cec5SDimitry Andric     return true;
850b57cec5SDimitry Andric   } else
860b57cec5SDimitry Andric     return false;
870b57cec5SDimitry Andric }
88