blob: feb042b03f65347651588995b65ede656b3bcdc4 [file] [log] [blame]
// Copyright 2019 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 <fuchsia/debugdata/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <zircon/fidl.h>
#include <zircon/process.h>
#include <zircon/sanitizer.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/log.h>
__attribute__((visibility("hidden"))) zx_handle_t __zircon_namespace_svc = ZX_HANDLE_INVALID;
namespace {
#if __has_feature(address_sanitizer)
[[clang::no_sanitize("address")]]
#endif
zx_status_t
_fuchsia_io_DirectoryOpen(zx_handle_t channel, uint32_t flags, uint32_t mode, const char* path_data,
size_t path_size, zx_handle_t object) {
if (path_size > fuchsia_io_MAX_PATH) {
_zx_handle_close(object);
return ZX_ERR_INVALID_ARGS;
}
FIDL_ALIGNDECL char wr_bytes[sizeof(fuchsia_io_DirectoryOpenRequest) + fuchsia_io_MAX_PATH] = {};
fuchsia_io_DirectoryOpenRequest* request = (fuchsia_io_DirectoryOpenRequest*)wr_bytes;
// TODO(38643) use fidl_init_txn_header once it is inline
memset(&request->hdr, 0, sizeof(request->hdr));
request->hdr.magic_number = kFidlWireFormatMagicNumberInitial;
request->hdr.ordinal = fuchsia_io_DirectoryOpenOrdinal;
request->flags = flags;
request->mode = mode;
request->path.data = (char*)FIDL_ALLOC_PRESENT;
request->path.size = path_size;
request->object = FIDL_HANDLE_PRESENT;
memcpy(&wr_bytes[sizeof(*request)], path_data, path_size);
return _zx_channel_write(
channel, 0u, wr_bytes,
static_cast<uint32_t>(sizeof(fuchsia_io_DirectoryOpenRequest) + FIDL_ALIGN(path_size)),
&object, 1);
}
#if __has_feature(address_sanitizer)
[[clang::no_sanitize("address")]]
#endif
zx_status_t
_fuchsia_debugdata_DebugDataPublish(zx_handle_t channel, const char* data_sink_data,
size_t data_sink_size, zx_handle_t data) {
if (data_sink_size > fuchsia_debugdata_MAX_NAME) {
_zx_handle_close(data);
return ZX_ERR_INVALID_ARGS;
}
FIDL_ALIGNDECL char
wr_bytes[sizeof(fuchsia_debugdata_DebugDataPublishRequest) + fuchsia_debugdata_MAX_NAME] = {};
fuchsia_debugdata_DebugDataPublishRequest* request =
(fuchsia_debugdata_DebugDataPublishRequest*)wr_bytes;
// TODO(38643) use fidl_init_txn_header once it is inline
memset(&request->hdr, 0, sizeof(request->hdr));
request->hdr.magic_number = kFidlWireFormatMagicNumberInitial;
request->hdr.ordinal = fuchsia_debugdata_DebugDataPublishGenOrdinal;
request->data_sink.data = (char*)FIDL_ALLOC_PRESENT;
request->data_sink.size = data_sink_size;
request->data = FIDL_HANDLE_PRESENT;
memcpy(&wr_bytes[sizeof(*request)], data_sink_data, data_sink_size);
return _zx_channel_write(channel, 0u, wr_bytes,
static_cast<uint32_t>(sizeof(fuchsia_debugdata_DebugDataPublishRequest) +
FIDL_ALIGN(data_sink_size)),
&data, 1);
}
#if __has_feature(address_sanitizer)
[[clang::no_sanitize("address")]]
#endif
zx_status_t
_fuchsia_debugdata_DebugDataLoadConfig(zx_handle_t channel, const char* config_name_data,
size_t config_name_size, zx_handle_t* out_config) {
if (config_name_size > fuchsia_debugdata_MAX_NAME) {
return ZX_ERR_INVALID_ARGS;
}
FIDL_ALIGNDECL char wr_bytes[sizeof(fuchsia_debugdata_DebugDataLoadConfigRequest) +
fuchsia_debugdata_MAX_NAME] = {};
fuchsia_debugdata_DebugDataLoadConfigRequest* request =
(fuchsia_debugdata_DebugDataLoadConfigRequest*)wr_bytes;
// TODO(38643) use fidl_init_txn_header once it is inline
memset(&request->hdr, 0, sizeof(request->hdr));
request->hdr.magic_number = kFidlWireFormatMagicNumberInitial;
request->hdr.ordinal = fuchsia_debugdata_DebugDataLoadConfigGenOrdinal;
request->config_name.data = (char*)FIDL_ALLOC_PRESENT;
request->config_name.size = config_name_size;
memcpy(&wr_bytes[sizeof(*request)], config_name_data, config_name_size);
FIDL_ALIGNDECL char rd_bytes[sizeof(fuchsia_debugdata_DebugDataLoadConfigResponse)];
zx_channel_call_args_t args = {
.wr_bytes = wr_bytes,
.wr_handles = nullptr,
.rd_bytes = rd_bytes,
.rd_handles = out_config,
.wr_num_bytes = static_cast<uint32_t>(sizeof(fuchsia_debugdata_DebugDataLoadConfigRequest) +
FIDL_ALIGN(config_name_size)),
.wr_num_handles = 0,
.rd_num_bytes = sizeof(fuchsia_debugdata_DebugDataLoadConfigResponse),
.rd_num_handles = 1,
};
uint32_t actual_bytes = 0u;
uint32_t actual_handles = 0u;
zx_status_t status =
zx_channel_call(channel, 0u, ZX_TIME_INFINITE, &args, &actual_bytes, &actual_handles);
if (!actual_handles)
*out_config = ZX_HANDLE_INVALID;
return status;
}
zx_handle_t sanitizer_debugdata_connect() {
zx_handle_t h0, h1;
zx_status_t status;
if ((status = _zx_channel_create(0, &h0, &h1)) != ZX_OK) {
constexpr const char kErrorChannelCreate[] = "Failed to create channel for debugdata service";
__sanitizer_log_write(kErrorChannelCreate, sizeof(kErrorChannelCreate) - 1);
return ZX_HANDLE_INVALID;
}
status = _fuchsia_io_DirectoryOpen(
__zircon_namespace_svc, fuchsia_io_OPEN_RIGHT_READABLE | fuchsia_io_OPEN_RIGHT_WRITABLE, 0,
fuchsia_debugdata_DebugData_Name, strlen(fuchsia_debugdata_DebugData_Name), h0);
if (status != ZX_OK) {
constexpr const char kErrorDirectoryOpen[] = "Failed to open service namespace";
__sanitizer_log_write(kErrorDirectoryOpen, sizeof(kErrorDirectoryOpen) - 1);
return ZX_HANDLE_INVALID;
}
return h1;
}
} // namespace
__EXPORT
void __sanitizer_publish_data(const char* sink_name, zx_handle_t vmo) {
zx_handle_t h = sanitizer_debugdata_connect();
// The handle is always consumed by the callee.
if (_fuchsia_debugdata_DebugDataPublish(h, sink_name, strlen(sink_name), vmo) != ZX_OK) {
constexpr const char kErrorPublish[] = "Failed to publish data";
__sanitizer_log_write(kErrorPublish, sizeof(kErrorPublish) - 1);
}
}
__EXPORT
zx_status_t __sanitizer_get_configuration(const char* name, zx_handle_t* out_vmo) {
zx_handle_t h = sanitizer_debugdata_connect();
zx_status_t status = _fuchsia_debugdata_DebugDataLoadConfig(h, name, strlen(name), out_vmo);
if (status != ZX_OK) {
constexpr const char kErrorLoadConfig[] = "Failed to get configuration file";
__sanitizer_log_write(kErrorLoadConfig, sizeof(kErrorLoadConfig) - 1);
}
return status;
}