blob: 4c13922e98207b65f82d2f9136b10647a089d128 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "crash-reporter/bluetooth_devcd_parser_util.h"
#include <vector>
#include <base/containers/span.h>
#include <base/files/file.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <brillo/strings/string_utils.h>
#include <gtest/gtest.h>
#include "crash-reporter/udev_bluetooth_util.h"
#include "crash-reporter/util.h"
namespace {
constexpr char kMetaHeader[] = "Bluetooth devcoredump";
std::vector<uint8_t> Flatten(const std::vector<std::vector<uint8_t>>& vec) {
std::vector<uint8_t> flattened;
for (const auto& v : vec) {
flattened.insert(flattened.end(), v.begin(), v.end());
}
return flattened;
}
} // namespace
class BluetoothDevcdParserUtilTest : public ::testing::Test {
protected:
void CreateDumpFile(const std::vector<std::string>& meta_data,
const std::vector<uint8_t>& data = {}) {
std::string meta_data_str = brillo::string_utils::Join("\n", meta_data);
std::string data_header = "\n--- Start dump ---\n";
// Clear previous test files, if any
ASSERT_TRUE(base::DeleteFile(dump_path_));
ASSERT_TRUE(base::DeleteFile(target_path_));
ASSERT_TRUE(base::DeleteFile(data_path_));
base::File file(dump_path_,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(file.IsValid());
ASSERT_TRUE(file.WriteAtCurrentPosAndCheck(
base::as_bytes(base::make_span(meta_data_str))));
if (!data.empty()) {
ASSERT_TRUE(file.WriteAtCurrentPosAndCheck(
base::as_bytes(base::make_span(data_header))));
ASSERT_TRUE(file.WriteAtCurrentPosAndCheck(base::make_span(data)));
}
}
void VerifyProcessedDump(const std::vector<std::string>& want_lines) {
base::File file(target_path_,
base::File::FLAG_OPEN | base::File::FLAG_READ);
std::string line;
for (const auto& want : want_lines) {
ASSERT_GT(util::GetNextLine(file, line), 0);
EXPECT_EQ(line, want);
}
// Make sure there are no more lines
ASSERT_EQ(util::GetNextLine(file, line), 0);
}
base::FilePath output_dir_;
base::FilePath dump_path_;
base::FilePath target_path_;
base::FilePath data_path_;
private:
void SetUp() override {
CHECK(tmp_dir_.CreateUniqueTempDir());
output_dir_ = tmp_dir_.GetPath();
dump_path_ = output_dir_.Append("bt_firmware.devcd");
target_path_ = output_dir_.Append("bt_firmware.txt");
data_path_ = output_dir_.Append("bt_firmware.data");
}
base::ScopedTempDir tmp_dir_;
};
// Test a failure case when reading the input coredump file fails.
TEST_F(BluetoothDevcdParserUtilTest, TestInvalidPath) {
std::string sig;
EXPECT_FALSE(bluetooth_util::ParseBluetoothCoredump(
dump_path_.ReplaceExtension("invalid"), output_dir_, true, &sig));
}
// A key-value pair in header fields is of type "<key>: <value>". Verify
// that malformed key-value pairs are not parsed and an error is returned.
TEST_F(BluetoothDevcdParserUtilTest, TestInvalidHeaderField) {
std::string sig;
// Test missing value in key-value pair
std::vector<std::string> meta_data = {
kMetaHeader,
"State:",
};
CreateDumpFile(meta_data);
EXPECT_FALSE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
// Test malformed key-value pair
meta_data = {
kMetaHeader,
"State 0",
};
CreateDumpFile(meta_data);
EXPECT_FALSE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
}
// Verify that the devcodedump state with a value other than 0-4 is reported
// as is. For values between 0 through 4, it's equivalent human readable state
// string is reported.
TEST_F(BluetoothDevcdParserUtilTest, TestInvalidState) {
std::vector<std::string> meta_data = {
kMetaHeader,
"State: -1",
"Driver: TestDrv",
"Vendor: TestVen",
"Controller Name: TestCon",
};
CreateDumpFile(meta_data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-TestDrv-TestVen_TestCon-00000000");
base::File file(target_path_, base::File::FLAG_OPEN | base::File::FLAG_READ);
std::string line;
util::GetNextLine(file, line);
EXPECT_EQ(line, "State=-1");
}
// The Driver Name, Vendor Name and Controller Name are required key-value
// pairs. Although we allow partial dumps, parsing should fail if any of
// these required keys are missing.
TEST_F(BluetoothDevcdParserUtilTest, TestMissingMetaKey) {
std::string sig;
// Test missing driver case
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 0",
"Vendor: TestVen",
"Controller Name: TestCon",
};
CreateDumpFile(meta_data);
EXPECT_FALSE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
// Test missing vendor case
meta_data = {
kMetaHeader,
"State: 0",
"Driver: TestDrv",
"Controller Name: TestCon",
};
CreateDumpFile(meta_data);
EXPECT_FALSE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
// Test missing controller name case
meta_data = {
kMetaHeader,
"State: 0",
"Driver: TestDrv",
"Vendor: TestVen",
};
CreateDumpFile(meta_data);
EXPECT_FALSE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
}
// After updating the devcoredump state, the Bluetooth HCI Devcoredump
// API adds a '\0' at the end of the "State:" key-value, i.e. before the
// "Driver:" key-value pair. Verify this case.
TEST_F(BluetoothDevcdParserUtilTest, TestHeaderWithNullChar) {
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
std::string("\0Driver: TestDrv", 16),
"Vendor: TestVen",
"Controller Name: TestCon",
};
CreateDumpFile(meta_data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-TestDrv-TestVen_TestCon-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete", "Driver=TestDrv", "Vendor=TestVen",
"Controller Name=TestCon", "PC=00000000",
};
VerifyProcessedDump(want_lines);
}
// A bluetooth devcoredump with just a header but no vendor specific binary
// data is a valid dump. Verify that the empty dump is reported properly.
TEST_F(BluetoothDevcdParserUtilTest, TestValidEmptyDump) {
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: TestDrv",
"Vendor: TestVen",
"Controller Name: TestCon",
};
CreateDumpFile(meta_data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-TestDrv-TestVen_TestCon-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete", "Driver=TestDrv", "Vendor=TestVen",
"Controller Name=TestCon", "PC=00000000",
};
VerifyProcessedDump(want_lines);
}
// For debugging purposes, vendor specific binary data is stored on a
// developer images. Verify that the header is stripped off correctly and
// the binary data is stored.
TEST_F(BluetoothDevcdParserUtilTest, TestDumpData) {
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: TestDrv",
"Vendor: TestVen",
"Controller Name: TestCon",
};
std::vector<uint8_t> data = {'T', 'e', 's', 't', '\n'};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
true, &sig));
EXPECT_EQ(sig, "bt_firmware-TestDrv-TestVen_TestCon-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete", "Driver=TestDrv", "Vendor=TestVen",
"Controller Name=TestCon", "PC=00000000",
};
VerifyProcessedDump(want_lines);
base::File file(data_path_, base::File::FLAG_OPEN | base::File::FLAG_READ);
std::string line;
util::GetNextLine(file, line);
EXPECT_EQ(line, "Test");
}
// Verify all Intel TLVs are parsed correctly and the PC is included in the
// crash signature.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelDumpWithPC) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header
{
0xFF, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Exception Type
{
0x01, 0x01, 0x01,
},
// TLV - Line Number
{
0x02, 0x02, 0x12, 0x34,
},
// TLV - Module Number
{
0x03, 0x01, 0x02,
},
// TLV - Error ID
{
0x04, 0x01, 0x03,
},
// TLV - Call Backtrace - Func 1 Addr, Func2 Addr ... Func 5 Addr
{
0x05, 0x14, 0x00, 0x00, 0xFC, 0x4D, 0x00, 0x0C, 0x44, 0x8E, 0x00,
0x06, 0x09, 0x28, 0x00, 0x00, 0xEE, 0x04, 0x00, 0x0C, 0x0C, 0x80,
},
// TLV - Aux Registers - CPSR, PC, SP, BLINK
{
0x06, 0x10, 0x00, 0x00, 0x4D, 0xFC, 0x00, 0x0C, 0x8E, 0x44, 0x00,
0x06, 0x28, 0x09, 0x00, 0x00, 0x04, 0xEE,
},
// TLV - Exception Subtype
{
0x07, 0x01, 0x04,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
// As per the Intel coredump format, 2nd byte of the data stores length of the
// dump data excluding size of the 1st byte (code) and 2nd byte (length byte).
data[1] = data.size() - 2;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-000C8E44");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF3B878003",
"Exception Type=01",
"Line Number=1234",
"Module Number=02",
"Error Id=03",
"Call Backtrace=0000FC4D 000C448E 00060928 0000EE04 000C0C80",
"CPSR=00004DFC",
"PC=000C8E44",
"SP=00062809",
"BLINK=000004EE",
"Exception Subtype=04",
};
VerifyProcessedDump(want_lines);
}
// Verify Aux Register Extended TLV is parsed correctly and the PC is included
// in the crash signature.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelDumpWithAuxRegExt) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header
{
0xFF, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Aux Registers Ext - BLINK, PC, ERSTATUS, ECR, EFA, IRQ, ICAUSE
{
0x06, 0x1C, 0x00, 0x00, 0x4D, 0xFC, 0x00, 0x0C, 0x8E, 0x44, 0x00,
0x06, 0x28, 0x09, 0x00, 0x00, 0x04, 0xEE, 0x00, 0x0C, 0x44, 0x8E,
0x00, 0x06, 0x09, 0x28, 0x00, 0x00, 0xEE, 0x04,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
// As per the Intel coredump format, 2nd byte of the data stores length of the
// dump data excluding size of the 1st byte (code) and 2nd byte (length byte).
data[1] = data.size() - 2;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-000C8E44");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF21878003",
"BLINK=00004DFC",
"PC=000C8E44",
"ERSTATUS=00062809",
"ECR=000004EE",
"EFA=000C448E",
"IRQ=00060928",
"ICAUSE=0000EE04",
};
VerifyProcessedDump(want_lines);
}
// Verify if the TLV containing PC is not present, a default PC (00000000)
// is reported.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelDumpWithoutPC) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header
{
0xFF, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Exception Type
{
0x01, 0x01, 0x01,
},
// TLV - Line Number
{
0x02, 0x02, 0x12, 0x34,
},
// TLV - Module Number
{
0x03, 0x01, 0x02,
},
// TLV - Error ID
{
0x04, 0x01, 0x03,
},
// TLV - Call Backtrace - Func 1 Addr, Func2 Addr ... Func 5 Addr
{
0x05, 0x14, 0x00, 0x00, 0xFC, 0x4D, 0x00, 0x0C, 0x44, 0x8E, 0x00,
0x06, 0x09, 0x28, 0x00, 0x00, 0xEE, 0x04, 0x00, 0x0C, 0x0C, 0x80,
},
// TLV - Exception Subtype
{
0x07, 0x01, 0x04,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
// As per the Intel coredump format, 2nd byte of the data stores length of the
// dump data excluding size of the 1st byte (code) and 2nd byte (length byte).
data[1] = data.size() - 2;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF29878003",
"Exception Type=01",
"Line Number=1234",
"Module Number=02",
"Error Id=03",
"Call Backtrace=0000FC4D 000C448E 00060928 0000EE04 000C0C80",
"Exception Subtype=04",
"PC=00000000",
};
VerifyProcessedDump(want_lines);
}
// Verify that the vendor specific private TLV is not processed and not
// included in the parsed devcoredump.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelDumpPrivateTLV) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header
{
0xFF, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Exception Type
{
0x01, 0x01, 0x01,
},
// Random Private TLV
{
0x12, 0x01, 0x03,
},
// TLV - Module Number
{
0x03, 0x01, 0x02,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
// As per the Intel coredump format, 2nd byte of the data stores length of the
// dump data excluding size of the 1st byte (code) and 2nd byte (length byte).
data[1] = data.size() - 2;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF0C878003",
"Exception Type=01",
"Module Number=02",
"PC=00000000",
};
VerifyProcessedDump(want_lines);
}
// Verify that when a TLV with incorrect length is encountered, parsing of the
// remaining devcoredump is skipped but already parsed data is still reported.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelDumpWithIncorrectTypeLen) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header
{
0xFF, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Exception Type with incorrect Type Len D0, should skip parsing of
// all remaining tuples
{
0x01, 0xD0, 0x01,
},
// TLV - Line Number
{
0x02, 0x02, 0x12, 0x34,
},
// TLV - Module Number
{
0x03, 0x01, 0x02,
},
// TLV - Error ID
{
0x04, 0x01, 0x03,
},
// TLV - Call Backtrace - Func 1 Addr, Func2 Addr ... Func 5 Addr
{
0x05, 0x14, 0x00, 0x00, 0xFC, 0x4D, 0x00, 0x0C, 0x44, 0x8E, 0x00,
0x06, 0x09, 0x28, 0x00, 0x00, 0xEE, 0x04, 0x00, 0x0C, 0x0C, 0x80,
},
// TLV - Aux Registers - CPSR, PC, SP, BLINK
{
0x06, 0x10, 0x00, 0x00, 0x4D, 0xFC, 0x00, 0x0C, 0x8E, 0x44, 0x00,
0x06, 0x28, 0x09, 0x00, 0x00, 0x04, 0xEE,
},
// TLV - Exception Subtype
{
0x07, 0x01, 0x04,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
// As per the Intel coredump format, 2nd byte of the data stores length of the
// dump data excluding size of the 1st byte (code) and 2nd byte (length byte).
data[1] = data.size() - 2;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_NE(sig, "bt_firmware-btusb-Intel_0x12-000C8E44");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF3B878003",
"Parse Failure Reason=2",
"PC=00000000",
};
VerifyProcessedDump(want_lines);
}
// Verify that the partial devcoredump is processed successfully and all the
// available data is parsed and reported.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelPartialDump) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header
{
0xFF, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Exception Type
{
0x01, 0x01, 0x01,
},
// TLV - Module Number (Incomplete)
{
0x03, 0x01,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
// As per the Intel coredump format, 2nd byte of the data stores length of the
// dump data excluding size of the 1st byte (code) and 2nd byte (length byte).
data[1] = data.size() - 2;
// Increase the data len without actually adding any data bytes to test the
// partial dump case.
data[1] += 10;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF12878003",
"Exception Type=01",
"Parse Failure Reason=2",
"PC=00000000",
};
VerifyProcessedDump(want_lines);
}
// Verify that the devcoredump with incorrect data length (i.e. data[1] byte)
// is processed successfully and the empty dump with just a parsed header is
// reported.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelIncorrectDataLen) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header
{
0xFF, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Exception Type
{
0x01, 0x01, 0x01,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF00878003",
"PC=00000000",
"Parse Failure Reason=1",
};
VerifyProcessedDump(want_lines);
}
// Verify that the devcoredump with incorrect debug code (i.e. data[0] byte)
// is processed successfully and the empty dump with just a parsed header is
// reported.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelIncorrectDebugCode) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> data_vec = {
// Intel coredump header (Incorrect debug code 0xFE - should skip parsing
// of all remaining tuples)
{
0xFE, 0x00, 0x87, 0x80, 0x03,
},
// TLV - Exception Type
{
0x01, 0x01, 0x01,
},
};
// clang-format on
std::vector<uint8_t> data = Flatten(data_vec);
// As per the Intel coredump format, 2nd byte of the data stores length of the
// dump data excluding size of the 1st byte (code) and 2nd byte (length byte).
data[1] = data.size() - 2;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FE06878003",
"PC=00000000",
"Parse Failure Reason=1",
};
VerifyProcessedDump(want_lines);
}
// Verify that the incomplete TLVs are processed successfully and all the other
// available data is parsed and reported.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelIncompleteTLVs) {
// Clang format expands the following to one hex value per line.
// Disable clang format to keep it as it is for better readability.
// clang-format off
std::vector<std::vector<uint8_t>> tlv_list = {
// TLV - Exception Type (incomplete)
{
0x01, 0x01,
},
// TLV - Line Number (incomplete)
{
0x02, 0x02,
},
// TLV - Module Number (incomplete)
{
0x03, 0x01,
},
// TLV - Error ID (incomplete)
{
0x04, 0x01,
},
// TLV - Call Backtrace (incomplete)
{
0x05, 0x14,
},
// TLV - Aux Registers (incomplete)
{
0x06, 0x10,
},
// TLV - Exception Subtype (incomplete)
{
0x07, 0x01,
},
};
// clang-format on
for (auto& tlv : tlv_list) {
// Intel coredump header
std::vector<uint8_t> data = {0xFF, 0x00, 0x87, 0x80, 0x03};
// Insert TLV after the header
data.insert(data.end(), tlv.begin(), tlv.end());
// As per the Intel coredump format, 2nd byte of the data stores len of the
// dump data excluding size of the 1st byte (code) and 2nd byte (len byte).
data[1] = data.size() - 2;
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data, data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete",
"Driver=btusb",
"Vendor=Intel",
"Controller Name=0x12",
"Intel Event Header=FF05878003",
"Parse Failure Reason=2",
"PC=00000000",
};
VerifyProcessedDump(want_lines);
}
}
// A bluetooth devcoredump with just a header but no vendor specific binary
// data is a valid dump. Verify that the empty dump is reported properly.
TEST_F(BluetoothDevcdParserUtilTest, TestIntelEmptyDump) {
std::vector<std::string> meta_data = {
kMetaHeader,
"State: 2",
"Driver: btusb",
"Vendor: Intel",
"Controller Name: 0x12",
};
CreateDumpFile(meta_data);
std::string sig;
EXPECT_TRUE(bluetooth_util::ParseBluetoothCoredump(dump_path_, output_dir_,
false, &sig));
EXPECT_EQ(sig, "bt_firmware-btusb-Intel_0x12-00000000");
std::vector<std::string> want_lines = {
"State=Devcoredump Complete", "Driver=btusb", "Vendor=Intel",
"Controller Name=0x12", "PC=00000000", "Parse Failure Reason=1",
};
VerifyProcessedDump(want_lines);
}