blob: ca8503b12c6aa986d1d5fdfa2333137d8a334a3b [file]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/debug/zxdb/debug_adapter/data_id.h"
#include <inttypes.h>
#include <lib/syslog/cpp/macros.h>
#include <limits>
#include <string>
#include <string_view>
#include "src/developer/debug/shared/arch.h"
#include "src/developer/debug/zxdb/client/breakpoint_settings.h"
#include "src/developer/debug/zxdb/common/err_or.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/lib/fxl/strings/string_number_conversions.h"
#include "src/lib/fxl/strings/string_printf.h"
namespace zxdb {
ErrOr<DataId> DataId::FromExprValue(debug::Arch arch, uint64_t process_koid,
const std::string& name, const ExprValue& value) {
FX_DCHECK(process_koid != 0);
const ExprValueSource& source = value.source();
if (source.type() != ExprValueSource::Type::kMemory) {
return Err(
"Expression '%s' is stored in a %s location. Only values stored in memory can be watched.",
name.c_str(), ExprValueSource::TypeToString(source.type()));
}
if (source.is_bitfield()) {
return Err("Bitfields cannot be watched.");
}
size_t raw_size = value.data().size();
uint32_t size = raw_size > std::numeric_limits<uint32_t>::max()
? std::numeric_limits<uint32_t>::max()
: static_cast<uint32_t>(raw_size);
if (Err err = BreakpointSettings::ValidateSize(arch, BreakpointSettings::Type::kWrite, size);
err.has_error()) {
return err;
}
uint64_t address = source.address();
if (address > std::numeric_limits<uint64_t>::max() - size) {
return Err("Address range overflows 64-bit address space.");
}
return DataId(process_koid, address, size);
}
ErrOr<DataId> DataId::Parse(std::string_view data_id) {
Err format_err("Invalid dataId format: " + std::string(data_id));
size_t first_colon = data_id.find(':');
if (first_colon == std::string_view::npos) {
return format_err;
}
size_t second_colon = data_id.find(':', first_colon + 1);
if (second_colon == std::string_view::npos ||
data_id.find(':', second_colon + 1) != std::string_view::npos) {
return format_err;
}
uint64_t koid = 0;
if (!fxl::StringToNumberWithError<uint64_t>(data_id.substr(0, first_colon), &koid,
fxl::Base::k10) ||
koid == 0) {
return format_err;
}
std::string_view addr_part = data_id.substr(first_colon + 1, second_colon - first_colon - 1);
std::string_view size_part = data_id.substr(second_colon + 1);
if (addr_part.size() <= 2 || addr_part[0] != '0' ||
(addr_part[1] != 'x' && addr_part[1] != 'X')) {
return format_err;
}
uint64_t address = 0;
uint32_t byte_size = 0;
if (!fxl::StringToNumberWithError<uint64_t>(addr_part.substr(2), &address, fxl::Base::k16) ||
!fxl::StringToNumberWithError<uint32_t>(size_part, &byte_size, fxl::Base::k10)) {
return format_err;
}
if (address > std::numeric_limits<uint64_t>::max() - byte_size) {
return format_err;
}
return DataId(koid, address, byte_size);
}
Err DataId::ValidateSize(debug::Arch arch, BreakpointSettings::Type type) const {
return BreakpointSettings::ValidateSize(arch, type, byte_size_);
}
std::string DataId::ToString() const {
return fxl::StringPrintf("%" PRIu64 ":0x%" PRIx64 ":%u", process_koid_, address_, byte_size_);
}
} // namespace zxdb