dbgstabs.pas 63 KB

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