dbgstabs.pas 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561
  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. type
  26. TDebugInfoStabs=class(TDebugInfo)
  27. private
  28. writing_def_stabs : boolean;
  29. global_stab_number : word;
  30. defnumberlist : TFPObjectList;
  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:TAsmList;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:TAsmList;def:tdef);
  44. procedure write_procdef(list:TAsmList;pd:tprocdef);
  45. procedure insertsym(list:TAsmList;sym:tsym);
  46. public
  47. procedure inserttypeinfo;override;
  48. procedure insertmoduleinfo;override;
  49. procedure insertlineinfo(list:TAsmList);override;
  50. procedure referencesections(list:TAsmList);override;
  51. procedure insertdef(list:TAsmList;def:tdef);override;
  52. procedure write_symtable_defs(list:TAsmList;st:tsymtable);override;
  53. end;
  54. implementation
  55. uses
  56. SysUtils,cutils,cfileutils,
  57. systems,globals,globtype,verbose,
  58. symconst,defutil,
  59. cpuinfo,cpubase,cgbase,paramgr,
  60. aasmbase,procinfo,
  61. finput,fmodule,ppu;
  62. const
  63. memsizeinc = 512;
  64. N_GSYM = $20;
  65. N_STSYM = 38; { initialized const }
  66. N_LCSYM = 40; { non initialized variable}
  67. N_Function = $24; { function or const }
  68. N_TextLine = $44;
  69. N_DataLine = $46;
  70. N_BssLine = $48;
  71. N_RSYM = $40; { register variable }
  72. N_LSYM = $80;
  73. N_tsym = 160;
  74. N_SourceFile = $64;
  75. N_IncludeFile = $84;
  76. N_BINCL = $82;
  77. N_EINCL = $A2;
  78. N_LBRAC = $C0;
  79. N_EXCL = $C2;
  80. N_RBRAC = $E0;
  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 pshortstring;
  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[0];
  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]:=pshortstring(varptr);
  145. if varptr>@varvaluedata[maxdata] then
  146. internalerrorproc(200411152);
  147. pshortstring(varptr)^:=get_var_value(varname,get_var_value_arg);
  148. inc(len,length(pshortstring(varptr)^));
  149. inc(varptr,length(pshortstring(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.dbg_state:=dbg_state_written;
  221. { Stab must already be written, or we must be busy writing it }
  222. if writing_def_stabs and
  223. not(def.dbg_state in [dbg_state_writing,dbg_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.dbg_state=dbg_state_unused then
  229. def.dbg_state:=dbg_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).vardef.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).vardef),
  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. freemem(newrec);
  308. {This should be used for case !!}
  309. inc(state^.recoffset,Tfieldvarsym(p).vardef.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.vardef.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.vardef.typesym) then
  365. begin
  366. arglength := length(Parasym.vardef.typesym.name);
  367. argnames := argnames + tostr(arglength)+Parasym.vardef.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.returndef),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. freemem(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);
  412. bytest:=def_stab_number(u8inttype);
  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);
  419. bytest:=def_stab_number(u8inttype);
  420. longst:=def_stab_number(u32inttype);
  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);
  428. result:=strpnew('*'+charst);
  429. end;
  430. st_widestring:
  431. begin
  432. { looks like a pwidechar }
  433. charst:=def_stab_number(cwidechartype);
  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 current_settings.globalswitches then
  476. begin
  477. case def.typ of
  478. uvoid :
  479. result:=strpnew(def_stab_number(def));
  480. bool8bit,
  481. bool16bit,
  482. bool32bit,
  483. bool64bit :
  484. result:=def_stabstr_evaluate(def,'r${numberstring};0;255;',[]);
  485. u32bit,
  486. s64bit,
  487. u64bit :
  488. result:=def_stabstr_evaluate(def,'r${numberstring};0;-1;',[]);
  489. else
  490. result:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low)),tostr(longint(def.high))]);
  491. end;
  492. end
  493. else
  494. begin
  495. case def.typ of
  496. uvoid :
  497. result:=strpnew(def_stab_number(def));
  498. uchar :
  499. result:=strpnew('-20;');
  500. uwidechar :
  501. result:=strpnew('-30;');
  502. bool8bit :
  503. result:=strpnew('-21;');
  504. bool16bit :
  505. result:=strpnew('-22;');
  506. bool32bit :
  507. result:=strpnew('-23;');
  508. bool64bit :
  509. { no clue if this is correct (FK) }
  510. result:=strpnew('-23;');
  511. u64bit :
  512. result:=strpnew('-32;');
  513. s64bit :
  514. result:=strpnew('-31;');
  515. {u32bit : result:=def_stab_number(s32inttype)+';0;-1;'); }
  516. else
  517. result:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low)),tostr(longint(def.high))]);
  518. end;
  519. end;
  520. end;
  521. function floatdef_stabstr(def:tfloatdef):Pchar;
  522. begin
  523. case def.typ of
  524. s32real,
  525. s64real,
  526. s80real:
  527. result:=def_stabstr_evaluate(def,'r$1;${savesize};0;',[def_stab_number(s32inttype)]);
  528. s64currency,
  529. s64comp:
  530. result:=def_stabstr_evaluate(def,'r$1;-${savesize};0;',[def_stab_number(s32inttype)]);
  531. else
  532. internalerror(200509261);
  533. end;
  534. end;
  535. function filedef_stabstr(def:tfiledef):pchar;
  536. begin
  537. {$ifdef cpu64bit}
  538. result:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$2,64,64;'+
  539. '_PRIVATE:ar$1;1;64;$3,128,256;USERDATA:ar$1;1;16;$3,384,128;'+
  540. 'NAME:ar$1;0;255;$4,512,2048;;',[def_stab_number(s32inttype),
  541. def_stab_number(s64inttype),
  542. def_stab_number(u8inttype),
  543. def_stab_number(cchartype)]);
  544. {$else cpu64bit}
  545. result:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$1,64,32;'+
  546. '_PRIVATE:ar$1;1;32;$3,96,256;USERDATA:ar$1;1;16;$2,352,128;'+
  547. 'NAME:ar$1;0;255;$3,480,2048;;',[def_stab_number(s32inttype),
  548. def_stab_number(u8inttype),
  549. def_stab_number(cchartype)]);
  550. {$endif cpu64bit}
  551. end;
  552. function procdef_stabstr(def:tprocdef):pchar;
  553. Var
  554. RType : Char;
  555. Obj,Info : String;
  556. stabsstr : string;
  557. p : pchar;
  558. begin
  559. obj := def.procsym.name;
  560. info := '';
  561. if (po_global in def.procoptions) then
  562. RType := 'F'
  563. else
  564. RType := 'f';
  565. if assigned(def.owner) then
  566. begin
  567. if (def.owner.symtabletype = objectsymtable) then
  568. obj := def.owner.name^+'__'+def.procsym.name;
  569. if not(cs_gdb_valgrind in current_settings.globalswitches) and
  570. (def.owner.symtabletype=localsymtable) and
  571. assigned(def.owner.defowner) and
  572. assigned(tprocdef(def.owner.defowner).procsym) then
  573. info := ','+def.procsym.name+','+tprocdef(def.owner.defowner).procsym.name;
  574. end;
  575. stabsstr:=def.mangledname;
  576. getmem(p,length(stabsstr)+255);
  577. strpcopy(p,'"'+obj+':'+RType
  578. +def_stab_number(def.returndef)+info+'",'+tostr(n_function)
  579. +',0,'+
  580. tostr(def.fileinfo.line)
  581. +',');
  582. strpcopy(strend(p),stabsstr);
  583. getmem(result,strlen(p)+1);
  584. move(p^,result^,strlen(p)+1);
  585. freemem(p);
  586. end;
  587. function recorddef_stabstr(def:trecorddef):pchar;
  588. var
  589. state : Trecord_stabgen_state;
  590. begin
  591. getmem(state.stabstring,memsizeinc);
  592. state.staballoc:=memsizeinc;
  593. strpcopy(state.stabstring,'s'+tostr(def.size));
  594. state.recoffset:=0;
  595. state.stabsize:=strlen(state.stabstring);
  596. def.symtable.foreach(@field_add_stabstr,@state);
  597. state.stabstring[state.stabsize]:=';';
  598. state.stabstring[state.stabsize+1]:=#0;
  599. reallocmem(state.stabstring,state.stabsize+2);
  600. result:=state.stabstring;
  601. end;
  602. function objectdef_stabstr(def:tobjectdef):pchar;
  603. var
  604. anc : tobjectdef;
  605. state :Trecord_stabgen_state;
  606. ts : string;
  607. begin
  608. { Write the invisible pointer for the class? }
  609. if (def.objecttype=odt_class) and
  610. (not def.writing_class_record_dbginfo) then
  611. begin
  612. result:=strpnew('*'+def_stab_classnumber(def));
  613. exit;
  614. end;
  615. state.staballoc:=memsizeinc;
  616. getmem(state.stabstring,state.staballoc);
  617. strpcopy(state.stabstring,'s'+tostr(tobjectsymtable(def.symtable).datasize));
  618. if assigned(def.childof) then
  619. begin
  620. {only one ancestor not virtual, public, at base offset 0 }
  621. { !1 , 0 2 0 , }
  622. strpcopy(strend(state.stabstring),'!1,020,'+def_stab_classnumber(def.childof)+';');
  623. end;
  624. {virtual table to implement yet}
  625. state.recoffset:=0;
  626. state.stabsize:=strlen(state.stabstring);
  627. def.symtable.foreach(@field_add_stabstr,@state);
  628. if (oo_has_vmt in def.objectoptions) then
  629. if not assigned(def.childof) or not(oo_has_vmt in def.childof.objectoptions) then
  630. begin
  631. ts:='$vf'+def_stab_classnumber(def)+':'+def_stab_number(vmtarraytype)+','+tostr(def.vmt_offset*8)+';';
  632. strpcopy(state.stabstring+state.stabsize,ts);
  633. inc(state.stabsize,length(ts));
  634. end;
  635. def.symtable.foreach(@method_add_stabstr,@state);
  636. if (oo_has_vmt in def.objectoptions) then
  637. begin
  638. anc := def;
  639. while assigned(anc.childof) and (oo_has_vmt in anc.childof.objectoptions) do
  640. anc := anc.childof;
  641. { just in case anc = self }
  642. ts:=';~%'+def_stab_classnumber(anc)+';';
  643. end
  644. else
  645. ts:=';';
  646. strpcopy(state.stabstring+state.stabsize,ts);
  647. inc(state.stabsize,length(ts));
  648. reallocmem(state.stabstring,state.stabsize+1);
  649. result:=state.stabstring;
  650. end;
  651. begin
  652. result:=nil;
  653. case def.deftype of
  654. stringdef :
  655. result:=stringdef_stabstr(tstringdef(def));
  656. enumdef :
  657. result:=enumdef_stabstr(tenumdef(def));
  658. orddef :
  659. result:=orddef_stabstr(torddef(def));
  660. floatdef :
  661. result:=floatdef_stabstr(tfloatdef(def));
  662. filedef :
  663. result:=filedef_stabstr(tfiledef(def));
  664. recorddef :
  665. result:=recorddef_stabstr(trecorddef(def));
  666. variantdef :
  667. result:=def_stabstr_evaluate(def,'formal${numberstring};',[]);
  668. pointerdef :
  669. result:=strpnew('*'+def_stab_number(tpointerdef(def).pointeddef));
  670. classrefdef :
  671. result:=strpnew(def_stab_number(pvmttype));
  672. setdef :
  673. result:=def_stabstr_evaluate(def,'@s$1;S$2',[tostr(def.size*8),def_stab_number(tsetdef(def).elementdef)]);
  674. formaldef :
  675. result:=def_stabstr_evaluate(def,'formal${numberstring};',[]);
  676. arraydef :
  677. if not is_packed_array(def) then
  678. result:=def_stabstr_evaluate(def,'ar$1;$2;$3;$4',[def_stab_number(tarraydef(def).rangedef),
  679. tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementdef)])
  680. else
  681. // will only show highrange-lowrange+1 bits in gdb
  682. result:=def_stabstr_evaluate(def,'@s$1;@S;S$2',
  683. [tostr(TConstExprInt(tarraydef(def).elepackedbitsize) * tarraydef(def).elecount),def_stabstr_evaluate(tarraydef(def).rangedef,'r${numberstring};$1;$2;',
  684. [tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange)
  685. ])]);
  686. // the @P seems to be ignored by gdb
  687. // 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)]);
  688. procdef :
  689. result:=procdef_stabstr(tprocdef(def));
  690. procvardef :
  691. result:=strpnew('*f'+def_stab_number(tprocvardef(def).returndef));
  692. objectdef :
  693. result:=objectdef_stabstr(tobjectdef(def));
  694. undefineddef :
  695. result:=def_stabstr_evaluate(def,'formal${numberstring};',[]);
  696. end;
  697. if result=nil then
  698. internalerror(200512203);
  699. end;
  700. procedure TDebugInfoStabs.write_def_stabstr(list:TAsmList;def:tdef);
  701. var
  702. stabchar : string[2];
  703. ss,st,su : pchar;
  704. begin
  705. { procdefs require a different stabs style without type prefix }
  706. if def.deftype=procdef then
  707. begin
  708. st:=def_stabstr(def);
  709. { add to list }
  710. list.concat(Tai_stab.create(stab_stabs,st));
  711. end
  712. else
  713. begin
  714. { type prefix }
  715. if def.deftype in tagtypes then
  716. stabchar := 'Tt'
  717. else
  718. stabchar := 't';
  719. { Here we maybe generate a type, so we have to use numberstring }
  720. if is_class(def) and
  721. tobjectdef(def).writing_class_record_dbginfo then
  722. st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_classnumber(tobjectdef(def))])
  723. else
  724. st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_number(def)]);
  725. ss:=def_stabstr(def);
  726. reallocmem(st,strlen(ss)+512);
  727. { line info is set to 0 for all defs, because the def can be in an other
  728. unit and then the linenumber is invalid in the current sourcefile }
  729. su:=def_stabstr_evaluate(def,'",${N_LSYM},0,0,0',[]);
  730. strcopy(strecopy(strend(st),ss),su);
  731. reallocmem(st,strlen(st)+1);
  732. freemem(ss);
  733. freemem(su);
  734. { add to list }
  735. list.concat(Tai_stab.create(stab_stabs,st));
  736. end;
  737. end;
  738. procedure TDebugInfoStabs.insertdef(list:TAsmList;def:tdef);
  739. var
  740. anc : tobjectdef;
  741. oldtypesym : tsym;
  742. begin
  743. if (def.dbg_state in [dbg_state_writing,dbg_state_written]) then
  744. exit;
  745. { never write generic template defs }
  746. if df_generic in def.defoptions then
  747. begin
  748. def.dbg_state:=dbg_state_written;
  749. exit;
  750. end;
  751. { to avoid infinite loops }
  752. def.dbg_state := dbg_state_writing;
  753. { write dependencies first }
  754. case def.deftype of
  755. stringdef :
  756. begin
  757. if tstringdef(def).string_typ=st_widestring then
  758. insertdef(list,cwidechartype)
  759. else
  760. begin
  761. insertdef(list,cchartype);
  762. insertdef(list,u8inttype);
  763. end;
  764. end;
  765. floatdef :
  766. insertdef(list,s32inttype);
  767. filedef :
  768. begin
  769. insertdef(list,s32inttype);
  770. {$ifdef cpu64bit}
  771. insertdef(list,s64inttype);
  772. {$endif cpu64bit}
  773. insertdef(list,u8inttype);
  774. insertdef(list,cchartype);
  775. end;
  776. classrefdef :
  777. insertdef(list,pvmttype);
  778. pointerdef :
  779. insertdef(list,tpointerdef(def).pointeddef);
  780. setdef :
  781. insertdef(list,tsetdef(def).elementdef);
  782. procvardef,
  783. procdef :
  784. insertdef(list,tabstractprocdef(def).returndef);
  785. arraydef :
  786. begin
  787. insertdef(list,tarraydef(def).rangedef);
  788. insertdef(list,tarraydef(def).elementdef);
  789. end;
  790. recorddef :
  791. trecorddef(def).symtable.foreach(@field_write_defs,list);
  792. enumdef :
  793. if assigned(tenumdef(def).basedef) then
  794. insertdef(list,tenumdef(def).basedef);
  795. objectdef :
  796. begin
  797. insertdef(list,vmtarraytype);
  798. { first the parents }
  799. anc:=tobjectdef(def);
  800. while assigned(anc.childof) do
  801. begin
  802. anc:=anc.childof;
  803. insertdef(list,anc);
  804. end;
  805. tobjectdef(def).symtable.foreach(@field_write_defs,list);
  806. tobjectdef(def).symtable.foreach(@method_write_defs,list);
  807. end;
  808. end;
  809. case def.deftype of
  810. objectdef :
  811. begin
  812. { classes require special code to write the record and the invisible pointer }
  813. if is_class(def) then
  814. begin
  815. { Write the record class itself }
  816. tobjectdef(def).writing_class_record_dbginfo:=true;
  817. write_def_stabstr(list,def);
  818. tobjectdef(def).writing_class_record_dbginfo:=false;
  819. { Write the invisible pointer class }
  820. oldtypesym:=def.typesym;
  821. def.typesym:=nil;
  822. write_def_stabstr(list,def);
  823. def.typesym:=oldtypesym;
  824. end
  825. else
  826. write_def_stabstr(list,def);
  827. { VMT symbol }
  828. if (oo_has_vmt in tobjectdef(def).objectoptions) and
  829. assigned(def.owner) and
  830. assigned(def.owner.name) then
  831. list.concat(Tai_stab.create(stab_stabs,strpnew('"vmt_'+def.owner.name^+tobjectdef(def).name+':S'+
  832. def_stab_number(vmttype)+'",'+tostr(N_STSYM)+',0,0,'+tobjectdef(def).vmt_mangledname)));
  833. end;
  834. procdef :
  835. begin
  836. { procdefs are handled separatly }
  837. end;
  838. else
  839. write_def_stabstr(list,def);
  840. end;
  841. def.dbg_state := dbg_state_written;
  842. end;
  843. procedure TDebugInfoStabs.write_symtable_defs(list:TAsmList;st:tsymtable);
  844. procedure dowritestabs(list:TAsmList;st:tsymtable);
  845. var
  846. p : tdef;
  847. begin
  848. p:=tdef(st.defindex.first);
  849. while assigned(p) do
  850. begin
  851. if (p.dbg_state=dbg_state_used) then
  852. insertdef(list,p);
  853. p:=tdef(p.indexnext);
  854. end;
  855. end;
  856. var
  857. old_writing_def_stabs : boolean;
  858. begin
  859. case st.symtabletype of
  860. staticsymtable :
  861. list.concat(tai_comment.Create(strpnew('Defs - Begin Staticsymtable')));
  862. globalsymtable :
  863. list.concat(tai_comment.Create(strpnew('Defs - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
  864. end;
  865. old_writing_def_stabs:=writing_def_stabs;
  866. writing_def_stabs:=true;
  867. dowritestabs(list,st);
  868. writing_def_stabs:=old_writing_def_stabs;
  869. case st.symtabletype of
  870. staticsymtable :
  871. list.concat(tai_comment.Create(strpnew('Defs - End Staticsymtable')));
  872. globalsymtable :
  873. list.concat(tai_comment.Create(strpnew('Defs - End unit '+st.name^+' has index '+tostr(st.moduleid))));
  874. end;
  875. end;
  876. procedure TDebugInfoStabs.write_procdef(list:TAsmList;pd:tprocdef);
  877. var
  878. templist : TAsmList;
  879. stabsendlabel : tasmlabel;
  880. mangled_length : longint;
  881. p,p1 : pchar;
  882. hs : string;
  883. begin
  884. if assigned(pd.procstarttai) then
  885. begin
  886. templist:=TAsmList.create;
  887. { end of procedure }
  888. current_asmdata.getlabel(stabsendlabel,alt_dbgtype);
  889. templist.concat(tai_label.create(stabsendlabel));
  890. current_asmdata.asmlists[al_procedures].insertlistbefore(pd.procendtai,templist);
  891. if assigned(pd.funcretsym) and
  892. (tabstractnormalvarsym(pd.funcretsym).refs>0) then
  893. begin
  894. if tabstractnormalvarsym(pd.funcretsym).localloc.loc=LOC_REFERENCE then
  895. begin
  896. {$warning Need to add gdb support for ret in param register calling}
  897. if paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
  898. hs:='X*'
  899. else
  900. hs:='X';
  901. templist.concat(Tai_stab.create(stab_stabs,strpnew(
  902. '"'+pd.procsym.name+':'+hs+def_stab_number(pd.returndef)+'",'+
  903. tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(pd.funcretsym).localloc.reference.offset))));
  904. if (m_result in current_settings.modeswitches) then
  905. templist.concat(Tai_stab.create(stab_stabs,strpnew(
  906. '"RESULT:'+hs+def_stab_number(pd.returndef)+'",'+
  907. tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(pd.funcretsym).localloc.reference.offset))));
  908. end;
  909. end;
  910. mangled_length:=length(pd.mangledname);
  911. getmem(p,2*mangled_length+50);
  912. strpcopy(p,tostr(N_LBRAC)+',0,0,');
  913. {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
  914. strpcopy(strend(p),pd.mangledname);
  915. if (tf_use_function_relative_addresses in target_info.flags) then
  916. begin
  917. strpcopy(strend(p),'-');
  918. {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
  919. strpcopy(strend(p),pd.mangledname);
  920. end;
  921. getmem(p1,strlen(p)+1);
  922. move(p^,p1^,strlen(p)+1);
  923. templist.concat(Tai_stab.Create(stab_stabn,p1));
  924. strpcopy(p,tostr(N_RBRAC)+',0,0,'+stabsendlabel.name);
  925. if (tf_use_function_relative_addresses in target_info.flags) then
  926. begin
  927. strpcopy(strend(p),'-');
  928. {$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
  929. strpcopy(strend(p),pd.mangledname);
  930. end;
  931. getmem(p1,strlen(p)+1);
  932. move(p^,p1^,strlen(p)+1);
  933. templist.concat(Tai_stab.Create(stab_stabn,p1));
  934. freemem(p,2*mangled_length+50);
  935. current_asmdata.asmlists[al_procedures].insertlistafter(pd.procendtai,templist);
  936. { "The stab representing a procedure is located immediately
  937. following the code of the procedure. This stab is in turn
  938. directly followed by a group of other stabs describing
  939. elements of the procedure. These other stabs describe the
  940. procedure's parameters, its block local variables, and its
  941. block structure." (stab docs) }
  942. { this is however incorrect in case "include source" statements }
  943. { appear in the block, in that case the procedure stab must }
  944. { appear before this include stabs (and we generate such an }
  945. { stabs for all functions) (JM) }
  946. { procdef }
  947. write_def_stabstr(templist,pd);
  948. current_asmdata.asmlists[al_procedures].insertlistbefore(pd.procstarttai,templist);
  949. { para types }
  950. if assigned(pd.parast) then
  951. write_symtable_syms(templist,pd.parast);
  952. { local type defs and vars should not be written
  953. inside the main proc stab }
  954. if assigned(pd.localst) and
  955. (pd.localst.symtabletype=localsymtable) then
  956. write_symtable_syms(templist,pd.localst);
  957. { after the endtai, because the ".size" must come before it }
  958. current_asmdata.asmlists[al_procedures].insertlistafter(pd.procendtai,templist);
  959. templist.free;
  960. end;
  961. end;
  962. {****************************************************************************
  963. TSym support
  964. ****************************************************************************}
  965. function TDebugInfoStabs.sym_var_value(const s:string;arg:pointer):string;
  966. var
  967. sym : tsym;
  968. begin
  969. sym:=tsym(arg);
  970. result:='';
  971. if s='name' then
  972. result:=sym.name
  973. else if s='mangledname' then
  974. result:=sym.mangledname
  975. else if s='ownername' then
  976. result:=sym.owner.name^
  977. else if s='line' then
  978. result:=tostr(sym.fileinfo.line)
  979. else if s='N_LSYM' then
  980. result:=tostr(N_LSYM)
  981. else if s='N_LCSYM' then
  982. result:=tostr(N_LCSYM)
  983. else if s='N_RSYM' then
  984. result:=tostr(N_RSYM)
  985. else if s='N_TSYM' then
  986. result:=tostr(N_TSYM)
  987. else if s='N_STSYM' then
  988. result:=tostr(N_STSYM)
  989. else if s='N_FUNCTION' then
  990. result:=tostr(N_FUNCTION)
  991. else
  992. internalerror(200401152);
  993. end;
  994. function TDebugInfoStabs.sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):Pchar;
  995. begin
  996. result:=string_evaluate(s,@sym_var_value,sym,vars);
  997. end;
  998. procedure TDebugInfoStabs.insertsym(list:TAsmList;sym:tsym);
  999. function fieldvarsym_stabstr(sym:tfieldvarsym):Pchar;
  1000. begin
  1001. result:=nil;
  1002. if (sym.owner.symtabletype=objectsymtable) and
  1003. (sp_static in sym.symoptions) then
  1004. result:=sym_stabstr_evaluate(sym,'"${ownername}__${name}:S$1",${N_LCSYM},0,${line},${mangledname}',
  1005. [def_stab_number(sym.vardef)]);
  1006. end;
  1007. function globalvarsym_stabstr(sym:tglobalvarsym):Pchar;
  1008. var
  1009. st : string;
  1010. threadvaroffset : string;
  1011. regidx : Tregisterindex;
  1012. begin
  1013. result:=nil;
  1014. { external symbols can't be resolved at link time, so we
  1015. can't generate stabs for them }
  1016. if vo_is_external in sym.varoptions then
  1017. exit;
  1018. st:=def_stab_number(sym.vardef);
  1019. case sym.localloc.loc of
  1020. LOC_REGISTER,
  1021. LOC_CREGISTER,
  1022. LOC_MMREGISTER,
  1023. LOC_CMMREGISTER,
  1024. LOC_FPUREGISTER,
  1025. LOC_CFPUREGISTER :
  1026. begin
  1027. regidx:=findreg_by_number(sym.localloc.register);
  1028. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1029. { this is the register order for GDB}
  1030. if regidx<>0 then
  1031. result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
  1032. end;
  1033. else
  1034. begin
  1035. if (vo_is_thread_var in sym.varoptions) then
  1036. threadvaroffset:='+'+tostr(sizeof(aint))
  1037. else
  1038. threadvaroffset:='';
  1039. { Here we used S instead of
  1040. because with G GDB doesn't look at the address field
  1041. but searches the same name or with a leading underscore
  1042. but these names don't exist in pascal !}
  1043. st:='S'+st;
  1044. result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_LCSYM},0,${line},${mangledname}$2',[st,threadvaroffset]);
  1045. end;
  1046. end;
  1047. end;
  1048. function localvarsym_stabstr(sym:tlocalvarsym):Pchar;
  1049. var
  1050. st : string;
  1051. regidx : Tregisterindex;
  1052. begin
  1053. result:=nil;
  1054. { There is no space allocated for not referenced locals }
  1055. if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
  1056. exit;
  1057. st:=def_stab_number(sym.vardef);
  1058. case sym.localloc.loc of
  1059. LOC_REGISTER,
  1060. LOC_CREGISTER,
  1061. LOC_MMREGISTER,
  1062. LOC_CMMREGISTER,
  1063. LOC_FPUREGISTER,
  1064. LOC_CFPUREGISTER :
  1065. begin
  1066. regidx:=findreg_by_number(sym.localloc.register);
  1067. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1068. { this is the register order for GDB}
  1069. if regidx<>0 then
  1070. result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
  1071. end;
  1072. LOC_REFERENCE :
  1073. { offset to ebp => will not work if the framepointer is esp
  1074. so some optimizing will make things harder to debug }
  1075. result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
  1076. else
  1077. internalerror(2003091814);
  1078. end;
  1079. end;
  1080. function paravarsym_stabstr(sym:tparavarsym):Pchar;
  1081. var
  1082. st : string;
  1083. regidx : Tregisterindex;
  1084. c : char;
  1085. begin
  1086. result:=nil;
  1087. { set loc to LOC_REFERENCE to get somewhat usable debugging info for -Or }
  1088. { while stabs aren't adapted for regvars yet }
  1089. if (vo_is_self in sym.varoptions) then
  1090. begin
  1091. case sym.localloc.loc of
  1092. LOC_REGISTER,
  1093. LOC_CREGISTER:
  1094. regidx:=findreg_by_number(sym.localloc.register);
  1095. LOC_REFERENCE: ;
  1096. else
  1097. internalerror(2003091815);
  1098. end;
  1099. if (po_classmethod in tabstractprocdef(sym.owner.defowner).procoptions) or
  1100. (po_staticmethod in tabstractprocdef(sym.owner.defowner).procoptions) then
  1101. begin
  1102. if (sym.localloc.loc=LOC_REFERENCE) then
  1103. result:=sym_stabstr_evaluate(sym,'"pvmt:p$1",${N_TSYM},0,0,$2',
  1104. [def_stab_number(pvmttype),tostr(sym.localloc.reference.offset)]);
  1105. (* else
  1106. result:=sym_stabstr_evaluate(sym,'"pvmt:r$1",${N_RSYM},0,0,$2',
  1107. [def_stab_number(pvmttype),tostr(regstabs_table[regidx])]) *)
  1108. end
  1109. else
  1110. begin
  1111. if not(is_class(tprocdef(sym.owner.defowner)._class)) then
  1112. c:='v'
  1113. else
  1114. c:='p';
  1115. if (sym.localloc.loc=LOC_REFERENCE) then
  1116. result:=sym_stabstr_evaluate(sym,'"$$t:$1",${N_TSYM},0,0,$2',
  1117. [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(sym.localloc.reference.offset)]);
  1118. (* else
  1119. result:=sym_stabstr_evaluate(sym,'"$$t:r$1",${N_RSYM},0,0,$2',
  1120. [c+def_stab_number(tprocdef(sym.owner.defowner)._class),tostr(regstabs_table[regidx])]); *)
  1121. end;
  1122. end
  1123. else
  1124. begin
  1125. st:=def_stab_number(sym.vardef);
  1126. if paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
  1127. not(vo_has_local_copy in sym.varoptions) and
  1128. not is_open_string(sym.vardef) then
  1129. st := 'v'+st { should be 'i' but 'i' doesn't work }
  1130. else
  1131. st := 'p'+st;
  1132. case sym.localloc.loc of
  1133. LOC_REGISTER,
  1134. LOC_CREGISTER,
  1135. LOC_MMREGISTER,
  1136. LOC_CMMREGISTER,
  1137. LOC_FPUREGISTER,
  1138. LOC_CFPUREGISTER :
  1139. begin
  1140. regidx:=findreg_by_number(sym.localloc.register);
  1141. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1142. { this is the register order for GDB}
  1143. if regidx<>0 then
  1144. result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(longint(regstabs_table[regidx]))]);
  1145. end;
  1146. LOC_REFERENCE :
  1147. { offset to ebp => will not work if the framepointer is esp
  1148. so some optimizing will make things harder to debug }
  1149. result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
  1150. else
  1151. internalerror(2003091814);
  1152. end;
  1153. end;
  1154. end;
  1155. function constsym_stabstr(sym:tconstsym):Pchar;
  1156. var
  1157. st : string;
  1158. begin
  1159. result:=nil;
  1160. { Don't write info for default parameter values, the N_Func breaks
  1161. the N_Func for the function itself.
  1162. Valgrind does not support constants }
  1163. if (sym.owner.symtabletype=parasymtable) or
  1164. (cs_gdb_valgrind in current_settings.globalswitches) then
  1165. exit;
  1166. case sym.consttyp of
  1167. conststring:
  1168. begin
  1169. if sym.value.len<200 then
  1170. st:='s'''+backspace_quote(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']),['"','\',#10,#13])+''''
  1171. else
  1172. st:='<constant string too long>';
  1173. end;
  1174. constord:
  1175. st:='i'+tostr(sym.value.valueord);
  1176. constpointer:
  1177. st:='i'+tostr(sym.value.valueordptr);
  1178. constreal:
  1179. begin
  1180. system.str(pbestreal(sym.value.valueptr)^,st);
  1181. st := 'r'+st;
  1182. end;
  1183. else
  1184. begin
  1185. { if we don't know just put zero !! }
  1186. st:='i0';
  1187. end;
  1188. end;
  1189. result:=sym_stabstr_evaluate(sym,'"${name}:c=$1;",${N_FUNCTION},0,${line},0',[st]);
  1190. end;
  1191. function typesym_stabstr(sym:ttypesym) : pchar;
  1192. var
  1193. stabchar : string[2];
  1194. begin
  1195. result:=nil;
  1196. if not assigned(sym.typedef) then
  1197. internalerror(200509262);
  1198. if sym.typedef.deftype in tagtypes then
  1199. stabchar:='Tt'
  1200. else
  1201. stabchar:='t';
  1202. result:=sym_stabstr_evaluate(sym,'"${name}:$1$2",${N_LSYM},0,${line},0',[stabchar,def_stab_number(sym.typedef)]);
  1203. end;
  1204. function procsym_stabstr(sym:tprocsym) : pchar;
  1205. var
  1206. i : longint;
  1207. begin
  1208. result:=nil;
  1209. for i:=1 to sym.procdef_count do
  1210. write_procdef(list,sym.procdef[i]);
  1211. end;
  1212. var
  1213. stabstr : Pchar;
  1214. begin
  1215. stabstr:=nil;
  1216. case sym.typ of
  1217. labelsym :
  1218. stabstr:=sym_stabstr_evaluate(sym,'"${name}",${N_LSYM},0,${line},0',[]);
  1219. fieldvarsym :
  1220. stabstr:=fieldvarsym_stabstr(tfieldvarsym(sym));
  1221. globalvarsym :
  1222. stabstr:=globalvarsym_stabstr(tglobalvarsym(sym));
  1223. localvarsym :
  1224. stabstr:=localvarsym_stabstr(tlocalvarsym(sym));
  1225. paravarsym :
  1226. stabstr:=paravarsym_stabstr(tparavarsym(sym));
  1227. typedconstsym :
  1228. stabstr:=sym_stabstr_evaluate(sym,'"${name}:S$1",${N_STSYM},0,${line},${mangledname}',
  1229. [def_stab_number(ttypedconstsym(sym).typedconstdef)]);
  1230. constsym :
  1231. stabstr:=constsym_stabstr(tconstsym(sym));
  1232. typesym :
  1233. stabstr:=typesym_stabstr(ttypesym(sym));
  1234. procsym :
  1235. stabstr:=procsym_stabstr(tprocsym(sym));
  1236. end;
  1237. if stabstr<>nil then
  1238. list.concat(Tai_stab.create(stab_stabs,stabstr));
  1239. { For object types write also the symtable entries }
  1240. if (sym.typ=typesym) and (ttypesym(sym).typedef.deftype=objectdef) then
  1241. write_symtable_syms(list,tobjectdef(ttypesym(sym).typedef).symtable);
  1242. sym.isdbgwritten:=true;
  1243. end;
  1244. procedure TDebugInfoStabs.write_symtable_syms(list:TAsmList;st:tsymtable);
  1245. var
  1246. p : tsym;
  1247. begin
  1248. case st.symtabletype of
  1249. staticsymtable :
  1250. list.concat(tai_comment.Create(strpnew('Syms - Begin Staticsymtable')));
  1251. globalsymtable :
  1252. list.concat(tai_comment.Create(strpnew('Syms - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
  1253. end;
  1254. p:=tsym(st.symindex.first);
  1255. while assigned(p) do
  1256. begin
  1257. if (not p.isdbgwritten) then
  1258. insertsym(list,p);
  1259. p:=tsym(p.indexnext);
  1260. end;
  1261. case st.symtabletype of
  1262. staticsymtable :
  1263. list.concat(tai_comment.Create(strpnew('Syms - End Staticsymtable')));
  1264. globalsymtable :
  1265. list.concat(tai_comment.Create(strpnew('Syms - End unit '+st.name^+' has index '+tostr(st.moduleid))));
  1266. end;
  1267. end;
  1268. {****************************************************************************
  1269. Proc/Module support
  1270. ****************************************************************************}
  1271. procedure tdebuginfostabs.inserttypeinfo;
  1272. var
  1273. stabsvarlist,
  1274. stabstypelist : TAsmList;
  1275. storefilepos : tfileposinfo;
  1276. i : longint;
  1277. begin
  1278. storefilepos:=current_filepos;
  1279. current_filepos:=current_module.mainfilepos;
  1280. global_stab_number:=0;
  1281. defnumberlist:=TFPObjectlist.create(false);
  1282. stabsvarlist:=TAsmList.create;
  1283. stabstypelist:=TAsmList.create;
  1284. { include symbol that will be referenced from the main to be sure to
  1285. include this debuginfo .o file }
  1286. current_module.flags:=current_module.flags or uf_has_debuginfo;
  1287. new_section(current_asmdata.asmlists[al_stabs],sec_data,current_module.localsymtable.name^,0);
  1288. current_asmdata.asmlists[al_stabs].concat(tai_symbol.Createname_global(make_mangledname('DEBUGINFO',current_module.localsymtable,''),AT_DATA,0));
  1289. { first write all global/local symbols. This will flag all required tdefs }
  1290. if assigned(current_module.globalsymtable) then
  1291. write_symtable_syms(stabsvarlist,current_module.globalsymtable);
  1292. if assigned(current_module.localsymtable) then
  1293. write_symtable_syms(stabsvarlist,current_module.localsymtable);
  1294. { reset unit type info flag }
  1295. reset_unit_type_info;
  1296. { write used types from the used units }
  1297. write_used_unit_type_info(stabstypelist,current_module);
  1298. { last write the types from this unit }
  1299. if assigned(current_module.globalsymtable) then
  1300. write_symtable_defs(stabstypelist,current_module.globalsymtable);
  1301. if assigned(current_module.localsymtable) then
  1302. write_symtable_defs(stabstypelist,current_module.localsymtable);
  1303. current_asmdata.asmlists[al_stabs].concatlist(stabstypelist);
  1304. current_asmdata.asmlists[al_stabs].concatlist(stabsvarlist);
  1305. { reset stab numbers }
  1306. for i:=0 to defnumberlist.count-1 do
  1307. begin
  1308. if assigned(defnumberlist[i]) then
  1309. begin
  1310. tdef(defnumberlist[i]).stab_number:=0;
  1311. tdef(defnumberlist[i]).dbg_state:=dbg_state_unused;
  1312. end;
  1313. end;
  1314. defnumberlist.free;
  1315. defnumberlist:=nil;
  1316. stabsvarlist.free;
  1317. stabstypelist.free;
  1318. current_filepos:=storefilepos;
  1319. end;
  1320. procedure tdebuginfostabs.insertlineinfo(list:TAsmList);
  1321. var
  1322. currfileinfo,
  1323. lastfileinfo : tfileposinfo;
  1324. currfuncname : pshortstring;
  1325. currsectype : TAsmSectiontype;
  1326. hlabel : tasmlabel;
  1327. hp : tai;
  1328. infile : tinputfile;
  1329. begin
  1330. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  1331. currfuncname:=nil;
  1332. currsectype:=sec_code;
  1333. hp:=Tai(list.first);
  1334. while assigned(hp) do
  1335. begin
  1336. case hp.typ of
  1337. ait_section :
  1338. currsectype:=tai_section(hp).sectype;
  1339. ait_function_name :
  1340. currfuncname:=tai_function_name(hp).funcname;
  1341. ait_force_line :
  1342. lastfileinfo.line:=-1;
  1343. end;
  1344. if (currsectype=sec_code) and
  1345. (hp.typ=ait_instruction) then
  1346. begin
  1347. currfileinfo:=tailineinfo(hp).fileinfo;
  1348. { file changed ? (must be before line info) }
  1349. if (currfileinfo.fileindex<>0) and
  1350. (lastfileinfo.fileindex<>currfileinfo.fileindex) then
  1351. begin
  1352. infile:=current_module.sourcefiles.get_file(currfileinfo.fileindex);
  1353. if assigned(infile) then
  1354. begin
  1355. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1356. { emit stabs }
  1357. if (infile.path^<>'') then
  1358. list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(n_includefile)+
  1359. ',0,0,'+hlabel.name),hp);
  1360. list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+FixFileName(infile.name^)+'",'+tostr(n_includefile)+
  1361. ',0,0,'+hlabel.name),hp);
  1362. list.insertbefore(tai_label.create(hlabel),hp);
  1363. { force new line info }
  1364. lastfileinfo.line:=-1;
  1365. end;
  1366. end;
  1367. { line changed ? }
  1368. if (currfileinfo.line>lastfileinfo.line) and (currfileinfo.line<>0) then
  1369. begin
  1370. if assigned(currfuncname) and
  1371. (tf_use_function_relative_addresses in target_info.flags) then
  1372. begin
  1373. current_asmdata.getlabel(hlabel,alt_dbgline);
  1374. list.insertbefore(Tai_stab.Create_str(stab_stabn,tostr(n_textline)+',0,'+tostr(currfileinfo.line)+','+
  1375. hlabel.name+' - '+{$IFDEF POWERPC64}'.'+{$ENDIF POWERPC64}currfuncname^),hp);
  1376. list.insertbefore(tai_label.create(hlabel),hp);
  1377. end
  1378. else
  1379. list.insertbefore(Tai_stab.Create_str(stab_stabd,tostr(n_textline)+',0,'+tostr(currfileinfo.line)),hp);
  1380. end;
  1381. lastfileinfo:=currfileinfo;
  1382. end;
  1383. hp:=tai(hp.next);
  1384. end;
  1385. end;
  1386. procedure tdebuginfostabs.insertmoduleinfo;
  1387. var
  1388. hlabel : tasmlabel;
  1389. infile : tinputfile;
  1390. begin
  1391. { emit main source n_sourcefile for start of module }
  1392. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1393. infile:=current_module.sourcefiles.get_file(1);
  1394. new_section(current_asmdata.asmlists[al_start],sec_code,make_mangledname('DEBUGSTART',current_module.localsymtable,''),0,secorder_begin);
  1395. current_asmdata.asmlists[al_start].concat(tai_symbol.Createname_global(make_mangledname('DEBUGSTART',current_module.localsymtable,''),AT_DATA,0));
  1396. if (infile.path^<>'') then
  1397. current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+'",'+tostr(n_sourcefile)+
  1398. ',0,0,'+hlabel.name));
  1399. current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stab_stabs,'"'+FixFileName(infile.name^)+'",'+tostr(n_sourcefile)+
  1400. ',0,0,'+hlabel.name));
  1401. current_asmdata.asmlists[al_start].concat(tai_label.create(hlabel));
  1402. { emit empty n_sourcefile for end of module }
  1403. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1404. new_section(current_asmdata.asmlists[al_end],sec_code,make_mangledname('DEBUGEND',current_module.localsymtable,''),0,secorder_end);
  1405. current_asmdata.asmlists[al_end].concat(tai_symbol.Createname_global(make_mangledname('DEBUGEND',current_module.localsymtable,''),AT_DATA,0));
  1406. current_asmdata.asmlists[al_end].concat(Tai_stab.Create_str(stab_stabs,'"",'+tostr(n_sourcefile)+',0,0,'+hlabel.name));
  1407. current_asmdata.asmlists[al_end].concat(tai_label.create(hlabel));
  1408. end;
  1409. procedure tdebuginfostabs.referencesections(list:TAsmList);
  1410. var
  1411. hp : tmodule;
  1412. dbgtable : tai_symbol;
  1413. begin
  1414. { Reference all DEBUGINFO sections from the main .text section }
  1415. if (target_info.system=system_powerpc_macos) then
  1416. exit;
  1417. list.concat(Tai_section.create(sec_data,'',0));
  1418. { make sure the debuginfo doesn't get stripped out }
  1419. if (target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
  1420. begin
  1421. dbgtable:=tai_symbol.createname('DEBUGINFOTABLE',AT_DATA,0);
  1422. list.concat(tai_directive.create(asd_no_dead_strip,dbgtable.sym.name));
  1423. list.concat(dbgtable);
  1424. end;
  1425. { include reference to all debuginfo sections of used units }
  1426. hp:=tmodule(loaded_units.first);
  1427. while assigned(hp) do
  1428. begin
  1429. If (hp.flags and uf_has_debuginfo)=uf_has_debuginfo then
  1430. begin
  1431. list.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',hp.localsymtable,''),0));
  1432. list.concat(Tai_const.Createname(make_mangledname('DEBUGSTART',hp.localsymtable,''),0));
  1433. list.concat(Tai_const.Createname(make_mangledname('DEBUGEND',hp.localsymtable,''),0));
  1434. end;
  1435. hp:=tmodule(hp.next);
  1436. end;
  1437. end;
  1438. const
  1439. dbg_stabs_info : tdbginfo =
  1440. (
  1441. id : dbg_stabs;
  1442. idtxt : 'STABS';
  1443. );
  1444. initialization
  1445. RegisterDebugInfo(dbg_stabs_info,TDebugInfoStabs);
  1446. end.