Path: blob/main/contrib/llvm-project/lldb/source/Core/DumpRegisterValue.cpp
96333 views
//===-- DumpRegisterValue.cpp ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Core/DumpRegisterValue.h"9#include "lldb/Core/DumpDataExtractor.h"10#include "lldb/Core/ValueObject.h"11#include "lldb/Core/ValueObjectConstResult.h"12#include "lldb/DataFormatters/DumpValueObjectOptions.h"13#include "lldb/Target/RegisterFlags.h"14#include "lldb/Utility/DataExtractor.h"15#include "lldb/Utility/Endian.h"16#include "lldb/Utility/RegisterValue.h"17#include "lldb/Utility/StreamString.h"18#include "lldb/lldb-private-types.h"19#include "llvm/ADT/bit.h"2021using namespace lldb;2223template <typename T>24static void dump_type_value(lldb_private::CompilerType &fields_type, T value,25lldb_private::ExecutionContextScope *exe_scope,26const lldb_private::RegisterInfo ®_info,27lldb_private::Stream &strm) {28lldb::ByteOrder target_order = exe_scope->CalculateProcess()->GetByteOrder();2930// For the bitfield types we generate, it is expected that the fields are31// in what is usually a big endian order. Most significant field first.32// This is also clang's internal ordering and the order we want to print33// them. On a big endian host this all matches up, for a little endian34// host we have to swap the order of the fields before display.35if (target_order == lldb::ByteOrder::eByteOrderLittle) {36value = reg_info.flags_type->ReverseFieldOrder(value);37}3839// Then we need to match the target's endian on a byte level as well.40if (lldb_private::endian::InlHostByteOrder() != target_order)41value = llvm::byteswap(value);4243lldb_private::DataExtractor data_extractor{44&value, sizeof(T), lldb_private::endian::InlHostByteOrder(), 8};4546lldb::ValueObjectSP vobj_sp = lldb_private::ValueObjectConstResult::Create(47exe_scope, fields_type, lldb_private::ConstString(), data_extractor);48lldb_private::DumpValueObjectOptions dump_options;49lldb_private::DumpValueObjectOptions::ChildPrintingDecider decider =50[](lldb_private::ConstString varname) {51// Unnamed bit-fields are padding that we don't want to show.52return varname.GetLength();53};54dump_options.SetChildPrintingDecider(decider).SetHideRootType(true);5556if (llvm::Error error = vobj_sp->Dump(strm, dump_options))57strm << "error: " << toString(std::move(error));58}5960void lldb_private::DumpRegisterValue(const RegisterValue ®_val, Stream &s,61const RegisterInfo ®_info,62bool prefix_with_name,63bool prefix_with_alt_name, Format format,64uint32_t reg_name_right_align_at,65ExecutionContextScope *exe_scope,66bool print_flags, TargetSP target_sp) {67DataExtractor data;68if (!reg_val.GetData(data))69return;7071bool name_printed = false;72// For simplicity, alignment of the register name printing applies only in73// the most common case where:74//75// prefix_with_name^prefix_with_alt_name is true76//77StreamString format_string;78if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name))79format_string.Printf("%%%us", reg_name_right_align_at);80else81format_string.Printf("%%s");82std::string fmt = std::string(format_string.GetString());83if (prefix_with_name) {84if (reg_info.name) {85s.Printf(fmt.c_str(), reg_info.name);86name_printed = true;87} else if (reg_info.alt_name) {88s.Printf(fmt.c_str(), reg_info.alt_name);89prefix_with_alt_name = false;90name_printed = true;91}92}93if (prefix_with_alt_name) {94if (name_printed)95s.PutChar('/');96if (reg_info.alt_name) {97s.Printf(fmt.c_str(), reg_info.alt_name);98name_printed = true;99} else if (!name_printed) {100// No alternate name but we were asked to display a name, so show the101// main name102s.Printf(fmt.c_str(), reg_info.name);103name_printed = true;104}105}106if (name_printed)107s.PutCString(" = ");108109if (format == eFormatDefault)110format = reg_info.format;111112DumpDataExtractor(data, &s,1130, // Offset in "data"114format, // Format to use when dumping115reg_info.byte_size, // item_byte_size1161, // item_count117UINT32_MAX, // num_per_line118LLDB_INVALID_ADDRESS, // base_addr1190, // item_bit_size1200, // item_bit_offset121exe_scope);122123if (!print_flags || !reg_info.flags_type || !exe_scope || !target_sp ||124(reg_info.byte_size != 4 && reg_info.byte_size != 8))125return;126127CompilerType fields_type = target_sp->GetRegisterType(128reg_info.name, *reg_info.flags_type, reg_info.byte_size);129130// Use a new stream so we can remove a trailing newline later.131StreamString fields_stream;132133if (reg_info.byte_size == 4) {134dump_type_value(fields_type, reg_val.GetAsUInt32(), exe_scope, reg_info,135fields_stream);136} else {137dump_type_value(fields_type, reg_val.GetAsUInt64(), exe_scope, reg_info,138fields_stream);139}140141// Registers are indented like:142// (lldb) register read foo143// foo = 0x12345678144// So we need to indent to match that.145146// First drop the extra newline that the value printer added. The register147// command will add one itself.148llvm::StringRef fields_str = fields_stream.GetString().drop_back();149150// End the line that contains " foo = 0x12345678".151s.EOL();152153// Then split the value lines and indent each one.154bool first = true;155while (fields_str.size()) {156std::pair<llvm::StringRef, llvm::StringRef> split = fields_str.split('\n');157fields_str = split.second;158// Indent as far as the register name did.159s.Printf(fmt.c_str(), "");160161// Lines after the first won't have " = " so compensate for that.162if (!first)163s << " ";164first = false;165166s << split.first;167168// On the last line we don't want a newline because the command will add169// one too.170if (fields_str.size())171s.EOL();172}173}174175176