brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.4 KiB · 449f85b Raw
313 lines · cpp
1//===-- RegisterContextUnifiedCore.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 "RegisterContextUnifiedCore.h"10#include "lldb/Target/DynamicRegisterInfo.h"11#include "lldb/Target/Process.h"12#include "lldb/Utility/DataExtractor.h"13#include "lldb/Utility/RegisterValue.h"14#include "lldb/Utility/StructuredData.h"15 16using namespace lldb;17using namespace lldb_private;18 19RegisterContextUnifiedCore::RegisterContextUnifiedCore(20    Thread &thread, uint32_t concrete_frame_idx,21    RegisterContextSP core_thread_regctx_sp,22    StructuredData::ObjectSP metadata_thread_registers)23    : RegisterContext(thread, concrete_frame_idx) {24 25  ProcessSP process_sp(thread.GetProcess());26  Target &target = process_sp->GetTarget();27  StructuredData::Dictionary *metadata_registers_dict = nullptr;28 29  // If we have thread metadata, check if the keys for register30  // definitions are present; if not, clear the ObjectSP.31  if (metadata_thread_registers &&32      metadata_thread_registers->GetAsDictionary() &&33      metadata_thread_registers->GetAsDictionary()->HasKey("register_info")) {34    metadata_registers_dict = metadata_thread_registers->GetAsDictionary()35                                  ->GetValueForKey("register_info")36                                  ->GetAsDictionary();37    if (metadata_registers_dict)38      if (!metadata_registers_dict->HasKey("sets") ||39          !metadata_registers_dict->HasKey("registers"))40        metadata_registers_dict = nullptr;41  }42 43  // When creating a register set list from the two sources,44  // the LC_THREAD aka core_thread_regctx_sp register sets45  // will be used at the same indexes.46  // Any additional sets named by the thread metadata registers47  // will be added after them.  If the thread metadata48  // specify a set with the same name as LC_THREAD, the already-used49  // index from the core register context will be used in50  // the RegisterInfo.51  std::map<size_t, size_t> metadata_regset_to_combined_regset;52 53  // Calculate the total size of the register store buffer we need54  // for all registers.  The corefile register definitions may include55  // RegisterInfo descriptions of registers that aren't actually56  // available.  For simplicity, calculate the size of all registers57  // as if they are available, so we can maintain the same offsets into58  // the buffer.59  uint32_t core_buffer_end = 0;60  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) {61    const RegisterInfo *reginfo =62        core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);63    core_buffer_end =64        std::max(reginfo->byte_offset + reginfo->byte_size, core_buffer_end);65  }66 67  // Add metadata register sizes to the total buffer size.68  uint32_t combined_buffer_end = core_buffer_end;69  if (metadata_registers_dict) {70    StructuredData::Array *registers = nullptr;71    if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))72      registers->ForEach(73          [&combined_buffer_end](StructuredData::Object *ent) -> bool {74            uint32_t bitsize;75            if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",76                                                                 bitsize))77              return false;78            combined_buffer_end += (bitsize / 8);79            return true;80          });81  }82  m_register_data.resize(combined_buffer_end, 0);83 84  // Copy the core register values into our combined data buffer,85  // skip registers that are contained within another (e.g. w0 vs. x0)86  // and registers that return as "unavailable".87  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterCount(); idx++) {88    const RegisterInfo *reginfo =89        core_thread_regctx_sp->GetRegisterInfoAtIndex(idx);90    RegisterValue val;91    if (!reginfo->value_regs &&92        core_thread_regctx_sp->ReadRegister(reginfo, val))93      memcpy(m_register_data.data() + reginfo->byte_offset, val.GetBytes(),94             val.GetByteSize());95  }96 97  // Set 'offset' fields for each register definition into our combined98  // register data buffer. DynamicRegisterInfo needs this field set to99  // parse the JSON.100  // Also copy the values of the registers into our register data buffer.101  if (metadata_registers_dict) {102    size_t offset = core_buffer_end;103    ByteOrder byte_order = core_thread_regctx_sp->GetByteOrder();104    StructuredData::Array *registers;105    if (metadata_registers_dict->GetValueForKeyAsArray("registers", registers))106      registers->ForEach([this, &offset,107                          byte_order](StructuredData::Object *ent) -> bool {108        uint64_t bitsize;109        uint64_t value;110        if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("bitsize",111                                                             bitsize))112          return false;113        if (!ent->GetAsDictionary()->GetValueForKeyAsInteger("value", value)) {114          // We had a bitsize but no value, so move the offset forward I guess.115          offset += (bitsize / 8);116          return false;117        }118        ent->GetAsDictionary()->AddIntegerItem("offset", offset);119        Status error;120        const int bytesize = bitsize / 8;121        switch (bytesize) {122        case 2: {123          Scalar value_scalar((uint16_t)value);124          value_scalar.GetAsMemoryData(m_register_data.data() + offset,125                                       bytesize, byte_order, error);126          offset += bytesize;127        } break;128        case 4: {129          Scalar value_scalar((uint32_t)value);130          value_scalar.GetAsMemoryData(m_register_data.data() + offset,131                                       bytesize, byte_order, error);132          offset += bytesize;133        } break;134        case 8: {135          Scalar value_scalar((uint64_t)value);136          value_scalar.GetAsMemoryData(m_register_data.data() + offset,137                                       bytesize, byte_order, error);138          offset += bytesize;139        } break;140        }141        return true;142      });143  }144 145  // Create a DynamicRegisterInfo from the metadata JSON.146  std::unique_ptr<DynamicRegisterInfo> additional_reginfo_up;147  if (metadata_registers_dict)148    additional_reginfo_up = DynamicRegisterInfo::Create(149        *metadata_registers_dict, target.GetArchitecture());150 151  // Put the RegisterSet names in the constant string pool,152  // to sidestep lifetime issues of char*'s.153  auto copy_regset_name = [](RegisterSet &dst, const RegisterSet &src) {154    dst.name = ConstString(src.name).AsCString();155    if (src.short_name)156      dst.short_name = ConstString(src.short_name).AsCString();157    else158      dst.short_name = nullptr;159  };160 161  // Copy the core thread register sets into our combined register set list.162  // RegisterSet indexes will be identical for the LC_THREAD RegisterContext.163  for (size_t idx = 0; idx < core_thread_regctx_sp->GetRegisterSetCount();164       idx++) {165    RegisterSet new_set;166    const RegisterSet *old_set = core_thread_regctx_sp->GetRegisterSet(idx);167    copy_regset_name(new_set, *old_set);168    m_register_sets.push_back(new_set);169  }170 171  // Add any additional metadata RegisterSets to our combined RegisterSet array.172  if (additional_reginfo_up) {173    for (size_t idx = 0; idx < additional_reginfo_up->GetNumRegisterSets();174         idx++) {175      // See if this metadata RegisterSet name matches one already present176      // from the LC_THREAD RegisterContext.177      bool found_match = false;178      const RegisterSet *old_set = additional_reginfo_up->GetRegisterSet(idx);179      for (size_t jdx = 0; jdx < m_register_sets.size(); jdx++) {180        if (strcmp(m_register_sets[jdx].name, old_set->name) == 0) {181          metadata_regset_to_combined_regset[idx] = jdx;182          found_match = true;183          break;184        }185      }186      // This metadata RegisterSet is a new one.187      // Add it to the combined RegisterSet array.188      if (!found_match) {189        RegisterSet new_set;190        copy_regset_name(new_set, *old_set);191        metadata_regset_to_combined_regset[idx] = m_register_sets.size();192        m_register_sets.push_back(new_set);193      }194    }195  }196 197  // Set up our combined RegisterInfo array, one RegisterSet at a time.198  for (size_t combined_regset_idx = 0;199       combined_regset_idx < m_register_sets.size(); combined_regset_idx++) {200    uint32_t registers_this_regset = 0;201 202    // Copy all LC_THREAD RegisterInfos that have a value into our203    // combined RegisterInfo array.  (the LC_THREAD RegisterContext204    // may describe registers that were not provided in this thread)205    //206    // LC_THREAD register set indexes are identical to the combined207    // register set indexes.  The combined register set array may have208    // additional entries.209    if (combined_regset_idx < core_thread_regctx_sp->GetRegisterSetCount()) {210      const RegisterSet *regset =211          core_thread_regctx_sp->GetRegisterSet(combined_regset_idx);212      // Copy all the registers that have values in.213      for (size_t j = 0; j < regset->num_registers; j++) {214        uint32_t reg_idx = regset->registers[j];215        const RegisterInfo *reginfo =216            core_thread_regctx_sp->GetRegisterInfoAtIndex(reg_idx);217        RegisterValue val;218        if (!reginfo->value_regs &&219            core_thread_regctx_sp->ReadRegister(reginfo, val)) {220          m_regset_regnum_collection[combined_regset_idx].push_back(221              m_register_infos.size());222          m_register_infos.push_back(*reginfo);223          registers_this_regset++;224        }225      }226    }227 228    // Copy all the metadata RegisterInfos into our combined combined229    // RegisterInfo array.230    // The metadata may add registers to one of the LC_THREAD register sets,231    // or its own newly added register sets.  metadata_regset_to_combined_regset232    // has the association of the RegisterSet indexes between the two.233    if (additional_reginfo_up) {234      // Find the register set in the metadata that matches this register235      // set, then copy all its RegisterInfos.236      for (size_t setidx = 0;237           setidx < additional_reginfo_up->GetNumRegisterSets(); setidx++) {238        if (metadata_regset_to_combined_regset[setidx] == combined_regset_idx) {239          const RegisterSet *regset =240              additional_reginfo_up->GetRegisterSet(setidx);241          for (size_t j = 0; j < regset->num_registers; j++) {242            uint32_t reg_idx = regset->registers[j];243            const RegisterInfo *reginfo =244                additional_reginfo_up->GetRegisterInfoAtIndex(reg_idx);245            m_regset_regnum_collection[combined_regset_idx].push_back(246                m_register_infos.size());247            m_register_infos.push_back(*reginfo);248            registers_this_regset++;249          }250        }251      }252    }253    m_register_sets[combined_regset_idx].num_registers = registers_this_regset;254    m_register_sets[combined_regset_idx].registers =255        m_regset_regnum_collection[combined_regset_idx].data();256  }257}258 259size_t RegisterContextUnifiedCore::GetRegisterCount() {260  return m_register_infos.size();261}262 263const RegisterInfo *264RegisterContextUnifiedCore::GetRegisterInfoAtIndex(size_t reg) {265  if (reg < m_register_infos.size())266    return &m_register_infos[reg];267  return nullptr;268}269 270size_t RegisterContextUnifiedCore::GetRegisterSetCount() {271  return m_register_sets.size();272}273 274const RegisterSet *RegisterContextUnifiedCore::GetRegisterSet(size_t set) {275  if (set < m_register_sets.size())276    return &m_register_sets[set];277  return nullptr;278}279 280bool RegisterContextUnifiedCore::ReadRegister(281    const lldb_private::RegisterInfo *reg_info,282    lldb_private::RegisterValue &value) {283  if (!reg_info)284    return false;285  if (ProcessSP process_sp = m_thread.GetProcess()) {286    DataExtractor regdata(m_register_data.data(), m_register_data.size(),287                          process_sp->GetByteOrder(),288                          process_sp->GetAddressByteSize());289    offset_t offset = reg_info->byte_offset;290    switch (reg_info->byte_size) {291    case 2:292      value.SetUInt16(regdata.GetU16(&offset));293      break;294    case 4:295      value.SetUInt32(regdata.GetU32(&offset));296      break;297    case 8:298      value.SetUInt64(regdata.GetU64(&offset));299      break;300    default:301      return false;302    }303    return true;304  }305  return false;306}307 308bool RegisterContextUnifiedCore::WriteRegister(309    const lldb_private::RegisterInfo *reg_info,310    const lldb_private::RegisterValue &value) {311  return false;312}313