dbgbase.pas 21 KB

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