summaryrefslogtreecommitdiff
path: root/absl/debugging
diff options
context:
space:
mode:
Diffstat (limited to 'absl/debugging')
-rw-r--r--absl/debugging/internal/demangle.cc28
-rw-r--r--absl/debugging/internal/demangle_test.cc30
-rw-r--r--absl/debugging/leak_check.cc1
-rw-r--r--absl/debugging/leak_check.h13
4 files changed, 56 insertions, 16 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 46cdb67b..5cd56320 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -386,24 +386,28 @@ static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
// by GCC 4.5.x and later versions (and our locally-modified version of GCC
// 4.4.x) to indicate functions which have been cloned during optimization.
// We treat any sequence (.<alpha>+.<digit>+)+ as a function clone suffix.
+// Additionally, '_' is allowed along with the alphanumeric sequence.
static bool IsFunctionCloneSuffix(const char *str) {
size_t i = 0;
while (str[i] != '\0') {
- // Consume a single .<alpha>+.<digit>+ sequence.
- if (str[i] != '.' || !IsAlpha(str[i + 1])) {
- return false;
+ bool parsed = false;
+ // Consume a single [.<alpha> | _]*[.<digit>]* sequence.
+ if (str[i] == '.' && (IsAlpha(str[i + 1]) || str[i + 1] == '_')) {
+ parsed = true;
+ i += 2;
+ while (IsAlpha(str[i]) || str[i] == '_') {
+ ++i;
+ }
}
- i += 2;
- while (IsAlpha(str[i])) {
- ++i;
+ if (str[i] == '.' && IsDigit(str[i + 1])) {
+ parsed = true;
+ i += 2;
+ while (IsDigit(str[i])) {
+ ++i;
+ }
}
- if (str[i] != '.' || !IsDigit(str[i + 1])) {
+ if (!parsed)
return false;
- }
- i += 2;
- while (IsDigit(str[i])) {
- ++i;
- }
}
return true; // Consumed everything in "str".
}
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index 0bed7359..6b142902 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -70,12 +70,34 @@ TEST(Demangle, Clones) {
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
- // Invalid (truncated), should not demangle.
- EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
+ // Demangle suffixes produced by -funique-internal-linkage-names.
+ EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345.isra.2.constprop.18", tmp,
+ sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // Suffixes without the number should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // Suffixes with just the number should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.123", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // (.clone. followed by non-number), should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // (.clone. followed by multiple numbers), should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.clone.123.456", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // (a long valid suffix), should demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp,
+ sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // Invalid (. without anything else), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
+ // Invalid (. with mix of alpha and digits), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
// Invalid (.clone. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
- // Invalid (.clone. followed by non-number), should not demangle.
- EXPECT_FALSE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
// Invalid (.constprop. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
}
diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc
index ff904955..db9d5d09 100644
--- a/absl/debugging/leak_check.cc
+++ b/absl/debugging/leak_check.cc
@@ -38,6 +38,7 @@ ABSL_NAMESPACE_END
namespace absl {
ABSL_NAMESPACE_BEGIN
bool HaveLeakSanitizer() { return true; }
+bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check(); }
void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); }
void RegisterLivePointers(const void* ptr, size_t size) {
__lsan_register_root_region(ptr, size);
diff --git a/absl/debugging/leak_check.h b/absl/debugging/leak_check.h
index b66a81c3..61c3216f 100644
--- a/absl/debugging/leak_check.h
+++ b/absl/debugging/leak_check.h
@@ -71,6 +71,19 @@ T* IgnoreLeak(T* ptr) {
return ptr;
}
+// FindAndReportLeaks()
+//
+// If any leaks are detected, prints a leak report and returns true. This
+// function may be called repeatedly, and does not affect end-of-process leak
+// checking.
+//
+// Example:
+// if (FindAndReportLeaks()) {
+// ... diagnostic already printed. Exit with failure code.
+// exit(1)
+// }
+bool FindAndReportLeaks();
+
// LeakCheckDisabler
//
// This helper class indicates that any heap allocations done in the code block