1"""Test that corefiles with LC_NOTE "kern ver str" and "main bin spec" load commands works.""" 2 3 4 5import os 6import re 7import subprocess 8 9import lldb 10from lldbsuite.test.decorators import * 11from lldbsuite.test.lldbtest import * 12from lldbsuite.test import lldbutil 13 14 15class TestFirmwareCorefiles(TestBase): 16 17 mydir = TestBase.compute_mydir(__file__) 18 19 def initial_setup(self): 20 self.build() 21 self.aout_exe = self.getBuildArtifact("a.out") 22 self.aout_exe_basename = "a.out" 23 self.create_corefile = self.getBuildArtifact("create-empty-corefile") 24 self.dsym_for_uuid = self.getBuildArtifact("dsym-for-uuid.sh") 25 self.verstr_corefile = self.getBuildArtifact("verstr.core") 26 self.verstr_corefile_addr = self.getBuildArtifact("verstr-addr.core") 27 self.binspec_corefile = self.getBuildArtifact("binspec.core") 28 self.binspec_corefile_addr = self.getBuildArtifact("binspec-addr.core") 29 30 ## We can hook in our dsym-for-uuid shell script to lldb with this env 31 ## var instead of requiring a defaults write. 32 os.environ['LLDB_APPLE_DSYMFORUUID_EXECUTABLE'] = self.dsym_for_uuid 33 self.addTearDownHook(lambda: os.environ.pop('LLDB_APPLE_DSYMFORUUID_EXECUTABLE', None)) 34 35 self.runCmd("settings set target.load-script-from-symbol-file true") 36 self.addTearDownHook(lambda: self.runCmd("settings set target.load-script-from-symbol-file false")) 37 38 dsym_python_dir = '%s.dSYM/Contents/Resources/Python' % (self.aout_exe) 39 os.makedirs(dsym_python_dir) 40 python_os_plugin_path = os.path.join(self.getSourceDir(), 41 'operating_system.py') 42 python_init = [ 43 'def __lldb_init_module(debugger, internal_dict):', 44 ' debugger.HandleCommand(\'settings set target.process.python-os-plugin-path %s\')' % python_os_plugin_path, 45 ] 46 with open(dsym_python_dir + "/a_out.py", "w") as writer: 47 for l in python_init: 48 writer.write(l + '\n') 49 50 dwarfdump_uuid_regex = re.compile( 51 'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*') 52 dwarfdump_cmd_output = subprocess.check_output( 53 ('/usr/bin/dwarfdump --uuid "%s"' % self.aout_exe), shell=True).decode("utf-8") 54 aout_uuid = None 55 for line in dwarfdump_cmd_output.splitlines(): 56 match = dwarfdump_uuid_regex.search(line) 57 if match: 58 aout_uuid = match.group(1) 59 self.assertNotEqual(aout_uuid, None, "Could not get uuid of built a.out") 60 61 ### Create our dsym-for-uuid shell script which returns self.aout_exe 62 shell_cmds = [ 63 '#! /bin/sh', 64 '# the last argument is the uuid', 65 'while [ $# -gt 1 ]', 66 'do', 67 ' shift', 68 'done', 69 'ret=0', 70 'echo "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>"', 71 'echo "<!DOCTYPE plist PUBLIC \\"-//Apple//DTD PLIST 1.0//EN\\" \\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\">"', 72 'echo "<plist version=\\"1.0\\">"', 73 '', 74 'if [ "$1" != "%s" ]' % (aout_uuid), 75 'then', 76 ' echo "<key>DBGError</key><string>not found</string>"', 77 ' echo "</plist>"', 78 ' exit 1', 79 'fi', 80 ' uuid=%s' % aout_uuid, 81 ' bin=%s' % self.aout_exe, 82 ' dsym=%s.dSYM/Contents/Resources/DWARF/%s' % (self.aout_exe, os.path.basename(self.aout_exe)), 83 'echo "<dict><key>$uuid</key><dict>"', 84 '', 85 'echo "<key>DBGDSYMPath</key><string>$dsym</string>"', 86 'echo "<key>DBGSymbolRichExecutable</key><string>$bin</string>"', 87 'echo "</dict></dict></plist>"', 88 'exit $ret' 89 ] 90 91 with open(self.dsym_for_uuid, "w") as writer: 92 for l in shell_cmds: 93 writer.write(l + '\n') 94 95 os.chmod(self.dsym_for_uuid, 0o755) 96 97 self.slide = 0x70000000000 98 99 ### Create our corefile 100 # 0xffffffffffffffff means load address unknown 101 retcode = call(self.create_corefile + " version-string " + self.verstr_corefile + " " + self.aout_exe + " 0xffffffffffffffff", shell=True) 102 retcode = call(self.create_corefile + " version-string " + self.verstr_corefile_addr + " " + self.aout_exe + (" 0x%x" % self.slide), shell=True) 103 retcode = call(self.create_corefile + " main-bin-spec " + self.binspec_corefile + " " + self.aout_exe + " 0xffffffffffffffff", shell=True) 104 retcode = call(self.create_corefile + " main-bin-spec " + self.binspec_corefile_addr + " " + self.aout_exe + (" 0x%x" % self.slide), shell=True) 105 106 @skipIf(debug_info=no_match(["dsym"]), bugnumber="This test is looking explicitly for a dSYM") 107 @skipIf(archs=no_match(['x86_64'])) 108 @skipUnlessDarwin 109 def test_lc_note_version_string(self): 110 self.initial_setup() 111 112 if self.TraceOn(): 113 self.runCmd("log enable lldb dyld host") 114 self.addTearDownHook(lambda: self.runCmd("log disable lldb dyld host")) 115 116 ### Now run lldb on the corefile 117 ### which will give us a UUID 118 ### which we call dsym-for-uuid.sh with 119 ### which gives us a binary and dSYM 120 ### which lldb should load! 121 122 # First, try the "kern ver str" corefile 123 self.target = self.dbg.CreateTarget('') 124 err = lldb.SBError() 125 if self.TraceOn(): 126 self.runCmd("script print('loading corefile %s')" % self.verstr_corefile) 127 self.process = self.target.LoadCore(self.verstr_corefile) 128 self.assertEqual(self.process.IsValid(), True) 129 if self.TraceOn(): 130 self.runCmd("image list") 131 self.runCmd("target mod dump sections") 132 self.assertEqual(self.target.GetNumModules(), 1) 133 fspec = self.target.GetModuleAtIndex(0).GetFileSpec() 134 self.assertEqual(fspec.GetFilename(), self.aout_exe_basename) 135 self.process.Kill() 136 self.process = None 137 self.target.Clear() 138 self.target = None 139 self.dbg.MemoryPressureDetected() 140 141 # Second, try the "kern ver str" corefile where it loads at an address 142 self.target = self.dbg.CreateTarget('') 143 err = lldb.SBError() 144 if self.TraceOn(): 145 self.runCmd("script print('loading corefile %s')" % self.verstr_corefile_addr) 146 self.process = self.target.LoadCore(self.verstr_corefile_addr) 147 self.assertEqual(self.process.IsValid(), True) 148 if self.TraceOn(): 149 self.runCmd("image list") 150 self.runCmd("target mod dump sections") 151 self.assertEqual(self.target.GetNumModules(), 1) 152 fspec = self.target.GetModuleAtIndex(0).GetFileSpec() 153 self.assertEqual(fspec.GetFilename(), self.aout_exe_basename) 154 main_sym = self.target.GetModuleAtIndex(0).FindSymbol("main", lldb.eSymbolTypeAny) 155 main_addr = main_sym.GetStartAddress() 156 self.assertGreater(main_addr.GetLoadAddress(self.target), self.slide) 157 self.assertNotEqual(main_addr.GetLoadAddress(self.target), lldb.LLDB_INVALID_ADDRESS) 158 self.process.Kill() 159 self.process = None 160 self.target.Clear() 161 self.target = None 162 self.dbg.MemoryPressureDetected() 163 164 @skipIf(debug_info=no_match(["dsym"]), bugnumber="This test is looking explicitly for a dSYM") 165 @skipIf(archs=no_match(['x86_64'])) 166 @skipUnlessDarwin 167 def test_lc_note_main_bin_spec(self): 168 self.initial_setup() 169 170 if self.TraceOn(): 171 self.runCmd("log enable lldb dyld host") 172 self.addTearDownHook(lambda: self.runCmd("log disable lldb dyld host")) 173 174 # Third, try the "main bin spec" corefile 175 self.target = self.dbg.CreateTarget('') 176 if self.TraceOn(): 177 self.runCmd("script print('loading corefile %s')" % self.binspec_corefile) 178 self.process = self.target.LoadCore(self.binspec_corefile) 179 self.assertEqual(self.process.IsValid(), True) 180 if self.TraceOn(): 181 self.runCmd("image list") 182 self.runCmd("target mod dump sections") 183 self.assertEqual(self.target.GetNumModules(), 1) 184 fspec = self.target.GetModuleAtIndex(0).GetFileSpec() 185 self.assertEqual(fspec.GetFilename(), self.aout_exe_basename) 186 self.process.Kill() 187 self.process = None 188 self.target.Clear() 189 self.target = None 190 self.dbg.MemoryPressureDetected() 191 192 # Fourth, try the "main bin spec" corefile where it loads at an address 193 self.target = self.dbg.CreateTarget('') 194 if self.TraceOn(): 195 self.runCmd("script print('loading corefile %s')" % self.binspec_corefile_addr) 196 self.process = self.target.LoadCore(self.binspec_corefile_addr) 197 self.assertEqual(self.process.IsValid(), True) 198 if self.TraceOn(): 199 self.runCmd("image list") 200 self.runCmd("target mod dump sections") 201 self.assertEqual(self.target.GetNumModules(), 1) 202 fspec = self.target.GetModuleAtIndex(0).GetFileSpec() 203 self.assertEqual(fspec.GetFilename(), self.aout_exe_basename) 204 main_sym = self.target.GetModuleAtIndex(0).FindSymbol("main", lldb.eSymbolTypeAny) 205 main_addr = main_sym.GetStartAddress() 206 self.assertGreater(main_addr.GetLoadAddress(self.target), self.slide) 207 self.assertNotEqual(main_addr.GetLoadAddress(self.target), lldb.LLDB_INVALID_ADDRESS) 208 self.process.Kill() 209 self.process = None 210 self.target.Clear() 211 self.target = None 212 self.dbg.MemoryPressureDetected() 213 214 @skipIf(debug_info=no_match(["dsym"]), bugnumber="This test is looking explicitly for a dSYM") 215 @skipIf(archs=no_match(['x86_64'])) 216 @skipUnlessDarwin 217 def test_lc_note_main_bin_spec_os_plugin(self): 218 self.initial_setup() 219 220 if self.TraceOn(): 221 self.runCmd("log enable lldb dyld host") 222 self.addTearDownHook(lambda: self.runCmd("log disable lldb dyld host")) 223 # Now load the binary and confirm that we load the OS plugin. 224 self.target = self.dbg.CreateTarget('') 225 226 if self.TraceOn(): 227 self.runCmd("script print('loading corefile %s with OS plugin')" % self.binspec_corefile_addr) 228 self.process = self.target.LoadCore(self.binspec_corefile_addr) 229 self.assertEqual(self.process.IsValid(), True) 230 if self.TraceOn(): 231 self.runCmd("image list") 232 self.runCmd("target mod dump sections") 233 self.runCmd("thread list") 234 self.assertEqual(self.target.GetNumModules(), 1) 235 fspec = self.target.GetModuleAtIndex(0).GetFileSpec() 236 self.assertEqual(fspec.GetFilename(), self.aout_exe_basename) 237 238 # Verify our OS plug-in threads showed up 239 thread = self.process.GetThreadByID(0x111111111) 240 self.assertTrue(thread.IsValid(), 241 "Make sure there is a thread 0x111111111 after we load the python OS plug-in") 242 thread = self.process.GetThreadByID(0x222222222) 243 self.assertTrue(thread.IsValid(), 244 "Make sure there is a thread 0x222222222 after we load the python OS plug-in") 245 thread = self.process.GetThreadByID(0x333333333) 246 self.assertTrue(thread.IsValid(), 247 "Make sure there is a thread 0x333333333 after we load the python OS plug-in") 248 249 self.process.Kill() 250 self.process = None 251 self.target.Clear() 252 self.target = None 253 self.dbg.MemoryPressureDetected() 254