dbgstabs.pas 57 KB

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