dbgstabs.pas 60 KB

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