gdbcon.pp 6.9 KB

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