[Lldb-commits] [lldb] 9df19ce - Add uncovered enums in switches caused by 9434c083475e42f47383f3067fe2a155db5c6a30

2024-04-01 Thread David Blaikie via lldb-commits

Author: David Blaikie
Date: 2024-04-01T23:07:01Z
New Revision: 9df19ce40281551bd348b262a131085cf98dadf5

URL: 
https://github.com/llvm/llvm-project/commit/9df19ce40281551bd348b262a131085cf98dadf5
DIFF: 
https://github.com/llvm/llvm-project/commit/9df19ce40281551bd348b262a131085cf98dadf5.diff

LOG: Add uncovered enums in switches caused by 
9434c083475e42f47383f3067fe2a155db5c6a30

These are probably actually unreachable - perhaps an lldb developer
would be interested in rephrasing this change to move the new cases into
some unreachable/unsupported bucket, rather than my half-hearted guess
at what the desired behavior would be (completely untested, because
they're probably untestable/unreachable - maybe debugging from modules?)

Added: 


Modified: 
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Removed: 




diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index ebcc3bc99a801f..4a1c8d57655215 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -4097,6 +4097,8 @@ 
TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) {
 return lldb::eTypeClassArray;
   case clang::Type::DependentSizedArray:
 return lldb::eTypeClassArray;
+  case clang::Type::ArrayParameter:
+return lldb::eTypeClassArray;
   case clang::Type::DependentSizedExtVector:
 return lldb::eTypeClassVector;
   case clang::Type::DependentVector:
@@ -4776,6 +4778,7 @@ lldb::Encoding 
TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type,
 
   case clang::Type::IncompleteArray:
   case clang::Type::VariableArray:
+  case clang::Type::ArrayParameter:
 break;
 
   case clang::Type::ConstantArray:
@@ -5109,6 +5112,7 @@ lldb::Format 
TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) {
 
   case clang::Type::IncompleteArray:
   case clang::Type::VariableArray:
+  case clang::Type::ArrayParameter:
 break;
 
   case clang::Type::ConstantArray:



___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Don't crash when attempting to parse breakpoint id `N.` as `N.*` (PR #87263)

2024-04-01 Thread Jordan Rupprecht via lldb-commits

https://github.com/rupprecht closed 
https://github.com/llvm/llvm-project/pull/87263
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] a6cacee - [lldb] Don't crash when attempting to parse breakpoint id `N.` as `N.*` (#87263)

2024-04-01 Thread via lldb-commits

Author: Jordan Rupprecht
Date: 2024-04-01T16:02:12-05:00
New Revision: a6caceed8d27d4ebd44c517c3114a36a64ebddfe

URL: 
https://github.com/llvm/llvm-project/commit/a6caceed8d27d4ebd44c517c3114a36a64ebddfe
DIFF: 
https://github.com/llvm/llvm-project/commit/a6caceed8d27d4ebd44c517c3114a36a64ebddfe.diff

LOG: [lldb] Don't crash when attempting to parse breakpoint id `N.` as `N.*` 
(#87263)

We check if the next character after `N.` is `*` before we check its
length. Using `split` on the string is cleaner and less error prone than
using indices with `find` and `substr`.

Note: this does not make `N.` mean anything, it just prevents assertion
failures. `N.` is treated the same as an unrecognized breakpoint name:

```
(lldb) breakpoint enable 1
1 breakpoints enabled.
(lldb) breakpoint enable 1.*
1 breakpoints enabled.
(lldb) breakpoint enable 1.
0 breakpoints enabled.
(lldb) breakpoint enable xyz
0 breakpoints enabled.
```

Found via LLDB fuzzers.

Added: 


Modified: 
lldb/source/Breakpoint/BreakpointIDList.cpp

lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py

Removed: 




diff  --git a/lldb/source/Breakpoint/BreakpointIDList.cpp 
b/lldb/source/Breakpoint/BreakpointIDList.cpp
index 851d074e753588..97af1d40eb7a58 100644
--- a/lldb/source/Breakpoint/BreakpointIDList.cpp
+++ b/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -16,6 +16,7 @@
 #include "lldb/Utility/StreamString.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -111,32 +112,27 @@ llvm::Error BreakpointIDList::FindAndReplaceIDRanges(
 } else {
   // See if user has specified id.*
   llvm::StringRef tmp_str = old_args[i].ref();
-  size_t pos = tmp_str.find('.');
-  if (pos != llvm::StringRef::npos) {
-llvm::StringRef bp_id_str = tmp_str.substr(0, pos);
-if (BreakpointID::IsValidIDExpression(bp_id_str) &&
-tmp_str[pos + 1] == '*' && tmp_str.size() == (pos + 2)) {
-
-  BreakpointSP breakpoint_sp;
-  auto bp_id = BreakpointID::ParseCanonicalReference(bp_id_str);
-  if (bp_id)
-breakpoint_sp = 
target->GetBreakpointByID(bp_id->GetBreakpointID());
-  if (!breakpoint_sp) {
-new_args.Clear();
-return llvm::createStringError(
-llvm::inconvertibleErrorCode(),
-"'%d' is not a valid breakpoint ID.\n",
-bp_id->GetBreakpointID());
-  }
-  const size_t num_locations = breakpoint_sp->GetNumLocations();
-  for (size_t j = 0; j < num_locations; ++j) {
-BreakpointLocation *bp_loc =
-breakpoint_sp->GetLocationAtIndex(j).get();
-StreamString canonical_id_str;
-BreakpointID::GetCanonicalReference(
-_id_str, bp_id->GetBreakpointID(), bp_loc->GetID());
-new_args.AppendArgument(canonical_id_str.GetString());
-  }
+  auto [prefix, suffix] = tmp_str.split('.');
+  if (suffix == "*" && BreakpointID::IsValidIDExpression(prefix)) {
+
+BreakpointSP breakpoint_sp;
+auto bp_id = BreakpointID::ParseCanonicalReference(prefix);
+if (bp_id)
+  breakpoint_sp = target->GetBreakpointByID(bp_id->GetBreakpointID());
+if (!breakpoint_sp) {
+  new_args.Clear();
+  return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "'%d' is not a valid breakpoint 
ID.\n",
+ bp_id->GetBreakpointID());
+}
+const size_t num_locations = breakpoint_sp->GetNumLocations();
+for (size_t j = 0; j < num_locations; ++j) {
+  BreakpointLocation *bp_loc =
+  breakpoint_sp->GetLocationAtIndex(j).get();
+  StreamString canonical_id_str;
+  BreakpointID::GetCanonicalReference(
+  _id_str, bp_id->GetBreakpointID(), bp_loc->GetID());
+  new_args.AppendArgument(canonical_id_str.GetString());
 }
   }
 }

diff  --git 
a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
 
b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
index 8930bea619bb6e..d87e6275f7b51e 100644
--- 
a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
+++ 
b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
@@ -293,6 +293,12 @@ def breakpoint_locations_test(self):
 startstr="3 breakpoints enabled.",
 )
 
+# The 'breakpoint enable 1.' command should not crash.
+self.expect(
+"breakpoint enable 1.",
+startstr="0 breakpoints enabled.",
+)
+
 # The 'breakpoint disable 1.1' command should disable 1 location.

[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);
+  }
+}
+
+bool ValueObject::GetValueAsBool() {
+  CompilerType val_type = GetCompilerType();
+  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+  val_type.IsPointerType()) {
+return GetValueAsAPSInt().getBoolValue();
+  }
+  if (val_type.IsFloat()) {
+return GetValueAsFloat().isNonZero();
+  }
+  if (val_type.IsArrayType()) {
+lldb::ValueObjectSP new_val =
+ValueObject::ValueObject::CreateValueObjectFromAddress(
+GetName().GetStringRef(), GetAddressOf(), GetExecutionContextRef(),
+val_type);
+return new_val->GetValueAsUnsigned(0) != 0;
+  }
+  return false;
+}
+
+void ValueObject::UpdateIntegerValue(const llvm::APInt ) {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  assert(value.getBitWidth() == byte_size * CHAR_BIT &&

clayborg wrote:

yes, no asserts and add error propagation.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -2809,6 +2919,243 @@ ValueObjectSP ValueObject::CastPointerType(const char 
*name, TypeSP _sp) {
   return valobj_sp;
 }
 
+lldb::addr_t ValueObject::GetLoadAddress() {
+  lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
+  lldb::TargetSP target_sp = GetTargetSP();
+  if (target_sp) {
+const bool scalar_is_load_address = true;
+AddressType addr_type;
+addr_value = GetAddressOf(scalar_is_load_address, _type);
+if (addr_type == eAddressTypeFile) {
+  lldb::ModuleSP module_sp(GetModule());
+  if (!module_sp)
+addr_value = LLDB_INVALID_ADDRESS;
+  else {
+Address tmp_addr;
+module_sp->ResolveFileAddress(addr_value, tmp_addr);
+addr_value = tmp_addr.GetLoadAddress(target_sp.get());
+  }
+} else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeHost)

clayborg wrote:

Double check for `eAddressTypeHost`, I am guessing the second one was meant to 
be `eAddressTypeInvalid`. We should also change `lldb::addr_t 
SBValue::GetLoadAddress()` to call this function

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {

clayborg wrote:

Resolving the float value already builds a `APFloat` in a `Scalar`, so no need 
to redo all of this. Should be very similar to `llvm::APSInt 
ValueObject::GetValueAsAPSInt()` suggestions above

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);
+  }
+}
+
+bool ValueObject::GetValueAsBool() {
+  CompilerType val_type = GetCompilerType();
+  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+  val_type.IsPointerType()) {
+return GetValueAsAPSInt().getBoolValue();
+  }
+  if (val_type.IsFloat()) {
+return GetValueAsFloat().isNonZero();
+  }
+  if (val_type.IsArrayType()) {
+lldb::ValueObjectSP new_val =
+ValueObject::ValueObject::CreateValueObjectFromAddress(
+GetName().GetStringRef(), GetAddressOf(), GetExecutionContextRef(),
+val_type);
+return new_val->GetValueAsUnsigned(0) != 0;
+  }
+  return false;
+}
+
+void ValueObject::UpdateIntegerValue(const llvm::APInt ) {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  assert(value.getBitWidth() == byte_size * CHAR_BIT &&
+ "illegal argument: new value should be of the same size");
+
+  lldb::DataExtractorSP data_sp;
+  Status error;
+  data_sp->SetData(value.getRawData(), byte_size,
+   target->GetArchitecture().GetByteOrder());

clayborg wrote:

This will crash, `data_sp` is never constructed or assigned. We also need to 
figure out if we are going to want the integer value to be replaced always with 
a local copy, or updated in the actual program memory, register, or local 
buffer.

I realize many of these APIs are probably only intended to be used in the new 
ValueObject based expression parser, but there are APIs being added to 
ValueObject so they should work regardless of where they come from or originate.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();

clayborg wrote:

Extract the `APInt` from the contained `Scalar` value directly. No need to 
create a location uint64_t and then try to re-create, the `Scalar` ivar already 
contains an `APInt`. So just do:
```
  if (CanProvideValue()) {
Scalar scalar;
if (ResolveValue(scalar)) {
  if (success)
*success = true;
  scalar.MakeUnsigned();
  return scalar.m_integer; // Might need to provide an accessor for 
Scalar::m_integer
}
  }
```

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);
+  }
+}
+
+bool ValueObject::GetValueAsBool() {
+  CompilerType val_type = GetCompilerType();
+  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+  val_type.IsPointerType()) {
+return GetValueAsAPSInt().getBoolValue();
+  }
+  if (val_type.IsFloat()) {
+return GetValueAsFloat().isNonZero();
+  }
+  if (val_type.IsArrayType()) {
+lldb::ValueObjectSP new_val =
+ValueObject::ValueObject::CreateValueObjectFromAddress(
+GetName().GetStringRef(), GetAddressOf(), GetExecutionContextRef(),
+val_type);
+return new_val->GetValueAsUnsigned(0) != 0;
+  }

clayborg wrote:

What is this attempting to do? It looks like this is taking an array type and 
returning an array pointer and trying to return `true` if the array is in 
memory? 

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;

clayborg wrote:

We really don't want to use native float types, we want to use real APFloat 
values that are correctly encoded. For instance if we are debugging from 
x86_64, we don't want to create a 10 byte Intel float and do the math with the 
native float, we want to use the value from the Scalar that is already set 
correctly. If we are cross debugging to an iPhone, we want the floating point 
values to match exactly, which requires us to use the APFloat and not do any 
manually create a native float and convert it. This all works for the value 
objects when they get the float as a string, and will be similar where we 
resolve the scalar and then can just use the Scalar::m_float directly.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -441,6 +441,19 @@ class ValueObject {
 
   virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = 
nullptr);
 
+  llvm::APSInt GetValueAsAPSInt();
+
+  llvm::APFloat GetValueAsFloat();
+
+  bool GetValueAsBool();
+
+  /// Update the value of the current object to be the integer in the 'value'
+  /// parameter.
+  void UpdateIntegerValue(const llvm::APInt );

clayborg wrote:

Should we name this similar to `SetValueFromCString(...)`? Something like: 
`SetValue(const llvm::APInt )` or `SetValueFromInteger(const llvm::APInt 
)`? Do we want an error to be returned in case this fails?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -668,6 +699,32 @@ class ValueObject {
   CreateValueObjectFromData(llvm::StringRef name, const DataExtractor ,
 const ExecutionContext _ctx, CompilerType 
type);
 
+  static lldb::ValueObjectSP
+  CreateValueObjectFromBytes(lldb::TargetSP target_sp, const void *bytes,
+ CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromBytes(lldb::TargetSP target,
+const void *bytes,
+lldb::BasicType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromAPInt(lldb::TargetSP target,
+const llvm::APInt ,
+CompilerType type);
+
+  static lldb::ValueObjectSP
+  CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat ,

clayborg wrote:

ditto for adding a name parameter.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);
+  }
+}
+
+bool ValueObject::GetValueAsBool() {
+  CompilerType val_type = GetCompilerType();
+  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+  val_type.IsPointerType()) {
+return GetValueAsAPSInt().getBoolValue();
+  }
+  if (val_type.IsFloat()) {
+return GetValueAsFloat().isNonZero();
+  }
+  if (val_type.IsArrayType()) {
+lldb::ValueObjectSP new_val =
+ValueObject::ValueObject::CreateValueObjectFromAddress(
+GetName().GetStringRef(), GetAddressOf(), GetExecutionContextRef(),
+val_type);
+return new_val->GetValueAsUnsigned(0) != 0;
+  }
+  return false;
+}
+
+void ValueObject::UpdateIntegerValue(const llvm::APInt ) {

clayborg wrote:

If I look at this API, I would expect this function to change the integer value 
of any ValueObject. The value object might have a variable that lives in memory 
(on the stack or heap), or if it lives in a register (update the register) or 
if there is already a local buffer, replace the bytes in the local buffer. 

This function seems to replace the integer value always with a local buffer?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -441,6 +441,19 @@ class ValueObject {
 
   virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = 
nullptr);
 
+  llvm::APSInt GetValueAsAPSInt();
+
+  llvm::APFloat GetValueAsFloat();
+
+  bool GetValueAsBool();
+
+  /// Update the value of the current object to be the integer in the 'value'
+  /// parameter.
+  void UpdateIntegerValue(const llvm::APInt );
+
+  /// Assign the integer value 'new_val_sp' to the current object.
+  void UpdateIntegerValue(lldb::ValueObjectSP new_val_sp);

clayborg wrote:

What does this function actually do? Are we wanting the current `ValueObject` 
to copy the integer value from `lldb::ValueObjectSP new_val_sp`? Seems like we 
should just be able to use the above `void UpdateIntegerValue(const llvm::APInt 
);`? Can you elaborate on why this is needed?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -441,6 +441,19 @@ class ValueObject {
 
   virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = 
nullptr);
 
+  llvm::APSInt GetValueAsAPSInt();
+
+  llvm::APFloat GetValueAsFloat();
+
+  bool GetValueAsBool();

clayborg wrote:

Do we need `GetValueAsBool()`  or can we just use `GetValueAsAPSInt()` and make 
sure bool gets converted to a suitable integer?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -668,6 +699,32 @@ class ValueObject {
   CreateValueObjectFromData(llvm::StringRef name, const DataExtractor ,
 const ExecutionContext _ctx, CompilerType 
type);
 
+  static lldb::ValueObjectSP
+  CreateValueObjectFromBytes(lldb::TargetSP target_sp, const void *bytes,
+ CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromBytes(lldb::TargetSP target,
+const void *bytes,
+lldb::BasicType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromAPInt(lldb::TargetSP target,
+const llvm::APInt ,
+CompilerType type);
+
+  static lldb::ValueObjectSP
+  CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat ,
+   CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromPointer(lldb::TargetSP 
target,
+  uintptr_t addr,
+  CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromBool(lldb::TargetSP target,
+   bool value);
+
+  static lldb::ValueObjectSP CreateValueObjectFromNullptr(lldb::TargetSP 
target,

clayborg wrote:

name arg?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -618,6 +631,24 @@ class ValueObject {
   virtual lldb::ValueObjectSP CastPointerType(const char *name,
   lldb::TypeSP _sp);
 
+  /// Return the target load address assocaited with this value object.
+  lldb::addr_t GetLoadAddress();

clayborg wrote:

Is this function just a copy of the contents of `lldb::addr_t 
SBValue::GetLoadAddress()`? If so, we should also fix that function to call 
this function. Might be nice to have this return `std::optional` 
for internal use as if the `ValueObject` is a variable that is in a register, 
this will need to return `LLDB_INVALID_ADDRESS`.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -668,6 +699,32 @@ class ValueObject {
   CreateValueObjectFromData(llvm::StringRef name, const DataExtractor ,
 const ExecutionContext _ctx, CompilerType 
type);
 
+  static lldb::ValueObjectSP
+  CreateValueObjectFromBytes(lldb::TargetSP target_sp, const void *bytes,
+ CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromBytes(lldb::TargetSP target,

clayborg wrote:

Do we need to be able to add a name for the value object? Some the creation 
APIs allow users to specify names and the native synthetic child providers 
could use these APIs if they can specify a name.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -618,6 +631,24 @@ class ValueObject {
   virtual lldb::ValueObjectSP CastPointerType(const char *name,
   lldb::TypeSP _sp);
 
+  /// Return the target load address assocaited with this value object.
+  lldb::addr_t GetLoadAddress();
+
+  lldb::ValueObjectSP CastDerivedToBaseType(CompilerType type,
+const std::vector );
+
+  lldb::ValueObjectSP CastBaseToDerivedType(CompilerType type, uint64_t 
offset);
+
+  lldb::ValueObjectSP CastScalarToBasicType(CompilerType type, Status );

clayborg wrote:

Same comment as Jim made below where the returned `lldb::ValueObjectSP` can 
have its error set correctly.

Also, we have a bunch of `CastTo` calls added below. Do we really need 
all of these? Can we just have one `lldb::ValueObjectSP Cast(CompilerType 
type)` function and deduce what should be done internally and fail gracefully? 

Or if we do need functions specific to `Scalar` and `Enum` we can add just 
`lldb::ValueObjectSP CastScalar(CompilerType type)` and `lldb::ValueObjectSP 
CastEnum(CompilerType type)`.

It would be great if we just have a single `lldb::ValueObjectSP 
Cast(CompilerType type)` function that works for everything. We should be able 
to figure out internally how things are stored (scalar, enum would be deduced 
from the current `ValueObject`, and figure out what we are casting it to with 
by looking at `CompilerType`

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Greg Clayton via lldb-commits


@@ -618,6 +631,24 @@ class ValueObject {
   virtual lldb::ValueObjectSP CastPointerType(const char *name,
   lldb::TypeSP _sp);
 
+  /// Return the target load address assocaited with this value object.
+  lldb::addr_t GetLoadAddress();
+
+  lldb::ValueObjectSP CastDerivedToBaseType(CompilerType type,
+const std::vector );

clayborg wrote:

Maybe use `const llvm::ArrayRef` instead of `const 
std::vector`? Some headerdoc on what this does might be nice. I would 
guess `idx` contains a base class index path? Maybe renamed `idx` to something 
more descriptive?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Don't crash when attempting to parse breakpoint id `N.` as `N.*` (PR #87263)

2024-04-01 Thread Alex Langford via lldb-commits

https://github.com/bulbazord approved this pull request.

Rewriting this has been on my backlog for a few months now. This looks better 
than what I had in mind. Thank you!  

https://github.com/llvm/llvm-project/pull/87263
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);
+  }
+}
+
+bool ValueObject::GetValueAsBool() {
+  CompilerType val_type = GetCompilerType();
+  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+  val_type.IsPointerType()) {
+return GetValueAsAPSInt().getBoolValue();
+  }
+  if (val_type.IsFloat()) {
+return GetValueAsFloat().isNonZero();
+  }
+  if (val_type.IsArrayType()) {
+lldb::ValueObjectSP new_val =
+ValueObject::ValueObject::CreateValueObjectFromAddress(
+GetName().GetStringRef(), GetAddressOf(), GetExecutionContextRef(),
+val_type);
+return new_val->GetValueAsUnsigned(0) != 0;
+  }
+  return false;
+}
+
+void ValueObject::UpdateIntegerValue(const llvm::APInt ) {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  assert(value.getBitWidth() == byte_size * CHAR_BIT &&

bulbazord wrote:

Instead of asserting this, why not have this function return an `llvm::Error`? 
If this invariant is not met, this can return this exact error message.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();

bulbazord wrote:

nit: `const` the bool.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -2809,6 +2919,243 @@ ValueObjectSP ValueObject::CastPointerType(const char 
*name, TypeSP _sp) {
   return valobj_sp;
 }
 
+lldb::addr_t ValueObject::GetLoadAddress() {
+  lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
+  lldb::TargetSP target_sp = GetTargetSP();
+  if (target_sp) {

bulbazord wrote:

nit: These lines can be rolled into one
```
if (auto target_sp = GetTargetSP()) {
```
(use of auto is personal preference)

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -2809,6 +2919,243 @@ ValueObjectSP ValueObject::CastPointerType(const char 
*name, TypeSP _sp) {
   return valobj_sp;
 }
 
+lldb::addr_t ValueObject::GetLoadAddress() {
+  lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
+  lldb::TargetSP target_sp = GetTargetSP();
+  if (target_sp) {
+const bool scalar_is_load_address = true;
+AddressType addr_type;
+addr_value = GetAddressOf(scalar_is_load_address, _type);
+if (addr_type == eAddressTypeFile) {
+  lldb::ModuleSP module_sp(GetModule());
+  if (!module_sp)
+addr_value = LLDB_INVALID_ADDRESS;
+  else {
+Address tmp_addr;
+module_sp->ResolveFileAddress(addr_value, tmp_addr);
+addr_value = tmp_addr.GetLoadAddress(target_sp.get());
+  }
+} else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeHost)
+  addr_value = LLDB_INVALID_ADDRESS;
+  }
+  return addr_value;
+}
+
+lldb::ValueObjectSP
+ValueObject::CastDerivedToBaseType(CompilerType type,
+   const std::vector ) {
+
+  lldb::TargetSP target = GetTargetSP();
+  assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");
+  assert(!idx.empty() && "invalid ast: children sequence should be non-empty");
+
+  // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
+  lldb::ValueObjectSP inner_value;
+
+  for (const uint32_t i : idx) {
+// Force static value, otherwise we can end up with the "real" type.
+inner_value = GetChildAtIndex(i, /*can_create_synthetic*/ false);
+  }
+
+  // At this point type of `inner_value` should be the dereferenced target 
type.
+  CompilerType inner_value_type = inner_value->GetCompilerType();
+  if (type.IsPointerType()) {
+assert(inner_value_type.CompareTypes(type.GetPointeeType()) &&
+   "casted value doesn't match the desired type");
+
+uintptr_t addr = inner_value->GetLoadAddress();
+return ValueObject::CreateValueObjectFromPointer(target, addr, type);
+  }
+
+  // At this point the target type should be a reference.
+  assert(inner_value_type.CompareTypes(type.GetNonReferenceType()) &&
+ "casted value doesn't match the desired type");

bulbazord wrote:

Same w/ this assertion.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -2809,6 +2919,243 @@ ValueObjectSP ValueObject::CastPointerType(const char 
*name, TypeSP _sp) {
   return valobj_sp;
 }
 
+lldb::addr_t ValueObject::GetLoadAddress() {
+  lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
+  lldb::TargetSP target_sp = GetTargetSP();
+  if (target_sp) {
+const bool scalar_is_load_address = true;
+AddressType addr_type;
+addr_value = GetAddressOf(scalar_is_load_address, _type);
+if (addr_type == eAddressTypeFile) {
+  lldb::ModuleSP module_sp(GetModule());
+  if (!module_sp)
+addr_value = LLDB_INVALID_ADDRESS;
+  else {
+Address tmp_addr;
+module_sp->ResolveFileAddress(addr_value, tmp_addr);
+addr_value = tmp_addr.GetLoadAddress(target_sp.get());
+  }
+} else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeHost)
+  addr_value = LLDB_INVALID_ADDRESS;
+  }
+  return addr_value;
+}
+
+lldb::ValueObjectSP
+ValueObject::CastDerivedToBaseType(CompilerType type,
+   const std::vector ) {
+
+  lldb::TargetSP target = GetTargetSP();
+  assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");
+  assert(!idx.empty() && "invalid ast: children sequence should be non-empty");
+
+  // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
+  lldb::ValueObjectSP inner_value;
+
+  for (const uint32_t i : idx) {
+// Force static value, otherwise we can end up with the "real" type.
+inner_value = GetChildAtIndex(i, /*can_create_synthetic*/ false);
+  }
+
+  // At this point type of `inner_value` should be the dereferenced target 
type.
+  CompilerType inner_value_type = inner_value->GetCompilerType();
+  if (type.IsPointerType()) {
+assert(inner_value_type.CompareTypes(type.GetPointeeType()) &&
+   "casted value doesn't match the desired type");
+
+uintptr_t addr = inner_value->GetLoadAddress();
+return ValueObject::CreateValueObjectFromPointer(target, addr, type);
+  }
+
+  // At this point the target type should be a reference.
+  assert(inner_value_type.CompareTypes(type.GetNonReferenceType()) &&
+ "casted value doesn't match the desired type");
+
+  return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
+}
+
+lldb::ValueObjectSP ValueObject::CastBaseToDerivedType(CompilerType type,
+   uint64_t offset) {
+  lldb::TargetSP target = GetTargetSP();
+
+  assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");

bulbazord wrote:

Same w/ this assertion

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -2809,6 +2919,243 @@ ValueObjectSP ValueObject::CastPointerType(const char 
*name, TypeSP _sp) {
   return valobj_sp;
 }
 
+lldb::addr_t ValueObject::GetLoadAddress() {
+  lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
+  lldb::TargetSP target_sp = GetTargetSP();
+  if (target_sp) {
+const bool scalar_is_load_address = true;
+AddressType addr_type;
+addr_value = GetAddressOf(scalar_is_load_address, _type);
+if (addr_type == eAddressTypeFile) {
+  lldb::ModuleSP module_sp(GetModule());
+  if (!module_sp)
+addr_value = LLDB_INVALID_ADDRESS;
+  else {
+Address tmp_addr;
+module_sp->ResolveFileAddress(addr_value, tmp_addr);
+addr_value = tmp_addr.GetLoadAddress(target_sp.get());
+  }
+} else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeHost)
+  addr_value = LLDB_INVALID_ADDRESS;
+  }
+  return addr_value;
+}
+
+lldb::ValueObjectSP
+ValueObject::CastDerivedToBaseType(CompilerType type,
+   const std::vector ) {
+
+  lldb::TargetSP target = GetTargetSP();
+  assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");
+  assert(!idx.empty() && "invalid ast: children sequence should be non-empty");
+
+  // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
+  lldb::ValueObjectSP inner_value;
+
+  for (const uint32_t i : idx) {
+// Force static value, otherwise we can end up with the "real" type.
+inner_value = GetChildAtIndex(i, /*can_create_synthetic*/ false);
+  }
+
+  // At this point type of `inner_value` should be the dereferenced target 
type.
+  CompilerType inner_value_type = inner_value->GetCompilerType();
+  if (type.IsPointerType()) {
+assert(inner_value_type.CompareTypes(type.GetPointeeType()) &&
+   "casted value doesn't match the desired type");
+
+uintptr_t addr = inner_value->GetLoadAddress();
+return ValueObject::CreateValueObjectFromPointer(target, addr, type);
+  }
+
+  // At this point the target type should be a reference.
+  assert(inner_value_type.CompareTypes(type.GetNonReferenceType()) &&
+ "casted value doesn't match the desired type");
+
+  return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
+}
+
+lldb::ValueObjectSP ValueObject::CastBaseToDerivedType(CompilerType type,
+   uint64_t offset) {
+  lldb::TargetSP target = GetTargetSP();
+
+  assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");
+
+  auto pointer_type =
+  type.IsPointerType() ? type : 
type.GetNonReferenceType().GetPointerType();
+
+  uintptr_t addr =
+  type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();
+
+  lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromPointer(
+  target, addr - offset, pointer_type);
+
+  if (type.IsPointerType()) {
+return value;
+  }
+
+  // At this point the target type is a reference. Since `value` is a pointer,
+  // it has to be dereferenced.
+  Status error;
+  return value->Dereference(error);
+}
+
+lldb::ValueObjectSP ValueObject::CastScalarToBasicType(CompilerType type,
+   Status ) {
+  assert(type.IsScalarType() && "target type must be an scalar");
+  assert(GetCompilerType().IsScalarType() && "argument must be a scalar");
+
+  lldb::TargetSP target = GetTargetSP();
+  if (type.IsBoolean()) {
+if (GetCompilerType().IsInteger()) {
+  return ValueObject::CreateValueObjectFromBool(target,
+GetValueAsUnsigned(0) != 
0);
+}
+if (GetCompilerType().IsFloat()) {
+  return ValueObject::CreateValueObjectFromBool(
+  target, !GetValueAsFloat().isZero());
+}
+  }
+  if (type.IsInteger()) {
+if (GetCompilerType().IsInteger()) {
+  uint64_t byte_size = 0;
+  if (auto temp = type.GetByteSize(target.get()))
+byte_size = temp.value();
+  llvm::APSInt ext = GetValueAsAPSInt().extOrTrunc(byte_size * CHAR_BIT);
+  return ValueObject::CreateValueObjectFromAPInt(target, ext, type);
+}
+if (GetCompilerType().IsFloat()) {
+  uint64_t byte_size = 0;
+  if (auto temp = type.GetByteSize(target.get()))
+byte_size = temp.value();
+  llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());
+  bool is_exact;
+  llvm::APFloatBase::opStatus status = GetValueAsFloat().convertToInteger(
+  integer, llvm::APFloat::rmTowardZero, _exact);
+
+  // Casting floating point values that are out of bounds of the target 
type
+  // is undefined behaviour.
+  if (status & llvm::APFloatBase::opInvalidOp) {
+error.SetErrorString("invalid type cast detected");
+  }
+
+  return ValueObject::CreateValueObjectFromAPInt(target, integer, 

[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);
+  }
+}
+
+bool ValueObject::GetValueAsBool() {
+  CompilerType val_type = GetCompilerType();
+  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+  val_type.IsPointerType()) {
+return GetValueAsAPSInt().getBoolValue();
+  }
+  if (val_type.IsFloat()) {
+return GetValueAsFloat().isNonZero();
+  }
+  if (val_type.IsArrayType()) {
+lldb::ValueObjectSP new_val =
+ValueObject::ValueObject::CreateValueObjectFromAddress(
+GetName().GetStringRef(), GetAddressOf(), GetExecutionContextRef(),
+val_type);
+return new_val->GetValueAsUnsigned(0) != 0;
+  }
+  return false;
+}
+
+void ValueObject::UpdateIntegerValue(const llvm::APInt ) {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  assert(value.getBitWidth() == byte_size * CHAR_BIT &&
+ "illegal argument: new value should be of the same size");
+
+  lldb::DataExtractorSP data_sp;
+  Status error;
+  data_sp->SetData(value.getRawData(), byte_size,
+   target->GetArchitecture().GetByteOrder());
+  data_sp->SetAddressByteSize(
+  static_cast(target->GetArchitecture().GetAddressByteSize()));
+  SetData(*data_sp, error);
+}
+
+void ValueObject::UpdateIntegerValue(lldb::ValueObjectSP new_val_sp) {
+  CompilerType new_val_type = new_val_sp->GetCompilerType();
+  assert((new_val_type.IsInteger() || new_val_type.IsFloat() ||
+  new_val_type.IsPointerType()) &&
+ "illegal argument: new value should be of the same size");

bulbazord wrote:

Same as above for this assertion.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -2809,6 +2919,243 @@ ValueObjectSP ValueObject::CastPointerType(const char 
*name, TypeSP _sp) {
   return valobj_sp;
 }
 
+lldb::addr_t ValueObject::GetLoadAddress() {
+  lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
+  lldb::TargetSP target_sp = GetTargetSP();
+  if (target_sp) {
+const bool scalar_is_load_address = true;
+AddressType addr_type;
+addr_value = GetAddressOf(scalar_is_load_address, _type);
+if (addr_type == eAddressTypeFile) {
+  lldb::ModuleSP module_sp(GetModule());
+  if (!module_sp)
+addr_value = LLDB_INVALID_ADDRESS;
+  else {
+Address tmp_addr;
+module_sp->ResolveFileAddress(addr_value, tmp_addr);
+addr_value = tmp_addr.GetLoadAddress(target_sp.get());
+  }
+} else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeHost)
+  addr_value = LLDB_INVALID_ADDRESS;
+  }
+  return addr_value;
+}
+
+lldb::ValueObjectSP
+ValueObject::CastDerivedToBaseType(CompilerType type,
+   const std::vector ) {
+
+  lldb::TargetSP target = GetTargetSP();
+  assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");
+  assert(!idx.empty() && "invalid ast: children sequence should be non-empty");

bulbazord wrote:

Same for these assertions as above.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -618,6 +631,24 @@ class ValueObject {
   virtual lldb::ValueObjectSP CastPointerType(const char *name,
   lldb::TypeSP _sp);
 
+  /// Return the target load address assocaited with this value object.
+  lldb::addr_t GetLoadAddress();
+
+  lldb::ValueObjectSP CastDerivedToBaseType(CompilerType type,
+const std::vector );
+
+  lldb::ValueObjectSP CastBaseToDerivedType(CompilerType type, uint64_t 
offset);
+
+  lldb::ValueObjectSP CastScalarToBasicType(CompilerType type, Status );
+
+  lldb::ValueObjectSP CastEnumToBasicType(CompilerType type);
+
+  lldb::ValueObjectSP CastPointerToBasicType(CompilerType type);
+
+  lldb::ValueObjectSP CastIntegerOrEnumToEnumType(CompilerType type);
+
+  lldb::ValueObjectSP CastFloatToEnumType(CompilerType type, Status );

bulbazord wrote:

Can you add some doxygen comments to these methods? It would help clarify the 
intent behind them as well as the purpose of some of the parameter (e.g. What 
does `idx` correspond to in `CastDerivedToBaseType`?)

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);

bulbazord wrote:

If `GetValueAsUnsigned` fails, this will give you an `APSInt` that looks like 
0, meaning there's no way to distinguish between a `ValueObject` that 
represents 0 and a failure value.
Suggestion: Either return an invalid `APSInt` (via default constructor) or 
return a `std::optional` or `llvm::Expected` if you want an 
error message back.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);

bulbazord wrote:

Where is `NAN` coming from? I don't see it in this file or the `APFloat` header.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {
+  lldb::BasicType basic_type =
+  GetCompilerType().GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::DataExtractorSP data_sp(new DataExtractor());
+  Status error;
+
+  switch (basic_type) {
+  case lldb::eBasicTypeFloat: {
+float v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read float data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(float));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  case lldb::eBasicTypeDouble:
+// No way to get more precision at the moment.
+  case lldb::eBasicTypeLongDouble: {
+double v = 0;
+GetData(*data_sp, error);
+assert(error.Success() && "Unable to read long double data from value");
+
+lldb::offset_t offset = 0;
+uint32_t old_offset = offset;
+void *ok = nullptr;
+ok = data_sp->GetU8(, (void *), sizeof(double));
+assert(offset != old_offset && ok != nullptr && "unable to read data");
+
+return llvm::APFloat(v);
+  }
+  default:
+return llvm::APFloat(NAN);
+  }
+}
+
+bool ValueObject::GetValueAsBool() {
+  CompilerType val_type = GetCompilerType();
+  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+  val_type.IsPointerType()) {
+return GetValueAsAPSInt().getBoolValue();
+  }
+  if (val_type.IsFloat()) {
+return GetValueAsFloat().isNonZero();
+  }
+  if (val_type.IsArrayType()) {
+lldb::ValueObjectSP new_val =
+ValueObject::ValueObject::CreateValueObjectFromAddress(
+GetName().GetStringRef(), GetAddressOf(), GetExecutionContextRef(),
+val_type);
+return new_val->GetValueAsUnsigned(0) != 0;
+  }
+  return false;
+}
+
+void ValueObject::UpdateIntegerValue(const llvm::APInt ) {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  assert(value.getBitWidth() == byte_size * CHAR_BIT &&
+ "illegal argument: new value should be of the same size");
+
+  lldb::DataExtractorSP data_sp;
+  Status error;
+  data_sp->SetData(value.getRawData(), byte_size,
+   target->GetArchitecture().GetByteOrder());
+  data_sp->SetAddressByteSize(
+  static_cast(target->GetArchitecture().GetAddressByteSize()));
+  SetData(*data_sp, error);
+}
+
+void ValueObject::UpdateIntegerValue(lldb::ValueObjectSP new_val_sp) {
+  CompilerType new_val_type = new_val_sp->GetCompilerType();
+  assert((new_val_type.IsInteger() || new_val_type.IsFloat() ||
+  new_val_type.IsPointerType()) &&
+ "illegal argument: new value should be of the same size");
+
+  if (new_val_type.IsInteger()) {
+UpdateIntegerValue(new_val_sp->GetValueAsAPSInt());
+  } else if (new_val_type.IsFloat()) {
+UpdateIntegerValue(new_val_sp->GetValueAsFloat().bitcastToAPInt());
+  } else if (new_val_type.IsPointerType()) {
+UpdateIntegerValue(llvm::APInt(64, new_val_sp->GetValueAsUnsigned(0)));

bulbazord wrote:

Is there a way we can get the width of a pointer type? 64 will work on most 
platforms, but there are definitely 32-bit platforms (e.g. ARM) that may want 
to use this code.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -1089,6 +1089,116 @@ int64_t ValueObject::GetValueAsSigned(int64_t 
fail_value, bool *success) {
   return fail_value;
 }
 
+llvm::APSInt ValueObject::GetValueAsAPSInt() {
+  lldb::TargetSP target = GetTargetSP();
+  uint64_t byte_size = 0;
+  if (auto temp = GetCompilerType().GetByteSize(target.get()))
+byte_size = temp.value();
+
+  unsigned bit_width = static_cast(byte_size * CHAR_BIT);
+  bool success = true;
+  uint64_t fail_value = 0;
+  uint64_t ret_val = GetValueAsUnsigned(fail_value, );
+  uint64_t new_value = fail_value;
+  if (success)
+new_value = ret_val;
+  bool is_signed = GetCompilerType().IsSigned();
+
+  return llvm::APSInt(llvm::APInt(bit_width, new_value, is_signed), 
!is_signed);
+}
+
+llvm::APFloat ValueObject::GetValueAsFloat() {

bulbazord wrote:

2 issues and a small nitpick:
Nit: The name could be `GetValueAsAPFloat` to differentiate between it and a 
potential function that would return a `float`/`double`?

1. I don't think assertions are the right way to make sure we have good data. 
`GetData` has error handling through its `Status &` out parameter, we should 
handle that appropriately instead of asserting that we got good data. What 
happens when we compile out the assertions for release builds? Reading data 
from the `DataExtractor` will fail and crash regardless.
2. This function has no way of returning a value that would indicate failure.

Suggestion: Return `std::optional` or 
`llvm::Expected`. There's no way to return an invalid `APFloat` 
from looking at the header, so that doesn't appear to be an option. Then if any 
of the steps fail, you can return either `std::nullopt` or an appropriate 
`llvm::Error`.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits


@@ -618,6 +631,24 @@ class ValueObject {
   virtual lldb::ValueObjectSP CastPointerType(const char *name,
   lldb::TypeSP _sp);
 
+  /// Return the target load address assocaited with this value object.

bulbazord wrote:

typo: `associated`

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits

https://github.com/bulbazord requested changes to this pull request.

+1 to all of Jim and Adrian's comments.

High level comments:
1. I'm a little concerned about the use of assertions in this patch. I 
generally like assertions when they are used to assert internal consistency. It 
looks like you're using them as an error-checking and parameter-checking 
mechanism. This seems pretty fragile, especially since it will be difficult to 
enforce that these functions are called "correctly" in all cases from all 
contributors.

2. There isn't a lot of documentation. It would be helpful to know the expected 
behavior for a lot of these methods (especially for people like me  who aren't 
super familiar with the ValueObject class and all of its tendrils).

3. Is there a way you can add some tests for the new functionality? I'm not 
sure how you could trigger these new methods from an API test, but a unit test 
might be possible?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Alex Langford via lldb-commits

https://github.com/bulbazord edited 
https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread via lldb-commits


@@ -719,6 +776,10 @@ class ValueObject {
 ClearUserVisibleData(eClearUserVisibleDataItemsSummary);
   }
 
+  void SetDerefValobj(ValueObject *deref) { m_deref_valobj = deref; }

jimingham wrote:

Synthetic child providers also have a way to provide the deref ValueObject 
dynamically.  How do these two ways of doing that job work together?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread via lldb-commits


@@ -668,6 +699,32 @@ class ValueObject {
   CreateValueObjectFromData(llvm::StringRef name, const DataExtractor ,
 const ExecutionContext _ctx, CompilerType 
type);
 
+  static lldb::ValueObjectSP
+  CreateValueObjectFromBytes(lldb::TargetSP target_sp, const void *bytes,
+ CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromBytes(lldb::TargetSP target,
+const void *bytes,
+lldb::BasicType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromAPInt(lldb::TargetSP target,
+const llvm::APInt ,
+CompilerType type);
+
+  static lldb::ValueObjectSP
+  CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat ,
+   CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromPointer(lldb::TargetSP 
target,

jimingham wrote:

How is this different from CreateValueObjectFromAddress?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Adrian Prantl via lldb-commits


@@ -668,6 +699,32 @@ class ValueObject {
   CreateValueObjectFromData(llvm::StringRef name, const DataExtractor ,
 const ExecutionContext _ctx, CompilerType 
type);
 
+  static lldb::ValueObjectSP
+  CreateValueObjectFromBytes(lldb::TargetSP target_sp, const void *bytes,
+ CompilerType type);
+
+  static lldb::ValueObjectSP CreateValueObjectFromBytes(lldb::TargetSP target,

adrian-prantl wrote:

These functions could all benefit from Doxygen comments. If we can use a 
StringRef, or DataExtractor/Buffer instead a raw pointer, that would likely 
also be safer.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Adrian Prantl via lldb-commits


@@ -441,6 +441,19 @@ class ValueObject {
 
   virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = 
nullptr);
 
+  llvm::APSInt GetValueAsAPSInt();
+
+  llvm::APFloat GetValueAsFloat();
+
+  bool GetValueAsBool();

adrian-prantl wrote:

same here

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Adrian Prantl via lldb-commits


@@ -441,6 +441,19 @@ class ValueObject {
 
   virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = 
nullptr);
 
+  llvm::APSInt GetValueAsAPSInt();
+
+  llvm::APFloat GetValueAsFloat();

adrian-prantl wrote:

same here

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread Adrian Prantl via lldb-commits


@@ -441,6 +441,19 @@ class ValueObject {
 
   virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = 
nullptr);
 
+  llvm::APSInt GetValueAsAPSInt();

adrian-prantl wrote:

if these errors matter to users then `llvm::Expected` would be 
the right choice. Otherwise std::optional is the way to go.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread via lldb-commits


@@ -668,6 +699,32 @@ class ValueObject {
   CreateValueObjectFromData(llvm::StringRef name, const DataExtractor ,
 const ExecutionContext _ctx, CompilerType 
type);
 
+  static lldb::ValueObjectSP

jimingham wrote:

Given targets can be big or little-endian, I'm a little worried about a "const 
void *bytes" that says nothing about what is in the bytes.  This is what 
DataBuffer's are for, why couldn't you use them?

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread via lldb-commits


@@ -618,6 +631,24 @@ class ValueObject {
   virtual lldb::ValueObjectSP CastPointerType(const char *name,
   lldb::TypeSP _sp);
 
+  /// Return the target load address assocaited with this value object.
+  lldb::addr_t GetLoadAddress();
+
+  lldb::ValueObjectSP CastDerivedToBaseType(CompilerType type,
+const std::vector );
+
+  lldb::ValueObjectSP CastBaseToDerivedType(CompilerType type, uint64_t 
offset);
+
+  lldb::ValueObjectSP CastScalarToBasicType(CompilerType type, Status );
+
+  lldb::ValueObjectSP CastEnumToBasicType(CompilerType type);
+
+  lldb::ValueObjectSP CastPointerToBasicType(CompilerType type);
+
+  lldb::ValueObjectSP CastIntegerOrEnumToEnumType(CompilerType type);
+
+  lldb::ValueObjectSP CastFloatToEnumType(CompilerType type, Status );

jimingham wrote:

You don't need an error parameter for anything that returns a ValueObject.  
ValueObjects carry their errors in the ValueObject (ValueObject::GetError()).

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)

2024-04-01 Thread via lldb-commits


@@ -441,6 +441,19 @@ class ValueObject {
 
   virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = 
nullptr);
 
+  llvm::APSInt GetValueAsAPSInt();

jimingham wrote:

Not all SBValues are representable as Int's or Floats, Bool's etc.  But I don't 
see any way to report errors with these new API's.

https://github.com/llvm/llvm-project/pull/87197
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Don't crash when attempting to parse breakpoint id `N.` as `N.*` (PR #87263)

2024-04-01 Thread via lldb-commits

https://github.com/jimingham approved this pull request.

LGMT

https://github.com/llvm/llvm-project/pull/87263
___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb] Don't crash when attempting to parse breakpoint id `N.` as `N.*` (PR #87263)

2024-04-01 Thread via lldb-commits

llvmbot wrote:




@llvm/pr-subscribers-lldb

Author: Jordan Rupprecht (rupprecht)


Changes

We check if the next character after `N.` is `*` before we check its length. 
Using `split` on the string is cleaner and less error prone than using indices 
with `find` and `substr`.

Note: this does not make `N.` mean anything, it just prevents assertion 
failures. `N.` is treated the same as an unrecognized breakpoint name:

```
(lldb) breakpoint enable 1
1 breakpoints enabled.
(lldb) breakpoint enable 1.*
1 breakpoints enabled.
(lldb) breakpoint enable 1.
0 breakpoints enabled.
(lldb) breakpoint enable xyz
0 breakpoints enabled.
```

Found via LLDB fuzzers.

---
Full diff: https://github.com/llvm/llvm-project/pull/87263.diff


2 Files Affected:

- (modified) lldb/source/Breakpoint/BreakpointIDList.cpp (+22-26) 
- (modified) 
lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
 (+6) 


``diff
diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp 
b/lldb/source/Breakpoint/BreakpointIDList.cpp
index 851d074e753588..97af1d40eb7a58 100644
--- a/lldb/source/Breakpoint/BreakpointIDList.cpp
+++ b/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -16,6 +16,7 @@
 #include "lldb/Utility/StreamString.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -111,32 +112,27 @@ llvm::Error BreakpointIDList::FindAndReplaceIDRanges(
 } else {
   // See if user has specified id.*
   llvm::StringRef tmp_str = old_args[i].ref();
-  size_t pos = tmp_str.find('.');
-  if (pos != llvm::StringRef::npos) {
-llvm::StringRef bp_id_str = tmp_str.substr(0, pos);
-if (BreakpointID::IsValidIDExpression(bp_id_str) &&
-tmp_str[pos + 1] == '*' && tmp_str.size() == (pos + 2)) {
-
-  BreakpointSP breakpoint_sp;
-  auto bp_id = BreakpointID::ParseCanonicalReference(bp_id_str);
-  if (bp_id)
-breakpoint_sp = 
target->GetBreakpointByID(bp_id->GetBreakpointID());
-  if (!breakpoint_sp) {
-new_args.Clear();
-return llvm::createStringError(
-llvm::inconvertibleErrorCode(),
-"'%d' is not a valid breakpoint ID.\n",
-bp_id->GetBreakpointID());
-  }
-  const size_t num_locations = breakpoint_sp->GetNumLocations();
-  for (size_t j = 0; j < num_locations; ++j) {
-BreakpointLocation *bp_loc =
-breakpoint_sp->GetLocationAtIndex(j).get();
-StreamString canonical_id_str;
-BreakpointID::GetCanonicalReference(
-_id_str, bp_id->GetBreakpointID(), bp_loc->GetID());
-new_args.AppendArgument(canonical_id_str.GetString());
-  }
+  auto [prefix, suffix] = tmp_str.split('.');
+  if (suffix == "*" && BreakpointID::IsValidIDExpression(prefix)) {
+
+BreakpointSP breakpoint_sp;
+auto bp_id = BreakpointID::ParseCanonicalReference(prefix);
+if (bp_id)
+  breakpoint_sp = target->GetBreakpointByID(bp_id->GetBreakpointID());
+if (!breakpoint_sp) {
+  new_args.Clear();
+  return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "'%d' is not a valid breakpoint 
ID.\n",
+ bp_id->GetBreakpointID());
+}
+const size_t num_locations = breakpoint_sp->GetNumLocations();
+for (size_t j = 0; j < num_locations; ++j) {
+  BreakpointLocation *bp_loc =
+  breakpoint_sp->GetLocationAtIndex(j).get();
+  StreamString canonical_id_str;
+  BreakpointID::GetCanonicalReference(
+  _id_str, bp_id->GetBreakpointID(), bp_loc->GetID());
+  new_args.AppendArgument(canonical_id_str.GetString());
 }
   }
 }
diff --git 
a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
 
b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
index 8930bea619bb6e..d87e6275f7b51e 100644
--- 
a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
+++ 
b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
@@ -293,6 +293,12 @@ def breakpoint_locations_test(self):
 startstr="3 breakpoints enabled.",
 )
 
+# The 'breakpoint enable 1.' command should not crash.
+self.expect(
+"breakpoint enable 1.",
+startstr="0 breakpoints enabled.",
+)
+
 # The 'breakpoint disable 1.1' command should disable 1 location.
 self.expect(
 "breakpoint disable 1.1",

``




https://github.com/llvm/llvm-project/pull/87263
___
lldb-commits mailing list
lldb-commits@lists.llvm.org

[Lldb-commits] [lldb] [lldb] Don't crash when attempting to parse breakpoint id `N.` as `N.*` (PR #87263)

2024-04-01 Thread Jordan Rupprecht via lldb-commits

https://github.com/rupprecht created 
https://github.com/llvm/llvm-project/pull/87263

We check if the next character after `N.` is `*` before we check its length. 
Using `split` on the string is cleaner and less error prone than using indices 
with `find` and `substr`.

Note: this does not make `N.` mean anything, it just prevents assertion 
failures. `N.` is treated the same as an unrecognized breakpoint name:

```
(lldb) breakpoint enable 1
1 breakpoints enabled.
(lldb) breakpoint enable 1.*
1 breakpoints enabled.
(lldb) breakpoint enable 1.
0 breakpoints enabled.
(lldb) breakpoint enable xyz
0 breakpoints enabled.
```

Found via LLDB fuzzers.

>From dc0aac066ec882d564dfc09acfae4b3dca5c8091 Mon Sep 17 00:00:00 2001
From: Jordan Rupprecht 
Date: Mon, 1 Apr 2024 16:44:09 +
Subject: [PATCH] [lldb] Don't crash when attempting to parse breakpoint id
 `N.` as `N.*`

We check if the next character after `N.` is `*` before we check its length. 
Using `split` on the string is cleaner and less error prone than using indices 
with `find` and `substr`.

Note: this does not make `N.` mean anything, it just prevents assertion 
failures. `N.` is treated the same as an unrecognized breakpoint name:

```
(lldb) breakpoint enable 1
1 breakpoints enabled.
(lldb) breakpoint enable 1.*
1 breakpoints enabled.
(lldb) breakpoint enable 1.
0 breakpoints enabled.
(lldb) breakpoint enable xyz
0 breakpoints enabled.
```

Found via LLDB fuzzers.
---
 lldb/source/Breakpoint/BreakpointIDList.cpp   | 48 +--
 .../TestBreakpointLocations.py|  6 +++
 2 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp 
b/lldb/source/Breakpoint/BreakpointIDList.cpp
index 851d074e753588..97af1d40eb7a58 100644
--- a/lldb/source/Breakpoint/BreakpointIDList.cpp
+++ b/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -16,6 +16,7 @@
 #include "lldb/Utility/StreamString.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -111,32 +112,27 @@ llvm::Error BreakpointIDList::FindAndReplaceIDRanges(
 } else {
   // See if user has specified id.*
   llvm::StringRef tmp_str = old_args[i].ref();
-  size_t pos = tmp_str.find('.');
-  if (pos != llvm::StringRef::npos) {
-llvm::StringRef bp_id_str = tmp_str.substr(0, pos);
-if (BreakpointID::IsValidIDExpression(bp_id_str) &&
-tmp_str[pos + 1] == '*' && tmp_str.size() == (pos + 2)) {
-
-  BreakpointSP breakpoint_sp;
-  auto bp_id = BreakpointID::ParseCanonicalReference(bp_id_str);
-  if (bp_id)
-breakpoint_sp = 
target->GetBreakpointByID(bp_id->GetBreakpointID());
-  if (!breakpoint_sp) {
-new_args.Clear();
-return llvm::createStringError(
-llvm::inconvertibleErrorCode(),
-"'%d' is not a valid breakpoint ID.\n",
-bp_id->GetBreakpointID());
-  }
-  const size_t num_locations = breakpoint_sp->GetNumLocations();
-  for (size_t j = 0; j < num_locations; ++j) {
-BreakpointLocation *bp_loc =
-breakpoint_sp->GetLocationAtIndex(j).get();
-StreamString canonical_id_str;
-BreakpointID::GetCanonicalReference(
-_id_str, bp_id->GetBreakpointID(), bp_loc->GetID());
-new_args.AppendArgument(canonical_id_str.GetString());
-  }
+  auto [prefix, suffix] = tmp_str.split('.');
+  if (suffix == "*" && BreakpointID::IsValidIDExpression(prefix)) {
+
+BreakpointSP breakpoint_sp;
+auto bp_id = BreakpointID::ParseCanonicalReference(prefix);
+if (bp_id)
+  breakpoint_sp = target->GetBreakpointByID(bp_id->GetBreakpointID());
+if (!breakpoint_sp) {
+  new_args.Clear();
+  return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "'%d' is not a valid breakpoint 
ID.\n",
+ bp_id->GetBreakpointID());
+}
+const size_t num_locations = breakpoint_sp->GetNumLocations();
+for (size_t j = 0; j < num_locations; ++j) {
+  BreakpointLocation *bp_loc =
+  breakpoint_sp->GetLocationAtIndex(j).get();
+  StreamString canonical_id_str;
+  BreakpointID::GetCanonicalReference(
+  _id_str, bp_id->GetBreakpointID(), bp_loc->GetID());
+  new_args.AppendArgument(canonical_id_str.GetString());
 }
   }
 }
diff --git 
a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
 
b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
index 8930bea619bb6e..d87e6275f7b51e 100644
--- 
a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py
+++