1*19c3b8c2SApple OSS Distributionsfrom __future__ import absolute_import, print_function 2*19c3b8c2SApple OSS Distributions 3*19c3b8c2SApple OSS Distributionsfrom builtins import object 4*19c3b8c2SApple OSS Distributions 5*19c3b8c2SApple OSS Distributionsimport getopt 6*19c3b8c2SApple OSS Distributionsimport os 7*19c3b8c2SApple OSS Distributionsimport sys 8*19c3b8c2SApple OSS Distributionsimport re 9*19c3b8c2SApple OSS Distributions 10*19c3b8c2SApple OSS Distributionsclass ArgumentError(Exception): 11*19c3b8c2SApple OSS Distributions """ Exception class for raising errors in command arguments. The lldb_command framework will catch this 12*19c3b8c2SApple OSS Distributions class of exceptions and print suitable error message to user. 13*19c3b8c2SApple OSS Distributions """ 14*19c3b8c2SApple OSS Distributions def __init__(self, msg): 15*19c3b8c2SApple OSS Distributions self.error_message = msg 16*19c3b8c2SApple OSS Distributions def __str__(self): 17*19c3b8c2SApple OSS Distributions return str(self.error_message) 18*19c3b8c2SApple OSS Distributions 19*19c3b8c2SApple OSS Distributions 20*19c3b8c2SApple OSS Distributionsclass RedirectStdStreams(object): 21*19c3b8c2SApple OSS Distributions def __init__(self, stdout=None, stderr=None): 22*19c3b8c2SApple OSS Distributions self._stdout = stdout or sys.stdout 23*19c3b8c2SApple OSS Distributions self._stderr = stderr or sys.stderr 24*19c3b8c2SApple OSS Distributions 25*19c3b8c2SApple OSS Distributions def __enter__(self): 26*19c3b8c2SApple OSS Distributions self.old_stdout, self.old_stderr = sys.stdout, sys.stderr 27*19c3b8c2SApple OSS Distributions self.old_stdout.flush(); self.old_stderr.flush() 28*19c3b8c2SApple OSS Distributions sys.stdout, sys.stderr = self._stdout, self._stderr 29*19c3b8c2SApple OSS Distributions 30*19c3b8c2SApple OSS Distributions def __exit__(self, exc_type, exc_value, traceback): 31*19c3b8c2SApple OSS Distributions self._stdout.flush(); self._stderr.flush() 32*19c3b8c2SApple OSS Distributions sys.stdout = self.old_stdout 33*19c3b8c2SApple OSS Distributions sys.stderr = self.old_stderr 34*19c3b8c2SApple OSS Distributions 35*19c3b8c2SApple OSS Distributionsclass IndentScope(object): 36*19c3b8c2SApple OSS Distributions def __init__(self, O): 37*19c3b8c2SApple OSS Distributions self._O = O 38*19c3b8c2SApple OSS Distributions 39*19c3b8c2SApple OSS Distributions def __enter__(self): 40*19c3b8c2SApple OSS Distributions self._O._indent += ' ' 41*19c3b8c2SApple OSS Distributions 42*19c3b8c2SApple OSS Distributions def __exit__(self, exc_type, exc_value, traceback): 43*19c3b8c2SApple OSS Distributions self._O._indent = self._O._indent[:-4] 44*19c3b8c2SApple OSS Distributions 45*19c3b8c2SApple OSS Distributionsclass HeaderScope(object): 46*19c3b8c2SApple OSS Distributions def __init__(self, O, hdr, indent = False): 47*19c3b8c2SApple OSS Distributions self._O = O 48*19c3b8c2SApple OSS Distributions self._header = hdr 49*19c3b8c2SApple OSS Distributions self._indent = indent 50*19c3b8c2SApple OSS Distributions 51*19c3b8c2SApple OSS Distributions def __enter__(self): 52*19c3b8c2SApple OSS Distributions self._oldHeader = self._O._header 53*19c3b8c2SApple OSS Distributions self._oldLastHeader = self._O._lastHeader 54*19c3b8c2SApple OSS Distributions self._O._header = self._header 55*19c3b8c2SApple OSS Distributions self._O._lastHeader = None 56*19c3b8c2SApple OSS Distributions if self._indent: 57*19c3b8c2SApple OSS Distributions self._O._indent += ' ' 58*19c3b8c2SApple OSS Distributions 59*19c3b8c2SApple OSS Distributions def __exit__(self, exc_type, exc_value, traceback): 60*19c3b8c2SApple OSS Distributions self._O._header = self._oldHeader 61*19c3b8c2SApple OSS Distributions self._O._lastHeader = self._oldLastHeader 62*19c3b8c2SApple OSS Distributions if self._indent: 63*19c3b8c2SApple OSS Distributions self._O._indent = self._O._indent[:-4] 64*19c3b8c2SApple OSS Distributions 65*19c3b8c2SApple OSS Distributionsclass VT(object): 66*19c3b8c2SApple OSS Distributions Black = "\033[38;5;0m" 67*19c3b8c2SApple OSS Distributions DarkRed = "\033[38;5;1m" 68*19c3b8c2SApple OSS Distributions DarkGreen = "\033[38;5;2m" 69*19c3b8c2SApple OSS Distributions Brown = "\033[38;5;3m" 70*19c3b8c2SApple OSS Distributions DarkBlue = "\033[38;5;4m" 71*19c3b8c2SApple OSS Distributions DarkMagenta = "\033[38;5;5m" 72*19c3b8c2SApple OSS Distributions DarkCyan = "\033[38;5;6m" 73*19c3b8c2SApple OSS Distributions Grey = "\033[38;5;7m" 74*19c3b8c2SApple OSS Distributions 75*19c3b8c2SApple OSS Distributions DarkGrey = "\033[38;5;8m" 76*19c3b8c2SApple OSS Distributions Red = "\033[38;5;9m" 77*19c3b8c2SApple OSS Distributions Green = "\033[38;5;10m" 78*19c3b8c2SApple OSS Distributions Yellow = "\033[38;5;11m" 79*19c3b8c2SApple OSS Distributions Blue = "\033[38;5;12m" 80*19c3b8c2SApple OSS Distributions Magenta = "\033[38;5;13m" 81*19c3b8c2SApple OSS Distributions Cyan = "\033[38;5;14m" 82*19c3b8c2SApple OSS Distributions White = "\033[38;5;15m" 83*19c3b8c2SApple OSS Distributions 84*19c3b8c2SApple OSS Distributions Default = "\033[39m" 85*19c3b8c2SApple OSS Distributions 86*19c3b8c2SApple OSS Distributions Bold = "\033[1m" 87*19c3b8c2SApple OSS Distributions EndBold = "\033[22m" 88*19c3b8c2SApple OSS Distributions 89*19c3b8c2SApple OSS Distributions Oblique = "\033[3m" 90*19c3b8c2SApple OSS Distributions EndOblique = "\033[23m" 91*19c3b8c2SApple OSS Distributions 92*19c3b8c2SApple OSS Distributions Underline = "\033[4m" 93*19c3b8c2SApple OSS Distributions EndUnderline = "\033[24m" 94*19c3b8c2SApple OSS Distributions 95*19c3b8c2SApple OSS Distributions Reset = "\033[0m" 96*19c3b8c2SApple OSS Distributions 97*19c3b8c2SApple OSS Distributionsclass NOVT(object): 98*19c3b8c2SApple OSS Distributions def __getattribute__(self, *args): 99*19c3b8c2SApple OSS Distributions return "" 100*19c3b8c2SApple OSS Distributions 101*19c3b8c2SApple OSS Distributionsclass CommandOutput(object): 102*19c3b8c2SApple OSS Distributions """ 103*19c3b8c2SApple OSS Distributions An output handler for all commands. Use Output.print to direct all output of macro via the handler. 104*19c3b8c2SApple OSS Distributions These arguments are passed after a "--". eg 105*19c3b8c2SApple OSS Distributions (lldb) zprint -- -o /tmp/zprint.out.txt 106*19c3b8c2SApple OSS Distributions 107*19c3b8c2SApple OSS Distributions Currently this provide capabilities 108*19c3b8c2SApple OSS Distributions -h show help 109*19c3b8c2SApple OSS Distributions -o path/to/filename 110*19c3b8c2SApple OSS Distributions The output of this command execution will be saved to file. Parser information or errors will 111*19c3b8c2SApple OSS Distributions not be sent to file though. eg /tmp/output.txt 112*19c3b8c2SApple OSS Distributions -s filter_string 113*19c3b8c2SApple OSS Distributions the "filter_string" param is parsed to python regex expression and each line of output 114*19c3b8c2SApple OSS Distributions will be printed/saved only if it matches the expression. 115*19c3b8c2SApple OSS Distributions The command header will not be filtered in any case. 116*19c3b8c2SApple OSS Distributions -p <plugin_name> 117*19c3b8c2SApple OSS Distributions Send the output of the command to plugin. 118*19c3b8c2SApple OSS Distributions -v ... 119*19c3b8c2SApple OSS Distributions Up verbosity 120*19c3b8c2SApple OSS Distributions -c <always|never|auto> 121*19c3b8c2SApple OSS Distributions configure color 122*19c3b8c2SApple OSS Distributions """ 123*19c3b8c2SApple OSS Distributions def __init__(self, cmd_name, CommandResult=None, fhandle=None): 124*19c3b8c2SApple OSS Distributions """ Create a new instance to handle command output. 125*19c3b8c2SApple OSS Distributions params: 126*19c3b8c2SApple OSS Distributions CommandResult : SBCommandReturnObject result param from lldb's command invocation. 127*19c3b8c2SApple OSS Distributions """ 128*19c3b8c2SApple OSS Distributions self.fname=None 129*19c3b8c2SApple OSS Distributions self.fhandle=fhandle 130*19c3b8c2SApple OSS Distributions self.FILTER=False 131*19c3b8c2SApple OSS Distributions self.pluginRequired = False 132*19c3b8c2SApple OSS Distributions self.pluginName = None 133*19c3b8c2SApple OSS Distributions self.cmd_name = cmd_name 134*19c3b8c2SApple OSS Distributions self.resultObj = CommandResult 135*19c3b8c2SApple OSS Distributions self.verbose_level = 0 136*19c3b8c2SApple OSS Distributions self.target_cmd_args = [] 137*19c3b8c2SApple OSS Distributions self.target_cmd_options = {} 138*19c3b8c2SApple OSS Distributions self.color = None 139*19c3b8c2SApple OSS Distributions self.isatty = os.isatty(sys.__stdout__.fileno()) 140*19c3b8c2SApple OSS Distributions self._indent = '' 141*19c3b8c2SApple OSS Distributions self._buffer = '' 142*19c3b8c2SApple OSS Distributions 143*19c3b8c2SApple OSS Distributions self._header = None 144*19c3b8c2SApple OSS Distributions self._lastHeader = None 145*19c3b8c2SApple OSS Distributions self._line = 0 146*19c3b8c2SApple OSS Distributions 147*19c3b8c2SApple OSS Distributions def _write(self, s): 148*19c3b8c2SApple OSS Distributions if self.fhandle != None: 149*19c3b8c2SApple OSS Distributions self.fhandle.write(self._indent + s + "\n") 150*19c3b8c2SApple OSS Distributions else: 151*19c3b8c2SApple OSS Distributions self.resultObj.AppendMessage(self._indent + s) 152*19c3b8c2SApple OSS Distributions self._line += 1 153*19c3b8c2SApple OSS Distributions 154*19c3b8c2SApple OSS Distributions def _doColor(self): 155*19c3b8c2SApple OSS Distributions if self.color is True: 156*19c3b8c2SApple OSS Distributions return True; 157*19c3b8c2SApple OSS Distributions return self.color is None and self.isatty 158*19c3b8c2SApple OSS Distributions 159*19c3b8c2SApple OSS Distributions def _needsHeader(self): 160*19c3b8c2SApple OSS Distributions if self._header is None: 161*19c3b8c2SApple OSS Distributions return False 162*19c3b8c2SApple OSS Distributions if self._lastHeader is None: 163*19c3b8c2SApple OSS Distributions return True 164*19c3b8c2SApple OSS Distributions if not self.isatty: 165*19c3b8c2SApple OSS Distributions return False 166*19c3b8c2SApple OSS Distributions return self._line - self._lastHeader > 40 167*19c3b8c2SApple OSS Distributions 168*19c3b8c2SApple OSS Distributions def indent(self): 169*19c3b8c2SApple OSS Distributions return IndentScope(self) 170*19c3b8c2SApple OSS Distributions 171*19c3b8c2SApple OSS Distributions def table(self, header, indent = False): 172*19c3b8c2SApple OSS Distributions return HeaderScope(self, header, indent) 173*19c3b8c2SApple OSS Distributions 174*19c3b8c2SApple OSS Distributions def format(self, s, *args, **kwargs): 175*19c3b8c2SApple OSS Distributions if self._doColor(): 176*19c3b8c2SApple OSS Distributions kwargs['VT'] = VT 177*19c3b8c2SApple OSS Distributions else: 178*19c3b8c2SApple OSS Distributions kwargs['VT'] = NOVT() 179*19c3b8c2SApple OSS Distributions 180*19c3b8c2SApple OSS Distributions return s.format(*args, **kwargs) 181*19c3b8c2SApple OSS Distributions 182*19c3b8c2SApple OSS Distributions def error(self, s, *args, **kwargs): 183*19c3b8c2SApple OSS Distributions print(self.format("{cmd.cmd_name}: {VT.Red}"+s+"{VT.Default}", cmd=self, *args, **kwargs)) 184*19c3b8c2SApple OSS Distributions 185*19c3b8c2SApple OSS Distributions def write(self, s): 186*19c3b8c2SApple OSS Distributions """ Handler for all commands output. By default just print to stdout """ 187*19c3b8c2SApple OSS Distributions 188*19c3b8c2SApple OSS Distributions s = self._buffer + s 189*19c3b8c2SApple OSS Distributions 190*19c3b8c2SApple OSS Distributions while s.find('\n') != -1: 191*19c3b8c2SApple OSS Distributions l, s = s.split("\n", 1) 192*19c3b8c2SApple OSS Distributions if self.FILTER: 193*19c3b8c2SApple OSS Distributions if not self.reg.search(l): 194*19c3b8c2SApple OSS Distributions continue 195*19c3b8c2SApple OSS Distributions if self._doColor(): 196*19c3b8c2SApple OSS Distributions l = self.reg.sub(VT.Underline + r"\g<0>" + VT.EndUnderline, l); 197*19c3b8c2SApple OSS Distributions 198*19c3b8c2SApple OSS Distributions if len(l) and self._needsHeader(): 199*19c3b8c2SApple OSS Distributions for hdr in self._header.split("\n"): 200*19c3b8c2SApple OSS Distributions self._write(self.format("{VT.Bold}{:s}{VT.EndBold}", hdr)) 201*19c3b8c2SApple OSS Distributions self._lastHeader = self._line 202*19c3b8c2SApple OSS Distributions 203*19c3b8c2SApple OSS Distributions self._write(l) 204*19c3b8c2SApple OSS Distributions 205*19c3b8c2SApple OSS Distributions self._buffer = s 206*19c3b8c2SApple OSS Distributions 207*19c3b8c2SApple OSS Distributions def flush(self): 208*19c3b8c2SApple OSS Distributions if self.fhandle != None: 209*19c3b8c2SApple OSS Distributions self.fhandle.flush() 210*19c3b8c2SApple OSS Distributions 211*19c3b8c2SApple OSS Distributions def __del__(self): 212*19c3b8c2SApple OSS Distributions """ closes any open files. report on any errors """ 213*19c3b8c2SApple OSS Distributions if self.fhandle != None and self.fname != None: 214*19c3b8c2SApple OSS Distributions self.fhandle.close() 215*19c3b8c2SApple OSS Distributions 216*19c3b8c2SApple OSS Distributions def setOptions(self, cmdargs, cmdoptions =''): 217*19c3b8c2SApple OSS Distributions """ parse the arguments passed to the command 218*19c3b8c2SApple OSS Distributions param : 219*19c3b8c2SApple OSS Distributions cmdargs => [] of <str> (typically args.split()) 220*19c3b8c2SApple OSS Distributions cmdoptions : str - string of command level options. 221*19c3b8c2SApple OSS Distributions These should be CAPITAL LETTER options only. 222*19c3b8c2SApple OSS Distributions """ 223*19c3b8c2SApple OSS Distributions opts=() 224*19c3b8c2SApple OSS Distributions args = cmdargs 225*19c3b8c2SApple OSS Distributions cmdoptions = cmdoptions.upper() 226*19c3b8c2SApple OSS Distributions try: 227*19c3b8c2SApple OSS Distributions opts,args = getopt.gnu_getopt(args,'hvo:s:p:c:'+ cmdoptions,[]) 228*19c3b8c2SApple OSS Distributions self.target_cmd_args = args 229*19c3b8c2SApple OSS Distributions except getopt.GetoptError as err: 230*19c3b8c2SApple OSS Distributions raise ArgumentError(str(err)) 231*19c3b8c2SApple OSS Distributions #continue with processing 232*19c3b8c2SApple OSS Distributions for o,a in opts : 233*19c3b8c2SApple OSS Distributions if o == "-h": 234*19c3b8c2SApple OSS Distributions # This is misuse of exception but 'self' has no info on doc string. 235*19c3b8c2SApple OSS Distributions # The caller may handle exception and display appropriate info 236*19c3b8c2SApple OSS Distributions raise ArgumentError("HELP") 237*19c3b8c2SApple OSS Distributions if o == "-o" and len(a) > 0: 238*19c3b8c2SApple OSS Distributions self.fname=os.path.normpath(os.path.expanduser(a.strip())) 239*19c3b8c2SApple OSS Distributions self.fhandle=open(self.fname,"w") 240*19c3b8c2SApple OSS Distributions print("saving results in file ",str(a)) 241*19c3b8c2SApple OSS Distributions self.fhandle.write("(lldb)%s %s \n" % (self.cmd_name, " ".join(cmdargs))) 242*19c3b8c2SApple OSS Distributions self.isatty = os.isatty(self.fhandle.fileno()) 243*19c3b8c2SApple OSS Distributions elif o == "-s" and len(a) > 0: 244*19c3b8c2SApple OSS Distributions self.reg = re.compile(a.strip(),re.MULTILINE|re.DOTALL) 245*19c3b8c2SApple OSS Distributions self.FILTER=True 246*19c3b8c2SApple OSS Distributions print("showing results for regex:",a.strip()) 247*19c3b8c2SApple OSS Distributions elif o == "-p" and len(a) > 0: 248*19c3b8c2SApple OSS Distributions self.pluginRequired = True 249*19c3b8c2SApple OSS Distributions self.pluginName = a.strip() 250*19c3b8c2SApple OSS Distributions #print "passing output to " + a.strip() 251*19c3b8c2SApple OSS Distributions elif o == "-v": 252*19c3b8c2SApple OSS Distributions self.verbose_level += 1 253*19c3b8c2SApple OSS Distributions elif o == "-c": 254*19c3b8c2SApple OSS Distributions if a in ["always", '1']: 255*19c3b8c2SApple OSS Distributions self.color = True 256*19c3b8c2SApple OSS Distributions elif a in ["never", '0']: 257*19c3b8c2SApple OSS Distributions self.color = False 258*19c3b8c2SApple OSS Distributions else: 259*19c3b8c2SApple OSS Distributions self.color = None 260*19c3b8c2SApple OSS Distributions else: 261*19c3b8c2SApple OSS Distributions o = o.strip() 262*19c3b8c2SApple OSS Distributions self.target_cmd_options[o] = a 263*19c3b8c2SApple OSS Distributions 264*19c3b8c2SApple OSS Distributions 265