llvm-project/lldb/source/DataFormatters/CXXFunctionPointer.cpp
Jason Molenda 223e8ca026 Set a default number of address bits on Darwin arm64 systems
With arm64e ARMv8.3 pointer authentication, lldb needs to know how
many bits are used for addressing and how many are used for pointer
auth signing.  This should be determined dynamically from the inferior
system / corefile, but there are some workflows where it still isn't
recorded and we fall back on a default value that is correct on some
Darwin environments.

This patch also explicitly sets the vendor of mach-o binaries to
Apple, so we select an Apple ABI instead of a random other ABI.

It adds a function pointer formatter for systems where pointer
authentication is in use, and we can strip the ptrauth bits off
of the function pointer address and get a different value that
points to an actual symbol.

Differential Revision: https://reviews.llvm.org/D115431
rdar://84644661
2021-12-09 22:53:01 -08:00

84 lines
3.2 KiB
C++

//===-- CXXFunctionPointer.cpp---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/DataFormatters/CXXFunctionPointer.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Stream.h"
#include <string>
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
bool lldb_private::formatters::CXXFunctionPointerSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
std::string destination;
StreamString sstr;
AddressType func_ptr_address_type = eAddressTypeInvalid;
addr_t func_ptr_address = valobj.GetPointerValue(&func_ptr_address_type);
if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) {
switch (func_ptr_address_type) {
case eAddressTypeInvalid:
case eAddressTypeFile:
case eAddressTypeHost:
break;
case eAddressTypeLoad: {
ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
Address so_addr;
Target *target = exe_ctx.GetTargetPtr();
if (target && !target->GetSectionLoadList().IsEmpty()) {
target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address,
so_addr);
if (so_addr.GetSection() == nullptr) {
// If we have an address that doesn't correspond to any symbol,
// it might have authentication bits. Strip them & see if it
// now points to a symbol -- if so, do the SymbolContext lookup
// based on the stripped address.
// If we find a symbol with the ptrauth bits stripped, print the
// raw value into the stream, and replace the Address with the
// one that points to a symbol for a fuller description.
if (Process *process = exe_ctx.GetProcessPtr()) {
if (ABISP abi_sp = process->GetABI()) {
addr_t fixed_addr = abi_sp->FixCodeAddress(func_ptr_address);
if (fixed_addr != func_ptr_address) {
Address test_address;
test_address.SetLoadAddress(fixed_addr, target);
if (test_address.GetSection() != nullptr) {
int addrsize = target->GetArchitecture().GetAddressByteSize();
sstr.Printf("actual=0x%*.*" PRIx64 " ", addrsize * 2,
addrsize * 2, fixed_addr);
so_addr = test_address;
}
}
}
}
}
if (so_addr.IsValid()) {
so_addr.Dump(&sstr, exe_ctx.GetBestExecutionContextScope(),
Address::DumpStyleResolvedDescription,
Address::DumpStyleSectionNameOffset);
}
}
} break;
}
}
if (sstr.GetSize() > 0) {
stream.Printf("(%s)", sstr.GetData());
return true;
} else
return false;
}