gdbcon.pp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. {
  2. Copyright (c) 1998 by Peter Vreman
  3. Lowlevel GDB interface which communicates directly with libgdb
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit GDBCon;
  11. interface
  12. uses
  13. GDBInt;
  14. type
  15. PGDBController=^TGDBController;
  16. TGDBController=object(TGDBInterface)
  17. progname,
  18. progdir,
  19. progargs : pchar;
  20. start_break_number,
  21. in_command,
  22. init_count : longint;
  23. constructor Init;
  24. destructor Done;
  25. procedure CommandBegin(const s:string);virtual;
  26. procedure Command(const s:string);
  27. procedure CommandEnd(const s:string);virtual;
  28. procedure Reset;virtual;
  29. { tracing }
  30. procedure StartTrace;
  31. procedure Run;virtual;
  32. procedure TraceStep;virtual;
  33. procedure TraceNext;virtual;
  34. procedure TraceStepI;virtual;
  35. procedure TraceNextI;virtual;
  36. procedure Continue;virtual;
  37. { needed for dos because newlines are only #10 (PM) }
  38. procedure WriteErrorBuf;
  39. procedure WriteOutputBuf;
  40. function GetOutput : Pchar;
  41. function GetError : Pchar;
  42. function LoadFile(var fn:string):boolean;
  43. procedure SetDir(const s : string);
  44. procedure SetArgs(const s : string);
  45. procedure ClearSymbols;
  46. end;
  47. procedure UnixDir(var s : string);
  48. implementation
  49. uses
  50. {$ifdef win32}
  51. windows,
  52. {$endif win32}
  53. dos,
  54. strings;
  55. {$ifdef win32}
  56. const
  57. CygDrivePrefixKey1 = 'Software';
  58. CygDrivePrefixKey2 = 'Cygnus Solutions';
  59. CygDrivePrefixKey3 = 'Cygwin';
  60. CygDrivePrefixKey4 = 'mounts v2';
  61. CygDrivePrefixKey = 'cygdrive prefix';
  62. function CygDrivePrefix : string;
  63. var
  64. i : longint;
  65. length : dword;
  66. Value : pchar;
  67. _type : dword;
  68. Key,NKey : HKey;
  69. begin
  70. Length:=0;
  71. Key:=HKEY_CURRENT_USER;
  72. i := RegOpenKeyEx(Key, CygDrivePrefixKey1, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  73. if i=ERROR_SUCCESS then
  74. begin
  75. Key:=NKey;
  76. i := RegOpenKeyEx(Key, CygDrivePrefixKey2, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  77. end;
  78. if i=ERROR_SUCCESS then
  79. begin
  80. RegCloseKey(Key);
  81. Key:=NKey;
  82. i := RegOpenKeyEx(Key, CygDrivePrefixKey3, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  83. end;
  84. if i=ERROR_SUCCESS then
  85. begin
  86. RegCloseKey(Key);
  87. Key:=NKey;
  88. i := RegOpenKeyEx(Key, CygDrivePrefixKey4, 0, KEY_ENUMERATE_SUB_KEYS, @NKey);
  89. end;
  90. if i=ERROR_SUCCESS then
  91. begin
  92. RegCloseKey(Key);
  93. Key:=NKey;
  94. i := RegQueryValueEx( Key, CygDrivePrefixKey, nil, @_type, nil, @length);
  95. end;
  96. if i<>ERROR_SUCCESS then
  97. CygDrivePrefix:='/cygdrive'
  98. else
  99. Begin
  100. GetMem(Value,Length);
  101. i := RegQueryValueEx( Key, CygDrivePrefixKey, nil, @_type, LPByte(Value), @length);
  102. if i<>ERROR_SUCCESS then
  103. CygDrivePrefix:='/cygdrive'
  104. else
  105. CygDrivePrefix:=StrPas(Value);
  106. FreeMem(Value,Length);
  107. End;
  108. if Key<>HKEY_CURRENT_USER then
  109. RegCloseKey(Key);
  110. end;
  111. {$endif win32}
  112. procedure UnixDir(var s : string);
  113. var i : longint;
  114. begin
  115. for i:=1 to length(s) do
  116. if s[i]='\' then
  117. {$ifdef win32}
  118. { Don't touch at '\ ' used to escapes spaces in windows file names PM }
  119. if (i=length(s)) or (s[i+1]<>' ') then
  120. {$endif win32}
  121. s[i]:='/';
  122. {$ifdef win32}
  123. {$ifndef USE_MINGW_GDB}
  124. { for win32 we should convert e:\ into //e/ PM }
  125. if (length(s)>2) and (s[2]=':') and (s[3]='/') then
  126. s:=CygDrivePrefix+'/'+s[1]+copy(s,3,length(s));
  127. {$endif USE_MINGW_GDB}
  128. {$endif win32}
  129. end;
  130. constructor TGDBController.Init;
  131. begin
  132. inherited init;
  133. end;
  134. destructor TGDBController.Done;
  135. begin
  136. if assigned(progname) then
  137. strdispose(progname);
  138. if assigned(progdir) then
  139. strdispose(progdir);
  140. if assigned(progargs) then
  141. strdispose(progargs);
  142. inherited done;
  143. end;
  144. procedure TGDBController.Command(const s:string);
  145. begin
  146. inc(in_command);
  147. CommandBegin(s);
  148. gdboutputbuf.reset;
  149. gdberrorbuf.reset;
  150. gdb_command(s);
  151. {
  152. What is that for ?? PM
  153. I had to comment it because
  154. it resets the debuggere after each command !!
  155. Maybe it can happen on errors ??
  156. if in_command<0 then
  157. begin
  158. in_command:=0;
  159. inc(in_command);
  160. Reset;
  161. dec(in_command);
  162. end; }
  163. CommandEnd(s);
  164. dec(in_command);
  165. end;
  166. procedure TGDBController.CommandBegin(const s:string);
  167. begin
  168. end;
  169. procedure TGDBController.CommandEnd(const s:string);
  170. begin
  171. end;
  172. function TGDBController.LoadFile(var fn:string):boolean;
  173. var
  174. cmd : string;
  175. begin
  176. getdir(0,cmd);
  177. UnixDir(cmd);
  178. cmd:='cd '+cmd;
  179. Command(cmd);
  180. GDB__Init;
  181. UnixDir(fn);
  182. if assigned(progname) then
  183. strdispose(progname);
  184. getmem(progname,length(fn)+1);
  185. strpcopy(progname,fn);
  186. if fn<>'' then
  187. Command('file '+fn);
  188. LoadFile:=true;
  189. end;
  190. procedure TGDBController.SetDir(const s : string);
  191. var
  192. hs : string;
  193. begin
  194. hs:=s;
  195. UnixDir(hs);
  196. if assigned(progdir) then
  197. strdispose(progdir);
  198. getmem(progdir,length(hs)+1);
  199. strpcopy(progdir,hs);
  200. command('cd '+hs);
  201. end;
  202. procedure TGDBController.SetArgs(const s : string);
  203. begin
  204. if assigned(progargs) then
  205. strdispose(progargs);
  206. getmem(progargs,length(s)+1);
  207. strpcopy(progargs,s);
  208. command('set args '+s);
  209. end;
  210. procedure TGDBController.Reset;
  211. begin
  212. call_reset:=false;
  213. { DeleteBreakPoints(); }
  214. if debuggee_started then
  215. begin
  216. reset_command:=true;
  217. BreakSession;
  218. Command('kill');
  219. reset_command:=false;
  220. debuggee_started:=false;
  221. end;
  222. end;
  223. procedure TGDBController.StartTrace;
  224. begin
  225. Command('tbreak PASCALMAIN');
  226. start_break_number:=last_breakpoint_number;
  227. Run;
  228. end;
  229. procedure TGDBController.Run;
  230. begin
  231. Command('run');
  232. inc(init_count);
  233. end;
  234. procedure TGDBController.TraceStep;
  235. begin
  236. Command('step');
  237. end;
  238. procedure TGDBController.TraceNext;
  239. begin
  240. Command('next');
  241. end;
  242. procedure TGDBController.TraceStepI;
  243. begin
  244. Command('stepi');
  245. end;
  246. procedure TGDBController.TraceNextI;
  247. begin
  248. Command('nexti');
  249. end;
  250. procedure TGDBController.Continue;
  251. begin
  252. Command('continue');
  253. end;
  254. procedure TGDBController.ClearSymbols;
  255. begin
  256. if debuggee_started then
  257. Reset;
  258. if init_count>0 then
  259. Command('file');
  260. end;
  261. procedure BufWrite(Buf : pchar);
  262. var p,pe : pchar;
  263. begin
  264. p:=buf;
  265. While assigned(p) do
  266. begin
  267. pe:=strscan(p,#10);
  268. if pe<>nil then
  269. pe^:=#0;
  270. Writeln(p);
  271. { restore for dispose }
  272. if pe<>nil then
  273. pe^:=#10;
  274. if pe=nil then
  275. p:=nil
  276. else
  277. begin
  278. p:=pe;
  279. inc(p);
  280. end;
  281. end;
  282. end;
  283. function TGDBController.GetOutput : Pchar;
  284. begin
  285. GetOutput:=gdboutputbuf.buf;
  286. end;
  287. function TGDBController.GetError : Pchar;
  288. var p : pchar;
  289. begin
  290. p:=gdberrorbuf.buf;
  291. if (p^=#0) and got_error then
  292. GetError:=pchar(ptrint(gdboutputbuf.buf)+gdboutputbuf.idx)
  293. else
  294. GetError:=p;
  295. end;
  296. procedure TGDBController.WriteErrorBuf;
  297. begin
  298. BufWrite(gdberrorbuf.buf);
  299. end;
  300. procedure TGDBController.WriteOutputBuf;
  301. begin
  302. BufWrite(gdboutputbuf.buf);
  303. end;
  304. end.