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