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