blob: 6beaec3ab6c72ecf957446a9e99e29538dfc270b [file]
/*
* Copyright (C) 2026 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 "src/trace_processor/shell/util_subcommand.h"
#include <fstream>
#include <istream>
#include <ostream>
#include <string>
#include <vector>
#include "perfetto/base/status.h"
#include "perfetto/ext/base/status_macros.h"
#include "src/trace_processor/shell/convert_helpers.h"
#include "src/trace_processor/shell/subcommand.h"
#include "src/traceconv/deobfuscate_profile.h"
#include "src/traceconv/symbolize_profile.h"
#include "src/traceconv/trace_unpack.h"
namespace perfetto::trace_processor::shell {
const char* UtilSubcommand::name() const {
return "util";
}
const char* UtilSubcommand::description() const {
return "Low-level trace utilities (symbolize, deobfuscate, etc.).";
}
const char* UtilSubcommand::usage_args() const {
return "<symbolize|deobfuscate|decompress_packets|text_to_binary> [input] "
"[output]";
}
const char* UtilSubcommand::detailed_help() const {
return R"(Low-level trace utilities.
Utilities:
symbolize Symbolize addresses in a profile, emitting symbol packets.
deobfuscate Emit deobfuscation packets from a trace.
decompress_packets Decompress compressed trace packets.
text_to_binary Convert a text-format trace proto to binary.
If no input file is given, reads from stdin.
If no output file is given, writes to stdout.
symbolize/deobfuscate are lower-level than 'bundle', which is the recommended
one-shot way to produce a self-contained, symbolized trace.)";
}
std::vector<FlagSpec> UtilSubcommand::GetFlags() {
return {
BoolFlag("verbose", '\0', "Print more detailed output.", &verbose_),
};
}
base::Status UtilSubcommand::Run(const SubcommandContext& ctx) {
if (ctx.positional_args.empty()) {
return base::ErrStatus(
"util: a utility ('symbolize' or 'deobfuscate') must be specified.");
}
const std::string& util = ctx.positional_args[0];
const std::string input_path =
ctx.positional_args.size() > 1 ? ctx.positional_args[1] : "";
const std::string output_path =
ctx.positional_args.size() > 2 ? ctx.positional_args[2] : "";
if (util != "symbolize" && util != "deobfuscate" &&
util != "decompress_packets" && util != "text_to_binary") {
return base::ErrStatus(
"util: unknown utility '%s' (expected 'symbolize', 'deobfuscate', "
"'decompress_packets' or 'text_to_binary').",
util.c_str());
}
std::ifstream input_file;
std::istream* input = nullptr;
RETURN_IF_ERROR(OpenConversionInput(input_path, &input_file, &input));
std::ofstream output_file;
std::ostream* output = nullptr;
RETURN_IF_ERROR(OpenConversionOutput(output_path, &output_file, &output));
int ret;
if (util == "symbolize") {
ret = trace_to_text::SymbolizeProfile(input, output, verbose_);
} else if (util == "deobfuscate") {
ret = trace_to_text::DeobfuscateProfile(input, output);
} else if (util == "decompress_packets") {
ret = trace_to_text::UnpackCompressedPackets(input, output) ? 0 : 1;
} else { // text_to_binary
ret = TextToTrace(input, output);
}
if (ret != 0)
return base::ErrStatus("util: '%s' failed.", util.c_str());
return base::OkStatus();
}
} // namespace perfetto::trace_processor::shell