From fdc80a5cf7a4f62e32c42641a48ae2e249e4572e Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Wed, 1 Feb 2012 01:49:50 +0000 Subject: [PATCH] lldb should warn when dSYM does not match the binary. o Symbols.cpp: Emit a warning message when dSYM does not match the binary. o warnings/uuid: Added regression test case. o lldbtest.py: Modified to allow test case writer to demand that the build command does not begin with a clean first; required to make TestUUIDMismatchWanring.py work. rdar://problem/10515708 llvm-svn: 149465 --- lldb/source/Host/macosx/Symbols.cpp | 14 ++- lldb/test/lldbtest.py | 12 +- lldb/test/plugins/builder_base.py | 39 ++++-- lldb/test/plugins/builder_darwin.py | 21 ++-- lldb/test/plugins/builder_linux2.py | 2 +- lldb/test/warnings/uuid/Makefile | 5 + .../warnings/uuid/TestUUIDMismatchWanring.py | 113 ++++++++++++++++++ lldb/test/warnings/uuid/main.cpp.template | 19 +++ 8 files changed, 197 insertions(+), 28 deletions(-) create mode 100644 lldb/test/warnings/uuid/Makefile create mode 100644 lldb/test/warnings/uuid/TestUUIDMismatchWanring.py create mode 100644 lldb/test/warnings/uuid/main.cpp.template diff --git a/lldb/source/Host/macosx/Symbols.cpp b/lldb/source/Host/macosx/Symbols.cpp index acaf563907ec..820126674bba 100644 --- a/lldb/source/Host/macosx/Symbols.cpp +++ b/lldb/source/Host/macosx/Symbols.cpp @@ -24,6 +24,7 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/UUID.h" #include "lldb/Host/Endian.h" +#include "lldb/Host/Host.h" #include "lldb/Utility/CleanUp.h" #include "Host/macosx/cfcpp/CFCBundle.h" #include "Host/macosx/cfcpp/CFCReleaser.h" @@ -116,7 +117,18 @@ SkinnyMachOFileContainsArchAndUUID if (cmd == LoadCommandUUID) { lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16); - return file_uuid == *uuid; + if (file_uuid == *uuid) + return true; + + // Emit some warning messages since the UUIDs do not match! + char path_buf[PATH_MAX]; + path_buf[0] = '\0'; + const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf + : file_spec.GetFilename().AsCString(); + Host::SystemLog (Host::eSystemLogWarning, + "warning: UUID mismatch detected between binary and:\n\t'%s'\n", + path); + return false; } data_offset = cmd_offset + cmd_size; } diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py index b6851e34b251..8690c4b70f24 100644 --- a/lldb/test/lldbtest.py +++ b/lldb/test/lldbtest.py @@ -854,28 +854,28 @@ class Base(unittest2.TestCase): # Build methods supported through a plugin interface # ================================================== - def buildDefault(self, architecture=None, compiler=None, dictionary=None): + def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True): """Platform specific way to build the default binaries.""" if lldb.skip_build_and_cleanup: return module = builder_module() - if not module.buildDefault(self, architecture, compiler, dictionary): + if not module.buildDefault(self, architecture, compiler, dictionary, clean): raise Exception("Don't know how to build default binary") - def buildDsym(self, architecture=None, compiler=None, dictionary=None): + def buildDsym(self, architecture=None, compiler=None, dictionary=None, clean=True): """Platform specific way to build binaries with dsym info.""" if lldb.skip_build_and_cleanup: return module = builder_module() - if not module.buildDsym(self, architecture, compiler, dictionary): + if not module.buildDsym(self, architecture, compiler, dictionary, clean): raise Exception("Don't know how to build binary with dsym") - def buildDwarf(self, architecture=None, compiler=None, dictionary=None): + def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True): """Platform specific way to build binaries with dwarf maps.""" if lldb.skip_build_and_cleanup: return module = builder_module() - if not module.buildDwarf(self, architecture, compiler, dictionary): + if not module.buildDwarf(self, architecture, compiler, dictionary, clean): raise Exception("Don't know how to build binary with dwarf") def cleanup(self, dictionary=None): diff --git a/lldb/test/plugins/builder_base.py b/lldb/test/plugins/builder_base.py index 19d5dc4f8680..697ffa47b5a9 100644 --- a/lldb/test/plugins/builder_base.py +++ b/lldb/test/plugins/builder_base.py @@ -63,25 +63,38 @@ def getCmdLine(d): return " " + cmdline -def buildDefault(sender=None, architecture=None, compiler=None, dictionary=None): +def buildDefault(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): """Build the binaries the default way.""" - lldbtest.system(["/bin/sh", "-c", - "make clean" + getCmdLine(dictionary) + "; make" - + getArchSpec(architecture) + getCCSpec(compiler) - + getCmdLine(dictionary)], - sender=sender) + if clean: + lldbtest.system(["/bin/sh", "-c", + "make clean" + getCmdLine(dictionary) + "; make" + + getArchSpec(architecture) + getCCSpec(compiler) + + getCmdLine(dictionary)], + sender=sender) + else: + lldbtest.system(["/bin/sh", "-c", + "make" + getArchSpec(architecture) + getCCSpec(compiler) + + getCmdLine(dictionary)], + sender=sender) # True signifies that we can handle building default. return True -def buildDwarf(sender=None, architecture=None, compiler=None, dictionary=None): +def buildDwarf(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): """Build the binaries with dwarf debug info.""" - lldbtest.system(["/bin/sh", "-c", - "make clean" + getCmdLine(dictionary) - + "; make MAKE_DSYM=NO" - + getArchSpec(architecture) + getCCSpec(compiler) - + getCmdLine(dictionary)], - sender=sender) + if clean: + lldbtest.system(["/bin/sh", "-c", + "make clean" + getCmdLine(dictionary) + + "; make MAKE_DSYM=NO" + + getArchSpec(architecture) + getCCSpec(compiler) + + getCmdLine(dictionary)], + sender=sender) + else: + lldbtest.system(["/bin/sh", "-c", + "make MAKE_DSYM=NO" + + getArchSpec(architecture) + getCCSpec(compiler) + + getCmdLine(dictionary)], + sender=sender) # True signifies that we can handle building dwarf. return True diff --git a/lldb/test/plugins/builder_darwin.py b/lldb/test/plugins/builder_darwin.py index 9ddbd18932cb..018de8f03183 100644 --- a/lldb/test/plugins/builder_darwin.py +++ b/lldb/test/plugins/builder_darwin.py @@ -5,14 +5,21 @@ from builder_base import * #print "Hello, darwin plugin!" -def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None): +def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): """Build the binaries with dsym debug info.""" - lldbtest.system(["/bin/sh", "-c", - "make clean" + getCmdLine(dictionary) - + "; make MAKE_DSYM=YES" - + getArchSpec(architecture) + getCCSpec(compiler) - + getCmdLine(dictionary)], - sender=sender) + if clean: + lldbtest.system(["/bin/sh", "-c", + "make clean" + getCmdLine(dictionary) + + "; make MAKE_DSYM=YES" + + getArchSpec(architecture) + getCCSpec(compiler) + + getCmdLine(dictionary)], + sender=sender) + else: + lldbtest.system(["/bin/sh", "-c", + "make MAKE_DSYM=YES" + + getArchSpec(architecture) + getCCSpec(compiler) + + getCmdLine(dictionary)], + sender=sender) # True signifies that we can handle building dsym. return True diff --git a/lldb/test/plugins/builder_linux2.py b/lldb/test/plugins/builder_linux2.py index eb08b4035c22..e56be429823e 100644 --- a/lldb/test/plugins/builder_linux2.py +++ b/lldb/test/plugins/builder_linux2.py @@ -1,4 +1,4 @@ from builder_base import * -def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None): +def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): return False diff --git a/lldb/test/warnings/uuid/Makefile b/lldb/test/warnings/uuid/Makefile new file mode 100644 index 000000000000..8a7102e347af --- /dev/null +++ b/lldb/test/warnings/uuid/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/warnings/uuid/TestUUIDMismatchWanring.py b/lldb/test/warnings/uuid/TestUUIDMismatchWanring.py new file mode 100644 index 000000000000..b22e7703463e --- /dev/null +++ b/lldb/test/warnings/uuid/TestUUIDMismatchWanring.py @@ -0,0 +1,113 @@ +"""Test that the 'warning: UUID mismatch detected ...' message is emitted.""" + +import os, time +import unittest2 +import lldb +import pexpect +from lldbtest import * + +@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") +class UUIDMismatchWarningCase(TestBase): + + mydir = os.path.join("warnings", "uuid") + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + system(["/bin/sh", "-c", "rm -f child_send.txt"]) + system(["/bin/sh", "-c", "rm -f child_read.txt"]) + + def setUp(self): + TestBase.setUp(self) + self.template = 'main.cpp.template' + self.source = 'main.cpp' + self.teardown_hook_added = False + + def test_uuid_mismatch_warning(self): + """Test that the 'warning: UUID mismatch detected ...' message is emitted.""" + + # Call the program generator to produce main.cpp, version 1. + self.generate_main_cpp(version=1) + self.line_to_break = line_number(self.source, '// Set breakpoint here.') + self.buildDsym(clean=True) + + # Insert some delay and then call the program generator to produce main.cpp, version 2. + time.sleep(5) + self.generate_main_cpp(version=101) + # Now call make again, but this time don't generate the dSYM. + self.buildDwarf(clean=False) + + self.exe_name = 'a.out' + self.check_executable_and_dsym(self.exe_name) + + def generate_main_cpp(self, version=0): + """Generate main.cpp from main.cpp.template.""" + temp = os.path.join(os.getcwd(), self.template) + with open(temp, 'r') as f: + content = f.read() + + new_content = content.replace('%ADD_EXTRA_CODE%', + 'printf("This is version %d\\n");' % version) + src = os.path.join(os.getcwd(), self.source) + with open(src, 'w') as f: + f.write(new_content) + + # The main.cpp has been generated, add a teardown hook to remove it. + if not self.teardown_hook_added: + self.addTearDownHook(lambda: os.remove(src)) + self.teardown_hook_added = True + + def check_executable_and_dsym(self, exe_name): + """Sanity check executable compiled from the auto-generated program.""" + + # The default lldb prompt. + prompt = "(lldb) " + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s %s' % (self.lldbHere, self.lldbOption)) + child = self.child + # Turn on logging for input/output to/from the child. + with open('child_send.txt', 'w') as f_send: + with open('child_read.txt', 'w') as f_read: + child.logfile_send = f_send + child.logfile_read = f_read + + child.expect_exact(prompt) + child.setecho(True) + + # Execute the file command, followed by a breakpoint set, the + # UUID mismatch warning should be generated by then. + + child.sendline("file %s" % exe_name) + child.expect_exact(prompt) + child.sendline("breakpoint set -f %s -l %d" % (self.source, self.line_to_break)) + child.expect_exact(prompt) + child.sendline("run") + child.expect_exact(prompt) + + # Now that the necessary logging is done, restore logfile to None to + # stop further logging. + child.logfile_send = None + child.logfile_read = None + + with open('child_send.txt', 'r') as fs: + if self.TraceOn(): + print "\n\nContents of child_send.txt:" + print fs.read() + with open('child_read.txt', 'r') as fr: + from_child = fr.read() + if self.TraceOn(): + print "\n\nContents of child_read.txt:" + print from_child + + # Test that str_input completes to our patterns. + # If each pattern matches from_child, the completion mechanism works! + self.expect(from_child, msg="UUID mismatch expected!", exe=False, + substrs = ['warning: UUID mismatch detected']) + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/warnings/uuid/main.cpp.template b/lldb/test/warnings/uuid/main.cpp.template new file mode 100644 index 000000000000..d952c9686b57 --- /dev/null +++ b/lldb/test/warnings/uuid/main.cpp.template @@ -0,0 +1,19 @@ +//===-- 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 + +int +main(int argc, char const *argv[]) +{ + int my_int = argc + 3; + printf("Hello UUID Mismatch: %d\n", my_int); // Set breakpoint here. + %ADD_EXTRA_CODE% + return 0; +}