dbgbase.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. {
  2. Copyright (c) 2003-2006 by Peter Vreman and Florian Klaempfl
  3. This units contains the base class for debug info generation
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit dbgbase;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,
  22. systems,
  23. parabase,
  24. symconst,symbase,symdef,symtype,symsym,
  25. fmodule,
  26. aasmtai,aasmdata;
  27. type
  28. TDebugInfo=class
  29. protected
  30. { definitions }
  31. { collect all defs in one list so we can reset them easily }
  32. defnumberlist : TFPObjectList;
  33. deftowritelist : TFPObjectList;
  34. procedure appenddef(list:TAsmList;def:tdef);
  35. procedure beforeappenddef(list:TAsmList;def:tdef);virtual;
  36. procedure afterappenddef(list:TAsmList;def:tdef);virtual;
  37. procedure appenddef_ord(list:TAsmList;def:torddef);virtual;
  38. procedure appenddef_float(list:TAsmList;def:tfloatdef);virtual;
  39. procedure appenddef_file(list:TAsmList;def:tfiledef);virtual;
  40. procedure appenddef_enum(list:TAsmList;def:tenumdef);virtual;
  41. procedure appenddef_array(list:TAsmList;def:tarraydef);virtual;
  42. procedure appenddef_record(list:TAsmList;def:trecorddef);virtual;
  43. procedure appenddef_object(list:TAsmList;def:tobjectdef);virtual;
  44. procedure appenddef_classref(list:TAsmList;def: tclassrefdef);virtual;
  45. procedure appenddef_pointer(list:TAsmList;def:tpointerdef);virtual;
  46. procedure appenddef_string(list:TAsmList;def:tstringdef);virtual;
  47. procedure appenddef_procvar(list:TAsmList;def:tprocvardef);virtual;
  48. procedure appenddef_variant(list:TAsmList;def:tvariantdef);virtual;
  49. procedure appenddef_set(list:TAsmList;def:tsetdef);virtual;
  50. procedure appenddef_formal(list:TAsmList;def:tformaldef);virtual;
  51. procedure appenddef_undefined(list:TAsmList;def: tundefineddef);virtual;
  52. procedure appendprocdef(list:TAsmList;def:tprocdef);virtual;
  53. procedure write_remaining_defs_to_write(list:TAsmList);
  54. { symbols }
  55. procedure appendsym(list:TAsmList;sym:tsym);
  56. procedure beforeappendsym(list:TAsmList;sym:tsym);virtual;
  57. procedure afterappendsym(list:TAsmList;sym:tsym);virtual;
  58. procedure appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);virtual;
  59. procedure appendsym_paravar(list:TAsmList;sym:tparavarsym);virtual;
  60. procedure appendsym_localvar(list:TAsmList;sym:tlocalvarsym);virtual;
  61. procedure appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);virtual;
  62. procedure appendsym_unit(list:TAsmList;sym:tunitsym);virtual;
  63. procedure appendsym_const(list:TAsmList;sym:tconstsym);virtual;
  64. procedure appendsym_type(list:TAsmList;sym:ttypesym);virtual;
  65. procedure appendsym_label(list:TAsmList;sym:tlabelsym);virtual;
  66. procedure appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);virtual;
  67. procedure appendsym_property(list:TAsmList;sym:tpropertysym);virtual;
  68. { symtable }
  69. procedure write_symtable_parasyms(list:TAsmList;paras: tparalist);
  70. procedure write_symtable_syms(list:TAsmList;st:TSymtable);
  71. procedure write_symtable_defs(list:TAsmList;st:TSymtable);
  72. procedure write_symtable_procdefs(list:TAsmList;st:TSymtable);
  73. procedure reset_unit_type_info;
  74. procedure write_used_unit_type_info(list:TAsmList;hp:tmodule);
  75. public
  76. constructor Create;virtual;
  77. procedure inserttypeinfo;virtual;
  78. procedure insertmoduleinfo;virtual;
  79. procedure insertlineinfo(list:TAsmList);virtual;
  80. procedure referencesections(list:TAsmList);virtual;
  81. end;
  82. TDebugInfoClass=class of TDebugInfo;
  83. var
  84. CDebugInfo : array[tdbg] of TDebugInfoClass;
  85. current_debuginfo : tdebuginfo;
  86. procedure InitDebugInfo(hp:tmodule; restore_current_debuginfo : boolean);
  87. procedure DoneDebugInfo(hp:tmodule;var current_debuginfo_reset : boolean);
  88. procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
  89. implementation
  90. uses
  91. cutils,
  92. verbose;
  93. constructor TDebugInfo.Create;
  94. begin
  95. end;
  96. procedure TDebugInfo.insertmoduleinfo;
  97. begin
  98. end;
  99. procedure TDebugInfo.inserttypeinfo;
  100. begin
  101. end;
  102. procedure TDebugInfo.insertlineinfo(list:TAsmList);
  103. begin
  104. end;
  105. procedure TDebugInfo.referencesections(list:TAsmList);
  106. begin
  107. end;
  108. {**************************************
  109. Definition
  110. **************************************}
  111. procedure TDebugInfo.appendprocdef(list:TAsmList;def:tprocdef);
  112. begin
  113. end;
  114. procedure TDebugInfo.beforeappenddef(list:TAsmList;def:tdef);
  115. begin
  116. end;
  117. procedure TDebugInfo.afterappenddef(list:TAsmList;def:tdef);
  118. begin
  119. end;
  120. procedure TDebugInfo.appenddef_ord(list:TAsmList;def:torddef);
  121. begin
  122. end;
  123. procedure TDebugInfo.appenddef_float(list:TAsmList;def:tfloatdef);
  124. begin
  125. end;
  126. procedure TDebugInfo.appenddef_formal(list:TAsmList;def: tformaldef);
  127. begin
  128. end;
  129. procedure TDebugInfo.appenddef_undefined(list:TAsmList;def: tundefineddef);
  130. begin
  131. end;
  132. procedure TDebugInfo.appenddef_set(list:TAsmList;def: tsetdef);
  133. begin
  134. end;
  135. procedure TDebugInfo.appenddef_object(list:TAsmList;def: tobjectdef);
  136. begin
  137. end;
  138. procedure TDebugInfo.appenddef_classref(list:TAsmList;def: tclassrefdef);
  139. begin
  140. appenddef_pointer(list,tpointerdef(pvmttype));
  141. end;
  142. procedure TDebugInfo.appenddef_variant(list:TAsmList;def: tvariantdef);
  143. begin
  144. end;
  145. procedure TDebugInfo.appenddef_enum(list:TAsmList;def:tenumdef);
  146. begin
  147. end;
  148. procedure TDebugInfo.appenddef_file(list:TAsmList;def: tfiledef);
  149. begin
  150. end;
  151. procedure TDebugInfo.appenddef_array(list:TAsmList;def:tarraydef);
  152. begin
  153. end;
  154. procedure TDebugInfo.appenddef_record(list:TAsmList;def:trecorddef);
  155. begin
  156. end;
  157. procedure TDebugInfo.appenddef_pointer(list:TAsmList;def:tpointerdef);
  158. begin
  159. end;
  160. procedure TDebugInfo.appenddef_string(list:TAsmList;def:tstringdef);
  161. begin
  162. end;
  163. procedure TDebugInfo.appenddef_procvar(list:TAsmList;def:tprocvardef);
  164. begin
  165. end;
  166. procedure TDebugInfo.appenddef(list:TAsmList;def:tdef);
  167. begin
  168. if (def.dbg_state in [dbg_state_writing,dbg_state_written]) then
  169. exit;
  170. { never write generic template defs }
  171. if df_generic in def.defoptions then
  172. begin
  173. def.dbg_state:=dbg_state_written;
  174. exit;
  175. end;
  176. { to avoid infinite loops }
  177. def.dbg_state := dbg_state_writing;
  178. beforeappenddef(list,def);
  179. { queued defs have to be written later }
  180. if (def.dbg_state=dbg_state_queued) then
  181. exit;
  182. case def.typ of
  183. stringdef :
  184. appenddef_string(list,tstringdef(def));
  185. enumdef :
  186. appenddef_enum(list,tenumdef(def));
  187. orddef :
  188. appenddef_ord(list,torddef(def));
  189. pointerdef :
  190. appenddef_pointer(list,tpointerdef(def));
  191. floatdef :
  192. appenddef_float(list,tfloatdef(def));
  193. filedef :
  194. appenddef_file(list,tfiledef(def));
  195. recorddef :
  196. appenddef_record(list,trecorddef(def));
  197. variantdef :
  198. appenddef_variant(list,tvariantdef(def));
  199. classrefdef :
  200. appenddef_classref(list,tclassrefdef(def));
  201. setdef :
  202. appenddef_set(list,tsetdef(def));
  203. formaldef :
  204. appenddef_formal(list,tformaldef(def));
  205. arraydef :
  206. appenddef_array(list,tarraydef(def));
  207. procvardef :
  208. appenddef_procvar(list,tprocvardef(def));
  209. objectdef :
  210. appenddef_object(list,tobjectdef(def));
  211. undefineddef :
  212. appenddef_undefined(list,tundefineddef(def));
  213. procdef :
  214. begin
  215. { procdefs are already written in a separate step. procdef
  216. support in appenddef is only needed for beforeappenddef to
  217. write all local type defs }
  218. end;
  219. else
  220. internalerror(200601281);
  221. end;
  222. afterappenddef(list,def);
  223. def.dbg_state := dbg_state_written;
  224. end;
  225. procedure TDebugInfo.write_remaining_defs_to_write(list:TAsmList);
  226. var
  227. n : integer;
  228. looplist,
  229. templist: TFPObjectList;
  230. def : tdef;
  231. begin
  232. templist := TFPObjectList.Create(False);
  233. looplist := deftowritelist;
  234. while looplist.count > 0 do
  235. begin
  236. deftowritelist := templist;
  237. for n := 0 to looplist.count - 1 do
  238. begin
  239. def := tdef(looplist[n]);
  240. case def.dbg_state of
  241. dbg_state_written:
  242. continue;
  243. dbg_state_writing:
  244. internalerror(200610052);
  245. dbg_state_unused:
  246. internalerror(200610053);
  247. dbg_state_used:
  248. appenddef(list,def);
  249. dbg_state_queued:
  250. begin
  251. { can happen in case an objectdef was used from another
  252. unit that was compiled without debug info, and we are
  253. using Stabs (which means that parent types have to be
  254. written before child types). In this case, the child
  255. objectdef will be queued and never written, because its
  256. definition is not inside the current unit and hence will
  257. not be encountered }
  258. if def.typ<>objectdef then
  259. internalerror(2012072401);
  260. if not assigned(tobjectdef(def).childof) or
  261. (tobjectdef(def).childof.dbg_state=dbg_state_written) then
  262. appenddef(list,def)
  263. else if tobjectdef(def).childof.dbg_state=dbg_state_queued then
  264. begin
  265. { ensure that the parent is indeed queued }
  266. deftowritelist.add(tobjectdef(def).childof);
  267. deftowritelist.add(def);
  268. end
  269. else if tobjectdef(def).childof.dbg_state=dbg_state_used then
  270. { comes somewhere after the current def in the looplist
  271. and will be written at that point, so we will have to
  272. wait until the next iteration }
  273. deftowritelist.add(def)
  274. else
  275. internalerror(2012072402);
  276. end;
  277. end;
  278. end;
  279. looplist.clear;
  280. templist := looplist;
  281. looplist := deftowritelist;
  282. end;
  283. templist.free;
  284. end;
  285. {**************************************
  286. Symbols
  287. **************************************}
  288. procedure TDebugInfo.beforeappendsym(list:TAsmList;sym:tsym);
  289. begin
  290. end;
  291. procedure TDebugInfo.afterappendsym(list:TAsmList;sym:tsym);
  292. begin
  293. end;
  294. procedure TDebugInfo.appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);
  295. begin
  296. end;
  297. procedure TDebugInfo.appendsym_paravar(list:TAsmList;sym: tparavarsym);
  298. begin
  299. end;
  300. procedure TDebugInfo.appendsym_localvar(list:TAsmList;sym: tlocalvarsym);
  301. begin
  302. end;
  303. procedure TDebugInfo.appendsym_fieldvar(list:TAsmList;sym: tfieldvarsym);
  304. begin
  305. end;
  306. procedure TDebugInfo.appendsym_const(list:TAsmList;sym:tconstsym);
  307. begin
  308. end;
  309. procedure TDebugInfo.appendsym_label(list:TAsmList;sym: tlabelsym);
  310. begin
  311. end;
  312. procedure TDebugInfo.appendsym_property(list:TAsmList;sym: tpropertysym);
  313. begin
  314. end;
  315. procedure TDebugInfo.appendsym_type(list:TAsmList;sym: ttypesym);
  316. begin
  317. end;
  318. procedure TDebugInfo.appendsym_unit(list:TAsmList;sym: tunitsym);
  319. begin
  320. end;
  321. procedure TDebugInfo.appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);
  322. begin
  323. end;
  324. procedure TDebugInfo.appendsym(list:TAsmList;sym:tsym);
  325. begin
  326. if sym.isdbgwritten then
  327. exit;
  328. beforeappendsym(list,sym);
  329. case sym.typ of
  330. staticvarsym :
  331. if not assigned(tstaticvarsym(sym).fieldvarsym) or
  332. not(df_generic in tdef(tstaticvarsym(sym).fieldvarsym.owner.defowner).defoptions) then
  333. appendsym_staticvar(list,tstaticvarsym(sym));
  334. unitsym:
  335. appendsym_unit(list,tunitsym(sym));
  336. labelsym :
  337. appendsym_label(list,tlabelsym(sym));
  338. localvarsym :
  339. appendsym_localvar(list,tlocalvarsym(sym));
  340. paravarsym :
  341. appendsym_paravar(list,tparavarsym(sym));
  342. constsym :
  343. appendsym_const(list,tconstsym(sym));
  344. typesym :
  345. appendsym_type(list,ttypesym(sym));
  346. enumsym :
  347. { ignore enum syms, they are written by the owner }
  348. ;
  349. syssym :
  350. { ignore sys syms, they are only of internal use }
  351. ;
  352. procsym :
  353. { ignore proc syms, they are written by procdefs }
  354. ;
  355. absolutevarsym :
  356. appendsym_absolute(list,tabsolutevarsym(sym));
  357. propertysym :
  358. appendsym_property(list,tpropertysym(sym));
  359. namespacesym :
  360. { ignore namespace syms, they are only of internal use }
  361. ;
  362. else
  363. internalerror(200601242);
  364. end;
  365. afterappendsym(list,sym);
  366. sym.isdbgwritten:=true;
  367. end;
  368. {**************************************
  369. Symtables
  370. **************************************}
  371. procedure TDebugInfo.write_symtable_defs(list:TAsmList;st:TSymtable);
  372. var
  373. def : tdef;
  374. i : longint;
  375. nonewadded : boolean;
  376. begin
  377. case st.symtabletype of
  378. staticsymtable :
  379. list.concat(tai_comment.Create(strpnew('Defs - Begin Staticsymtable')));
  380. globalsymtable :
  381. list.concat(tai_comment.Create(strpnew('Defs - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
  382. else
  383. ;
  384. end;
  385. repeat
  386. nonewadded:=true;
  387. for i:=0 to st.DefList.Count-1 do
  388. begin
  389. def:=tdef(st.DefList[i]);
  390. if (def.dbg_state in [dbg_state_used,dbg_state_queued]) then
  391. begin
  392. appenddef(list,def);
  393. nonewadded:=false;
  394. end;
  395. end;
  396. until nonewadded;
  397. case st.symtabletype of
  398. staticsymtable :
  399. list.concat(tai_comment.Create(strpnew('Defs - End Staticsymtable')));
  400. globalsymtable :
  401. list.concat(tai_comment.Create(strpnew('Defs - End unit '+st.name^+' has index '+tostr(st.moduleid))));
  402. else
  403. ;
  404. end;
  405. end;
  406. procedure TDebugInfo.write_symtable_parasyms(list:TAsmList;paras: tparalist);
  407. var
  408. i : longint;
  409. sym : tsym;
  410. begin
  411. for i:=0 to paras.Count-1 do
  412. begin
  413. sym:=tsym(paras[i]);
  414. if (sym.visibility<>vis_hidden) then
  415. begin
  416. appendsym(list,sym);
  417. { if we ever write this procdef again for some reason (this
  418. can happen with DWARF), then we want to write all the
  419. parasyms again as well. }
  420. sym.isdbgwritten:=false;
  421. end;
  422. end;
  423. end;
  424. procedure TDebugInfo.write_symtable_syms(list:TAsmList;st:TSymtable);
  425. var
  426. i : longint;
  427. sym : tsym;
  428. begin
  429. case st.symtabletype of
  430. staticsymtable :
  431. list.concat(tai_comment.Create(strpnew('Syms - Begin Staticsymtable')));
  432. globalsymtable :
  433. list.concat(tai_comment.Create(strpnew('Syms - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
  434. else
  435. ;
  436. end;
  437. for i:=0 to st.SymList.Count-1 do
  438. begin
  439. sym:=tsym(st.SymList[i]);
  440. if (sym.visibility<>vis_hidden) and
  441. (not sym.isdbgwritten) and
  442. { avoid all generic symbols }
  443. not (sp_generic_dummy in sym.symoptions) and
  444. not ((sym.typ=typesym) and assigned(ttypesym(sym).typedef) and
  445. (df_generic in ttypesym(sym).typedef.defoptions)) then
  446. appendsym(list,sym);
  447. end;
  448. case st.symtabletype of
  449. staticsymtable :
  450. list.concat(tai_comment.Create(strpnew('Syms - End Staticsymtable')));
  451. globalsymtable :
  452. list.concat(tai_comment.Create(strpnew('Syms - End unit '+st.name^+' has index '+tostr(st.moduleid))));
  453. else
  454. ;
  455. end;
  456. end;
  457. procedure TDebugInfo.write_symtable_procdefs(list:TAsmList;st:TSymtable);
  458. var
  459. i : longint;
  460. def : tdef;
  461. begin
  462. for i:=0 to st.DefList.Count-1 do
  463. begin
  464. def:=tdef(st.DefList[i]);
  465. case def.typ of
  466. procdef :
  467. begin
  468. appendprocdef(list,tprocdef(def));
  469. if assigned(tprocdef(def).localst) then
  470. write_symtable_procdefs(list,tprocdef(def).localst);
  471. end;
  472. objectdef,recorddef :
  473. begin
  474. write_symtable_procdefs(list,tabstractrecorddef(def).symtable);
  475. end;
  476. else
  477. ;
  478. end;
  479. end;
  480. end;
  481. procedure TDebugInfo.reset_unit_type_info;
  482. var
  483. hp : tmodule;
  484. begin
  485. hp:=tmodule(loaded_units.first);
  486. while assigned(hp) do
  487. begin
  488. hp.is_dbginfo_written:=false;
  489. hp:=tmodule(hp.next);
  490. end;
  491. end;
  492. procedure TDebugInfo.write_used_unit_type_info(list:TAsmList;hp:tmodule);
  493. var
  494. pu : tused_unit;
  495. begin
  496. pu:=tused_unit(hp.used_units.first);
  497. while assigned(pu) do
  498. begin
  499. if not pu.u.is_dbginfo_written and not assigned(pu.u.package) then
  500. begin
  501. { prevent infinte loop for circular dependencies }
  502. pu.u.is_dbginfo_written:=true;
  503. { write type info from used units, use a depth first
  504. strategy to reduce the recursion in writing all
  505. dependent stabs }
  506. write_used_unit_type_info(list,pu.u);
  507. if assigned(pu.u.globalsymtable) then
  508. write_symtable_defs(list,pu.u.globalsymtable);
  509. end;
  510. pu:=tused_unit(pu.next);
  511. end;
  512. end;
  513. {****************************************************************************
  514. Init / Done
  515. ****************************************************************************}
  516. procedure InitDebugInfo(hp:tmodule; restore_current_debuginfo : boolean);
  517. begin
  518. if not assigned(CDebugInfo[target_dbg.id]) then
  519. begin
  520. Comment(V_Fatal,'cg_f_debuginfo_output_not_supported');
  521. exit;
  522. end;
  523. hp.DebugInfo:=CDebugInfo[target_dbg.id].Create;
  524. if restore_current_debuginfo then
  525. begin
  526. if current_debuginfo=nil then
  527. current_debuginfo:=tdebuginfo(hp.DebugInfo)
  528. else
  529. internalerror(2012032101);
  530. end;
  531. end;
  532. procedure DoneDebugInfo(hp:tmodule;var current_debuginfo_reset : boolean);
  533. begin
  534. current_debuginfo_reset:=false;
  535. if assigned(hp.DebugInfo) then
  536. begin
  537. if hp.DebugInfo=current_debuginfo then
  538. begin
  539. current_debuginfo:=nil;
  540. current_debuginfo_reset:=true;
  541. end;
  542. hp.DebugInfo.Free;
  543. hp.DebugInfo:=nil;
  544. end;
  545. end;
  546. procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
  547. var
  548. t : tdbg;
  549. begin
  550. t:=r.id;
  551. if assigned(dbginfos[t]) then
  552. writeln('Warning: DebugInfo is already registered!')
  553. else
  554. Getmem(dbginfos[t],sizeof(tdbginfo));
  555. dbginfos[t]^:=r;
  556. CDebugInfo[t]:=c;
  557. end;
  558. const
  559. dbg_none_info : tdbginfo =
  560. (
  561. id : dbg_none;
  562. idtxt : 'NONE';
  563. );
  564. initialization
  565. RegisterDebugInfo(dbg_none_info,TDebugInfo);
  566. end.