dump-examine.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. import struct
  2. from enum import Enum
  3. import itertools
  4. import argparse
  5. '''
  6. Big thanks to the following for the format reference:
  7. https://github.com/libyal/libmdmp/blob/main/documentation/Minidump%20(MDMP)%20format.asciidoc#57-32-bit-memory-range-descriptor
  8. https://github.com/skelsec/minidump
  9. '''
  10. classes_interest = ['fxDTSBrick', 'AIPlayer', 'Player', 'WheeledVehicle', 'FlyingVehicle', 'HoverVehicle']
  11. def num_to_hex(n, leading_zeros):
  12. return "{0:#0{1}x}".format(n, leading_zeros + 2)
  13. parser = argparse.ArgumentParser()
  14. parser.add_argument('analyze_file', nargs='?', type=str, help = "analyze an MDMP file")
  15. #parser.add_argument("-o", "--output-file", type=str, default=None, help = "output file for analysis results")
  16. parser.add_argument("--analyze-objects", action='store_true', help = "Analyze objects from object dictionary; the default offset works for r2033")
  17. parser.add_argument("--print-tracebuddy", action='store_true', help = "Print TraceBuddy journal; also define --tbd or --tbo")
  18. #parser.add_argument("--print-objecttrace", action='store_true', help = "Print ObjectTrace journal; also define --otd or --oto")
  19. parser.add_argument("--bl-object-offset", "--bloo", type=str, default='0x3C7234', help = "offset of object ID dictionary (tsf_gIdDictionaryLoc)")
  20. parser.add_argument("--tracebuddy-direct-address", "--tbd", type=str, default=None, help = "direct pointer to trace_lines std::list; now recorded in console.log from TraceBuddy version 2.1")
  21. parser.add_argument("--tracebuddy-offset", "--tbo", type=str, default=None, help = "offset of trace_lines std::list from image base of DLL")
  22. #parser.add_argument("--objecttrace-direct-address", "--otd", type=str, default=None, help = "direct pointer to object_journal std::list; you are told this in console.log when ObjectTrace.dll initializes")
  23. #parser.add_argument("--objecttrace-offset", "--oto", type=str, default=None, help = "offset of object_journal std::list from image base of DLL")
  24. parser.add_argument("--help-offsets", action='store_true', help = "List common offsets")
  25. args = parser.parse_args()
  26. if args.help_offsets:
  27. # print('ObjectTrace.dll (all versions) print the direct address near top of console.log so you can use --otd')
  28. #print()
  29. print('Note: TraceBuddy versions 2.1.0 and above print the direct address near top of console.log so you can use --tbd')
  30. print('TraceBuddy.dll version 2.1.0')
  31. print(' md5sum: 990c6bc179524f2ba88c50bcd662fb62')
  32. print(' released: November 6, 2023')
  33. print(' offset: 0x100034')
  34. print()
  35. print('TraceBuddy.dll version 2.0.0')
  36. print(' md5sum: ed71583537dc6077f97500e897aa0ed9')
  37. print(' released: October 28, 2023')
  38. print(' offset: 0x100034')
  39. print()
  40. print('TraceBuddy.dll (Buddy\'s private version)')
  41. print(' md5sum: 2b41150e2a549d2053ad5db432f3b79f')
  42. print(' offset: 0xFB034')
  43. print()
  44. print('TraceBuddy.dll version 1.0.1')
  45. print(' md5sum: 03885bed372f753795b77e9b40da930d')
  46. print(' released: March 6, 2022')
  47. print(' offset: 0xC400C')
  48. print()
  49. print('TraceBuddy.dll version 1.0.0 did not use std::list.')
  50. exit(0)
  51. args.bl_object_offset = int(args.bl_object_offset.replace("0x", ""), 16)
  52. stdlist_routines = {\
  53. 'TraceBuddy': {},
  54. #'ObjectTrace': {},
  55. }
  56. stdlist_routines['TraceBuddy']['offset'] = args.tracebuddy_offset
  57. stdlist_routines['TraceBuddy']['direct_address'] = args.tracebuddy_direct_address
  58. stdlist_routines['TraceBuddy']['ptr_name'] = 'trace_lines'
  59. '''
  60. stdlist_routines['ObjectTrace']['offset'] = args.objecttrace_offset
  61. stdlist_routines['ObjectTrace']['direct_address'] = args.objecttrace_direct_address
  62. stdlist_routines['ObjectTrace']['ptr_name'] = 'journal_lines'
  63. '''
  64. for name, data in stdlist_routines.items():
  65. data['mode_direct_address'] = False
  66. data['mode_offset'] = False
  67. data['base_addr'] = 0
  68. data['detected_offset'] = 0
  69. #Neither - assume offset for TraceBuddy version 2.1.0
  70. if data['offset'] is None and data['direct_address'] is None:
  71. if name == 'TraceBuddy':
  72. data['offset'] = 0x100034
  73. data['mode_offset'] = True
  74. '''
  75. elif name == 'ObjectTrace':
  76. data['offset'] = 0x10105C
  77. data['mode_offset'] = True
  78. '''
  79. else:
  80. if data['offset'] is not None:
  81. data['offset'] = int(data['offset'].replace("0x", ""), 16)
  82. data['mode_offset'] = True
  83. if data['direct_address'] is not None:
  84. data['direct_address'] = int(data['direct_address'].replace("0x", ""), 16)
  85. data['mode_direct_address'] = True
  86. if data['mode_offset'] and data['mode_direct_address']:
  87. print('Can not use both offset and direct-address for', name)
  88. exit(1)
  89. class MINIDUMP_STREAM_TYPE(Enum):
  90. UnusedStream = 0
  91. ThreadListStream = 3
  92. ModuleListStream = 4
  93. MemoryListStream = 5
  94. SystemInfoStream = 7
  95. Memory64ListStream = 9 #64-bit memory allocation information stream
  96. HandleDataStream = 12
  97. MiscInfoStream = 15
  98. MemoryInfoListStream = 16 #Memory region description information stream
  99. ThreadInfoListStream = 17
  100. Unknown21 = 21
  101. Unknown22 = 22
  102. f = None
  103. memory_range_list = []
  104. memory_rva = 0
  105. base_addr_blockland = 0
  106. def seek_to_memory_ranged(addr):
  107. base_offset_in_file = memory_rva
  108. for memory_range in memory_range_list:
  109. if addr >= memory_range['rva'] and addr < (memory_range['rva'] + memory_range['size']):
  110. offset_in_range = addr - memory_range['rva']
  111. f.seek(base_offset_in_file + offset_in_range)
  112. return True
  113. base_offset_in_file += memory_range['size']
  114. return False
  115. def read_stdlist_common(routine_name):
  116. routine_data = stdlist_routines[routine_name]
  117. list_trace_lines_ptr_loc = 0
  118. if routine_data['mode_offset']:
  119. list_trace_lines_ptr_loc = routine_data['offset'] + routine_data['base_addr']
  120. else:
  121. list_trace_lines_ptr_loc = routine_data['direct_address']
  122. print("Reading pointer at", num_to_hex(list_trace_lines_ptr_loc, 8))
  123. seek_to_memory_ranged(list_trace_lines_ptr_loc)
  124. if not list_trace_lines_ptr_loc:
  125. print('Could not locate memory block containing pointer')
  126. return
  127. if list_trace_lines_ptr_loc == 0:
  128. print('Null pointer')
  129. return
  130. list_trace_lines_ptr = struct.unpack('I', f.read(4))[0]
  131. print(routine_data['ptr_name'], "std::list starts at", num_to_hex(list_trace_lines_ptr, 8))
  132. addr_next = list_trace_lines_ptr
  133. #Read first element
  134. seek_to_memory_ranged(addr_next + 4)
  135. addr_prev = struct.unpack('I', f.read(4))[0]
  136. if addr_prev == list_trace_lines_ptr_loc:
  137. print('Located first element')
  138. print()
  139. line_count=0
  140. while addr_next != list_trace_lines_ptr_loc:
  141. seek_to_memory_ranged(addr_next)
  142. addr_next = struct.unpack('I', f.read(4))[0]
  143. addr_prev = struct.unpack('I', f.read(4))[0]
  144. addr_str = struct.unpack('I', f.read(4))[0]
  145. str_len = struct.unpack('I', f.read(4))[0]
  146. seek_to_memory_ranged(addr_str)
  147. print(f.read(str_len).decode('cp1252'), end='')
  148. line_count += 1
  149. print()
  150. print('Found', line_count, 'lines of data for', routine_data['ptr_name'], 'in', routine_name)
  151. if routine_data['mode_direct_address']:
  152. calc_offset = hex(routine_data['detected_offset'])[2:].upper()
  153. print('For dumps with this same DLL, use this offset instead of reading the pointer from the console log: 0x'+ str(calc_offset))
  154. def read_objects():
  155. all_object_addresses = {}
  156. tsf_gIdDictionaryPtrLoc = base_addr_blockland + args.bl_object_offset
  157. seek_to_memory_ranged(tsf_gIdDictionaryPtrLoc)
  158. tsf_gIdDictionaryPtr = struct.unpack('I', f.read(4))[0]
  159. for bucket_num in range(0, 4096):
  160. seek_to_memory_ranged(tsf_gIdDictionaryPtr + bucket_num * 4)
  161. next_obj_ptr = struct.unpack('I', f.read(4))[0]
  162. while True:
  163. if next_obj_ptr == 0:
  164. break
  165. seek_to_memory_ranged(next_obj_ptr)
  166. obj_ptr = next_obj_ptr
  167. f.read(16)
  168. #SimObject* SimObject->nextIdObject
  169. next_obj_ptr = struct.unpack('I', f.read(4))[0]
  170. f.read(12)
  171. obj_id = struct.unpack('i', f.read(4))[0]
  172. all_object_addresses[obj_id] = obj_ptr
  173. for obj_id in sorted(all_object_addresses.keys()):
  174. obj_addr = all_object_addresses[obj_id]
  175. seek_to_memory_ranged(obj_addr)
  176. vt=struct.unpack('I', f.read(4))[0]
  177. obj_name_ptr=struct.unpack('I', f.read(4))[0]
  178. f.read(8)
  179. #SimObject* SimObject->nextIdObject
  180. next_obj_ptr = struct.unpack('I', f.read(4))[0]
  181. f.read(12)
  182. obj_id = struct.unpack('i', f.read(4))[0]
  183. namespace_addr = struct.unpack('I', f.read(4))[0]
  184. print('Object', num_to_hex(obj_addr, 8))
  185. obj_name=b''
  186. if obj_name_ptr != 0:
  187. seek_to_memory_ranged(obj_name_ptr)
  188. next_char = f.read(1)
  189. while next_char != b'\0':
  190. obj_name += next_char
  191. next_char = f.read(1)
  192. obj_name = obj_name.decode('utf-8')
  193. print(' Name:', obj_name)
  194. print(' id:', obj_id)
  195. ns_name='NULL'
  196. this_namespace_addr = namespace_addr
  197. while this_namespace_addr != 0:
  198. seek_to_memory_ranged(this_namespace_addr)
  199. ptr_ns_name=struct.unpack('I', f.read(4))[0]
  200. f.read(4)
  201. ptr_mParent = struct.unpack('I', f.read(4))[0]
  202. f.read(4)
  203. ptr_mClassRep = struct.unpack('I', f.read(4))[0]
  204. if ptr_mClassRep != 0:
  205. if ptr_ns_name == 0:
  206. break
  207. seek_to_memory_ranged(ptr_ns_name)
  208. next_char = f.read(1)
  209. ns_name=b''
  210. while next_char != b'\0':
  211. ns_name += next_char
  212. next_char = f.read(1)
  213. ns_name = ns_name.decode('utf-8')
  214. break
  215. this_namespace_addr = ptr_mParent
  216. print(' class:', ns_name)
  217. if ns_name in classes_interest:
  218. seek_to_memory_ranged(obj_addr + 92)
  219. #obj->mObjToWorld
  220. matrix_f_vals = []
  221. for i in range(0, 16):
  222. matrix_f_vals += [str(struct.unpack('f', f.read(4))[0])]
  223. pos = ' '.join([matrix_f_vals[3], matrix_f_vals[7], matrix_f_vals[11]])
  224. print(' pos:', pos)
  225. print()
  226. with open(args.analyze_file, "rb") as f:
  227. print_stack_locs = []
  228. header_sig = f.read(4)
  229. if header_sig != b'MDMP':
  230. print("Not an MDMP file")
  231. exit(1)
  232. version = f.read(2)
  233. version_imp = f.read(2)
  234. num_streams = struct.unpack('I', f.read(4))[0]
  235. stream_dir_RVA = struct.unpack('I', f.read(4))[0]
  236. checksum = f.read(4)
  237. timestamp = f.read(4)
  238. flags = struct.unpack('Q', f.read(8))[0]
  239. #Flags set:
  240. #MiniDumpWithFullMemory
  241. #MiniDumpWithHandleData
  242. #MiniDumpWithFullMemoryInfo
  243. for stream_num in range(0, num_streams):
  244. f.seek(stream_dir_RVA + stream_num * 4 * 3, 0 )
  245. stream_type = struct.unpack('I', f.read(4))[0]
  246. stream_data_size = struct.unpack('I', f.read(4))[0]
  247. stream_RVA = struct.unpack('I', f.read(4))[0]
  248. if stream_type not in \
  249. [MINIDUMP_STREAM_TYPE.ModuleListStream.value,\
  250. MINIDUMP_STREAM_TYPE.ThreadListStream.value,\
  251. MINIDUMP_STREAM_TYPE.ThreadInfoListStream.value,\
  252. MINIDUMP_STREAM_TYPE.Memory64ListStream.value]:
  253. continue
  254. print(MINIDUMP_STREAM_TYPE(stream_type).name, 'size =', stream_data_size, 'location =', stream_RVA)
  255. f.seek(stream_RVA, 0)
  256. if stream_type == MINIDUMP_STREAM_TYPE.ThreadListStream.value:
  257. num_threads = struct.unpack('i', f.read(4))[0]
  258. print(' Num threads:', num_threads)
  259. tell_pos = f.tell()
  260. for thread_index_num in range(0, num_threads):
  261. f.seek(tell_pos)
  262. thread_id = struct.unpack('i', f.read(4))[0]
  263. suspend_count = struct.unpack('i', f.read(4))[0]
  264. priority_class = struct.unpack('i', f.read(4))[0]
  265. priority = struct.unpack('i', f.read(4))[0]
  266. teb = struct.unpack('Q', f.read(8))[0]
  267. stack_data_size = struct.unpack('i', f.read(4))[0]
  268. stack_rva = struct.unpack('i', f.read(4))[0]
  269. thread_context_data_size = struct.unpack('i', f.read(4))[0]
  270. thread_context_rva = struct.unpack('i', f.read(4))[0]
  271. tell_pos = f.tell()
  272. if thread_context_rva != 0:
  273. f.seek(thread_context_rva)
  274. ctx = {}
  275. print(thread_id, num_to_hex(teb, 16), num_to_hex(stack_rva, 8), num_to_hex(thread_context_rva, 8))
  276. #print(f.read(thread_context_data_size))
  277. '''
  278. self.file_handle.seek(rva)
  279. if self.sysinfo.ProcessorArchitecture == PROCESSOR_ARCHITECTURE.AMD64:
  280. thread.ContextObject = CONTEXT.parse(self.file_handle)
  281. elif self.sysinfo.ProcessorArchitecture == PROCESSOR_ARCHITECTURE.INTEL:
  282. thread.ContextObject = WOW64_CONTEXT.parse(self.file_handle)
  283. '''
  284. ctx['P1Home'] = struct.unpack('Q', f.read(8))[0]
  285. ctx['P2Home'] = struct.unpack('Q', f.read(8))[0]
  286. ctx['P3Home'] = struct.unpack('Q', f.read(8))[0]
  287. ctx['P4Home'] = struct.unpack('Q', f.read(8))[0]
  288. ctx['P5Home'] = struct.unpack('Q', f.read(8))[0]
  289. ctx['P6Home'] = struct.unpack('Q', f.read(8))[0]
  290. ctx['ContextFlags'] = struct.unpack('i', f.read(4))[0]
  291. ctx['MxCsr'] = struct.unpack('i', f.read(4))[0]
  292. ctx['SegCs'] = struct.unpack('H', f.read(2))[0]
  293. ctx['SegDs'] = struct.unpack('H', f.read(2))[0]
  294. ctx['SegEs'] = struct.unpack('H', f.read(2))[0]
  295. ctx['SegFs'] = struct.unpack('H', f.read(2))[0]
  296. ctx['SegGs'] = struct.unpack('H', f.read(2))[0]
  297. ctx['SegSs'] = struct.unpack('H', f.read(2))[0]
  298. ctx['EFlags'] = struct.unpack('i', f.read(4))[0]
  299. ctx['Dr0'] = struct.unpack('Q', f.read(8))[0]
  300. ctx['Dr1'] = struct.unpack('Q', f.read(8))[0]
  301. ctx['Dr2'] = struct.unpack('Q', f.read(8))[0]
  302. ctx['Dr3'] = struct.unpack('Q', f.read(8))[0]
  303. ctx['Dr6'] = struct.unpack('Q', f.read(8))[0]
  304. ctx['Dr7'] = struct.unpack('Q', f.read(8))[0]
  305. ctx['Rax'] = struct.unpack('Q', f.read(8))[0]
  306. ctx['Rcx'] = struct.unpack('Q', f.read(8))[0]
  307. ctx['Rdx'] = struct.unpack('Q', f.read(8))[0]
  308. ctx['Rbx'] = struct.unpack('Q', f.read(8))[0]
  309. ctx['Rsp'] = struct.unpack('Q', f.read(8))[0]
  310. ctx['Rbp'] = struct.unpack('Q', f.read(8))[0]
  311. ctx['Rsi'] = struct.unpack('Q', f.read(8))[0]
  312. ctx['Rdi'] = struct.unpack('Q', f.read(8))[0]
  313. ctx['R8'] = struct.unpack('Q', f.read(8))[0]
  314. ctx['R9'] = struct.unpack('Q', f.read(8))[0]
  315. ctx['R10'] = struct.unpack('Q', f.read(8))[0]
  316. ctx['R11'] = struct.unpack('Q', f.read(8))[0]
  317. ctx['R12'] = struct.unpack('Q', f.read(8))[0]
  318. ctx['R13'] = struct.unpack('Q', f.read(8))[0]
  319. ctx['R14'] = struct.unpack('Q', f.read(8))[0]
  320. ctx['R15'] = struct.unpack('Q', f.read(8))[0]
  321. ctx['Rip'] = struct.unpack('Q', f.read(8))[0]
  322. print(ctx.items())
  323. print('rip:', num_to_hex(ctx['Rip'], 16))
  324. print('rsp:', num_to_hex(ctx['Rsp'], 16))
  325. if ctx['Rsp'] != 0:
  326. print_stack_locs += [ctx['Rsp']]
  327. '''
  328. ctx.DUMMYUNIONNAME = CTX_DUMMYUNIONNAME.parse(buff)
  329. ctx.VectorRegister = M128A.parse_array(buff, 26) # M128A [26]
  330. ctx.VectorControl = int.from_bytes(buff.read(8), byteorder = 'little', signed = False) # DWORD64
  331. ctx.DebugControl = int.from_bytes(buff.read(8), byteorder = 'little', signed = False) # DWORD64
  332. ctx.LastBranchToRip = int.from_bytes(buff.read(8), byteorder = 'little', signed = False) # DWORD64
  333. ctx.LastBranchFromRip = int.from_bytes(buff.read(8), byteorder = 'little', signed = False) # DWORD64
  334. ctx.LastExceptionToRip = int.from_bytes(buff.read(8), byteorder = 'little', signed = False) # DWORD64
  335. ctx.LastExceptionFromRip = int.from_bytes(buff.read(8), byteorder = 'little', signed = False) # DWORD64
  336. '''
  337. '''
  338. if stream_type == MINIDUMP_STREAM_TYPE.ThreadInfoListStream.value:
  339. size_of_header = struct.unpack('i', f.read(4))[0]
  340. size_of_entry = struct.unpack('i', f.read(4))[0]
  341. num_entries = struct.unpack('i', f.read(4))[0]
  342. for thread_entry_num in range(0, num_entries):
  343. thread_id = struct.unpack('i', f.read(4))[0]
  344. dump_flags = struct.unpack('i', f.read(4))[0]
  345. dump_error = struct.unpack('i', f.read(4))[0]
  346. exit_status = struct.unpack('i', f.read(4))[0]
  347. create_time = struct.unpack('Q', f.read(8))[0]
  348. exit_time = struct.unpack('Q', f.read(8))[0]
  349. kernel_time = struct.unpack('Q', f.read(8))[0]
  350. user_time = struct.unpack('Q', f.read(8))[0]
  351. start_address = struct.unpack('Q', f.read(8))[0]
  352. affinity = struct.unpack('Q', f.read(8))[0]
  353. '''
  354. if stream_type == MINIDUMP_STREAM_TYPE.ModuleListStream.value:
  355. num_modules = struct.unpack('I', f.read(4))[0]
  356. print(' Num modules:', num_modules)
  357. module_list_base = f.tell()
  358. for module_num in range(0, num_modules):
  359. f.seek(module_list_base + module_num * 108, 0)
  360. image_base = struct.unpack('Q', f.read(8))[0]
  361. image_size = struct.unpack('I', f.read(4))[0]
  362. module_checksum = struct.unpack('I', f.read(4))[0]
  363. module_timestamp = struct.unpack('I', f.read(4))[0]
  364. module_name_rva = struct.unpack('I', f.read(4))[0]
  365. module_version_info = f.read(52)
  366. f.seek(module_name_rva)
  367. module_name_size = struct.unpack('I', f.read(4))[0]
  368. module_name_str_full = f.read(module_name_size).decode('utf-16-le')
  369. module_name_str = module_name_str_full.split('\\')[-1]
  370. print(' ', num_to_hex(image_base, 8), image_size, module_name_size, module_name_str_full)
  371. if module_name_str == 'TraceBuddy.dll': # or module_name_str == 'ObjectTrace.dll':
  372. routine_name = module_name_str[0:-4]
  373. routine = stdlist_routines[routine_name]
  374. print(' Found '+ module_name_str)
  375. routine['base_addr'] = image_base
  376. if routine['mode_direct_address']:
  377. detected_offset = routine['direct_address'] - image_base
  378. routine['detected_offset'] = detected_offset
  379. calc_offset = hex(detected_offset)[2:].upper()
  380. print(' Back-calculated the offset: 0x'+ str(calc_offset))
  381. if module_name_str == 'Blockland.exe':
  382. print(' Found Blockland.exe')
  383. base_addr_blockland = image_base
  384. if stream_type == MINIDUMP_STREAM_TYPE.Memory64ListStream.value:
  385. m64list_num_ranges = struct.unpack('Q', f.read(8))[0]
  386. m64list_rva = struct.unpack('Q', f.read(8))[0]
  387. memory_rva = m64list_rva
  388. memory_range_total_sizes = 0
  389. for memory_range_num in range(0, m64list_num_ranges):
  390. memory_range_rva = struct.unpack('Q', f.read(8))[0]
  391. memory_range_size = struct.unpack('Q', f.read(8))[0]
  392. memory_range_total_sizes += memory_range_size
  393. memory_range_list += [{'rva': memory_range_rva, 'size': memory_range_size}]
  394. print(' Found', memory_range_total_sizes, 'bytes of memory in', m64list_num_ranges, 'sections')
  395. print()
  396. for stack_loc in print_stack_locs:
  397. print(num_to_hex(stack_loc, 8))
  398. for i in range(0, 16):
  399. for j in range(0, 16):
  400. seek_to_memory_ranged(stack_loc - (i * 16 + j) * 4)
  401. print(num_to_hex(struct.unpack('I', f.read(4))[0], 1).rjust(10), end=' ')
  402. print()
  403. if args.print_tracebuddy:
  404. read_stdlist_common('TraceBuddy')
  405. #if args.print_objecttrace:
  406. # read_stdlist_common('ObjectTrace')
  407. if args.analyze_objects:
  408. read_objects()