blob: d08a842867453d93de3719e10042578bf626a5fb [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 <lib/fidl/txn_header.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>
#include <iterator>
#include <vector>
#include "fuchsia-io-constants.h"
__attribute__((visibility("hidden"))) zx_handle_t __zircon_namespace_svc = ZX_HANDLE_INVALID;
namespace {
// TODO(https://fxbug.dev/42072760): This should be generated by Zither
constexpr const char fuchsia_debugdata_Publisher_Name[] = "fuchsia.debugdata.Publisher";
constexpr uint64_t fuchsia_debugdata_PublisherPublishOrdinal = 0xF52F8806121E066;
struct fuchsia_debugdata_PublisherPublishRequestMessage {
FIDL_ALIGNDECL
fidl_message_header_t hdr;
fidl_string_t data_sink;
zx_handle_t data;
zx_handle_t vmo_token;
};
#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_LENGTH) {
_zx_handle_close(object);
return ZX_ERR_INVALID_ARGS;
}
FIDL_ALIGNDECL char
wr_bytes[sizeof(fuchsia_io_DirectoryOpenRequest) + fuchsia_io_MAX_PATH_LENGTH] = {};
fuchsia_io_DirectoryOpenRequest* request = (fuchsia_io_DirectoryOpenRequest*)wr_bytes;
fidl_init_txn_header(&request->hdr, 0, fuchsia_io_DirectoryOpenOrdinal, 0);
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_PublisherPublish(zx_handle_t debug_data_channel, const char* data_sink_data,
size_t data_sink_size, zx_handle_t data,
zx_handle_t vmo_token) {
if (data_sink_size > fuchsia_io_MAX_NAME_LENGTH) {
_zx_handle_close(data);
return ZX_ERR_INVALID_ARGS;
}
FIDL_ALIGNDECL char wr_bytes[sizeof(fuchsia_debugdata_PublisherPublishRequestMessage) +
fuchsia_io_MAX_NAME_LENGTH] = {};
fuchsia_debugdata_PublisherPublishRequestMessage* request =
(fuchsia_debugdata_PublisherPublishRequestMessage*)wr_bytes;
fidl_init_txn_header(&request->hdr, 0, fuchsia_debugdata_PublisherPublishOrdinal, 0);
request->data_sink.data = (char*)FIDL_ALLOC_PRESENT;
request->data_sink.size = data_sink_size;
request->data = FIDL_HANDLE_PRESENT;
request->vmo_token = FIDL_HANDLE_PRESENT;
zx_handle_t handles[2] = {data, vmo_token};
memcpy(&wr_bytes[sizeof(*request)], data_sink_data, data_sink_size);
return _zx_channel_write(
debug_data_channel, 0u, wr_bytes,
static_cast<uint32_t>(sizeof(fuchsia_debugdata_PublisherPublishRequestMessage) +
FIDL_ALIGN(data_sink_size)),
handles, std::size(handles));
}
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, 0, 0, fuchsia_debugdata_Publisher_Name,
sizeof(fuchsia_debugdata_Publisher_Name) - 1, h0);
if (status != ZX_OK) {
constexpr const char kErrorDirectoryOpen[] = "Failed to open service namespace";
__sanitizer_log_write(kErrorDirectoryOpen, sizeof(kErrorDirectoryOpen) - 1);
_zx_handle_close(h1);
return ZX_HANDLE_INVALID;
}
return h1;
}
} // namespace
// Publish VMO and return back event pair handle which controls the lifetime of
// the VMO.
__EXPORT
zx_handle_t __sanitizer_publish_data(const char* sink_name, zx_handle_t vmo) {
if (__zircon_namespace_svc == ZX_HANDLE_INVALID) {
_zx_handle_close(vmo);
return ZX_HANDLE_INVALID;
}
zx_handle_t vmo_token_client, vmo_token_server;
if (_zx_eventpair_create(0, &vmo_token_client, &vmo_token_server) != ZX_OK) {
constexpr char kErrorEventPairCreate[] = "Failed to create eventpair for debugdata VMO token";
__sanitizer_log_write(kErrorEventPairCreate, sizeof(kErrorEventPairCreate) - 1);
return ZX_HANDLE_INVALID;
}
zx_handle_t debugdata_channel = sanitizer_debugdata_connect();
zx_status_t status = _fuchsia_debugdata_PublisherPublish(
debugdata_channel, sink_name, strlen(sink_name), vmo, vmo_token_server);
_zx_handle_close(debugdata_channel);
if (status != ZX_OK) {
constexpr const char kErrorPublish[] = "Failed to publish data";
__sanitizer_log_write(kErrorPublish, sizeof(kErrorPublish) - 1);
_zx_handle_close(vmo_token_client);
return ZX_HANDLE_INVALID;
}
return vmo_token_client;
}