3588 lines · 112.0 KB · Python
RawDownload
<li>The disassembler is available. Currently, only Intel XED is supported - see <a href=#xed>Intel XED Setup</a></li><li>The object code is available. Currently, only the perf build ID cache is searched for object code.The default directory ~/.debug can be overridden by setting environment variable PERF_BUILDID_DIR.One exception is kcore where the DSO long name is used (refer dsos_view on the Tables menu),or alternatively, set environment variable PERF_KCORE to the kcore file name.</li></ol><h4 id=xed>Intel XED Setup</h4>To use Intel XED, libxed.so must be present.  To build and install libxed.so:<pre>git clone https://github.com/intelxed/mbuild.git mbuildgit clone https://github.com/intelxed/xedcd xed./mfile.py --sharesudo ./mfile.py --prefix=/usr/local installsudo ldconfig</pre><h3>Instructions per Cycle (IPC)</h3>If available, IPC information is displayed in columns 'insn_cnt', 'cyc_cnt' and 'IPC'.<p><b>Intel PT note:</b> The information applies to the blocks of code ending with, and including, that branch.Due to the granularity of timing information, the number of cycles for some code blocks will not be known.In that case, 'insn_cnt', 'cyc_cnt' and 'IPC' are zero, but when 'IPC' is displayed it covers the periodsince the previous displayed 'IPC'.<h3>Find</h3>Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match.Refer to Python documentation for the regular expression syntax.All columns are searched, but only currently fetched rows are searched.<h2 id=selectedbranches>1.4 Selected branches</h2>This is the same as the <a href=#allbranches>All branches</a> report but with the data reducedby various selection criteria. A dialog box displays available criteria which are AND'ed together.<h3>1.4.1 Time ranges</h3>The time ranges hint text shows the total time range. Relative time ranges can also be entered inms, us or ns. Also, negative values are relative to the end of trace.  Examples:<pre>	81073085947329-81073085958238	From 81073085947329 to 81073085958238	100us-200us		From 100us to 200us	10ms-			From 10ms to the end	-100ns			The first 100ns	-10ms-			The last 10ms</pre>N.B. Due to the granularity of timestamps, there could be no branches in any given time range.<h2 id=topcallsbyelapsedtime>1.5 Top calls by elapsed time</h2>The Top calls by elapsed time report displays calls in descending order of time elapsed between when the function was called and when it returned.The data is reduced by various selection criteria. A dialog box displays available criteria which are AND'ed together.If not all data is fetched, a Fetch bar is provided. Ctrl-F displays a Find bar.<h1 id=tables>2. Tables</h1>The Tables menu shows all tables and views in the database. Most tables have an associated viewwhich displays the information in a more friendly way. Not all data for large tables is fetchedimmediately. More records can be fetched using the Fetch bar provided. Columns can be sorted,but that can be slow for large tables.<p>There are also tables of database meta-information.For SQLite3 databases, the sqlite_master table is included.For PostgreSQL databases, information_schema.tables/views/columns are included.<h3>Find</h3>Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match.Refer to Python documentation for the regular expression syntax.All columns are searched, but only currently fetched rows are searched.<p>N.B. Results are found in id order, so if the table is re-ordered, find-next and find-previouswill go to the next/previous result in id order, instead of display order.""" # Help window class HelpWindow(QMdiSubWindow): 	def __init__(self, glb, parent=None):		super(HelpWindow, self).__init__(parent) 		self.text = QTextBrowser()		self.text.setHtml(glb_help_text)		self.text.setReadOnly(True)		self.text.setOpenExternalLinks(True) 		self.setWidget(self.text) 		AddSubWindow(glb.mainwindow.mdi_area, self, "Exported SQL Viewer Help") # Main window that only displays the help text class HelpOnlyWindow(QMainWindow): 	def __init__(self, parent=None):		super(HelpOnlyWindow, self).__init__(parent) 		self.setMinimumSize(200, 100)		self.resize(800, 600)		self.setWindowTitle("Exported SQL Viewer Help")		self.setWindowIcon(self.style().standardIcon(QStyle.SP_MessageBoxInformation)) 		self.text = QTextBrowser()		self.text.setHtml(glb_help_text)		self.text.setReadOnly(True)		self.text.setOpenExternalLinks(True) 		self.setCentralWidget(self.text) # PostqreSQL server version def PostqreSQLServerVersion(db):	query = QSqlQuery(db)	QueryExec(query, "SELECT VERSION()")	if query.next():		v_str = query.value(0)		v_list = v_str.strip().split(" ")		if v_list[0] == "PostgreSQL" and v_list[2] == "on":			return v_list[1]		return v_str	return "Unknown" # SQLite version def SQLiteVersion(db):	query = QSqlQuery(db)	QueryExec(query, "SELECT sqlite_version()")	if query.next():		return query.value(0)	return "Unknown" # About dialog class AboutDialog(QDialog): 	def __init__(self, glb, parent=None):		super(AboutDialog, self).__init__(parent) 		self.setWindowTitle("About Exported SQL Viewer")		self.setMinimumWidth(300) 		pyside_version = "1" if pyside_version_1 else "2" 		text = "<pre>"		text += "Python version:     " + sys.version.split(" ")[0] + "\n"		text += "PySide version:     " + pyside_version + "\n"		text += "Qt version:         " + qVersion() + "\n"		if glb.dbref.is_sqlite3:			text += "SQLite version:     " + SQLiteVersion(glb.db) + "\n"		else:			text += "PostqreSQL version: " + PostqreSQLServerVersion(glb.db) + "\n"		text += "</pre>" 		self.text = QTextBrowser()		self.text.setHtml(text)		self.text.setReadOnly(True)		self.text.setOpenExternalLinks(True) 		self.vbox = QVBoxLayout()		self.vbox.addWidget(self.text) 		self.setLayout(self.vbox) # Font resize def ResizeFont(widget, diff):	font = widget.font()	sz = font.pointSize()	font.setPointSize(sz + diff)	widget.setFont(font) def ShrinkFont(widget):	ResizeFont(widget, -1) def EnlargeFont(widget):	ResizeFont(widget, 1) # Unique name for sub-windows def NumberedWindowName(name, nr):	if nr > 1:		name += " <" + str(nr) + ">"	return name def UniqueSubWindowName(mdi_area, name):	nr = 1	while True:		unique_name = NumberedWindowName(name, nr)		ok = True		for sub_window in mdi_area.subWindowList():			if sub_window.name == unique_name:				ok = False				break		if ok:			return unique_name		nr += 1 # Add a sub-window def AddSubWindow(mdi_area, sub_window, name):	unique_name = UniqueSubWindowName(mdi_area, name)	sub_window.setMinimumSize(200, 100)	sub_window.resize(800, 600)	sub_window.setWindowTitle(unique_name)	sub_window.setAttribute(Qt.WA_DeleteOnClose)	sub_window.setWindowIcon(sub_window.style().standardIcon(QStyle.SP_FileIcon))	sub_window.name = unique_name	mdi_area.addSubWindow(sub_window)	sub_window.show() # Main window class MainWindow(QMainWindow): 	def __init__(self, glb, parent=None):		super(MainWindow, self).__init__(parent) 		self.glb = glb 		self.setWindowTitle("Exported SQL Viewer: " + glb.dbname)		self.setWindowIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))		self.setMinimumSize(200, 100) 		self.mdi_area = QMdiArea()		self.mdi_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)		self.mdi_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) 		self.setCentralWidget(self.mdi_area) 		menu = self.menuBar() 		file_menu = menu.addMenu("&File")		file_menu.addAction(CreateExitAction(glb.app, self)) 		edit_menu = menu.addMenu("&Edit")		edit_menu.addAction(CreateAction("&Copy", "Copy to clipboard", self.CopyToClipboard, self, QKeySequence.Copy))		edit_menu.addAction(CreateAction("Copy as CS&V", "Copy to clipboard as CSV", self.CopyToClipboardCSV, self))		edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find))		edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)]))		edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")]))		edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")])) 		reports_menu = menu.addMenu("&Reports")		if IsSelectable(glb.db, "calls"):			reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self)) 		if IsSelectable(glb.db, "calls", "WHERE parent_id >= 0"):			reports_menu.addAction(CreateAction("Call &Tree", "Create a new window containing a call tree", self.NewCallTree, self)) 		self.EventMenu(GetEventList(glb.db), reports_menu) 		if IsSelectable(glb.db, "calls"):			reports_menu.addAction(CreateAction("&Top calls by elapsed time", "Create a new window displaying top calls by elapsed time", self.NewTopCalls, self)) 		self.TableMenu(GetTableList(glb), menu) 		self.window_menu = WindowMenu(self.mdi_area, menu) 		help_menu = menu.addMenu("&Help")		help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents))		help_menu.addAction(CreateAction("&About Exported SQL Viewer", "About this application", self.About, self)) 	def Try(self, fn):		win = self.mdi_area.activeSubWindow()		if win:			try:				fn(win.view)			except:				pass 	def CopyToClipboard(self):		self.Try(CopyCellsToClipboardHdr) 	def CopyToClipboardCSV(self):		self.Try(CopyCellsToClipboardCSV) 	def Find(self):		win = self.mdi_area.activeSubWindow()		if win:			try:				win.find_bar.Activate()			except:				pass 	def FetchMoreRecords(self):		win = self.mdi_area.activeSubWindow()		if win:			try:				win.fetch_bar.Activate()			except:				pass 	def ShrinkFont(self):		self.Try(ShrinkFont) 	def EnlargeFont(self):		self.Try(EnlargeFont) 	def EventMenu(self, events, reports_menu):		branches_events = 0		for event in events:			event = event.split(":")[0]			if event == "branches":				branches_events += 1		dbid = 0		for event in events:			dbid += 1			event = event.split(":")[0]			if event == "branches":				label = "All branches" if branches_events == 1 else "All branches " + "(id=" + dbid + ")"				reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda a=None,x=dbid: self.NewBranchView(x), self))				label = "Selected branches" if branches_events == 1 else "Selected branches " + "(id=" + dbid + ")"				reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda a=None,x=dbid: self.NewSelectedBranchView(x), self)) 	def TableMenu(self, tables, menu):		table_menu = menu.addMenu("&Tables")		for table in tables:			table_menu.addAction(CreateAction(table, "Create a new window containing a table view", lambda a=None,t=table: self.NewTableView(t), self)) 	def NewCallGraph(self):		CallGraphWindow(self.glb, self) 	def NewCallTree(self):		CallTreeWindow(self.glb, self) 	def NewTopCalls(self):		dialog = TopCallsDialog(self.glb, self)		ret = dialog.exec_()		if ret:			TopCallsWindow(self.glb, dialog.report_vars, self) 	def NewBranchView(self, event_id):		BranchWindow(self.glb, event_id, ReportVars(), self) 	def NewSelectedBranchView(self, event_id):		dialog = SelectedBranchDialog(self.glb, self)		ret = dialog.exec_()		if ret:			BranchWindow(self.glb, event_id, dialog.report_vars, self) 	def NewTableView(self, table_name):		TableWindow(self.glb, table_name, self) 	def Help(self):		HelpWindow(self.glb, self) 	def About(self):		dialog = AboutDialog(self.glb, self)		dialog.exec_() # XED Disassembler class xed_state_t(Structure): 	_fields_ = [		("mode", c_int),		("width", c_int)	] class XEDInstruction(): 	def __init__(self, libxed):		# Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion		xedd_t = c_byte * 512		self.xedd = xedd_t()		self.xedp = addressof(self.xedd)		libxed.xed_decoded_inst_zero(self.xedp)		self.state = xed_state_t()		self.statep = addressof(self.state)		# Buffer for disassembled instruction text		self.buffer = create_string_buffer(256)		self.bufferp = addressof(self.buffer) class LibXED(): 	def __init__(self):		try:			self.libxed = CDLL("libxed.so")		except:			self.libxed = None		if not self.libxed:			self.libxed = CDLL("/usr/local/lib/libxed.so") 		self.xed_tables_init = self.libxed.xed_tables_init		self.xed_tables_init.restype = None		self.xed_tables_init.argtypes = [] 		self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero		self.xed_decoded_inst_zero.restype = None		self.xed_decoded_inst_zero.argtypes = [ c_void_p ] 		self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode		self.xed_operand_values_set_mode.restype = None		self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ] 		self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode		self.xed_decoded_inst_zero_keep_mode.restype = None		self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ] 		self.xed_decode = self.libxed.xed_decode		self.xed_decode.restype = c_int		self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ] 		self.xed_format_context = self.libxed.xed_format_context		self.xed_format_context.restype = c_uint		self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ] 		self.xed_tables_init() 	def Instruction(self):		return XEDInstruction(self) 	def SetMode(self, inst, mode):		if mode:			inst.state.mode = 4 # 32-bit			inst.state.width = 4 # 4 bytes		else:			inst.state.mode = 1 # 64-bit			inst.state.width = 8 # 8 bytes		self.xed_operand_values_set_mode(inst.xedp, inst.statep) 	def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip):		self.xed_decoded_inst_zero_keep_mode(inst.xedp)		err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt)		if err:			return 0, ""		# Use AT&T mode (2), alternative is Intel (3)		ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)		if not ok:			return 0, ""		if sys.version_info[0] == 2:			result = inst.buffer.value		else:			result = inst.buffer.value.decode()		# Return instruction length and the disassembled instruction text		# For now, assume the length is in byte 166		return inst.xedd[166], result def TryOpen(file_name):	try:		return open(file_name, "rb")	except:		return None def Is64Bit(f):	result = sizeof(c_void_p)	# ELF support only	pos = f.tell()	f.seek(0)	header = f.read(7)	f.seek(pos)	magic = header[0:4]	if sys.version_info[0] == 2:		eclass = ord(header[4])		encoding = ord(header[5])		version = ord(header[6])	else:		eclass = header[4]		encoding = header[5]		version = header[6]	if magic == chr(127) + "ELF" and eclass > 0 and eclass < 3 and encoding > 0 and encoding < 3 and version == 1:		result = True if eclass == 2 else False	return result # Global data class Glb(): 	def __init__(self, dbref, db, dbname):		self.dbref = dbref		self.db = db		self.dbname = dbname		self.home_dir = os.path.expanduser("~")		self.buildid_dir = os.getenv("PERF_BUILDID_DIR")		if self.buildid_dir:			self.buildid_dir += "/.build-id/"		else:			self.buildid_dir = self.home_dir + "/.debug/.build-id/"		self.app = None		self.mainwindow = None		self.instances_to_shutdown_on_exit = weakref.WeakSet()		try:			self.disassembler = LibXED()			self.have_disassembler = True		except:			self.have_disassembler = False 	def FileFromBuildId(self, build_id):		file_name = self.buildid_dir + build_id[0:2] + "/" + build_id[2:] + "/elf"		return TryOpen(file_name) 	def FileFromNamesAndBuildId(self, short_name, long_name, build_id):		# Assume current machine i.e. no support for virtualization		if short_name[0:7] == "[kernel" and os.path.basename(long_name) == "kcore":			file_name = os.getenv("PERF_KCORE")			f = TryOpen(file_name) if file_name else None			if f:				return f			# For now, no special handling if long_name is /proc/kcore			f = TryOpen(long_name)			if f:				return f		f = self.FileFromBuildId(build_id)		if f:			return f		return None 	def AddInstanceToShutdownOnExit(self, instance):		self.instances_to_shutdown_on_exit.add(instance) 	# Shutdown any background processes or threads	def ShutdownInstances(self):		for x in self.instances_to_shutdown_on_exit:			try:

Lines 3001–3500 of 3588. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t