forked from OSchip/llvm-project
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
This commit is contained in:
parent
05e8d19446
commit
fdc80a5cf7
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -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()
|
|
@ -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 <stdio.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue