dbgstabs.pas 62 KB

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