Example #1
0
  void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                   lldb::addr_t process_address, Status &err) override {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

    const lldb::addr_t load_addr = process_address + m_offset;

    if (log) {
      log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64
                  ", m_register_info = %s]",
                  (uint64_t)load_addr, m_register_info.name);
    }

    RegisterValue reg_value;

    if (!frame_sp.get()) {
      err.SetErrorStringWithFormat(
          "couldn't materialize register %s without a stack frame",
          m_register_info.name);
      return;
    }

    lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();

    if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
      err.SetErrorStringWithFormat("couldn't read the value of register %s",
                                   m_register_info.name);
      return;
    }

    DataExtractor register_data;

    if (!reg_value.GetData(register_data)) {
      err.SetErrorStringWithFormat("couldn't get the data for register %s",
                                   m_register_info.name);
      return;
    }

    if (register_data.GetByteSize() != m_register_info.byte_size) {
      err.SetErrorStringWithFormat(
          "data for register %s had size %llu but we expected %llu",
          m_register_info.name, (unsigned long long)register_data.GetByteSize(),
          (unsigned long long)m_register_info.byte_size);
      return;
    }

    m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(),
                                                 register_data.GetByteSize()));

    Status write_error;

    map.WriteMemory(load_addr, register_data.GetDataStart(),
                    register_data.GetByteSize(), write_error);

    if (!write_error.Success()) {
      err.SetErrorStringWithFormat(
          "couldn't write the contents of register %s: %s",
          m_register_info.name, write_error.AsCString());
      return;
    }
  }
Example #2
0
  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

    const lldb::addr_t load_addr = process_address + m_offset;

    if (log) {
      log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64
                  ", m_register_info = %s]",
                  (uint64_t)load_addr, m_register_info.name);
    }

    Status extract_error;

    DataExtractor register_data;

    if (!frame_sp.get()) {
      err.SetErrorStringWithFormat(
          "couldn't dematerialize register %s without a stack frame",
          m_register_info.name);
      return;
    }

    lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();

    map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
                      extract_error);

    if (!extract_error.Success()) {
      err.SetErrorStringWithFormat("couldn't get the data for register %s: %s",
                                   m_register_info.name,
                                   extract_error.AsCString());
      return;
    }

    if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
                register_data.GetByteSize())) {
      // No write required, and in particular we avoid errors if the register
      // wasn't writable

      m_register_contents.reset();
      return;
    }

    m_register_contents.reset();

    RegisterValue register_value(
        const_cast<uint8_t *>(register_data.GetDataStart()),
        register_data.GetByteSize(), register_data.GetByteOrder());

    if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
      err.SetErrorStringWithFormat("couldn't write the value of register %s",
                                   m_register_info.name);
      return;
    }
  }
Example #3
0
Materializer::DematerializerSP
Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                          lldb::addr_t process_address, Status &error) {
  ExecutionContextScope *exe_scope = frame_sp.get();

  if (!exe_scope)
    exe_scope = map.GetBestExecutionContextScope();

  DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();

  if (dematerializer_sp) {
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't materialize: already materialized");
  }

  DematerializerSP ret(
      new Dematerializer(*this, frame_sp, map, process_address));

  if (!exe_scope) {
    error.SetErrorToGenericError();
    error.SetErrorString("Couldn't materialize: target doesn't exist");
  }

  for (EntityUP &entity_up : m_entities) {
    entity_up->Materialize(frame_sp, map, process_address, error);

    if (!error.Success())
      return DematerializerSP();
  }

  if (Log *log =
          lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
    log->Printf(
        "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
        ") materialized:",
        static_cast<void *>(frame_sp.get()), process_address);
    for (EntityUP &entity_up : m_entities)
      entity_up->DumpToLog(map, process_address, log);
  }

  m_dematerializer_wp = ret;

  return ret;
}
Example #4
0
Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
                                           lldb::ValueObjectSP &new_value_sp) {
  Status error;
  if (!new_value_sp) {
    error.SetErrorString("Empty value object for return value.");
    return error;
  }

  CompilerType compiler_type = new_value_sp->GetCompilerType();
  if (!compiler_type) {
    error.SetErrorString("Null clang type for return value.");
    return error;
  }

  Thread *thread = frame_sp->GetThread().get();

  bool is_signed;
  uint32_t count;
  bool is_complex;

  RegisterContext *reg_ctx = thread->GetRegisterContext().get();

  bool set_it_simple = false;
  if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
      compiler_type.IsPointerType()) {
    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);

    DataExtractor data;
    Status data_error;
    size_t num_bytes = new_value_sp->GetData(data, data_error);
    if (data_error.Fail()) {
      error.SetErrorStringWithFormat(
          "Couldn't convert return value to raw data: %s",
          data_error.AsCString());
      return error;
    }
    lldb::offset_t offset = 0;
    if (num_bytes <= 8) {
      uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);

      if (reg_ctx->WriteRegisterFromUnsigned(reg_info, raw_value))
        set_it_simple = true;
    } else {
      error.SetErrorString("We don't support returning longer than 64 bit "
                           "integer values at present.");
    }
  } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
    if (is_complex)
      error.SetErrorString(
          "We don't support returning complex values at present");
    else {
      size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
      if (bit_width <= 64) {
        DataExtractor data;
        Status data_error;
        size_t num_bytes = new_value_sp->GetData(data, data_error);
        if (data_error.Fail()) {
          error.SetErrorStringWithFormat(
              "Couldn't convert return value to raw data: %s",
              data_error.AsCString());
          return error;
        }

        unsigned char buffer[16];
        ByteOrder byte_order = data.GetByteOrder();

        data.CopyByteOrderedData(0, num_bytes, buffer, 16, byte_order);
        set_it_simple = true;
      } else {
        // FIXME - don't know how to do 80 bit long doubles yet.
        error.SetErrorString(
            "We don't support returning float values > 64 bits at present");
      }
    }
  }

  if (!set_it_simple) {
    // Okay we've got a structure or something that doesn't fit in a simple
    // register.
    // We should figure out where it really goes, but we don't support this yet.
    error.SetErrorString("We only support setting simple integer and float "
                         "return types at present.");
  }

  return error;
}
Example #5
0
  void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                     lldb::addr_t process_address, lldb::addr_t frame_top,
                     lldb::addr_t frame_bottom, Status &err) override {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

    const lldb::addr_t load_addr = process_address + m_offset;
    if (log) {
      log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64
                  ", m_variable_sp = %s]",
                  (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
    }

    if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
      ExecutionContextScope *scope = frame_sp.get();

      if (!scope)
        scope = map.GetBestExecutionContextScope();

      lldb::ValueObjectSP valobj_sp =
          ValueObjectVariable::Create(scope, m_variable_sp);

      if (!valobj_sp) {
        err.SetErrorStringWithFormat(
            "couldn't get a value object for variable %s",
            m_variable_sp->GetName().AsCString());
        return;
      }

      lldb_private::DataExtractor data;

      Status extract_error;

      map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(),
                        extract_error);

      if (!extract_error.Success()) {
        err.SetErrorStringWithFormat("couldn't get the data for variable %s",
                                     m_variable_sp->GetName().AsCString());
        return;
      }

      bool actually_write = true;

      if (m_original_data) {
        if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
            !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
                    data.GetByteSize())) {
          actually_write = false;
        }
      }

      Status set_error;

      if (actually_write) {
        valobj_sp->SetData(data, set_error);

        if (!set_error.Success()) {
          err.SetErrorStringWithFormat(
              "couldn't write the new contents of %s back into the variable",
              m_variable_sp->GetName().AsCString());
          return;
        }
      }

      Status free_error;

      map.Free(m_temporary_allocation, free_error);

      if (!free_error.Success()) {
        err.SetErrorStringWithFormat(
            "couldn't free the temporary region for %s: %s",
            m_variable_sp->GetName().AsCString(), free_error.AsCString());
        return;
      }

      m_original_data.reset();
      m_temporary_allocation = LLDB_INVALID_ADDRESS;
      m_temporary_allocation_size = 0;
    }
  }
Example #6
0
  void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
                   lldb::addr_t process_address, Status &err) override {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));

    const lldb::addr_t load_addr = process_address + m_offset;
    if (log) {
      log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64
                  ", m_variable_sp = %s]",
                  (uint64_t)load_addr, m_variable_sp->GetName().AsCString());
    }

    ExecutionContextScope *scope = frame_sp.get();

    if (!scope)
      scope = map.GetBestExecutionContextScope();

    lldb::ValueObjectSP valobj_sp =
        ValueObjectVariable::Create(scope, m_variable_sp);

    if (!valobj_sp) {
      err.SetErrorStringWithFormat(
          "couldn't get a value object for variable %s",
          m_variable_sp->GetName().AsCString());
      return;
    }

    Status valobj_error = valobj_sp->GetError();

    if (valobj_error.Fail()) {
      err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s",
                                   m_variable_sp->GetName().AsCString(),
                                   valobj_error.AsCString());
      return;
    }

    if (m_is_reference) {
      DataExtractor valobj_extractor;
      Status extract_error;
      valobj_sp->GetData(valobj_extractor, extract_error);

      if (!extract_error.Success()) {
        err.SetErrorStringWithFormat(
            "couldn't read contents of reference variable %s: %s",
            m_variable_sp->GetName().AsCString(), extract_error.AsCString());
        return;
      }

      lldb::offset_t offset = 0;
      lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);

      Status write_error;
      map.WritePointerToMemory(load_addr, reference_addr, write_error);

      if (!write_error.Success()) {
        err.SetErrorStringWithFormat("couldn't write the contents of reference "
                                     "variable %s to memory: %s",
                                     m_variable_sp->GetName().AsCString(),
                                     write_error.AsCString());
        return;
      }
    } else {
      AddressType address_type = eAddressTypeInvalid;
      const bool scalar_is_load_address = false;
      lldb::addr_t addr_of_valobj =
          valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
      if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
        Status write_error;
        map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);

        if (!write_error.Success()) {
          err.SetErrorStringWithFormat(
              "couldn't write the address of variable %s to memory: %s",
              m_variable_sp->GetName().AsCString(), write_error.AsCString());
          return;
        }
      } else {
        DataExtractor data;
        Status extract_error;
        valobj_sp->GetData(data, extract_error);
        if (!extract_error.Success()) {
          err.SetErrorStringWithFormat("couldn't get the value of %s: %s",
                                       m_variable_sp->GetName().AsCString(),
                                       extract_error.AsCString());
          return;
        }

        if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
          err.SetErrorStringWithFormat(
              "trying to create a temporary region for %s but one exists",
              m_variable_sp->GetName().AsCString());
          return;
        }

        if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) {
          if (data.GetByteSize() == 0 &&
              m_variable_sp->LocationExpression().IsValid() == false) {
            err.SetErrorStringWithFormat("the variable '%s' has no location, "
                                         "it may have been optimized out",
                                         m_variable_sp->GetName().AsCString());
          } else {
            err.SetErrorStringWithFormat(
                "size of variable %s (%" PRIu64
                ") is larger than the ValueObject's size (%" PRIu64 ")",
                m_variable_sp->GetName().AsCString(),
                m_variable_sp->GetType()->GetByteSize(), data.GetByteSize());
          }
          return;
        }

        size_t bit_align =
            m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign();
        size_t byte_align = (bit_align + 7) / 8;

        if (!byte_align)
          byte_align = 1;

        Status alloc_error;
        const bool zero_memory = false;

        m_temporary_allocation = map.Malloc(
            data.GetByteSize(), byte_align,
            lldb::ePermissionsReadable | lldb::ePermissionsWritable,
            IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);

        m_temporary_allocation_size = data.GetByteSize();

        m_original_data.reset(
            new DataBufferHeap(data.GetDataStart(), data.GetByteSize()));

        if (!alloc_error.Success()) {
          err.SetErrorStringWithFormat(
              "couldn't allocate a temporary region for %s: %s",
              m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
          return;
        }

        Status write_error;

        map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
                        data.GetByteSize(), write_error);

        if (!write_error.Success()) {
          err.SetErrorStringWithFormat(
              "couldn't write to the temporary region for %s: %s",
              m_variable_sp->GetName().AsCString(), write_error.AsCString());
          return;
        }

        Status pointer_write_error;

        map.WritePointerToMemory(load_addr, m_temporary_allocation,
                                 pointer_write_error);

        if (!pointer_write_error.Success()) {
          err.SetErrorStringWithFormat(
              "couldn't write the address of the temporary region for %s: %s",
              m_variable_sp->GetName().AsCString(),
              pointer_write_error.AsCString());
        }
      }
    }
  }