brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · aff4d2c Raw
175 lines · cpp
1//===-- DumpRegisterValue.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/DumpRegisterValue.h"10#include "lldb/Core/DumpDataExtractor.h"11#include "lldb/DataFormatters/DumpValueObjectOptions.h"12#include "lldb/Target/RegisterFlags.h"13#include "lldb/Utility/DataExtractor.h"14#include "lldb/Utility/Endian.h"15#include "lldb/Utility/RegisterValue.h"16#include "lldb/Utility/StreamString.h"17#include "lldb/ValueObject/ValueObject.h"18#include "lldb/ValueObject/ValueObjectConstResult.h"19#include "lldb/lldb-private-types.h"20#include "llvm/ADT/bit.h"21 22using namespace lldb;23 24template <typename T>25static void dump_type_value(lldb_private::CompilerType &fields_type, T value,26                            lldb_private::ExecutionContextScope *exe_scope,27                            const lldb_private::RegisterInfo &reg_info,28                            lldb_private::Stream &strm) {29  lldb::ByteOrder target_order = exe_scope->CalculateProcess()->GetByteOrder();30 31  // For the bitfield types we generate, it is expected that the fields are32  // in what is usually a big endian order. Most significant field first.33  // This is also clang's internal ordering and the order we want to print34  // them. On a big endian host this all matches up, for a little endian35  // host we have to swap the order of the fields before display.36  if (target_order == lldb::ByteOrder::eByteOrderLittle) {37    value = reg_info.flags_type->ReverseFieldOrder(value);38  }39 40  // Then we need to match the target's endian on a byte level as well.41  if (lldb_private::endian::InlHostByteOrder() != target_order)42    value = llvm::byteswap(value);43 44  lldb_private::DataExtractor data_extractor{45      &value, sizeof(T), lldb_private::endian::InlHostByteOrder(), 8};46 47  lldb::ValueObjectSP vobj_sp = lldb_private::ValueObjectConstResult::Create(48      exe_scope, fields_type, lldb_private::ConstString(), data_extractor);49  lldb_private::DumpValueObjectOptions dump_options;50  lldb_private::DumpValueObjectOptions::ChildPrintingDecider decider =51      [](lldb_private::ConstString varname) {52        // Unnamed bit-fields are padding that we don't want to show.53        return varname.GetLength();54      };55  dump_options.SetChildPrintingDecider(decider).SetHideRootType(true);56 57  if (llvm::Error error = vobj_sp->Dump(strm, dump_options))58    strm << "error: " << toString(std::move(error));59}60 61void lldb_private::DumpRegisterValue(const RegisterValue &reg_val, Stream &s,62                                     const RegisterInfo &reg_info,63                                     bool prefix_with_name,64                                     bool prefix_with_alt_name, Format format,65                                     uint32_t reg_name_right_align_at,66                                     ExecutionContextScope *exe_scope,67                                     bool print_flags, TargetSP target_sp) {68  DataExtractor data;69  if (!reg_val.GetData(data))70    return;71 72  bool name_printed = false;73  // For simplicity, alignment of the register name printing applies only in74  // the most common case where:75  //76  //     prefix_with_name^prefix_with_alt_name is true77  //78  StreamString format_string;79  if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name))80    format_string.Printf("%%%us", reg_name_right_align_at);81  else82    format_string.Printf("%%s");83  std::string fmt = std::string(format_string.GetString());84  if (prefix_with_name) {85    if (reg_info.name) {86      s.Printf(fmt.c_str(), reg_info.name);87      name_printed = true;88    } else if (reg_info.alt_name) {89      s.Printf(fmt.c_str(), reg_info.alt_name);90      prefix_with_alt_name = false;91      name_printed = true;92    }93  }94  if (prefix_with_alt_name) {95    if (name_printed)96      s.PutChar('/');97    if (reg_info.alt_name) {98      s.Printf(fmt.c_str(), reg_info.alt_name);99      name_printed = true;100    } else if (!name_printed) {101      // No alternate name but we were asked to display a name, so show the102      // main name103      s.Printf(fmt.c_str(), reg_info.name);104      name_printed = true;105    }106  }107  if (name_printed)108    s.PutCString(" = ");109 110  if (format == eFormatDefault)111    format = reg_info.format;112 113  DumpDataExtractor(data, &s,114                    0,                    // Offset in "data"115                    format,               // Format to use when dumping116                    reg_info.byte_size,   // item_byte_size117                    1,                    // item_count118                    UINT32_MAX,           // num_per_line119                    LLDB_INVALID_ADDRESS, // base_addr120                    0,                    // item_bit_size121                    0,                    // item_bit_offset122                    exe_scope);123 124  if (!print_flags || !reg_info.flags_type || !exe_scope || !target_sp ||125      (reg_info.byte_size != 4 && reg_info.byte_size != 8))126    return;127 128  CompilerType fields_type = target_sp->GetRegisterType(129      reg_info.name, *reg_info.flags_type, reg_info.byte_size);130 131  // Use a new stream so we can remove a trailing newline later.132  StreamString fields_stream;133 134  if (reg_info.byte_size == 4) {135    dump_type_value(fields_type, reg_val.GetAsUInt32(), exe_scope, reg_info,136                    fields_stream);137  } else {138    dump_type_value(fields_type, reg_val.GetAsUInt64(), exe_scope, reg_info,139                    fields_stream);140  }141 142  // Registers are indented like:143  // (lldb) register read foo144  //     foo = 0x12345678145  // So we need to indent to match that.146 147  // First drop the extra newline that the value printer added. The register148  // command will add one itself.149  llvm::StringRef fields_str = fields_stream.GetString().drop_back();150 151  // End the line that contains "    foo = 0x12345678".152  s.EOL();153 154  // Then split the value lines and indent each one.155  bool first = true;156  while (fields_str.size()) {157    std::pair<llvm::StringRef, llvm::StringRef> split = fields_str.split('\n');158    fields_str = split.second;159    // Indent as far as the register name did.160    s.Printf(fmt.c_str(), "");161 162    // Lines after the first won't have " = " so compensate for that.163    if (!first)164      s << "   ";165    first = false;166 167    s << split.first;168 169    // On the last line we don't want a newline because the command will add170    // one too.171    if (fields_str.size())172      s.EOL();173  }174}175