Snap for 12309590 from c6427b61ead131a449fdebf0c3ba74cf3b4a8c4e to 24Q4-release
Change-Id: I6b7fb11dc3bea288481d3896e162ddf285b69121
diff --git a/btf_reader.cc b/btf_reader.cc
index 397d996..ad5248d 100644
--- a/btf_reader.cc
+++ b/btf_reader.cc
@@ -151,33 +151,19 @@
maker_.Set<Node>(id, std::forward<Args>(args)...);
}
-bool IsAlignedForBtf(std::string_view btf_data) {
- return reinterpret_cast<uintptr_t>(btf_data.data()) % alignof(btf_header) ==
- 0;
-}
-
Id Structs::Process(std::string_view btf_data) {
- Check(sizeof(btf_header) <= btf_data.size())
- << "BTF section too small for header";
- if (IsAlignedForBtf(btf_data)) {
- return ProcessAligned(btf_data);
- }
- // Copy the data to aligned memory.
- // Check that minimum amount of BTF data containing just btf_header will be
- // heap allocated and will not fit inside the std::string due to small string
- // optimization.
// TODO: Remove this hack once the upstream binaries have proper
// alignment.
- static_assert(
- sizeof(btf_header) >= sizeof(std::string),
- "btf_header may hit small string optimization and be misaligned");
- const std::string aligned_btf_data(btf_data);
- Check(IsAlignedForBtf(aligned_btf_data))
- << "std::string with BTF data is misaligned";
- return ProcessAligned(aligned_btf_data);
+ //
+ // Copy the data to aligned heap-allocated memory, if needed.
+ return reinterpret_cast<uintptr_t>(btf_data.data()) % alignof(btf_header) > 0
+ ? ProcessAligned(std::string(btf_data))
+ : ProcessAligned(btf_data);
}
Id Structs::ProcessAligned(std::string_view btf_data) {
+ Check(sizeof(btf_header) <= btf_data.size())
+ << "BTF section too small for header";
const btf_header* header =
reinterpret_cast<const btf_header*>(btf_data.data());
Check(header->magic == 0xEB9F) << "Magic field must be 0xEB9F for BTF";
diff --git a/doc/stgdiff.md b/doc/stgdiff.md
index 62d6dd2..7f0c33b 100644
--- a/doc/stgdiff.md
+++ b/doc/stgdiff.md
@@ -133,11 +133,16 @@
* Loss or gain of type definitions
* Loss or gain of type information for symbols
-## Output formats
+## Output
All outputs are based on a diff graph which is rooted at the comparison of two
symbol table nodes.
+The `--format` and `--output` options may be repeated to obtain outputs of
+different formats.
+
+### Formats
+
* `plain`
Serialise the diff graph via depth first search, avoiding revisiting nodes
diff --git a/proto_reader.cc b/proto_reader.cc
index f046458..264a54d 100644
--- a/proto_reader.cc
+++ b/proto_reader.cc
@@ -24,13 +24,17 @@
#include <cerrno>
#include <cstdint>
#include <fstream>
+#include <limits>
#include <map>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/repeated_ptr_field.h>
#include <google/protobuf/text_format.h>
@@ -456,54 +460,70 @@
const std::array<uint32_t, 3> kSupportedFormatVersions = {0, 1, 2};
-void CheckFormatVersion(uint32_t version, std::optional<std::string> path) {
+void CheckFormatVersion(uint32_t version) {
Check(std::binary_search(kSupportedFormatVersions.begin(),
kSupportedFormatVersions.end(), version))
<< "STG format version " << version
<< " is not supported, minimum supported version: "
<< kSupportedFormatVersions.front();
if (version != kSupportedFormatVersions.back()) {
- auto warn = Warn();
- warn << "STG format version " << version
- << " is deprecated, consider upgrading stg format to latest version ("
- << kSupportedFormatVersions.back() << ")";
- if (path) {
- warn << " with: stg --stg " << *path << " --output " << *path;
- }
+ Warn() << "STG format version " << version
+ << " is deprecated, consider upgrading to the latest version ("
+ << kSupportedFormatVersions.back() << ")";
+ }
+}
+
+class ErrorSink : public google::protobuf::io::ErrorCollector {
+ public:
+ void AddError(int line, google::protobuf::io::ColumnNumber column,
+ const std::string& message) final {
+ Moan("error", line, column, message);
+ }
+ void AddWarning(int line, google::protobuf::io::ColumnNumber column,
+ const std::string& message) final {
+ Moan("warning", line, column, message);
+ }
+
+ private:
+ static void Moan(std::string_view which, int line,
+ google::protobuf::io::ColumnNumber column,
+ const std::string& message) {
+ Warn() << "google::protobuf::TextFormat " << which << " at line " << (line + 1)
+ << " column " << (column + 1) << ": " << message;
+ }
+};
+
+Id ReadHelper(Runtime& runtime, Graph& graph,
+ google::protobuf::io::ZeroCopyInputStream& is) {
+ proto::STG stg;
+ {
+ const Time t(runtime, "proto.Parse");
+ ErrorSink error_sink;
+ google::protobuf::TextFormat::Parser parser;
+ parser.RecordErrorsTo(&error_sink);
+ Check(parser.Parse(&is, &stg)) << "failed to parse input as STG";
+ }
+ {
+ const Time t(runtime, "proto.Transform");
+ CheckFormatVersion(stg.version());
+ return Transformer(graph).Transform(stg);
}
}
} // namespace
Id Read(Runtime& runtime, Graph& graph, const std::string& path) {
- proto::STG stg;
- {
- const Time t(runtime, "proto.Parse");
- std::ifstream ifs(path);
- Check(ifs.good()) << "error opening file '" << path
- << "' for reading: " << Error(errno);
- google::protobuf::io::IstreamInputStream is(&ifs);
- google::protobuf::TextFormat::Parse(&is, &stg);
- }
- {
- const Time t(runtime, "proto.Transform");
- CheckFormatVersion(stg.version(), path);
- return Transformer(graph).Transform(stg);
- }
+ std::ifstream ifs(path);
+ Check(ifs.good()) << "error opening file '" << path << "' for reading: "
+ << Error(errno);
+ google::protobuf::io::IstreamInputStream is(&ifs);
+ return ReadHelper(runtime, graph, is);
}
Id ReadFromString(Runtime& runtime, Graph& graph, std::string_view input) {
- proto::STG stg;
- {
- const Time t(runtime, "proto.Parse");
- // TODO: Pass string_view once AOSP Protobuf supports this.
- google::protobuf::TextFormat::ParseFromString(std::string(input), &stg);
- }
- {
- const Time t(runtime, "proto.Transform");
- CheckFormatVersion(stg.version(), std::nullopt);
- return Transformer(graph).Transform(stg);
- }
+ Check(input.size() <= std::numeric_limits<int>::max()) << "input too big";
+ google::protobuf::io::ArrayInputStream is(input.data(), static_cast<int>(input.size()));
+ return ReadHelper(runtime, graph, is);
}
} // namespace proto
diff --git a/test_cases/info_tests/variant/optional_empty.rs b/test_cases/info_tests/variant/optional_empty.rs
index 1cda07c..f1552c5 100644
--- a/test_cases/info_tests/variant/optional_empty.rs
+++ b/test_cases/info_tests/variant/optional_empty.rs
@@ -4,6 +4,5 @@
pub fn is_none(opt: Option<Empty>) -> bool {
match opt {
None => true,
- _ => false,
}
}