forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1847098 - Report library version from filename at crash r=gsvelto
Differential Revision: https://phabricator.services.mozilla.com/D202249
- Loading branch information
Alexandre Lissy
committed
Feb 28, 2024
1 parent
8a3bc14
commit 0cf18a2
Showing
12 changed files
with
320 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#include "linux_utils.h" | ||
|
||
bool ElfFileSoVersion(const char* mapping_name, | ||
VersionComponents* version_components) { | ||
if (!version_components) { | ||
return false; | ||
} | ||
|
||
std::string path = std::string(mapping_name); | ||
std::string filename = path.substr(path.find_last_of('/') + 1); | ||
|
||
std::string dot_so_dot(".so."); | ||
// We found no version so just report 0 | ||
size_t has_dot_so_dot = filename.find(dot_so_dot); | ||
if (has_dot_so_dot == std::string::npos) { | ||
return true; | ||
} | ||
|
||
std::string so_version = | ||
filename.substr(has_dot_so_dot + dot_so_dot.length()); | ||
std::string tmp; | ||
for (std::string::iterator it = so_version.begin(); it != so_version.end(); | ||
++it) { | ||
// We can't have more than four: MAJOR.minor.release.patch | ||
if (version_components->size() == 4) { | ||
break; | ||
} | ||
|
||
char c = *it; | ||
if (c != '.') { | ||
if (isdigit(c)) { | ||
tmp += c; | ||
} | ||
|
||
if (std::next(it) != so_version.end()) { | ||
continue; | ||
} | ||
} | ||
|
||
if (tmp.length() > 0) { | ||
int t = std::stoi(tmp); // assume tmp is < UINT32T_MAX | ||
if (t < 0) { | ||
return false; | ||
} | ||
|
||
uint32_t casted_tmp = static_cast<uint32_t>(t); | ||
// We have lost some information we should warn. | ||
if ((unsigned int)t != casted_tmp) { | ||
return false; | ||
} | ||
version_components->push_back(casted_tmp); | ||
} | ||
tmp = ""; | ||
} | ||
|
||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#ifndef toolkit_breakpad_linux_utils_h__ | ||
#define toolkit_breakpad_linux_utils_h__ | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <string> | ||
#include <vector> | ||
|
||
using VersionComponents = std::vector<uint32_t>; | ||
|
||
bool ElfFileSoVersion(const char* mapping_name, VersionComponents* version); | ||
|
||
#endif /* toolkit_breakpad_linux_utils_h__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#include "gtest/gtest.h" | ||
#include "mozilla/SpinEventLoopUntil.h" | ||
|
||
#include "linux_utils.h" | ||
|
||
#define ASSERT_EQ_UNSIGNED(v, e) ASSERT_EQ((v), (uint32_t)(e)) | ||
|
||
using namespace mozilla; | ||
|
||
class CrashReporter : public ::testing::Test {}; | ||
|
||
TEST_F(CrashReporter, ElfSoNoVersion) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libdbus1.so", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 0); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSo6) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libm.so.6", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 1); | ||
ASSERT_EQ_UNSIGNED(version[0], 6); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoNormalShort) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libdbus1.so.1.2", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 2); | ||
ASSERT_EQ_UNSIGNED(version[0], 1); | ||
ASSERT_EQ_UNSIGNED(version[1], 2); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoNormalComplete) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libdbus1.so.1.2.3", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 3); | ||
ASSERT_EQ_UNSIGNED(version[0], 1); | ||
ASSERT_EQ_UNSIGNED(version[1], 2); | ||
ASSERT_EQ_UNSIGNED(version[2], 3); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoNormalPrerelease) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libdbus1.so.1.2.3.98", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 4); | ||
ASSERT_EQ_UNSIGNED(version[0], 1); | ||
ASSERT_EQ_UNSIGNED(version[1], 2); | ||
ASSERT_EQ_UNSIGNED(version[2], 3); | ||
ASSERT_EQ_UNSIGNED(version[3], 98); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoNormalPrereleaseToomuch) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libdbus1.so.1.2.3.98.9.2.3", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 4); | ||
ASSERT_EQ_UNSIGNED(version[0], 1); | ||
ASSERT_EQ_UNSIGNED(version[1], 2); | ||
ASSERT_EQ_UNSIGNED(version[2], 3); | ||
ASSERT_EQ_UNSIGNED(version[3], 98); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoBig) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libatk-1.0.so.0.25009.1", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 3); | ||
ASSERT_EQ_UNSIGNED(version[0], 0); | ||
ASSERT_EQ_UNSIGNED(version[1], 25009); | ||
ASSERT_EQ_UNSIGNED(version[2], 1); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoCairo) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libcairo.so.2.11800.3", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 3); | ||
ASSERT_EQ_UNSIGNED(version[0], 2); | ||
ASSERT_EQ_UNSIGNED(version[1], 11800); | ||
ASSERT_EQ_UNSIGNED(version[2], 3); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoMax) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion( | ||
"libcairo.so.2147483647.2147483647.2147483647.2147483647", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 4); | ||
ASSERT_EQ_UNSIGNED(version[0], INT32_MAX); | ||
ASSERT_EQ_UNSIGNED(version[1], INT32_MAX); | ||
ASSERT_EQ_UNSIGNED(version[2], INT32_MAX); | ||
ASSERT_EQ_UNSIGNED(version[3], INT32_MAX); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoTimestamp) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libabsl_time_zone.so.20220623.0.0", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 3); | ||
ASSERT_EQ_UNSIGNED(version[0], 20220623); | ||
ASSERT_EQ_UNSIGNED(version[1], 0); | ||
ASSERT_EQ_UNSIGNED(version[2], 0); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoChars) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libabsl_time_zone.so.1.2.3rc4", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 3); | ||
ASSERT_EQ_UNSIGNED(version[0], 1); | ||
ASSERT_EQ_UNSIGNED(version[1], 2); | ||
ASSERT_EQ_UNSIGNED(version[2], 34); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoCharsMore) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libabsl_time_zone.so.1.2.3rc4.9", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 4); | ||
ASSERT_EQ_UNSIGNED(version[0], 1); | ||
ASSERT_EQ_UNSIGNED(version[1], 2); | ||
ASSERT_EQ_UNSIGNED(version[2], 34); | ||
ASSERT_EQ_UNSIGNED(version[3], 9); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoCharsOnly) { | ||
VersionComponents version; | ||
bool rv = ElfFileSoVersion("libabsl_time_zone.so.final", &version); | ||
ASSERT_TRUE(rv); | ||
ASSERT_EQ_UNSIGNED(version.size(), 0); | ||
} | ||
|
||
TEST_F(CrashReporter, ElfSoNullVersion) { | ||
bool rv = ElfFileSoVersion("libabsl_time_zone.so.1", nullptr); | ||
ASSERT_FALSE(rv); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- | ||
# vim: set filetype=python: | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this | ||
# file, you can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
Library("crashreportertest") | ||
|
||
if CONFIG["OS_ARCH"] == "Linux": | ||
UNIFIED_SOURCES = [ | ||
"TestElfSoVersion.cpp", | ||
] | ||
|
||
include("/ipc/chromium/chromium-config.mozbuild") | ||
|
||
FINAL_LIBRARY = "xul-gtest" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
toolkit/crashreporter/test/unit/test_crash_modules_linux.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
add_task(async function run_test() { | ||
if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) { | ||
dump( | ||
"INFO | test_crash_modules.js | Can't test crashreporter in a non-libxul build.\n" | ||
); | ||
return; | ||
} | ||
|
||
await do_crash( | ||
function () { | ||
crashType = CrashTestUtils.CRASH_ABORT; | ||
}, | ||
async function (mdump, extra, extraFile) { | ||
runMinidumpAnalyzer(mdump); | ||
|
||
// Refresh updated extra data | ||
extra = await IOUtils.readJSON(extraFile.path); | ||
|
||
// Check modules' versions | ||
const modules = extra.StackTraces.modules; | ||
const version_regexp = /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/; | ||
|
||
for (let module of modules) { | ||
console.debug("module", module); | ||
console.debug("version => ", module.version); | ||
console.debug("version regex => ", version_regexp.exec(module.version)); | ||
Assert.notEqual(version_regexp.exec(module.version), null); | ||
} | ||
}, | ||
// process will exit with a zero exit status | ||
true | ||
); | ||
}); |
Oops, something went wrong.