dbgstabs.pas 60 KB

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