dbgstabs.pas 58 KB

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