dbgstabs.pas 60 KB

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