001 package nl.cwi.sen1.tide.adapters.gdb; 002 003 import java.io.BufferedReader; 004 import java.io.File; 005 import java.io.IOException; 006 import java.io.InputStreamReader; 007 import java.io.OutputStreamWriter; 008 import java.io.Writer; 009 import java.util.Iterator; 010 011 import nl.cwi.sen1.tide.adapters.DebugAdapter; 012 import nl.cwi.sen1.tide.adapters.DebugAdapterRule; 013 import aterm.ATermFactory; 014 import aterm.pure.PureFactory; 015 016 public class GdbAdapter extends DebugAdapter { 017 static public final int MODE_STEP_INTO = 0; 018 static public final int MODE_STEP_OVER = 1; 019 static public final int MODE_RUN = 2; 020 021 private String name; 022 private GdbProcess process; 023 024 private BufferedReader input; 025 private BufferedReader error; 026 private Writer output; 027 028 static public final void main(String[] args) throws IOException { 029 int pid = -1; 030 int port = 9500; 031 String program = null; 032 String arguments = ""; 033 ATermFactory factory = new PureFactory(); 034 035 for (int i = 0; i < args.length; i++) { 036 if (args[i].equals("-attach")) { 037 pid = Integer.parseInt(args[++i]); 038 } else if (args[i].equals("-program")) { 039 program = args[++i]; 040 } else if (args[i].equals("-help")) { 041 usage(); 042 } else if (args[i].equals("-args")) { 043 arguments = arguments + " " + args[++i]; 044 } else if (args[i].equals("-port")) { 045 port = Integer.parseInt(args[++i]); 046 } 047 } 048 049 if (program == null) { 050 usage(); 051 } 052 053 // String cmd = "gdb -interpreter=mi -f -q " + program; 054 String cmd = "gdb -f -q " + program; 055 if (pid >= 0) { 056 cmd += " " + pid; 057 } 058 059 Process process = Runtime.getRuntime().exec(cmd); 060 debugMsg("gdb started"); 061 GdbAdapter adapter = new GdbAdapter(factory, program, args, arguments, process, port); 062 adapter.run(); 063 } 064 065 static void usage() { 066 System.err.println( 067 "usage: tide-gdb -port <tide-port> -program <prg> [-attach <pid>]"); 068 System.exit(1); 069 } 070 071 static private void debugMsg(String msg) { 072 System.err.println(msg); 073 } 074 075 public GdbAdapter( 076 ATermFactory factory, 077 String filename, 078 String[] args, 079 String processArguments, 080 Process proc, 081 int port) 082 throws IOException { 083 super(factory, args, port); 084 085 File file = new File(filename); 086 this.name = file.getName(); 087 088 createGdbIOReaders(proc); 089 buildGdbConnection(processArguments, name); 090 run(); 091 } 092 093 private void buildGdbConnection(String args, String name) { 094 writeln("set args " + args); 095 writeln("set prompt (gdb)\\n"); 096 writeln("define hook-stop"); 097 writeln("bt -1"); 098 writeln("end"); 099 100 process = new GdbProcess(this,name); 101 102 evaluate(new SetBreakpointCmd(this, "main")); 103 evaluate(new ContinueCmd(this, process) { 104 public String command() { 105 return "run\n"; 106 } 107 }); 108 evaluate(new RetrievePidCmd(this, process)); 109 110 processCreated(process); 111 } 112 113 private void createGdbIOReaders(Process proc) { 114 input = new BufferedReader(new InputStreamReader(proc.getInputStream())); 115 error = new BufferedReader(new InputStreamReader(proc.getErrorStream())); 116 output = new OutputStreamWriter(proc.getOutputStream()); 117 } 118 119 public void writeln(String line) { 120 try { 121 output.write(line); 122 output.write("\n"); 123 output.flush(); 124 } catch (IOException e) { 125 debugMsg("connection with gdb broken!"); 126 } 127 } 128 public void evaluate(Command cmd) { 129 try { 130 String string = cmd.command(); 131 debugMsg("entering poll mode with gdb command:\n\t" + string); 132 output.write(string); 133 output.flush(); 134 String line; 135 do { 136 line = input.readLine(); 137 debugMsg("processing line in poll mode:\n\t" + line); 138 if (line.length() == 0) { 139 continue; // Ignore empty lines 140 } else if (line.startsWith("(gdb)")) { 141 continue; // Ignore prompt 142 } else if (line.startsWith("Starting program:")) { 143 continue; // Ignore 'Starting program:' line 144 } 145 } while (!cmd.response(line)); 146 debugMsg("poll mode done!"); 147 } catch (IOException e) { 148 debugMsg("connection with GDB broken."); 149 System.exit(1); 150 } 151 } 152 153 public int calcRunMode() { 154 if (process.rulesPerPort[DebugAdapterRule.PORT_STEP].size() == 0) { 155 return MODE_RUN; 156 } 157 158 // Look for any 'non step-over' rules 159 Iterator<DebugAdapterRule> iter = process.rulesPerPort[DebugAdapterRule.PORT_STEP].iterator(); 160 while (iter.hasNext()) { 161 DebugAdapterRule rule = iter.next(); 162 if (!rule.isStepOver()) { 163 return MODE_STEP_INTO; 164 } 165 } 166 167 return MODE_STEP_OVER; 168 } 169 }