dbgstabs.pas 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692
  1. {
  2. Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl
  3. This units contains support for STABS 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 dbgstabs;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,
  22. dbgbase,
  23. symtype,symdef,symsym,symtable,symbase,
  24. aasmtai,aasmdata;
  25. const
  26. { stab types }
  27. N_GSYM = $20;
  28. N_STSYM = 38; { initialized const }
  29. N_LCSYM = 40; { non initialized variable}
  30. N_Function = $24; { function or const }
  31. N_TextLine = $44;
  32. N_DataLine = $46;
  33. N_BssLine = $48;
  34. N_RSYM = $40; { register variable }
  35. N_LSYM = $80;
  36. N_tsym = 160;
  37. N_SourceFile = $64;
  38. { APPLE LOCAL N_OSO: This is the stab that associated the .o file with the
  39. N_SO stab, in the case where debug info is mostly stored in the .o file. }
  40. N_OSO = $66;
  41. N_IncludeFile = $84;
  42. N_BINCL = $82;
  43. N_EINCL = $A2;
  44. N_LBRAC = $C0;
  45. N_EXCL = $C2;
  46. N_RBRAC = $E0;
  47. type
  48. TDebugInfoStabs=class(TDebugInfo)
  49. private
  50. writing_def_stabs : boolean;
  51. global_stab_number : word;
  52. defnumberlist : TFPObjectList;
  53. { tsym writing }
  54. function sym_var_value(const s:string;arg:pointer):string;
  55. function sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):Pchar;
  56. procedure write_symtable_syms(list:TAsmList;st:TSymtable);
  57. { tdef writing }
  58. function def_stab_number(def:tdef):string;
  59. function def_stab_classnumber(def:tobjectdef):string;
  60. function def_var_value(const s:string;arg:pointer):string;
  61. function def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):Pchar;
  62. procedure field_add_stabstr(p:TObject;arg:pointer);
  63. procedure method_add_stabstr(p:TObject;arg:pointer);
  64. function def_stabstr(def:tdef):pchar;
  65. procedure write_def_stabstr(list:TAsmList;def:tdef);
  66. procedure write_procdef(list:TAsmList;pd:tprocdef);
  67. procedure insertsym(list:TAsmList;sym:tsym);
  68. public
  69. procedure inserttypeinfo;override;
  70. procedure insertmoduleinfo;override;
  71. procedure insertlineinfo(list:TAsmList);override;
  72. procedure referencesections(list:TAsmList);override;
  73. procedure insertdef(list:TAsmList;def:tdef);override;
  74. procedure write_symtable_defs(list:TAsmList;st:TSymtable);override;
  75. end;
  76. implementation
  77. uses
  78. SysUtils,cutils,cfileutl,
  79. systems,globals,globtype,verbose,constexp,
  80. symconst,defutil,
  81. cpuinfo,cpubase,cgbase,paramgr,
  82. aasmbase,procinfo,
  83. finput,fmodule,ppu;
  84. function GetSymName(Sym : TSymEntry) : string;
  85. begin
  86. if Not (cs_stabs_preservecase in current_settings.globalswitches) then
  87. result := Sym.Name
  88. else
  89. result := Sym.RealName;
  90. end;
  91. function GetSymTableName(SymTable : TSymTable) : string;
  92. begin
  93. if Not (cs_stabs_preservecase in current_settings.globalswitches) then
  94. result := SymTable.Name^
  95. else
  96. result := SymTable.RealName^;
  97. end;
  98. const
  99. memsizeinc = 512;
  100. tagtypes = [
  101. recorddef,
  102. enumdef,
  103. stringdef,
  104. filedef,
  105. objectdef
  106. ];
  107. type
  108. get_var_value_proc=function(const s:string;arg:pointer):string of object;
  109. Trecord_stabgen_state=record
  110. stabstring:Pchar;
  111. stabsize,staballoc,recoffset:integer;
  112. end;
  113. Precord_stabgen_state=^Trecord_stabgen_state;
  114. function string_evaluate(s:string;get_var_value:get_var_value_proc;
  115. get_var_value_arg:pointer;
  116. const vars:array of string):Pchar;
  117. (*
  118. S contains a prototype of a result. Stabstr_evaluate will expand
  119. variables and parameters.
  120. Output is s in ASCIIZ format, with the following expanded:
  121. ${varname} - The variable name is expanded.
  122. $n - The parameter n is expanded.
  123. $$ - Is expanded to $
  124. *)
  125. const maxvalue=9;
  126. maxdata=1023;
  127. var i,j:byte;
  128. varname:string[63];
  129. varno,varcounter:byte;
  130. varvalues:array[0..9] of pshortstring;
  131. {1 kb of parameters is the limit. 256 extra bytes are allocated to
  132. ensure buffer integrity.}
  133. varvaluedata:array[0..maxdata+256] of char;
  134. varptr:Pchar;
  135. varidx : byte;
  136. len:longint;
  137. r:Pchar;
  138. begin
  139. {Two pass approach, first, calculate the length and receive variables.}
  140. i:=1;
  141. len:=0;
  142. varcounter:=0;
  143. varptr:=@varvaluedata[0];
  144. while i<=length(s) do
  145. begin
  146. if (s[i]='$') and (i<length(s)) then
  147. begin
  148. if s[i+1]='$' then
  149. begin
  150. inc(len);
  151. inc(i);
  152. end
  153. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  154. begin
  155. varname:='';
  156. inc(i,2);
  157. repeat
  158. inc(varname[0]);
  159. varname[length(varname)]:=s[i];
  160. s[i]:=char(varcounter);
  161. inc(i);
  162. until s[i]='}';
  163. varvalues[varcounter]:=pshortstring(varptr);
  164. if varptr>@varvaluedata[maxdata] then
  165. internalerrorproc(200411152);
  166. pshortstring(varptr)^:=get_var_value(varname,get_var_value_arg);
  167. inc(len,length(pshortstring(varptr)^));
  168. inc(varptr,length(pshortstring(varptr)^)+1);
  169. inc(varcounter);
  170. end
  171. else if s[i+1] in ['1'..'9'] then
  172. begin
  173. varidx:=byte(s[i+1])-byte('1');
  174. if varidx>high(vars) then
  175. internalerror(200509263);
  176. inc(len,length(vars[varidx]));
  177. inc(i);
  178. end;
  179. end
  180. else
  181. inc(len);
  182. inc(i);
  183. end;
  184. {Second pass, writeout result.}
  185. getmem(r,len+1);
  186. string_evaluate:=r;
  187. i:=1;
  188. while i<=length(s) do
  189. begin
  190. if (s[i]='$') and (i<length(s)) then
  191. begin
  192. if s[i+1]='$' then
  193. begin
  194. r^:='$';
  195. inc(r);
  196. inc(i);
  197. end
  198. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  199. begin
  200. varname:='';
  201. inc(i,2);
  202. varno:=byte(s[i]);
  203. repeat
  204. inc(i);
  205. until s[i]='}';
  206. for j:=1 to length(varvalues[varno]^) do
  207. begin
  208. r^:=varvalues[varno]^[j];
  209. inc(r);
  210. end;
  211. end
  212. else if s[i+1] in ['0'..'9'] then
  213. begin
  214. for j:=1 to length(vars[byte(s[i+1])-byte('1')]) do
  215. begin
  216. r^:=vars[byte(s[i+1])-byte('1')][j];
  217. inc(r);
  218. end;
  219. inc(i);
  220. end
  221. end
  222. else
  223. begin
  224. r^:=s[i];
  225. inc(r);
  226. end;
  227. inc(i);
  228. end;
  229. r^:=#0;
  230. end;
  231. {****************************************************************************
  232. TDef support
  233. ****************************************************************************}
  234. function TDebugInfoStabs.def_stab_number(def:tdef):string;
  235. begin
  236. { procdefs only need a number, mark them as already written
  237. so they won't be written implicitly }
  238. if (def.typ=procdef) then
  239. def.dbg_state:=dbg_state_written;
  240. { Stab must already be written, or we must be busy writing it }
  241. if writing_def_stabs and
  242. not(def.dbg_state in [dbg_state_writing,dbg_state_written,dbg_state_queued]) then
  243. internalerror(200403091);
  244. { Keep track of used stabs, this info is only usefull for stabs
  245. referenced by the symbols. Definitions will always include all
  246. required stabs }
  247. if def.dbg_state=dbg_state_unused then
  248. def.dbg_state:=dbg_state_used;
  249. { Need a new number? }
  250. if def.stab_number=0 then
  251. begin
  252. inc(global_stab_number);
  253. { classes require 2 numbers }
  254. if is_class(def) then
  255. inc(global_stab_number);
  256. def.stab_number:=global_stab_number;
  257. if global_stab_number>=defnumberlist.count then
  258. defnumberlist.count:=global_stab_number+250;
  259. defnumberlist[global_stab_number]:=def;
  260. end;
  261. result:=tostr(def.stab_number);
  262. end;
  263. function TDebugInfoStabs.def_stab_classnumber(def:tobjectdef):string;
  264. begin
  265. if def.stab_number=0 then
  266. def_stab_number(def);
  267. if (def.objecttype=odt_class) then
  268. result:=tostr(def.stab_number-1)
  269. else
  270. result:=tostr(def.stab_number);
  271. end;
  272. function TDebugInfoStabs.def_var_value(const s:string;arg:pointer):string;
  273. var
  274. def : tdef;
  275. begin
  276. def:=tdef(arg);
  277. result:='';
  278. if s='numberstring' then
  279. result:=def_stab_number(def)
  280. else if s='sym_name' then
  281. begin
  282. if assigned(def.typesym) then
  283. result:=GetSymName(Ttypesym(def.typesym));
  284. end
  285. else if s='N_LSYM' then
  286. result:=tostr(N_LSYM)
  287. else if s='savesize' then
  288. result:=tostr(def.size);
  289. end;
  290. function TDebugInfoStabs.def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):Pchar;
  291. begin
  292. result:=string_evaluate(s,@def_var_value,def,vars);
  293. end;
  294. procedure TDebugInfoStabs.field_add_stabstr(p:TObject;arg:pointer);
  295. var
  296. newrec : Pchar;
  297. spec : string[3];
  298. varsize : aint;
  299. state : Precord_stabgen_state;
  300. begin
  301. state:=arg;
  302. { static variables from objects are like global objects }
  303. if (Tsym(p).typ=fieldvarsym) and
  304. not(sp_static in Tsym(p).symoptions) then
  305. begin
  306. if ([sp_protected,sp_strictprotected]*tsym(p).symoptions)<>[] then
  307. spec:='/1'
  308. else if ([sp_private,sp_strictprivate]*tsym(p).symoptions)<>[] then
  309. spec:='/0'
  310. else
  311. spec:='';
  312. if (tabstractrecordsymtable(tsym(p).owner).usefieldalignment<>bit_alignment) then
  313. begin
  314. varsize:=tfieldvarsym(p).vardef.size;
  315. { open arrays made overflows !! }
  316. { how can a record/object/class contain an open array? (JM) }
  317. if varsize>$fffffff then
  318. varsize:=$fffffff;
  319. newrec:=def_stabstr_evaluate(nil,'$1:$2,$3,$4;',[GetSymName(tfieldvarsym(p)),
  320. spec+def_stab_number(tfieldvarsym(p).vardef),
  321. tostr(TConstExprInt(tfieldvarsym(p).fieldoffset)*8),tostr(varsize*8)])
  322. end
  323. else
  324. newrec:=def_stabstr_evaluate(nil,'$1:$2,$3,$4;',[GetSymName(tfieldvarsym(p)),
  325. spec+def_stab_number(tfieldvarsym(p).vardef),
  326. tostr(TConstExprInt(tfieldvarsym(p).fieldoffset)),tostr(tfieldvarsym(p).vardef.packedbitsize)]);
  327. if state^.stabsize+strlen(newrec)>=state^.staballoc-256 then
  328. begin
  329. inc(state^.staballoc,strlen(newrec)+64);
  330. reallocmem(state^.stabstring,state^.staballoc);
  331. end;
  332. strcopy(state^.stabstring+state^.stabsize,newrec);
  333. inc(state^.stabsize,strlen(newrec));
  334. freemem(newrec);
  335. {This should be used for case !!}
  336. if int64(state^.recoffset)+Tfieldvarsym(p).vardef.size>high(longint) then
  337. state^.recoffset:=high(longint)
  338. else
  339. inc(state^.recoffset,Tfieldvarsym(p).vardef.size);
  340. end;
  341. end;
  342. procedure TDebugInfoStabs.method_add_stabstr(p:TObject;arg:pointer);
  343. var virtualind,argnames : string;
  344. newrec : pchar;
  345. pd : tprocdef;
  346. lindex : longint;
  347. arglength : byte;
  348. sp : char;
  349. state:^Trecord_stabgen_state;
  350. olds:integer;
  351. i : integer;
  352. parasym : tparavarsym;
  353. begin
  354. state:=arg;
  355. if tsym(p).typ = procsym then
  356. begin
  357. pd :=tprocdef(tprocsym(p).ProcdefList[0]);
  358. if (po_virtualmethod in pd.procoptions) then
  359. begin
  360. lindex := pd.extnumber;
  361. {doesnt seem to be necessary
  362. lindex := lindex or $80000000;}
  363. virtualind := '*'+tostr(lindex)+';'+def_stab_classnumber(pd._class)+';'
  364. end
  365. else
  366. virtualind := '.';
  367. { used by gdbpas to recognize constructor and destructors }
  368. if (pd.proctypeoption=potype_constructor) then
  369. argnames:='__ct__'
  370. else if (pd.proctypeoption=potype_destructor) then
  371. argnames:='__dt__'
  372. else
  373. argnames := '';
  374. { arguments are not listed here }
  375. {we don't need another definition}
  376. for i:=0 to pd.paras.count-1 do
  377. begin
  378. parasym:=tparavarsym(pd.paras[i]);
  379. if Parasym.vardef.typ = formaldef then
  380. begin
  381. case Parasym.varspez of
  382. vs_var :
  383. argnames := argnames+'3var';
  384. vs_const :
  385. argnames:=argnames+'5const';
  386. vs_out :
  387. argnames:=argnames+'3out';
  388. end;
  389. end
  390. else
  391. begin
  392. { if the arg definition is like (v: ^byte;..
  393. there is no sym attached to data !!! }
  394. if assigned(Parasym.vardef.typesym) then
  395. begin
  396. arglength := length(GetSymName(Parasym.vardef.typesym));
  397. argnames := argnames + tostr(arglength)+GetSymName(Parasym.vardef.typesym);
  398. end
  399. else
  400. argnames:=argnames+'11unnamedtype';
  401. end;
  402. end;
  403. { here 2A must be changed for private and protected }
  404. { 0 is private 1 protected and 2 public }
  405. if ([sp_private,sp_strictprivate]*tsym(p).symoptions)<>[] then
  406. sp:='0'
  407. else if ([sp_protected,sp_strictprotected]*tsym(p).symoptions)<>[] then
  408. sp:='1'
  409. else
  410. sp:='2';
  411. newrec:=def_stabstr_evaluate(nil,'$1::$2=##$3;:$4;$5A$6;',[GetSymName(tsym(p)),def_stab_number(pd),
  412. def_stab_number(pd.returndef),argnames,sp,
  413. virtualind]);
  414. { get spare place for a string at the end }
  415. olds:=state^.stabsize;
  416. inc(state^.stabsize,strlen(newrec));
  417. if state^.stabsize>=state^.staballoc-256 then
  418. begin
  419. inc(state^.staballoc,strlen(newrec)+64);
  420. reallocmem(state^.stabstring,state^.staballoc);
  421. end;
  422. strcopy(state^.stabstring+olds,newrec);
  423. freemem(newrec);
  424. {This should be used for case !!
  425. RecOffset := RecOffset + pd.size;}
  426. end;
  427. end;
  428. function TDebugInfoStabs.def_stabstr(def:tdef):pchar;
  429. function stringdef_stabstr(def:tstringdef):pchar;
  430. var
  431. slen : aint;
  432. bytest,charst,longst : string;
  433. begin
  434. case def.stringtype of
  435. st_shortstring:
  436. begin
  437. { fix length of openshortstring }
  438. slen:=def.len;
  439. if slen=0 then
  440. slen:=255;
  441. charst:=def_stab_number(cchartype);
  442. bytest:=def_stab_number(u8inttype);
  443. result:=def_stabstr_evaluate(def,'s$1length:$2,0,8;st:ar$2;1;$3;$4,8,$5;;',
  444. [tostr(slen+1),bytest,tostr(slen),charst,tostr(slen*8)]);
  445. end;
  446. st_longstring:
  447. begin
  448. charst:=def_stab_number(cchartype);
  449. bytest:=def_stab_number(u8inttype);
  450. longst:=def_stab_number(u32inttype);
  451. result:=def_stabstr_evaluate(def,'s$1length:$2,0,32;dummy:$6,32,8;st:ar$2;1;$3;$4,40,$5;;',
  452. [tostr(def.len+5),longst,tostr(def.len),charst,tostr(def.len*8),bytest]);
  453. end;
  454. st_ansistring:
  455. begin
  456. { looks like a pchar }
  457. charst:=def_stab_number(cchartype);
  458. result:=strpnew('*'+charst);
  459. end;
  460. st_unicodestring,
  461. st_widestring:
  462. begin
  463. { looks like a pwidechar }
  464. charst:=def_stab_number(cwidechartype);
  465. result:=strpnew('*'+charst);
  466. end;
  467. end;
  468. end;
  469. function enumdef_stabstr(def:tenumdef):pchar;
  470. var
  471. st : Pchar;
  472. p : Tenumsym;
  473. s : string;
  474. memsize,
  475. stl : aint;
  476. begin
  477. memsize:=memsizeinc;
  478. getmem(st,memsize);
  479. { we can specify the size with @s<size>; prefix PM }
  480. if def.size <> std_param_align then
  481. strpcopy(st,'@s'+tostr(def.size*8)+';e')
  482. else
  483. strpcopy(st,'e');
  484. p := tenumsym(def.firstenum);
  485. stl:=strlen(st);
  486. while assigned(p) do
  487. begin
  488. s :=GetSymName(p)+':'+tostr(p.value)+',';
  489. { place for the ending ';' also }
  490. if (stl+length(s)+1>=memsize) then
  491. begin
  492. inc(memsize,memsizeinc);
  493. reallocmem(st,memsize);
  494. end;
  495. strpcopy(st+stl,s);
  496. inc(stl,length(s));
  497. p:=p.nextenum;
  498. end;
  499. st[stl]:=';';
  500. st[stl+1]:=#0;
  501. reallocmem(st,stl+2);
  502. result:=st;
  503. end;
  504. function orddef_stabstr(def:torddef):pchar;
  505. begin
  506. if cs_gdb_valgrind in current_settings.globalswitches then
  507. begin
  508. case def.ordtype of
  509. uvoid :
  510. result:=strpnew(def_stab_number(def));
  511. pasbool,
  512. bool8bit,
  513. bool16bit,
  514. bool32bit,
  515. bool64bit :
  516. result:=def_stabstr_evaluate(def,'r${numberstring};0;255;',[]);
  517. u32bit,
  518. s64bit,
  519. u64bit :
  520. result:=def_stabstr_evaluate(def,'r${numberstring};0;-1;',[]);
  521. else
  522. result:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low.svalue)),tostr(longint(def.high.svalue))]);
  523. end;
  524. end
  525. else
  526. begin
  527. case def.ordtype of
  528. uvoid :
  529. result:=strpnew(def_stab_number(def));
  530. uchar :
  531. result:=strpnew('-20;');
  532. uwidechar :
  533. result:=strpnew('-30;');
  534. pasbool,
  535. bool8bit :
  536. result:=strpnew('-21;');
  537. bool16bit :
  538. result:=strpnew('-22;');
  539. bool32bit :
  540. result:=strpnew('-23;');
  541. bool64bit :
  542. { no clue if this is correct (FK) }
  543. result:=strpnew('-23;');
  544. u64bit :
  545. result:=strpnew('-32;');
  546. s64bit :
  547. result:=strpnew('-31;');
  548. {u32bit : result:=def_stab_number(s32inttype)+';0;-1;'); }
  549. else
  550. result:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low.svalue)),tostr(longint(def.high.svalue))]);
  551. end;
  552. end;
  553. end;
  554. function floatdef_stabstr(def:tfloatdef):Pchar;
  555. begin
  556. case def.floattype of
  557. s32real,
  558. s64real,
  559. s80real:
  560. result:=def_stabstr_evaluate(def,'r$1;${savesize};0;',[def_stab_number(s32inttype)]);
  561. s64currency,
  562. s64comp:
  563. result:=def_stabstr_evaluate(def,'r$1;-${savesize};0;',[def_stab_number(s32inttype)]);
  564. else
  565. internalerror(200509261);
  566. end;
  567. end;
  568. function filedef_stabstr(def:tfiledef):pchar;
  569. begin
  570. {$ifdef cpu64bit}
  571. result:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$2,64,64;'+
  572. '_PRIVATE:ar$1;1;64;$3,128,256;USERDATA:ar$1;1;16;$3,384,128;'+
  573. 'NAME:ar$1;0;255;$4,512,2048;;',[def_stab_number(s32inttype),
  574. def_stab_number(s64inttype),
  575. def_stab_number(u8inttype),
  576. def_stab_number(cchartype)]);
  577. {$else cpu64bit}
  578. result:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$1,64,32;'+
  579. '_PRIVATE:ar$1;1;32;$3,96,256;USERDATA:ar$1;1;16;$2,352,128;'+
  580. 'NAME:ar$1;0;255;$3,480,2048;;',[def_stab_number(s32inttype),
  581. def_stab_number(u8inttype),
  582. def_stab_number(cchartype)]);
  583. {$endif cpu64bit}
  584. end;
  585. function procdef_stabstr(def:tprocdef):pchar;
  586. Var
  587. RType : Char;
  588. Obj,Info : String;
  589. stabsstr : string;
  590. p : pchar;
  591. begin
  592. obj := GetSymName(def.procsym);
  593. info := '';
  594. if (po_global in def.procoptions) then
  595. RType := 'F'
  596. else
  597. RType := 'f';
  598. if assigned(def.owner) then
  599. begin
  600. if (def.owner.symtabletype = objecTSymtable) then
  601. obj := GetSymTableName(def.owner)+'__'+GetSymName(def.procsym);
  602. if not(cs_gdb_valgrind in current_settings.globalswitches) and
  603. (def.owner.symtabletype=localsymtable) and
  604. assigned(def.owner.defowner) and
  605. assigned(tprocdef(def.owner.defowner).procsym) then
  606. info := ','+GetSymName(def.procsym)+','+GetSymName(tprocdef(def.owner.defowner).procsym);
  607. end;
  608. stabsstr:=def.mangledname;
  609. getmem(p,length(stabsstr)+255);
  610. strpcopy(p,'"'+obj+':'+RType
  611. +def_stab_number(def.returndef)+info+'",'+tostr(n_function)
  612. +',0,'+
  613. tostr(def.fileinfo.line)
  614. +',');
  615. strpcopy(strend(p),stabsstr);
  616. getmem(result,strlen(p)+1);
  617. move(p^,result^,strlen(p)+1);
  618. freemem(p);
  619. end;
  620. function recorddef_stabstr(def:trecorddef):pchar;
  621. var
  622. state : Trecord_stabgen_state;
  623. begin
  624. getmem(state.stabstring,memsizeinc);
  625. state.staballoc:=memsizeinc;
  626. strpcopy(state.stabstring,'s'+tostr(def.size));
  627. state.recoffset:=0;
  628. state.stabsize:=strlen(state.stabstring);
  629. def.symtable.SymList.ForEachCall(@field_add_stabstr,@state);
  630. state.stabstring[state.stabsize]:=';';
  631. state.stabstring[state.stabsize+1]:=#0;
  632. reallocmem(state.stabstring,state.stabsize+2);
  633. result:=state.stabstring;
  634. end;
  635. function objectdef_stabstr(def:tobjectdef):pchar;
  636. var
  637. anc : tobjectdef;
  638. state :Trecord_stabgen_state;
  639. ts : string;
  640. begin
  641. { Write the invisible pointer for the class? }
  642. if (def.objecttype=odt_class) and
  643. (not def.writing_class_record_dbginfo) then
  644. begin
  645. result:=strpnew('*'+def_stab_classnumber(def));
  646. exit;
  647. end;
  648. state.staballoc:=memsizeinc;
  649. getmem(state.stabstring,state.staballoc);
  650. strpcopy(state.stabstring,'s'+tostr(tobjecTSymtable(def.symtable).datasize));
  651. if assigned(def.childof) then
  652. begin
  653. {only one ancestor not virtual, public, at base offset 0 }
  654. { !1 , 0 2 0 , }
  655. strpcopy(strend(state.stabstring),'!1,020,'+def_stab_classnumber(def.childof)+';');
  656. end;
  657. {virtual table to implement yet}
  658. state.recoffset:=0;
  659. state.stabsize:=strlen(state.stabstring);
  660. def.symtable.symList.ForEachCall(@field_add_stabstr,@state);
  661. if (oo_has_vmt in def.objectoptions) then
  662. if not assigned(def.childof) or not(oo_has_vmt in def.childof.objectoptions) then
  663. begin
  664. ts:='$vf'+def_stab_classnumber(def)+':'+def_stab_number(vmtarraytype)+','+tostr(def.vmt_offset*8)+';';
  665. strpcopy(state.stabstring+state.stabsize,ts);
  666. inc(state.stabsize,length(ts));
  667. end;
  668. def.symtable.symList.ForEachCall(@method_add_stabstr,@state);
  669. if (oo_has_vmt in def.objectoptions) then
  670. begin
  671. anc := def;
  672. while assigned(anc.childof) and (oo_has_vmt in anc.childof.objectoptions) do
  673. anc := anc.childof;
  674. { just in case anc = self }
  675. ts:=';~%'+def_stab_classnumber(anc)+';';
  676. end
  677. else
  678. ts:=';';
  679. strpcopy(state.stabstring+state.stabsize,ts);
  680. inc(state.stabsize,length(ts));
  681. reallocmem(state.stabstring,state.stabsize+1);
  682. result:=state.stabstring;
  683. end;
  684. var
  685. tempstr: pchar;
  686. begin
  687. result:=nil;
  688. case def.typ of
  689. stringdef :
  690. result:=stringdef_stabstr(tstringdef(def));
  691. enumdef :
  692. result:=enumdef_stabstr(tenumdef(def));
  693. orddef :
  694. result:=orddef_stabstr(torddef(def));
  695. floatdef :
  696. result:=floatdef_stabstr(tfloatdef(def));
  697. filedef :
  698. result:=filedef_stabstr(tfiledef(def));
  699. recorddef :
  700. result:=recorddef_stabstr(trecorddef(def));
  701. variantdef :
  702. result:=def_stabstr_evaluate(def,'${numberstring};',[]);
  703. pointerdef :
  704. result:=strpnew('*'+def_stab_number(tpointerdef(def).pointeddef));
  705. classrefdef :
  706. result:=strpnew(def_stab_number(pvmttype));
  707. setdef :
  708. result:=def_stabstr_evaluate(def,'@s$1;S$2',[tostr(def.size*8),def_stab_number(tsetdef(def).elementdef)]);
  709. formaldef :
  710. result:=def_stabstr_evaluate(def,'${numberstring};',[]);
  711. arraydef :
  712. if not is_packed_array(def) then
  713. result:=def_stabstr_evaluate(def,'ar$1;$2;$3;$4',[def_stab_number(tarraydef(def).rangedef),
  714. tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementdef)])
  715. else
  716. begin
  717. // the @P seems to be ignored by gdb
  718. // result:=def_stabstr_evaluate(def,'ar$1;$2;$3;$4;@P;',[def_stab_number(tarraydef(def).rangedef),tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementdef)]);
  719. tempstr:=def_stabstr_evaluate(tarraydef(def).rangedef,'r${numberstring};$1;$2;',
  720. [tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange)]);
  721. // will only show highrange-lowrange+1 bits in gdb
  722. result:=def_stabstr_evaluate(def,'@s$1;@S;S$2',
  723. [tostr(TConstExprInt(tarraydef(def).elepackedbitsize) * tarraydef(def).elecount),tempstr]);
  724. freemem(tempstr);
  725. end;
  726. procdef :
  727. result:=procdef_stabstr(tprocdef(def));
  728. procvardef :
  729. result:=strpnew('*f'+def_stab_number(tprocvardef(def).returndef));
  730. objectdef :
  731. result:=objectdef_stabstr(tobjectdef(def));
  732. undefineddef :
  733. result:=def_stabstr_evaluate(def,'${numberstring};',[]);
  734. end;
  735. if result=nil then
  736. internalerror(200512203);
  737. end;
  738. procedure TDebugInfoStabs.write_def_stabstr(list:TAsmList;def:tdef);
  739. var
  740. stabchar : string[2];
  741. ss,st,su : pchar;
  742. begin
  743. { procdefs require a different stabs style without type prefix }
  744. if def.typ=procdef then
  745. begin
  746. st:=def_stabstr(def);
  747. { add to list }
  748. list.concat(Tai_stab.create(stab_stabs,st));
  749. end
  750. else
  751. begin
  752. { type prefix }
  753. if def.typ in tagtypes then
  754. stabchar := 'Tt'
  755. else
  756. stabchar := 't';
  757. { Here we maybe generate a type, so we have to use numberstring }
  758. if is_class(def) and
  759. tobjectdef(def).writing_class_record_dbginfo then
  760. st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_classnumber(tobjectdef(def))])
  761. else
  762. st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_number(def)]);
  763. ss:=def_stabstr(def);
  764. reallocmem(st,strlen(ss)+512);
  765. { line info is set to 0 for all defs, because the def can be in an other
  766. unit and then the linenumber is invalid in the current sourcefile }
  767. su:=def_stabstr_evaluate(def,'",${N_LSYM},0,0,0',[]);
  768. strcopy(strecopy(strend(st),ss),su);
  769. reallocmem(st,strlen(st)+1);
  770. freemem(ss);
  771. freemem(su);
  772. { add to list }
  773. list.concat(Tai_stab.create(stab_stabs,st));
  774. end;
  775. end;
  776. procedure TDebugInfoStabs.insertdef(list:TAsmList;def:tdef);
  777. var
  778. anc : tobjectdef;
  779. oldtypesym : tsym;
  780. i : longint;
  781. begin
  782. if (def.dbg_state in [dbg_state_writing,dbg_state_written]) then
  783. exit;
  784. { never write generic template defs }
  785. if df_generic in def.defoptions then
  786. begin
  787. def.dbg_state:=dbg_state_written;
  788. exit;
  789. end;
  790. { to avoid infinite loops }
  791. def.dbg_state := dbg_state_writing;
  792. { write dependencies first }
  793. case def.typ of
  794. stringdef :
  795. begin
  796. if tstringdef(def).stringtype in [st_widestring,st_unicodestring] then
  797. insertdef(list,cwidechartype)
  798. else
  799. begin
  800. insertdef(list,cchartype);
  801. insertdef(list,u8inttype);
  802. end;
  803. end;
  804. floatdef :
  805. insertdef(list,s32inttype);
  806. filedef :
  807. begin
  808. insertdef(list,s32inttype);
  809. {$ifdef cpu64bit}
  810. insertdef(list,s64inttype);
  811. {$endif cpu64bit}
  812. insertdef(list,u8inttype);
  813. insertdef(list,cchartype);
  814. end;
  815. classrefdef :
  816. insertdef(list,pvmttype);
  817. pointerdef :
  818. insertdef(list,tpointerdef(def).pointeddef);
  819. setdef :
  820. insertdef(list,tsetdef(def).elementdef);
  821. procvardef :
  822. begin
  823. insertdef(list,tprocvardef(def).returndef);
  824. if assigned(tprocvardef(def).parast) then
  825. write_symtable_defs(list,tprocvardef(def).parast);
  826. end;
  827. procdef :
  828. begin
  829. insertdef(list,tprocdef(def).returndef);
  830. if assigned(tprocdef(def).parast) then
  831. write_symtable_defs(list,tprocdef(def).parast);
  832. if assigned(tprocdef(def).localst) and
  833. (tprocdef(def).localst.symtabletype=localsymtable) then
  834. write_symtable_defs(list,tprocdef(def).localst);
  835. end;
  836. arraydef :
  837. begin
  838. insertdef(list,tarraydef(def).rangedef);
  839. insertdef(list,tarraydef(def).elementdef);
  840. end;
  841. recorddef :
  842. trecorddef(def).symtable.symList.ForEachCall(@field_write_defs,list);
  843. enumdef :
  844. if assigned(tenumdef(def).basedef) then
  845. insertdef(list,tenumdef(def).basedef);
  846. objectdef :
  847. begin
  848. { make sure we don't write child classdefs before their parent }
  849. { classdefs, because this crashes gdb }
  850. anc:=tobjectdef(def);
  851. while assigned(anc.childof) do
  852. begin
  853. anc:=anc.childof;
  854. if (anc.dbg_state=dbg_state_writing) then
  855. { happens in case a field of a parent is of the (forward }
  856. { defined) child type }
  857. begin
  858. { We don't explicitly requeue it, but the fact that }
  859. { a child type was used in a parent before the child }
  860. { type was fully defined means that it was forward }
  861. { declared, and will still be encountered later (it }
  862. { cannot have been declared in another unit, because }
  863. { then this and that other unit would depend on }
  864. { eachother's interface) }
  865. { Setting the state to queued however allows us to }
  866. { get the def number already without an IE }
  867. def.dbg_state:=dbg_state_queued;
  868. exit;
  869. end;
  870. end;
  871. insertdef(list,vmtarraytype);
  872. if assigned(tobjectdef(def).ImplementedInterfaces) then
  873. for i:=0 to tobjectdef(def).ImplementedInterfaces.Count-1 do
  874. insertdef(list,TImplementedInterface(tobjectdef(def).ImplementedInterfaces[i]).IntfDef);
  875. { first the parents }
  876. anc:=tobjectdef(def);
  877. while assigned(anc.childof) do
  878. begin
  879. anc:=anc.childof;
  880. insertdef(list,anc);
  881. if assigned(anc.ImplementedInterfaces) then
  882. for i:=0 to anc.ImplementedInterfaces.Count-1 do
  883. insertdef(list,TImplementedInterface(anc.ImplementedInterfaces[i]).IntfDef);
  884. end;
  885. tobjectdef(def).symtable.symList.ForEachCall(@field_write_defs,list);
  886. tobjectdef(def).symtable.symList.ForEachCall(@method_write_defs,list);
  887. end;
  888. end;
  889. case def.typ of
  890. objectdef :
  891. begin
  892. { classes require special code to write the record and the invisible pointer }
  893. if is_class(def) then
  894. begin
  895. { Write the record class itself }
  896. tobjectdef(def).writing_class_record_dbginfo:=true;
  897. write_def_stabstr(list,def);
  898. tobjectdef(def).writing_class_record_dbginfo:=false;
  899. { Write the invisible pointer class }
  900. oldtypesym:=def.typesym;
  901. def.typesym:=nil;
  902. write_def_stabstr(list,def);
  903. def.typesym:=oldtypesym;
  904. end
  905. else
  906. write_def_stabstr(list,def);
  907. { VMT symbol }
  908. if (oo_has_vmt in tobjectdef(def).objectoptions) and
  909. assigned(def.owner) and
  910. assigned(def.owner.name) then
  911. list.concat(Tai_stab.create(stab_stabs,strpnew('"vmt_'+GetSymTableName(def.owner)+tobjectdef(def).objname^+':S'+
  912. def_stab_number(vmttype)+'",'+tostr(N_STSYM)+',0,0,'+tobjectdef(def).vmt_mangledname)));
  913. end;
  914. procdef :
  915. begin
  916. { procdefs are handled separatly }
  917. end;
  918. else
  919. write_def_stabstr(list,def);
  920. end;
  921. def.dbg_state := dbg_state_written;
  922. end;
  923. procedure TDebugInfoStabs.write_symtable_defs(list:TAsmList;st:TSymtable);
  924. procedure dowritestabs(list:TAsmList;st:TSymtable);
  925. var
  926. def : tdef;
  927. i : longint;
  928. begin
  929. for i:=0 to st.DefList.Count-1 do
  930. begin
  931. def:=tdef(st.DefList[i]);
  932. if (def.dbg_state in [dbg_state_used,dbg_state_queued]) then
  933. insertdef(list,def);
  934. end;
  935. end;
  936. var
  937. old_writing_def_stabs : boolean;
  938. begin
  939. case st.symtabletype of
  940. staticsymtable :
  941. list.concat(tai_comment.Create(strpnew('Defs - Begin Staticsymtable')));
  942. globalsymtable :
  943. list.concat(tai_comment.Create(strpnew('Defs - Begin unit '+GetSymTableName(st)+' has index '+tostr(st.moduleid))));
  944. end;
  945. old_writing_def_stabs:=writing_def_stabs;
  946. writing_def_stabs:=true;
  947. dowritestabs(list,st);
  948. writing_def_stabs:=old_writing_def_stabs;
  949. case st.symtabletype of
  950. staticsymtable :
  951. list.concat(tai_comment.Create(strpnew('Defs - End Staticsymtable')));
  952. globalsymtable :
  953. list.concat(tai_comment.Create(strpnew('Defs - End unit '+GetSymTableName(st)+' has index '+tostr(st.moduleid))));
  954. end;
  955. end;
  956. procedure TDebugInfoStabs.write_procdef(list:TAsmList;pd:tprocdef);
  957. var
  958. templist : TAsmList;
  959. stabsendlabel : tasmlabel;
  960. mangled_length : longint;
  961. p,p1 : pchar;
  962. hs : string;
  963. begin
  964. if assigned(pd.procstarttai) then
  965. begin
  966. { mark as used, so also the local and para defs will be written }
  967. pd.dbg_state:=dbg_state_used;
  968. templist:=TAsmList.create;
  969. { end of procedure }
  970. current_asmdata.getlabel(stabsendlabel,alt_dbgtype);
  971. if assigned(pd.funcretsym) and
  972. (tabstractnormalvarsym(pd.funcretsym).refs>0) then
  973. begin
  974. if tabstractnormalvarsym(pd.funcretsym).localloc.loc=LOC_REFERENCE then
  975. begin
  976. {$warning Need to add gdb support for ret in param register calling}
  977. if paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
  978. hs:='X*'
  979. else
  980. hs:='X';
  981. templist.concat(Tai_stab.create(stab_stabs,strpnew(
  982. '"'+GetSymName(pd.procsym)+':'+hs+def_stab_number(pd.returndef)+'",'+
  983. tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(pd.funcretsym).localloc.reference.offset))));
  984. if (m_result in current_settings.modeswitches) then
  985. templist.concat(Tai_stab.create(stab_stabs,strpnew(
  986. '"RESULT:'+hs+def_stab_number(pd.returndef)+'",'+
  987. tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(pd.funcretsym).localloc.reference.offset))));
  988. end;
  989. end;
  990. mangled_length:=length(pd.mangledname);
  991. getmem(p,2*mangled_length+50);
  992. strpcopy(p,tostr(N_LBRAC)+',0,0,');
  993. {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
  994. strpcopy(strend(p),pd.mangledname);
  995. if (tf_use_function_relative_addresses in target_info.flags) then
  996. begin
  997. strpcopy(strend(p),'-');
  998. {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
  999. strpcopy(strend(p),pd.mangledname);
  1000. end;
  1001. getmem(p1,strlen(p)+1);
  1002. move(p^,p1^,strlen(p)+1);
  1003. templist.concat(Tai_stab.Create(stab_stabn,p1));
  1004. strpcopy(p,tostr(N_RBRAC)+',0,0,'+stabsendlabel.name);
  1005. if (tf_use_function_relative_addresses in target_info.flags) then
  1006. begin
  1007. strpcopy(strend(p),'-');
  1008. {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
  1009. strpcopy(strend(p),pd.mangledname);
  1010. end;
  1011. getmem(p1,strlen(p)+1);
  1012. move(p^,p1^,strlen(p)+1);
  1013. templist.concat(Tai_stab.Create(stab_stabn,p1));
  1014. freemem(p,2*mangled_length+50);
  1015. { the stabsendlabel must come after all other stabs for this }
  1016. { function }
  1017. templist.concat(tai_label.create(stabsendlabel));
  1018. { Add a "size" stab as described in the last paragraph of 2.5 at }
  1019. { http://sourceware.org/gdb/current/onlinedocs/stabs_2.html#SEC12 }
  1020. { This works at least on Darwin (and is needed on Darwin to get }
  1021. { correct smartlinking of stabs), but I don't know which binutils }
  1022. { version is required on other platforms }
  1023. { This stab must come after all other stabs for the procedure, }
  1024. { including the LBRAC/RBRAC ones }
  1025. if (target_info.system in systems_darwin) then
  1026. templist.concat(Tai_stab.create(stab_stabs,
  1027. strpnew('"",'+tostr(N_FUNCTION)+',0,0,'+stabsendlabel.name+'-'+pd.mangledname)));
  1028. current_asmdata.asmlists[al_procedures].insertlistafter(pd.procendtai,templist);
  1029. { "The stab representing a procedure is located immediately
  1030. following the code of the procedure. This stab is in turn
  1031. directly followed by a group of other stabs describing
  1032. elements of the procedure. These other stabs describe the
  1033. procedure's parameters, its block local variables, and its
  1034. block structure." (stab docs) }
  1035. { this is however incorrect in case "include source" statements }
  1036. { appear in the block, in that case the procedure stab must }
  1037. { appear before this include stabs (and we generate such an }
  1038. { stabs for all functions) (JM) }
  1039. { procdef }
  1040. write_def_stabstr(templist,pd);
  1041. current_asmdata.asmlists[al_procedures].insertlistbefore(pd.procstarttai,templist);
  1042. { para types }
  1043. if assigned(pd.parast) then
  1044. write_symtable_syms(templist,pd.parast);
  1045. { local type defs and vars should not be written
  1046. inside the main proc stab }
  1047. if assigned(pd.localst) and
  1048. (pd.localst.symtabletype=localsymtable) then
  1049. write_symtable_syms(templist,pd.localst);
  1050. current_asmdata.asmlists[al_procedures].insertlistbefore(pd.procstarttai,templist);
  1051. templist.free;
  1052. end;
  1053. end;
  1054. {****************************************************************************
  1055. TSym support
  1056. ****************************************************************************}
  1057. function TDebugInfoStabs.sym_var_value(const s:string;arg:pointer):string;
  1058. var
  1059. sym : tsym;
  1060. begin
  1061. sym:=tsym(arg);
  1062. result:='';
  1063. if s='name' then
  1064. result:=GetSymName(sym)
  1065. else if s='mangledname' then
  1066. result:=sym.mangledname
  1067. else if s='ownername' then
  1068. result:=GetSymTableName(sym.owner)
  1069. else if s='line' then
  1070. result:=tostr(sym.fileinfo.line)
  1071. else if s='N_LSYM' then
  1072. result:=tostr(N_LSYM)
  1073. else if s='N_LCSYM' then
  1074. result:=tostr(N_LCSYM)
  1075. else if s='N_RSYM' then
  1076. result:=tostr(N_RSYM)
  1077. else if s='N_TSYM' then
  1078. result:=tostr(N_TSYM)
  1079. else if s='N_STSYM' then
  1080. result:=tostr(N_STSYM)
  1081. else if s='N_FUNCTION' then
  1082. result:=tostr(N_FUNCTION)
  1083. else
  1084. internalerror(200401152);
  1085. end;
  1086. function TDebugInfoStabs.sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):Pchar;
  1087. begin
  1088. result:=string_evaluate(s,@sym_var_value,sym,vars);
  1089. end;
  1090. procedure TDebugInfoStabs.insertsym(list:TAsmList;sym:tsym);
  1091. function fieldvarsym_stabstr(sym:tfieldvarsym):Pchar;
  1092. begin
  1093. result:=nil;
  1094. if (sym.owner.symtabletype=objecTSymtable) and
  1095. (sp_static in sym.symoptions) then
  1096. result:=sym_stabstr_evaluate(sym,'"${ownername}__${name}:S$1",${N_LCSYM},0,${line},${mangledname}',
  1097. [def_stab_number(sym.vardef)]);
  1098. end;
  1099. function staticvarsym_stabstr(sym:tstaticvarsym):Pchar;
  1100. var
  1101. st : string;
  1102. threadvaroffset : string;
  1103. regidx : Tregisterindex;
  1104. nsym : string[7];
  1105. begin
  1106. result:=nil;
  1107. { external symbols can't be resolved at link time, so we
  1108. can't generate stabs for them }
  1109. if vo_is_external in sym.varoptions then
  1110. exit;
  1111. st:=def_stab_number(sym.vardef);
  1112. case sym.localloc.loc of
  1113. LOC_REGISTER,
  1114. LOC_CREGISTER,
  1115. LOC_MMREGISTER,
  1116. LOC_CMMREGISTER,
  1117. LOC_FPUREGISTER,
  1118. LOC_CFPUREGISTER :
  1119. begin
  1120. regidx:=findreg_by_number(sym.localloc.register);
  1121. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1122. { this is the register order for GDB}
  1123. if regidx<>0 then
  1124. result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
  1125. end;
  1126. else
  1127. begin
  1128. if (vo_is_thread_var in sym.varoptions) then
  1129. threadvaroffset:='+'+tostr(sizeof(aint))
  1130. else
  1131. threadvaroffset:='';
  1132. if (vo_is_typed_const in sym.varoptions) then
  1133. nsym:='N_STSYM'
  1134. else
  1135. nsym:='N_LCSYM';
  1136. { Here we used S instead of
  1137. because with G GDB doesn't look at the address field
  1138. but searches the same name or with a leading underscore
  1139. but these names don't exist in pascal !}
  1140. st:='S'+st;
  1141. result:=sym_stabstr_evaluate(sym,'"${name}:$1",${'+nsym+'},0,${line},${mangledname}$2',[st,threadvaroffset]);
  1142. end;
  1143. end;
  1144. end;
  1145. function localvarsym_stabstr(sym:tlocalvarsym):Pchar;
  1146. var
  1147. st : string;
  1148. regidx : Tregisterindex;
  1149. begin
  1150. result:=nil;
  1151. { There is no space allocated for not referenced locals }
  1152. if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
  1153. exit;
  1154. st:=def_stab_number(sym.vardef);
  1155. case sym.localloc.loc of
  1156. LOC_REGISTER,
  1157. LOC_CREGISTER,
  1158. LOC_MMREGISTER,
  1159. LOC_CMMREGISTER,
  1160. LOC_FPUREGISTER,
  1161. LOC_CFPUREGISTER :
  1162. begin
  1163. regidx:=findreg_by_number(sym.localloc.register);
  1164. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1165. { this is the register order for GDB}
  1166. if regidx<>0 then
  1167. result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
  1168. end;
  1169. LOC_REFERENCE :
  1170. { offset to ebp => will not work if the framepointer is esp
  1171. so some optimizing will make things harder to debug }
  1172. result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
  1173. else
  1174. internalerror(2003091814);
  1175. end;
  1176. end;
  1177. function paravarsym_stabstr(sym:tparavarsym):Pchar;
  1178. var
  1179. st : string;
  1180. regidx : Tregisterindex;
  1181. c : char;
  1182. begin
  1183. result:=nil;
  1184. { set loc to LOC_REFERENCE to get somewhat usable debugging info for -Or }
  1185. { while stabs aren't adapted for regvars yet }
  1186. if (vo_is_self in sym.varoptions) then
  1187. begin
  1188. case sym.localloc.loc of
  1189. LOC_REGISTER,
  1190. LOC_CREGISTER:
  1191. regidx:=findreg_by_number(sym.localloc.register);
  1192. LOC_REFERENCE: ;
  1193. else
  1194. internalerror(2003091815);
  1195. end;
  1196. if (po_classmethod in tabstractprocdef(sym.owner.defowner).procoptions) or
  1197. (po_staticmethod in tabstractprocdef(sym.owner.defowner).procoptions) then
  1198. begin
  1199. if (sym.localloc.loc=LOC_REFERENCE) then
  1200. result:=sym_stabstr_evaluate(sym,'"pvmt:p$1",${N_TSYM},0,0,$2',
  1201. [def_stab_number(pvmttype),tostr(sym.localloc.reference.offset)])
  1202. else
  1203. begin
  1204. regidx:=findreg_by_number(sym.localloc.register);
  1205. result:=sym_stabstr_evaluate(sym,'"pvmt:r$1",${N_RSYM},0,0,$2',
  1206. [def_stab_number(pvmttype),tostr(regstabs_table[regidx])]);
  1207. end
  1208. end
  1209. else
  1210. begin
  1211. if not(is_class(tprocdef(sym.owner.defowner)._class)) then
  1212. c:='v'
  1213. else
  1214. c:='p';
  1215. if (sym.localloc.loc=LOC_REFERENCE) then
  1216. result:=sym_stabstr_evaluate(sym,'"$$t:$1",${N_TSYM},0,0,$2',
  1217. [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(sym.localloc.reference.offset)])
  1218. else
  1219. begin
  1220. regidx:=findreg_by_number(sym.localloc.register);
  1221. result:=sym_stabstr_evaluate(sym,'"$$t:r$1",${N_RSYM},0,0,$2',
  1222. [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(regstabs_table[regidx])]);
  1223. end
  1224. end;
  1225. end
  1226. else
  1227. begin
  1228. st:=def_stab_number(sym.vardef);
  1229. if paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
  1230. not(vo_has_local_copy in sym.varoptions) and
  1231. not is_open_string(sym.vardef) then
  1232. c:='v' { should be 'i' but 'i' doesn't work }
  1233. else
  1234. c:='p';
  1235. case sym.localloc.loc of
  1236. LOC_REGISTER,
  1237. LOC_CREGISTER,
  1238. LOC_MMREGISTER,
  1239. LOC_CMMREGISTER,
  1240. LOC_FPUREGISTER,
  1241. LOC_CFPUREGISTER :
  1242. begin
  1243. if c='p' then
  1244. c:='R'
  1245. else
  1246. c:='a';
  1247. st:=c+st;
  1248. regidx:=findreg_by_number(sym.localloc.register);
  1249. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1250. { this is the register order for GDB}
  1251. if regidx<>0 then
  1252. result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_RSYM},0,${line},$2',[st,tostr(longint(regstabs_table[regidx]))]);
  1253. end;
  1254. LOC_REFERENCE :
  1255. begin
  1256. st:=c+st;
  1257. { offset to ebp => will not work if the framepointer is esp
  1258. so some optimizing will make things harder to debug }
  1259. result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
  1260. end;
  1261. else
  1262. internalerror(2003091814);
  1263. end;
  1264. end;
  1265. end;
  1266. function constsym_stabstr(sym:tconstsym):Pchar;
  1267. var
  1268. st : string;
  1269. begin
  1270. result:=nil;
  1271. { Don't write info for default parameter values, the N_Func breaks
  1272. the N_Func for the function itself.
  1273. Valgrind does not support constants }
  1274. if (sym.owner.symtabletype=parasymtable) or
  1275. (cs_gdb_valgrind in current_settings.globalswitches) then
  1276. exit;
  1277. case sym.consttyp of
  1278. conststring:
  1279. begin
  1280. if sym.value.len<200 then
  1281. st:='s'''+backspace_quote(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']),['"','\',#10,#13])+''''
  1282. else
  1283. st:='<constant string too long>';
  1284. end;
  1285. constord:
  1286. st:='i'+tostr(sym.value.valueord);
  1287. constpointer:
  1288. st:='i'+tostr(sym.value.valueordptr);
  1289. constreal:
  1290. begin
  1291. system.str(pbestreal(sym.value.valueptr)^,st);
  1292. st := 'r'+st;
  1293. end;
  1294. else
  1295. begin
  1296. { if we don't know just put zero !! }
  1297. st:='i0';
  1298. end;
  1299. end;
  1300. result:=sym_stabstr_evaluate(sym,'"${name}:c=$1;",${N_FUNCTION},0,${line},0',[st]);
  1301. end;
  1302. function typesym_stabstr(sym:ttypesym) : pchar;
  1303. var
  1304. stabchar : string[2];
  1305. begin
  1306. result:=nil;
  1307. if not assigned(sym.typedef) then
  1308. internalerror(200509262);
  1309. if sym.typedef.typ in tagtypes then
  1310. stabchar:='Tt'
  1311. else
  1312. stabchar:='t';
  1313. result:=sym_stabstr_evaluate(sym,'"${name}:$1$2",${N_LSYM},0,${line},0',[stabchar,def_stab_number(sym.typedef)]);
  1314. end;
  1315. function procsym_stabstr(sym:tprocsym) : pchar;
  1316. var
  1317. i : longint;
  1318. begin
  1319. result:=nil;
  1320. for i:=0 to sym.ProcdefList.Count-1 do
  1321. write_procdef(list,tprocdef(sym.ProcdefList[i]));
  1322. end;
  1323. var
  1324. stabstr : Pchar;
  1325. begin
  1326. stabstr:=nil;
  1327. case sym.typ of
  1328. labelsym :
  1329. stabstr:=sym_stabstr_evaluate(sym,'"${name}",${N_LSYM},0,${line},0',[]);
  1330. fieldvarsym :
  1331. stabstr:=fieldvarsym_stabstr(tfieldvarsym(sym));
  1332. staticvarsym :
  1333. stabstr:=staticvarsym_stabstr(tstaticvarsym(sym));
  1334. localvarsym :
  1335. stabstr:=localvarsym_stabstr(tlocalvarsym(sym));
  1336. paravarsym :
  1337. stabstr:=paravarsym_stabstr(tparavarsym(sym));
  1338. constsym :
  1339. stabstr:=constsym_stabstr(tconstsym(sym));
  1340. typesym :
  1341. stabstr:=typesym_stabstr(ttypesym(sym));
  1342. procsym :
  1343. stabstr:=procsym_stabstr(tprocsym(sym));
  1344. end;
  1345. if stabstr<>nil then
  1346. list.concat(Tai_stab.create(stab_stabs,stabstr));
  1347. { For object types write also the symtable entries }
  1348. if (sym.typ=typesym) and (ttypesym(sym).typedef.typ=objectdef) then
  1349. write_symtable_syms(list,tobjectdef(ttypesym(sym).typedef).symtable);
  1350. sym.isdbgwritten:=true;
  1351. end;
  1352. procedure TDebugInfoStabs.write_symtable_syms(list:TAsmList;st:TSymtable);
  1353. var
  1354. sym : tsym;
  1355. i : longint;
  1356. begin
  1357. case st.symtabletype of
  1358. staticsymtable :
  1359. list.concat(tai_comment.Create(strpnew('Syms - Begin Staticsymtable')));
  1360. globalsymtable :
  1361. list.concat(tai_comment.Create(strpnew('Syms - Begin unit '+GetSymTableName(st)+' has index '+tostr(st.moduleid))));
  1362. end;
  1363. for i:=0 to st.SymList.Count-1 do
  1364. begin
  1365. sym:=tsym(st.SymList[i]);
  1366. if not(sp_hidden in sym.symoptions) and
  1367. (not sym.isdbgwritten) then
  1368. insertsym(list,sym);
  1369. end;
  1370. case st.symtabletype of
  1371. staticsymtable :
  1372. list.concat(tai_comment.Create(strpnew('Syms - End Staticsymtable')));
  1373. globalsymtable :
  1374. list.concat(tai_comment.Create(strpnew('Syms - End unit '+GetSymTableName(st)+' has index '+tostr(st.moduleid))));
  1375. end;
  1376. end;
  1377. {****************************************************************************
  1378. Proc/Module support
  1379. ****************************************************************************}
  1380. procedure tdebuginfostabs.inserttypeinfo;
  1381. var
  1382. stabsvarlist,
  1383. stabstypelist : TAsmList;
  1384. storefilepos : tfileposinfo;
  1385. i : longint;
  1386. begin
  1387. storefilepos:=current_filepos;
  1388. current_filepos:=current_module.mainfilepos;
  1389. global_stab_number:=0;
  1390. defnumberlist:=TFPObjectlist.create(false);
  1391. stabsvarlist:=TAsmList.create;
  1392. stabstypelist:=TAsmList.create;
  1393. { include symbol that will be referenced from the main to be sure to
  1394. include this debuginfo .o file }
  1395. current_module.flags:=current_module.flags or uf_has_debuginfo;
  1396. if not(target_info.system in systems_darwin) then
  1397. begin
  1398. new_section(current_asmdata.asmlists[al_stabs],sec_data,GetSymTableName(current_module.localsymtable),0);
  1399. current_asmdata.asmlists[al_stabs].concat(tai_symbol.Createname_global(make_mangledname('DEBUGINFO',current_module.localsymtable,''),AT_DATA,0));
  1400. end
  1401. else
  1402. new_section(current_asmdata.asmlists[al_stabs],sec_code,GetSymTableName(current_module.localsymtable),0);
  1403. { first write all global/local symbols. This will flag all required tdefs }
  1404. if assigned(current_module.globalsymtable) then
  1405. write_symtable_syms(stabsvarlist,current_module.globalsymtable);
  1406. if assigned(current_module.localsymtable) then
  1407. write_symtable_syms(stabsvarlist,current_module.localsymtable);
  1408. { reset unit type info flag }
  1409. reset_unit_type_info;
  1410. { write used types from the used units }
  1411. write_used_unit_type_info(stabstypelist,current_module);
  1412. { last write the types from this unit }
  1413. if assigned(current_module.globalsymtable) then
  1414. write_symtable_defs(stabstypelist,current_module.globalsymtable);
  1415. if assigned(current_module.localsymtable) then
  1416. write_symtable_defs(stabstypelist,current_module.localsymtable);
  1417. current_asmdata.asmlists[al_stabs].concatlist(stabstypelist);
  1418. current_asmdata.asmlists[al_stabs].concatlist(stabsvarlist);
  1419. { reset stab numbers }
  1420. for i:=0 to defnumberlist.count-1 do
  1421. begin
  1422. if assigned(defnumberlist[i]) then
  1423. begin
  1424. tdef(defnumberlist[i]).stab_number:=0;
  1425. tdef(defnumberlist[i]).dbg_state:=dbg_state_unused;
  1426. end;
  1427. end;
  1428. defnumberlist.free;
  1429. defnumberlist:=nil;
  1430. stabsvarlist.free;
  1431. stabstypelist.free;
  1432. current_filepos:=storefilepos;
  1433. end;
  1434. procedure tdebuginfostabs.insertlineinfo(list:TAsmList);
  1435. var
  1436. currfileinfo,
  1437. lastfileinfo : tfileposinfo;
  1438. currfuncname : pshortstring;
  1439. currsectype : TAsmSectiontype;
  1440. hlabel : tasmlabel;
  1441. hp : tai;
  1442. infile : tinputfile;
  1443. begin
  1444. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  1445. currfuncname:=nil;
  1446. currsectype:=sec_code;
  1447. hp:=Tai(list.first);
  1448. while assigned(hp) do
  1449. begin
  1450. case hp.typ of
  1451. ait_section :
  1452. currsectype:=tai_section(hp).sectype;
  1453. ait_function_name :
  1454. currfuncname:=tai_function_name(hp).funcname;
  1455. ait_force_line :
  1456. lastfileinfo.line:=-1;
  1457. end;
  1458. if (currsectype=sec_code) and
  1459. (hp.typ=ait_instruction) then
  1460. begin
  1461. currfileinfo:=tailineinfo(hp).fileinfo;
  1462. { file changed ? (must be before line info) }
  1463. if (currfileinfo.fileindex<>0) and
  1464. ((lastfileinfo.fileindex<>currfileinfo.fileindex) or
  1465. (lastfileinfo.moduleindex<>currfileinfo.moduleindex)) then
  1466. begin
  1467. infile:=get_module(currfileinfo.moduleindex).sourcefiles.get_file(currfileinfo.fileindex);
  1468. if assigned(infile) then
  1469. begin
  1470. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1471. { emit stabs }
  1472. if (infile.path^<>'') then
  1473. list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(n_includefile)+
  1474. ',0,0,'+hlabel.name),hp);
  1475. list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+FixFileName(infile.name^)+'",'+tostr(n_includefile)+
  1476. ',0,0,'+hlabel.name),hp);
  1477. list.insertbefore(tai_label.create(hlabel),hp);
  1478. { force new line info }
  1479. lastfileinfo.line:=-1;
  1480. end;
  1481. end;
  1482. { line changed ? }
  1483. if (currfileinfo.line>lastfileinfo.line) and (currfileinfo.line<>0) then
  1484. begin
  1485. if assigned(currfuncname) and
  1486. (tf_use_function_relative_addresses in target_info.flags) then
  1487. begin
  1488. current_asmdata.getlabel(hlabel,alt_dbgline);
  1489. list.insertbefore(Tai_stab.Create_str(stab_stabn,tostr(n_textline)+',0,'+tostr(currfileinfo.line)+','+
  1490. hlabel.name+' - '+{$IFDEF POWERPC64}'.'+{$ENDIF POWERPC64}currfuncname^),hp);
  1491. list.insertbefore(tai_label.create(hlabel),hp);
  1492. end
  1493. else
  1494. list.insertbefore(Tai_stab.Create_str(stab_stabd,tostr(n_textline)+',0,'+tostr(currfileinfo.line)),hp);
  1495. end;
  1496. lastfileinfo:=currfileinfo;
  1497. end;
  1498. hp:=tai(hp.next);
  1499. end;
  1500. end;
  1501. procedure tdebuginfostabs.insertmoduleinfo;
  1502. var
  1503. hlabel : tasmlabel;
  1504. infile : tinputfile;
  1505. begin
  1506. { emit main source n_sourcefile for start of module }
  1507. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1508. infile:=current_module.sourcefiles.get_file(1);
  1509. new_section(current_asmdata.asmlists[al_start],sec_code,make_mangledname('DEBUGSTART',current_module.localsymtable,''),0,secorder_begin);
  1510. if not(target_info.system in systems_darwin) then
  1511. current_asmdata.asmlists[al_start].concat(tai_symbol.Createname_global(make_mangledname('DEBUGSTART',current_module.localsymtable,''),AT_DATA,0));
  1512. if (infile.path^<>'') then
  1513. current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(n_sourcefile)+
  1514. ',0,0,'+hlabel.name));
  1515. current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stab_stabs,'"'+FixFileName(infile.name^)+'",'+tostr(n_sourcefile)+
  1516. ',0,0,'+hlabel.name));
  1517. current_asmdata.asmlists[al_start].concat(tai_label.create(hlabel));
  1518. { for darwin, you need a "module marker" too to work around }
  1519. { either some assembler or gdb bug (radar 4386531 according to a }
  1520. { comment in dbxout.c of Apple's gcc) }
  1521. if (target_info.system in systems_darwin) then
  1522. current_asmdata.asmlists[al_end].concat(Tai_stab.Create_str(stab_stabs,'"",'+tostr(N_OSO)+',0,0,0'));
  1523. { emit empty n_sourcefile for end of module }
  1524. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1525. new_section(current_asmdata.asmlists[al_end],sec_code,make_mangledname('DEBUGEND',current_module.localsymtable,''),0,secorder_end);
  1526. if not(target_info.system in systems_darwin) then
  1527. current_asmdata.asmlists[al_end].concat(tai_symbol.Createname_global(make_mangledname('DEBUGEND',current_module.localsymtable,''),AT_DATA,0));
  1528. current_asmdata.asmlists[al_end].concat(Tai_stab.Create_str(stab_stabs,'"",'+tostr(n_sourcefile)+',0,0,'+hlabel.name));
  1529. current_asmdata.asmlists[al_end].concat(tai_label.create(hlabel));
  1530. end;
  1531. procedure tdebuginfostabs.referencesections(list:TAsmList);
  1532. var
  1533. hp : tmodule;
  1534. dbgtable : tai_symbol;
  1535. begin
  1536. { Reference all DEBUGINFO sections from the main .fpc section }
  1537. if (target_info.system in ([system_powerpc_macos]+systems_darwin)) then
  1538. exit;
  1539. list.concat(Tai_section.create(sec_fpc,'links',0));
  1540. { make sure the debuginfo doesn't get stripped out }
  1541. if (target_info.system in systems_darwin) then
  1542. begin
  1543. dbgtable:=tai_symbol.createname('DEBUGINFOTABLE',AT_DATA,0);
  1544. list.concat(tai_directive.create(asd_no_dead_strip,dbgtable.sym.name));
  1545. list.concat(dbgtable);
  1546. end;
  1547. { include reference to all debuginfo sections of used units }
  1548. hp:=tmodule(loaded_units.first);
  1549. while assigned(hp) do
  1550. begin
  1551. If (hp.flags and uf_has_debuginfo)=uf_has_debuginfo then
  1552. begin
  1553. list.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',hp.localsymtable,''),0));
  1554. list.concat(Tai_const.Createname(make_mangledname('DEBUGSTART',hp.localsymtable,''),0));
  1555. list.concat(Tai_const.Createname(make_mangledname('DEBUGEND',hp.localsymtable,''),0));
  1556. end;
  1557. hp:=tmodule(hp.next);
  1558. end;
  1559. end;
  1560. const
  1561. dbg_stabs_info : tdbginfo =
  1562. (
  1563. id : dbg_stabs;
  1564. idtxt : 'STABS';
  1565. );
  1566. initialization
  1567. RegisterDebugInfo(dbg_stabs_info,TDebugInfoStabs);
  1568. end.