[tsan] Prefer mangled name looking up variable declaration for racy address

For Thread Sanitizer reports, LLDB tries to find a global variable declaration
corresponding to the racy address in order to provide a filename and line
number. This commit changes the lookup of the variable to use the mangled
name for lookup and fall back to the demangled version if unavailable. This
is needed to report locations of races on Swift global variables.

I've also added a test to make sure we look up C++ globals correctly.

rdar://problem/26459401

Differential Revision: http://reviews.llvm.org/D20760

llvm-svn: 271433
This commit is contained in:
Devin Coughlin 2016-06-01 21:32:45 +00:00
parent b96d3b2dd8
commit a10ab76b16
4 changed files with 99 additions and 1 deletions

View File

@ -0,0 +1,6 @@
LEVEL = ../../../make
CXX_SOURCES := main.cpp
CFLAGS_EXTRAS := -fsanitize=thread -g
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,54 @@
"""
Tests that TSan correctly reports the filename and line number of a racy global C++ variable.
"""
import os, time
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
import json
class TsanCPPGlobalLocationTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)")
@skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default
@skipIfRemote
@skipUnlessCompilerRt
@skipUnlessThreadSanitizer
def test (self):
self.build ()
self.tsan_tests ()
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
def tsan_tests (self):
exe = os.path.join (os.getcwd(), "a.out")
self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ])
self.runCmd("run")
stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason()
if stop_reason == lldb.eStopReasonExec:
# On OS X 10.10 and older, we need to re-exec to enable interceptors.
self.runCmd("continue")
# the stop reason of the thread should be breakpoint.
self.expect("thread list", "A data race should be detected",
substrs = ['stopped', 'stop reason = Data race detected'])
self.expect("thread info -s", "The extended stop info should contain the TSan provided fields",
substrs = ["instrumentation_class", "description", "mops"])
output_lines = self.res.GetOutput().split('\n')
json_line = '\n'.join(output_lines[2:])
data = json.loads(json_line)
self.assertEqual(data["instrumentation_class"], "ThreadSanitizer")
self.assertEqual(data["issue_type"], "data-race")
self.assertTrue(data["location_filename"].endswith("/main.cpp"))
self.assertEqual(data["location_line"], line_number('main.cpp', '// global variable'))

View File

@ -0,0 +1,38 @@
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
long my_global_variable; // global variable
void *f1(void *p) {
my_global_variable = 42;
return NULL;
}
void *f2(void *p) {
my_global_variable = 43;
return NULL;
}
int main (int argc, char const *argv[])
{
pthread_t t1;
pthread_create(&t1, NULL, f1, NULL);
pthread_t t2;
pthread_create(&t2, NULL, f2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}

View File

@ -523,7 +523,7 @@ GetSymbolDeclarationFromAddress(ProcessSP process_sp, addr_t addr, Declaration &
if (! symbol)
return;
ConstString sym_name = symbol->GetName();
ConstString sym_name = symbol->GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled);
ModuleSP module = symbol->CalculateSymbolContextModule();
if (! module)