Merge "Add Rust wrapper for tombstoned client using cxx."
This commit is contained in:
commit
fad82b6c15
|
@ -2,6 +2,9 @@
|
||||||
"presubmit": [
|
"presubmit": [
|
||||||
{
|
{
|
||||||
"name": "debuggerd_test"
|
"name": "debuggerd_test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "libtombstoned_client_rust_test"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package {
|
||||||
|
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library_static {
|
||||||
|
name: "libtombstoned_client_wrapper",
|
||||||
|
srcs: [
|
||||||
|
"wrapper.cpp",
|
||||||
|
],
|
||||||
|
generated_sources: [
|
||||||
|
"libtombstoned_client_rust_bridge_code"
|
||||||
|
],
|
||||||
|
header_libs: [
|
||||||
|
"libbase_headers",
|
||||||
|
"libdebuggerd_common_headers",
|
||||||
|
],
|
||||||
|
shared_libs: [
|
||||||
|
"libtombstoned_client",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_defaults {
|
||||||
|
name: "libtombstoned_client_rust_defaults",
|
||||||
|
crate_name: "tombstoned_client",
|
||||||
|
srcs: ["src/lib.rs"],
|
||||||
|
edition: "2021",
|
||||||
|
rustlibs: [
|
||||||
|
"libcxx",
|
||||||
|
"libthiserror",
|
||||||
|
],
|
||||||
|
static_libs: [
|
||||||
|
"libtombstoned_client_wrapper",
|
||||||
|
],
|
||||||
|
shared_libs: [
|
||||||
|
"libtombstoned_client",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_library {
|
||||||
|
name: "libtombstoned_client_rust",
|
||||||
|
defaults: ["libtombstoned_client_rust_defaults"],
|
||||||
|
apex_available: ["com.android.virt"],
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_test {
|
||||||
|
name: "libtombstoned_client_rust_test",
|
||||||
|
defaults: ["libtombstoned_client_rust_defaults"],
|
||||||
|
require_root: true,
|
||||||
|
test_suites: ["device-tests"],
|
||||||
|
}
|
||||||
|
|
||||||
|
genrule {
|
||||||
|
name: "libtombstoned_client_rust_bridge_code",
|
||||||
|
tools: ["cxxbridge"],
|
||||||
|
cmd: "$(location cxxbridge) $(in) >> $(out)",
|
||||||
|
srcs: ["src/lib.rs"],
|
||||||
|
out: ["libtombstoned_client_cxx_generated.cc"],
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
// Copyright 2022, The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! Rust wrapper for tombstoned client.
|
||||||
|
|
||||||
|
pub use ffi::DebuggerdDumpType;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Error communicating with tombstoned.
|
||||||
|
#[derive(Clone, Debug, Error, Eq, PartialEq)]
|
||||||
|
#[error("Error communicating with tombstoned")]
|
||||||
|
pub struct Error;
|
||||||
|
|
||||||
|
/// File descriptors for communicating with tombstoned.
|
||||||
|
pub struct TombstonedConnection {
|
||||||
|
/// The socket connection to tombstoned.
|
||||||
|
///
|
||||||
|
/// This is actually a Unix SOCK_SEQPACKET socket not a file, but the Rust standard library
|
||||||
|
/// doesn't have an appropriate type and it's not really worth bringing in a dependency on `uds`
|
||||||
|
/// or something when all we do is pass it back to C++ or close it.
|
||||||
|
tombstoned_socket: File,
|
||||||
|
/// The file descriptor for text output.
|
||||||
|
pub text_output: Option<File>,
|
||||||
|
/// The file descriptor for proto output.
|
||||||
|
pub proto_output: Option<File>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TombstonedConnection {
|
||||||
|
unsafe fn from_raw_fds(
|
||||||
|
tombstoned_socket: RawFd,
|
||||||
|
text_output_fd: RawFd,
|
||||||
|
proto_output_fd: RawFd,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
tombstoned_socket: File::from_raw_fd(tombstoned_socket),
|
||||||
|
text_output: if text_output_fd >= 0 {
|
||||||
|
Some(File::from_raw_fd(text_output_fd))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
proto_output: if proto_output_fd >= 0 {
|
||||||
|
Some(File::from_raw_fd(proto_output_fd))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connects to tombstoned.
|
||||||
|
pub fn connect(pid: i32, dump_type: DebuggerdDumpType) -> Result<Self, Error> {
|
||||||
|
let mut tombstoned_socket = -1;
|
||||||
|
let mut text_output_fd = -1;
|
||||||
|
let mut proto_output_fd = -1;
|
||||||
|
if ffi::tombstoned_connect_files(
|
||||||
|
pid,
|
||||||
|
&mut tombstoned_socket,
|
||||||
|
&mut text_output_fd,
|
||||||
|
&mut proto_output_fd,
|
||||||
|
dump_type,
|
||||||
|
) {
|
||||||
|
Ok(unsafe { Self::from_raw_fds(tombstoned_socket, text_output_fd, proto_output_fd) })
|
||||||
|
} else {
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Notifies tombstoned that the dump is complete.
|
||||||
|
pub fn notify_completion(&self) -> Result<(), Error> {
|
||||||
|
if ffi::tombstoned_notify_completion(self.tombstoned_socket.as_raw_fd()) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cxx::bridge]
|
||||||
|
mod ffi {
|
||||||
|
/// The type of dump.
|
||||||
|
enum DebuggerdDumpType {
|
||||||
|
/// A native backtrace.
|
||||||
|
#[cxx_name = "kDebuggerdNativeBacktrace"]
|
||||||
|
NativeBacktrace,
|
||||||
|
/// A tombstone.
|
||||||
|
#[cxx_name = "kDebuggerdTombstone"]
|
||||||
|
Tombstone,
|
||||||
|
/// A Java backtrace.
|
||||||
|
#[cxx_name = "kDebuggerdJavaBacktrace"]
|
||||||
|
JavaBacktrace,
|
||||||
|
/// Any intercept.
|
||||||
|
#[cxx_name = "kDebuggerdAnyIntercept"]
|
||||||
|
AnyIntercept,
|
||||||
|
/// A tombstone proto.
|
||||||
|
#[cxx_name = "kDebuggerdTombstoneProto"]
|
||||||
|
TombstoneProto,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C++" {
|
||||||
|
include!("wrapper.hpp");
|
||||||
|
|
||||||
|
type DebuggerdDumpType;
|
||||||
|
|
||||||
|
fn tombstoned_connect_files(
|
||||||
|
pid: i32,
|
||||||
|
tombstoned_socket: &mut i32,
|
||||||
|
text_output_fd: &mut i32,
|
||||||
|
proto_output_fd: &mut i32,
|
||||||
|
dump_type: DebuggerdDumpType,
|
||||||
|
) -> bool;
|
||||||
|
|
||||||
|
fn tombstoned_notify_completion(tombstoned_socket: i32) -> bool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use std::{io::Write, process};
|
||||||
|
|
||||||
|
// Verify that we can connect to tombstoned, write something to the file descriptor it returns,
|
||||||
|
// and notify completion, without any errors.
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
let connection =
|
||||||
|
TombstonedConnection::connect(process::id() as i32, DebuggerdDumpType::Tombstone)
|
||||||
|
.expect("Failed to connect to tombstoned.");
|
||||||
|
|
||||||
|
assert!(connection.proto_output.is_none());
|
||||||
|
connection
|
||||||
|
.text_output
|
||||||
|
.as_ref()
|
||||||
|
.expect("No text output FD returned.")
|
||||||
|
.write_all(b"test data")
|
||||||
|
.expect("Failed to write to text output FD.");
|
||||||
|
|
||||||
|
connection
|
||||||
|
.notify_completion()
|
||||||
|
.expect("Failed to notify completion.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022, The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wrapper.hpp"
|
||||||
|
|
||||||
|
#include <android-base/unique_fd.h>
|
||||||
|
|
||||||
|
#include "tombstoned/tombstoned.h"
|
||||||
|
|
||||||
|
using android::base::unique_fd;
|
||||||
|
|
||||||
|
bool tombstoned_connect_files(pid_t pid, int& tombstoned_socket, int& text_output_fd,
|
||||||
|
int& proto_output_fd, DebuggerdDumpType dump_type) {
|
||||||
|
unique_fd tombstoned_socket_unique, text_output_unique, proto_output_unique;
|
||||||
|
|
||||||
|
bool result = tombstoned_connect(pid, &tombstoned_socket_unique, &text_output_unique,
|
||||||
|
&proto_output_unique, dump_type);
|
||||||
|
if (result) {
|
||||||
|
tombstoned_socket = tombstoned_socket_unique.release();
|
||||||
|
text_output_fd = text_output_unique.release();
|
||||||
|
proto_output_fd = proto_output_unique.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022, The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "tombstoned/tombstoned.h"
|
||||||
|
|
||||||
|
bool tombstoned_connect_files(pid_t pid, int& tombstoned_socket, int& text_output_fd,
|
||||||
|
int& proto_output_fd, DebuggerdDumpType dump_type);
|
Loading…
Reference in New Issue