1""" 2Test the lldb disassemble command on lib stdc++. 3""" 4 5import os 6import re 7import lldb 8from lldbsuite.test.lldbtest import * 9import lldbsuite.test.lldbutil as lldbutil 10from lldbsuite.test.decorators import * 11 12 13class StdCXXDisassembleTestCase(TestBase): 14 @skipIfWindows 15 def test_stdcxx_disasm(self): 16 """Do 'disassemble' on each and every 'Code' symbol entry from the std c++ lib.""" 17 self.build() 18 (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 19 self, "// Set break point at this line", lldb.SBFileSpec("main.cpp") 20 ) 21 22 # Disassemble the functions on the call stack. 23 self.runCmd("thread backtrace") 24 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 25 self.assertIsNotNone(thread) 26 depth = thread.GetNumFrames() 27 for i in range(depth - 1): 28 frame = thread.GetFrameAtIndex(i) 29 function = frame.GetFunction() 30 if function.GetName(): 31 self.runCmd("disassemble -n '%s'" % function.GetName()) 32 33 lib_stdcxx = "FAILHORRIBLYHERE" 34 # Find the stdc++ library... 35 stdlib_regex = re.compile(r"/lib(std)?c\+\+") 36 for module in target.module[stdlib_regex]: 37 lib_stdcxx = module.file.fullpath 38 break 39 40 # At this point, lib_stdcxx is the full path to the stdc++ library and 41 # module is the corresponding SBModule. 42 43 if "lib" not in lib_stdcxx: 44 self.skipTest( 45 "This test requires libstdc++.so or libc++.dylib in the target's module list." 46 ) 47 48 self.runCmd("image dump symtab '%s'" % lib_stdcxx) 49 raw_output = self.res.GetOutput() 50 # Now, look for every 'Code' symbol and feed its load address into the 51 # command: 'disassemble -s load_address -e end_address', where the 52 # end_address is taken from the next consecutive 'Code' symbol entry's 53 # load address. 54 # 55 # The load address column comes after the file address column, with both 56 # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits. 57 codeRE = re.compile( 58 r""" 59 \ Code\ {9} # ' Code' followed by 9 SPCs, 60 0x[0-9a-f]{16} # the file address column, and 61 \ # a SPC, and 62 (0x[0-9a-f]{16}) # the load address column, and 63 .* # the rest. 64 """, 65 re.VERBOSE, 66 ) 67 # Maintain a start address variable; if we arrive at a consecutive Code 68 # entry, then the load address of the that entry is fed as the end 69 # address to the 'disassemble -s SA -e LA' command. 70 SA = None 71 for line in raw_output.split(os.linesep): 72 match = codeRE.search(line) 73 if match: 74 LA = match.group(1) 75 if self.TraceOn(): 76 print("line:", line) 77 print("load address:", LA) 78 print("SA:", SA) 79 if SA and LA: 80 if int(LA, 16) > int(SA, 16): 81 self.runCmd("disassemble -s %s -e %s" % (SA, LA)) 82 SA = LA 83 else: 84 # This entry is not a Code entry. Reset SA = None. 85 SA = None 86