Skip to content

Commit 00be357

Browse files
committed
[asan] Keep Itanium mangled names in global metadata
The runtime calls `MaybeDemangleGlobalName` for error reporting and `__cxxabiv1::__cxa_demangle` is called if available, so demanging Itanium mangled names in global metadata is unnecessary and wastes data size. Add `MaybeDemangleGlobalName` in ODR violation detection to support demangled names in a suppressions file. `MaybeDemangleGlobalName` may call `DemangleCXXABI` and leak memory. Use an internal allocation to prevent lsan leak (in case there is no fatal asan error). The debug feature `report_globals=2` prints information for all instrumented global variables. `MaybeDemangleGlobalName` would be slow, so don't do that. The output looks like `Added Global[0x56448f092d60]: beg=0x56448fa66d60 size=4/32 name=_ZL13test_global_2` and I think the mangled name is fine. Other mangled schemes e.g. Windows (see win-string-literal.ll) remain the current behavior. Reviewed By: hctim Differential Revision: https://reviews.llvm.org/D138095
1 parent 3c36de5 commit 00be357

File tree

5 files changed

+27
-17
lines changed

5 files changed

+27
-17
lines changed

compiler-rt/lib/asan/asan_globals.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ static void CheckODRViolationViaIndicator(const Global *g) {
148148
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
149149
if (g->odr_indicator == l->g->odr_indicator &&
150150
(flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
151-
!IsODRViolationSuppressed(g->name))
152-
ReportODRViolation(g, FindRegistrationSite(g),
153-
l->g, FindRegistrationSite(l->g));
151+
!IsODRViolationSuppressed(MaybeDemangleGlobalName(g->name)))
152+
ReportODRViolation(g, FindRegistrationSite(g), l->g,
153+
FindRegistrationSite(l->g));
154154
}
155155
}
156156

@@ -164,7 +164,7 @@ static void CheckODRViolationViaPoisoning(const Global *g) {
164164
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
165165
if (g->beg == l->g->beg &&
166166
(flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
167-
!IsODRViolationSuppressed(g->name))
167+
!IsODRViolationSuppressed(MaybeDemangleGlobalName(g->name)))
168168
ReportODRViolation(g, FindRegistrationSite(g),
169169
l->g, FindRegistrationSite(l->g));
170170
}

compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,17 @@ const char *DemangleCXXABI(const char *name) {
4949
// FIXME: __cxa_demangle aggressively insists on allocating memory.
5050
// There's not much we can do about that, short of providing our
5151
// own demangler (libc++abi's implementation could be adapted so that
52-
// it does not allocate). For now, we just call it anyway, and we leak
53-
// the returned value.
54-
if (&__cxxabiv1::__cxa_demangle)
55-
if (const char *demangled_name =
56-
__cxxabiv1::__cxa_demangle(name, 0, 0, 0))
57-
return demangled_name;
52+
// it does not allocate). For now, we just call it anyway, and use
53+
// InternalAlloc to prevent lsan error.
54+
if (&__cxxabiv1::__cxa_demangle) {
55+
if (char *demangled_name = __cxxabiv1::__cxa_demangle(name, 0, 0, 0)) {
56+
size_t size = internal_strlen(demangled_name) + 1;
57+
char *buf = (char *)InternalAlloc(size);
58+
internal_memcpy(buf, demangled_name, size);
59+
free(demangled_name);
60+
return buf;
61+
}
62+
}
5863

5964
return name;
6065
}

compiler-rt/test/asan/TestCases/Linux/odr_indicators.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ int test_global_1;
1111
// INDICATOR1-DAG: Added Global{{.*}} name=test_global_1{{.*}} odr_indicator={{0x0*[^0]+.*$}}
1212

1313
static int test_global_2;
14-
// CHECK-DAG: Added Global{{.*}} name=test_global_2{{.*}} odr_indicator={{0xf+$}}
14+
// CHECK-DAG: Added Global{{.*}} name=_ZL13test_global_2 {{.*}} odr_indicator={{0xf+$}}
1515

1616
namespace {
1717
static int test_global_3;
18-
// CHECK-DAG: Added Global{{.*}} name={{.*}}::test_global_3{{.*}} odr_indicator={{0xf+$}}
18+
// CHECK-DAG: Added Global{{.*}} name=_ZN12_GLOBAL__N_113test_global_3E {{.*}} odr_indicator={{0xf+$}}
1919
} // namespace
2020

2121
int main() {

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,9 +2264,11 @@ bool ModuleAddressSanitizer::InstrumentGlobals(IRBuilder<> &IRB, Module &M,
22642264
if (G->hasSanitizerMetadata())
22652265
MD = G->getSanitizerMetadata();
22662266

2267-
// TODO: Symbol names in the descriptor can be demangled by the runtime
2268-
// library. This could save ~0.4% of VM size for a private large binary.
2269-
std::string NameForGlobal = llvm::demangle(G->getName().str());
2267+
// ASan runtime demangles Itanium mangled names, so keep the original name
2268+
// to prevent unneeded size increase of the string table.
2269+
std::string NameForGlobal = G->getName().str();
2270+
if (!StringRef(NameForGlobal).startswith("_Z"))
2271+
NameForGlobal = llvm::demangle(NameForGlobal);
22702272
GlobalVariable *Name =
22712273
createPrivateGlobalForString(M, NameForGlobal,
22722274
/*AllowMerging*/ true, kAsanGenPrefix);

llvm/test/Instrumentation/AddressSanitizer/local_alias.ll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@ target triple = "x86_64-unknown-linux-gnu"
1313
@a = dso_local global [2 x i32] zeroinitializer, align 4
1414
@b = private global [2 x i32] zeroinitializer, align 4
1515
@c = internal global [2 x i32] zeroinitializer, align 4
16-
@d = unnamed_addr global [2 x i32] zeroinitializer, align 4
16+
@_ZL1d = unnamed_addr global [2 x i32] zeroinitializer, align 4
1717

1818
; Check that we generate internal alias and odr indicator symbols for global to be protected.
1919
; CHECK-NOINDICATOR-NOT: __odr_asan_gen_a
2020
; CHECK-NOALIAS-NOT: private alias
21+
; CHECK-INDICATOR: @___asan_gen_.1 = private unnamed_addr constant [2 x i8] c"a\00", align 1
2122
; CHECK-INDICATOR: @__odr_asan_gen_a = global i8 0, align 1
23+
; CHECK-INDICATOR: @___asan_gen_.4 = private unnamed_addr constant [6 x i8] c"_ZL1d\00", align 1
24+
; CHECK-INDICATOR: @__odr_asan_gen__ZL1d = global i8 0, align 1
2225
; CHECK-ALIAS: @0 = private alias { [2 x i32], [24 x i8] }, ptr @a
2326

2427
; CHECK-ALIAS: @1 = private alias { [2 x i32], [24 x i8] }, ptr @b
2528
; CHECK-ALIAS: @2 = private alias { [2 x i32], [24 x i8] }, ptr @c
26-
; CHECK-ALIAS: @3 = private alias { [2 x i32], [24 x i8] }, ptr @d
29+
; CHECK-ALIAS: @3 = private alias { [2 x i32], [24 x i8] }, ptr @_ZL1d
2730

2831
; Function Attrs: nounwind sanitize_address uwtable
2932
define i32 @foo(i32 %M) #0 {

0 commit comments

Comments
 (0)