dbgstabs.pas 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889
  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. systems,dbgbase,cgbase,
  23. symconst,symtype,symdef,symsym,symtable,symbase,
  24. aasmtai,aasmdata;
  25. const
  26. { stab types }
  27. STABS_N_GSYM = $20;
  28. STABS_N_STSYM = 38; { initialized const }
  29. STABS_N_LCSYM = 40; { non initialized variable}
  30. STABS_N_Function = $24; { function or const }
  31. STABS_N_TextLine = $44;
  32. STABS_N_DataLine = $46;
  33. STABS_N_BssLine = $48;
  34. STABS_N_RSYM = $40; { register variable }
  35. STABS_N_LSYM = $80;
  36. STABS_N_DECL = $8c;
  37. STABS_N_RPSYM = $8e;
  38. STABS_N_tsym = 160;
  39. STABS_N_SourceFile = $64;
  40. { APPLE LOCAL N_OSO: This is the stab that associated the .o file with the
  41. N_SO stab, in the case where debug info is mostly stored in the .o file. }
  42. STABS_N_OSO = $66;
  43. STABS_N_IncludeFile = $84;
  44. STABS_N_BINCL = $82;
  45. STABS_N_EINCL = $A2;
  46. STABS_N_LBRAC = $C0;
  47. STABS_N_EXCL = $C2;
  48. STABS_N_RBRAC = $E0;
  49. type
  50. TDebugInfoStabs=class(TDebugInfo)
  51. protected
  52. dbgtype: tdbg;
  53. stabsdir: TStabType;
  54. def_stab,
  55. regvar_stab,
  56. procdef_stab,
  57. constsym_stab,
  58. typesym_stab,
  59. globalvarsym_uninited_stab,
  60. globalvarsym_inited_stab,
  61. staticvarsym_uninited_stab,
  62. staticvarsym_inited_stab,
  63. localvarsymref_stab,
  64. paravarsymref_stab: byte;
  65. writing_def_stabs : boolean;
  66. global_stab_number : word;
  67. vardatadef: trecorddef;
  68. tagtypeprefix: ansistring;
  69. { tsym writing }
  70. function sym_var_value(const s:string;arg:pointer):string;
  71. function sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):ansistring;
  72. procedure write_sym_stabstr(list:TAsmList;sym:tsym;const ss:ansistring);
  73. function staticvarsym_mangled_name(sym: tstaticvarsym):string;virtual;
  74. procedure maybe_add_vmt_sym(list:TAsmList;def: tobjectdef);virtual;
  75. { tdef writing }
  76. function def_stab_number(def:tdef):string;
  77. function def_stab_classnumber(def:tabstractrecorddef):string;
  78. function def_var_value(const s:string;arg:pointer):string;
  79. function def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):ansistring;
  80. procedure write_def_stabstr(list:TAsmList;def:tdef;const ss:ansistring);virtual;
  81. procedure field_add_stabstr(p:TObject;arg:pointer);
  82. procedure method_add_stabstr(p:TObject;arg:pointer);
  83. procedure field_write_defs(p:TObject;arg:pointer);
  84. function get_enum_defstr(def: tenumdef; lowerbound: longint): ansistring;
  85. function get_appendsym_paravar_reg(sym:tparavarsym;const typ,stabstr:string;reg: tregister): ansistring;
  86. function base_stabs_str(typ: longint; const other, desc, value: ansistring): ansistring;overload;
  87. function base_stabs_str(const typ, other, desc, value: ansistring): ansistring;overload;virtual;
  88. function gen_procdef_startsym_stabs(def: tprocdef): TAsmList;virtual;
  89. function gen_procdef_endsym_stabs(def: tprocdef): TAsmList;virtual;
  90. protected
  91. procedure appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);override;
  92. procedure appendsym_paravar(list:TAsmList;sym:tparavarsym);override;
  93. procedure appendsym_localvar(list:TAsmList;sym:tlocalvarsym);override;
  94. procedure appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);override;
  95. procedure appendsym_const(list:TAsmList;sym:tconstsym);override;
  96. procedure appendsym_type(list:TAsmList;sym:ttypesym);override;
  97. procedure appendsym_label(list:TAsmList;sym:tlabelsym);override;
  98. procedure beforeappenddef(list:TAsmList;def:tdef);override;
  99. procedure appenddef_ord(list:TAsmList;def:torddef);override;
  100. procedure appenddef_float(list:TAsmList;def:tfloatdef);override;
  101. procedure appenddef_file(list:TAsmList;def:tfiledef);override;
  102. procedure appenddef_enum(list:TAsmList;def:tenumdef);override;
  103. procedure appenddef_array(list:TAsmList;def:tarraydef);override;
  104. procedure appenddef_record(list:TAsmList;def:trecorddef);override;
  105. procedure appenddef_object(list:TAsmList;def:tobjectdef);override;
  106. procedure appenddef_pointer(list:TAsmList;def:tpointerdef);override;
  107. procedure appenddef_string(list:TAsmList;def:tstringdef);override;
  108. procedure appenddef_procvar(list:TAsmList;def:tprocvardef);override;
  109. procedure appenddef_variant(list:TAsmList;def:tvariantdef);override;
  110. procedure appenddef_set(list:TAsmList;def:tsetdef);override;
  111. procedure appenddef_formal(list:TAsmList;def:tformaldef);override;
  112. procedure appenddef_undefined(list:TAsmList;def: tundefineddef);override;
  113. procedure appendprocdef(list:TAsmList;def:tprocdef);override;
  114. public
  115. procedure inserttypeinfo;override;
  116. procedure insertmoduleinfo;override;
  117. procedure insertlineinfo(list:TAsmList);override;
  118. procedure referencesections(list:TAsmList);override;
  119. constructor Create;override;
  120. end;
  121. function GetSymTableName(SymTable : TSymTable) : string;
  122. const
  123. tagtypes = [
  124. recorddef,
  125. variantdef,
  126. enumdef,
  127. stringdef,
  128. filedef,
  129. objectdef
  130. ];
  131. implementation
  132. uses
  133. SysUtils,cutils,cfileutl,
  134. globals,globtype,verbose,constexp,
  135. defutil, cgutils, parabase,
  136. cpuinfo,cpubase,cpupi,paramgr,
  137. aasmbase,procinfo,
  138. finput,fmodule,ppu;
  139. const
  140. current_procdef : tprocdef = nil;
  141. function GetOffsetStr(reference : TReference) : string;
  142. begin
  143. {$ifdef MIPS}
  144. if (reference.index=NR_STACK_POINTER_REG) or
  145. (reference.base=NR_STACK_POINTER_REG) then
  146. GetOffsetStr:=tostr(reference.offset
  147. - mips_extra_offset(current_procdef))
  148. else
  149. {$endif MIPS}
  150. GetOffsetStr:=tostr(reference.offset);
  151. end;
  152. function GetParaOffsetStr(reference : TCGParaReference) : string;
  153. begin
  154. {$ifdef MIPS}
  155. if reference.index=NR_STACK_POINTER_REG then
  156. GetParaOffsetStr:=tostr(reference.offset
  157. - mips_extra_offset(current_procdef))
  158. else
  159. {$endif MIPS}
  160. GetParaOffsetStr:=tostr(reference.offset);
  161. end;
  162. function GetSymName(Sym : TSymEntry) : string;
  163. begin
  164. if Not (cs_stabs_preservecase in current_settings.globalswitches) then
  165. result := Sym.Name
  166. else
  167. result := Sym.RealName;
  168. if (Sym.typ=typesym) and (ttypesym(Sym).Fprettyname<>'') then
  169. result:=ttypesym(Sym).FPrettyName;
  170. if target_asm.dollarsign<>'$' then
  171. result:=ReplaceForbiddenAsmSymbolChars(result);
  172. end;
  173. function GetSymTableName(SymTable : TSymTable) : string;
  174. begin
  175. if Not (cs_stabs_preservecase in current_settings.globalswitches) then
  176. result := SymTable.Name^
  177. else
  178. result := SymTable.RealName^;
  179. if target_asm.dollarsign<>'$' then
  180. result:=ReplaceForbiddenAsmSymbolChars(result);
  181. end;
  182. const
  183. memsizeinc = 512;
  184. type
  185. get_var_value_proc=function(const s:string;arg:pointer):string of object;
  186. function string_evaluate(s:string;get_var_value:get_var_value_proc;get_var_value_arg:pointer;const vars:array of string):ansistring;
  187. (*
  188. S contains a prototype of a result. Stabstr_evaluate will expand
  189. variables and parameters.
  190. Output is s in ASCIIZ format, with the following expanded:
  191. ${varname} - The variable name is expanded.
  192. $n - The parameter n is expanded.
  193. $$ - Is expanded to $
  194. *)
  195. const maxvalue=9;
  196. maxdata=1023;
  197. var i,j:byte;
  198. varname:string[63];
  199. varno,varcounter:byte;
  200. varvalues:array[0..9] of pshortstring;
  201. {1 kb of parameters is the limit. 256 extra bytes are allocated to
  202. ensure buffer integrity.}
  203. varvaluedata:array[0..maxdata+256] of char;
  204. varptr:Pchar;
  205. varidx : byte;
  206. len:longint;
  207. r:Pchar;
  208. begin
  209. {Two pass approach, first, calculate the length and receive variables.}
  210. i:=1;
  211. len:=0;
  212. varcounter:=0;
  213. varptr:=@varvaluedata[0];
  214. varvalues[0]:=nil;
  215. while i<=length(s) do
  216. begin
  217. if (s[i]='$') and (i<length(s)) then
  218. begin
  219. if s[i+1]='$' then
  220. begin
  221. inc(len);
  222. inc(i);
  223. end
  224. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  225. begin
  226. varname:='';
  227. inc(i,2);
  228. repeat
  229. inc(varname[0]);
  230. varname[length(varname)]:=s[i];
  231. s[i]:=char(varcounter);
  232. inc(i);
  233. until s[i]='}';
  234. varvalues[varcounter]:=pshortstring(varptr);
  235. if varptr>@varvaluedata[maxdata] then
  236. internalerrorproc(200411152);
  237. pshortstring(varptr)^:=get_var_value(varname,get_var_value_arg);
  238. inc(len,length(pshortstring(varptr)^));
  239. inc(varptr,length(pshortstring(varptr)^)+1);
  240. inc(varcounter);
  241. end
  242. else if s[i+1] in ['1'..'9'] then
  243. begin
  244. varidx:=byte(s[i+1])-byte('1');
  245. if varidx>high(vars) then
  246. internalerror(200509263);
  247. inc(len,length(vars[varidx]));
  248. inc(i);
  249. end;
  250. end
  251. else
  252. inc(len);
  253. inc(i);
  254. end;
  255. {Second pass, writeout result.}
  256. setlength(result,len);
  257. r:=pchar(result);
  258. i:=1;
  259. while i<=length(s) do
  260. begin
  261. if (s[i]='$') and (i<length(s)) then
  262. begin
  263. if s[i+1]='$' then
  264. begin
  265. r^:='$';
  266. inc(r);
  267. inc(i);
  268. end
  269. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  270. begin
  271. varname:='';
  272. inc(i,2);
  273. varno:=byte(s[i]);
  274. repeat
  275. inc(i);
  276. until s[i]='}';
  277. for j:=1 to length(varvalues[varno]^) do
  278. begin
  279. r^:=varvalues[varno]^[j];
  280. inc(r);
  281. end;
  282. end
  283. else if s[i+1] in ['0'..'9'] then
  284. begin
  285. for j:=1 to length(vars[byte(s[i+1])-byte('1')]) do
  286. begin
  287. r^:=vars[byte(s[i+1])-byte('1')][j];
  288. inc(r);
  289. end;
  290. inc(i);
  291. end
  292. end
  293. else
  294. begin
  295. r^:=s[i];
  296. inc(r);
  297. end;
  298. inc(i);
  299. end;
  300. { verify that the length was correct }
  301. if r^<>#0 then
  302. internalerror(200802031);
  303. end;
  304. {****************************************************************************
  305. TDef support
  306. ****************************************************************************}
  307. function TDebugInfoStabs.def_stab_number(def:tdef):string;
  308. begin
  309. { procdefs only need a number, mark them as already written
  310. so they won't be written implicitly }
  311. if (def.typ=procdef) then
  312. def.dbg_state:=dbg_state_written;
  313. { Stab must already be written, or we must be busy writing it }
  314. if writing_def_stabs and
  315. not(def.dbg_state in [dbg_state_writing,dbg_state_written,dbg_state_queued]) then
  316. internalerror(200403091);
  317. { Keep track of used stabs, this info is only useful for stabs
  318. referenced by the symbols. Definitions will always include all
  319. required stabs }
  320. if def.dbg_state=dbg_state_unused then
  321. begin
  322. def.dbg_state:=dbg_state_used;
  323. deftowritelist.Add(def);
  324. end;
  325. { Need a new number? }
  326. if def.stab_number=0 then
  327. begin
  328. inc(global_stab_number);
  329. { classes require 2 numbers }
  330. if is_class(def) then
  331. inc(global_stab_number);
  332. def.stab_number:=global_stab_number;
  333. if global_stab_number>=defnumberlist.count then
  334. defnumberlist.count:=global_stab_number+250;
  335. defnumberlist[global_stab_number]:=def;
  336. end;
  337. result:=tostr(def.stab_number);
  338. end;
  339. function TDebugInfoStabs.def_stab_classnumber(def:tabstractrecorddef):string;
  340. begin
  341. if def.stab_number=0 then
  342. def_stab_number(def);
  343. if (def.typ=objectdef) and (tobjectdef(def).objecttype=odt_class) then
  344. result:=tostr(def.stab_number-1)
  345. else
  346. result:=tostr(def.stab_number);
  347. end;
  348. function TDebugInfoStabs.def_var_value(const s:string;arg:pointer):string;
  349. var
  350. def : tdef;
  351. begin
  352. def:=tdef(arg);
  353. result:='';
  354. if s='numberstring' then
  355. result:=def_stab_number(def)
  356. else if s='sym_name' then
  357. begin
  358. if assigned(def.typesym) then
  359. result:=GetSymName(Ttypesym(def.typesym));
  360. end
  361. else if s='savesize' then
  362. result:=tostr(def.size);
  363. end;
  364. function TDebugInfoStabs.def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):ansistring;
  365. begin
  366. result:=string_evaluate(s,@def_var_value,def,vars);
  367. end;
  368. procedure TDebugInfoStabs.field_add_stabstr(p:TObject;arg:pointer);
  369. var
  370. spec : string[3];
  371. varsize : asizeint;
  372. newss : ansistring;
  373. ss : pansistring absolute arg;
  374. begin
  375. if (tsym(p).visibility=vis_hidden) then
  376. exit;
  377. { static variables from objects are like global objects }
  378. if (Tsym(p).typ=fieldvarsym) and
  379. not(sp_static in Tsym(p).symoptions) then
  380. begin
  381. case tsym(p).visibility of
  382. vis_private,
  383. vis_strictprivate :
  384. spec:='/0';
  385. vis_protected,
  386. vis_strictprotected :
  387. spec:='/1';
  388. else
  389. spec:='';
  390. end;
  391. if (tabstractrecordsymtable(tsym(p).owner).usefieldalignment<>bit_alignment) then
  392. begin
  393. varsize:=tfieldvarsym(p).vardef.size;
  394. { open arrays made overflows !! }
  395. { how can a record/object/class contain an open array? (JM) }
  396. {$ifdef cpu16bitaddr}
  397. if varsize>$fff then
  398. varsize:=$fff;
  399. {$else cpu16bitaddr}
  400. if varsize>$fffffff then
  401. varsize:=$fffffff;
  402. {$endif cpu16bitaddr}
  403. newss:=def_stabstr_evaluate(nil,'$1:$2,$3,$4;',[GetSymName(tfieldvarsym(p)),
  404. spec+def_stab_number(tfieldvarsym(p).vardef),
  405. tostr(TConstExprInt(tfieldvarsym(p).fieldoffset)*8),tostr(varsize*8)])
  406. end
  407. else
  408. newss:=def_stabstr_evaluate(nil,'$1:$2,$3,$4;',[GetSymName(tfieldvarsym(p)),
  409. spec+def_stab_number(tfieldvarsym(p).vardef),
  410. tostr(TConstExprInt(tfieldvarsym(p).fieldoffset)),tostr(tfieldvarsym(p).vardef.packedbitsize)]);
  411. ss^:=ss^+newss;
  412. end;
  413. end;
  414. procedure TDebugInfoStabs.method_add_stabstr(p:TObject;arg:pointer);
  415. var
  416. virtualind,argnames : string;
  417. pd : tprocdef;
  418. lindex : longint;
  419. arglength : byte;
  420. sp : char;
  421. i : integer;
  422. parasym : tparavarsym;
  423. newss : ansistring;
  424. ss : pansistring absolute arg;
  425. begin
  426. if tsym(p).typ = procsym then
  427. begin
  428. pd :=tprocdef(tprocsym(p).ProcdefList[0]);
  429. if (po_virtualmethod in pd.procoptions) and
  430. not is_objectpascal_helper(pd.struct) then
  431. begin
  432. lindex := pd.extnumber;
  433. {doesnt seem to be necessary
  434. lindex := lindex or $80000000;}
  435. virtualind := '*'+tostr(lindex)+';'+def_stab_classnumber(pd.struct)+';'
  436. end
  437. else
  438. virtualind := '.';
  439. { used by gdbpas to recognize constructor and destructors }
  440. if (pd.proctypeoption=potype_constructor) then
  441. argnames:='__ct__'
  442. else if (pd.proctypeoption=potype_destructor) then
  443. argnames:='__dt__'
  444. else
  445. argnames := '';
  446. { arguments are not listed here }
  447. {we don't need another definition}
  448. for i:=0 to pd.paras.count-1 do
  449. begin
  450. parasym:=tparavarsym(pd.paras[i]);
  451. if Parasym.vardef.typ = formaldef then
  452. begin
  453. case Parasym.varspez of
  454. vs_var :
  455. argnames := argnames+'3var';
  456. vs_const :
  457. argnames:=argnames+'5const';
  458. vs_out :
  459. argnames:=argnames+'3out';
  460. vs_constref :
  461. argnames:=argnames+'8constref';
  462. end;
  463. end
  464. else
  465. begin
  466. { if the arg definition is like (v: ^byte;..
  467. there is no sym attached to data !!! }
  468. if assigned(Parasym.vardef.typesym) then
  469. begin
  470. arglength := length(GetSymName(Parasym.vardef.typesym));
  471. argnames := argnames + tostr(arglength)+GetSymName(Parasym.vardef.typesym);
  472. end
  473. else
  474. argnames:=argnames+'11unnamedtype';
  475. end;
  476. end;
  477. { here 2A must be changed for private and protected }
  478. { 0 is private 1 protected and 2 public }
  479. case tsym(p).visibility of
  480. vis_private,
  481. vis_strictprivate :
  482. sp:='0';
  483. vis_protected,
  484. vis_strictprotected :
  485. sp:='1'
  486. else
  487. sp:='2';
  488. end;
  489. newss:=def_stabstr_evaluate(nil,'$1::$2=##$3;:$4;$5A$6;',[GetSymName(tsym(p)),def_stab_number(pd),
  490. def_stab_number(pd.returndef),argnames,sp,
  491. virtualind]);
  492. ss^:=ss^+newss;
  493. end;
  494. end;
  495. procedure TDebugInfoStabs.field_write_defs(p:TObject;arg:pointer);
  496. begin
  497. if (Tsym(p).typ=fieldvarsym) and
  498. not(sp_static in Tsym(p).symoptions) then
  499. appenddef(TAsmList(arg),tfieldvarsym(p).vardef);
  500. end;
  501. procedure TDebugInfoStabs.write_def_stabstr(list:TAsmList;def:tdef;const ss:ansistring);
  502. var
  503. stabchar : string[2];
  504. symname : string[20];
  505. st : ansistring;
  506. begin
  507. { type prefix }
  508. if def.typ in tagtypes then
  509. stabchar := tagtypeprefix
  510. else
  511. stabchar := 't';
  512. { in case of writing the class record structure, we always have to
  513. use the class name (so it refers both to the struct and the
  514. pointer to the struct), otherwise gdb crashes (see tests/webtbs/tw9766.pp) }
  515. if is_class(def) and
  516. tobjectdef(def).writing_class_record_dbginfo then
  517. st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_classnumber(tobjectdef(def))])
  518. else
  519. begin
  520. { Type names for types defined in the current unit are already written in
  521. the typesym }
  522. if (def.owner.symtabletype=globalsymtable) and
  523. not(def.owner.iscurrentunit) then
  524. symname:='${sym_name}'
  525. else
  526. symname:='';
  527. st:=def_stabstr_evaluate(def,'"'+symname+':$1$2=',[stabchar,def_stab_number(def)]);
  528. end;
  529. st:=st+ss;
  530. { line info is set to 0 for all defs, because the def can be in another
  531. unit and then the linenumber is invalid in the current sourcefile }
  532. st:=st+def_stabstr_evaluate(def,'",'+base_stabs_str(def_stab,'0','0','0'),[]);
  533. { add to list }
  534. list.concat(Tai_stab.create_ansistr(stabsdir,st));
  535. end;
  536. procedure TDebugInfoStabs.appenddef_string(list:TAsmList;def:tstringdef);
  537. var
  538. bytest,charst,longst : string;
  539. ss : ansistring;
  540. slen : longint;
  541. begin
  542. ss:='';
  543. case def.stringtype of
  544. st_shortstring:
  545. begin
  546. { fix length of openshortstring }
  547. slen:=def.len;
  548. if slen=0 then
  549. slen:=255;
  550. charst:=def_stab_number(cansichartype);
  551. bytest:=def_stab_number(u8inttype);
  552. ss:=def_stabstr_evaluate(def,'s$1length:$2,0,8;st:ar$2;1;$3;$4,8,$5;;',
  553. [tostr(slen+1),bytest,tostr(slen),charst,tostr(slen*8)]);
  554. end;
  555. st_longstring:
  556. begin
  557. charst:=def_stab_number(cansichartype);
  558. bytest:=def_stab_number(u8inttype);
  559. longst:=def_stab_number(u32inttype);
  560. ss:=def_stabstr_evaluate(def,'s$1length:$2,0,32;dummy:$6,32,8;st:ar$2;1;$3;$4,40,$5;;',
  561. [tostr(def.len+5),longst,tostr(def.len),charst,tostr(def.len*8),bytest]);
  562. end;
  563. st_ansistring:
  564. begin
  565. { looks like a pchar }
  566. ss:='*'+def_stab_number(cansichartype);
  567. end;
  568. st_unicodestring,
  569. st_widestring:
  570. begin
  571. { looks like a pwidechar }
  572. ss:='*'+def_stab_number(cwidechartype);
  573. end;
  574. end;
  575. write_def_stabstr(list,def,ss);
  576. end;
  577. function TDebugInfoStabs.get_enum_defstr(def: tenumdef; lowerbound: longint): ansistring;
  578. var
  579. i: longint;
  580. p: tenumsym;
  581. begin
  582. { we can specify the size with @s<size>; prefix PM }
  583. if def.size <> std_param_align then
  584. result:='@s'+tostr(def.size*8)+';e'
  585. else
  586. result:='e';
  587. { the if-test is required because pred(def.minval) might overflow;
  588. the longint() typecast should be safe because stabs is not
  589. supported for 64 bit targets }
  590. if (def.minval<>lowerbound) then
  591. for i:=lowerbound to pred(longint(def.minval)) do
  592. result:=result+'<invalid>:'+tostr(i)+',';
  593. for i := 0 to def.symtable.SymList.Count - 1 do
  594. begin
  595. p := tenumsym(def.symtable.SymList[i]);
  596. if p.value<def.minval then
  597. continue
  598. else
  599. if p.value>def.maxval then
  600. break;
  601. result:=result+GetSymName(p)+':'+tostr(p.value)+',';
  602. end;
  603. { the final ',' is required to have a valid stabs }
  604. result:=result+';';
  605. end;
  606. procedure TDebugInfoStabs.appenddef_enum(list:TAsmList;def:tenumdef);
  607. begin
  608. write_def_stabstr(list,def,get_enum_defstr(def,def.minval));
  609. end;
  610. procedure TDebugInfoStabs.appenddef_ord(list:TAsmList;def:torddef);
  611. var
  612. ss : ansistring;
  613. begin
  614. ss:='';
  615. if cs_gdb_valgrind in current_settings.globalswitches then
  616. begin
  617. case def.ordtype of
  618. uvoid :
  619. ss:=def_stab_number(def);
  620. pasbool8,
  621. pasbool16,
  622. pasbool32,
  623. pasbool64,
  624. bool8bit,
  625. bool16bit,
  626. bool32bit,
  627. bool64bit :
  628. ss:=def_stabstr_evaluate(def,'r${numberstring};0;255;',[]);
  629. u32bit,
  630. s64bit,
  631. u64bit :
  632. ss:=def_stabstr_evaluate(def,'r${numberstring};0;-1;',[]);
  633. else
  634. ss:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low.svalue)),tostr(longint(def.high.svalue))]);
  635. end;
  636. end
  637. else
  638. begin
  639. case def.ordtype of
  640. uvoid :
  641. ss:=def_stab_number(def);
  642. uchar :
  643. ss:='-20;';
  644. uwidechar :
  645. ss:='-30;';
  646. pasbool8,
  647. bool8bit :
  648. ss:='-21;';
  649. pasbool16,
  650. bool16bit :
  651. ss:='-22;';
  652. pasbool32,
  653. bool32bit :
  654. ss:='-23;';
  655. pasbool64,
  656. bool64bit :
  657. { no clue if this is correct (FK) }
  658. ss:='-23;';
  659. u64bit :
  660. ss:='-32;';
  661. s64bit :
  662. ss:='-31;';
  663. {u32bit : result:=def_stab_number(s32inttype)+';0;-1;'); }
  664. else
  665. begin
  666. if def.size <> std_param_align then
  667. ss:='@s'+tostr(def.size*8)+';'
  668. else
  669. ss:='';
  670. ss:=ss+def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low.svalue)),tostr(longint(def.high.svalue))]);
  671. end;
  672. end;
  673. end;
  674. write_def_stabstr(list,def,ss);
  675. end;
  676. procedure TDebugInfoStabs.appenddef_float(list:TAsmList;def:tfloatdef);
  677. var
  678. ss : ansistring;
  679. begin
  680. ss:='';
  681. case def.floattype of
  682. s32real,
  683. s64real,
  684. s80real,
  685. sc80real:
  686. ss:=def_stabstr_evaluate(def,'r$1;${savesize};0;',[def_stab_number(s32inttype)]);
  687. s64currency,
  688. s64comp:
  689. ss:=def_stabstr_evaluate(def,'r$1;-${savesize};0;',[def_stab_number(s32inttype)]);
  690. else
  691. internalerror(200509261);
  692. end;
  693. write_def_stabstr(list,def,ss);
  694. end;
  695. procedure TDebugInfoStabs.appenddef_file(list:TAsmList;def:tfiledef);
  696. var
  697. ss : ansistring;
  698. begin
  699. {$ifdef cpu64bitaddr}
  700. ss:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$2,64,64;'+
  701. '_PRIVATE:ar$1;1;64;$3,128,256;USERDATA:ar$1;1;32;$3,384,256;'+
  702. 'NAME:ar$1;0;255;$4,640,2048;;',[def_stab_number(s32inttype),
  703. def_stab_number(s64inttype),
  704. def_stab_number(u8inttype),
  705. def_stab_number(cansichartype)]);
  706. {$else cpu64bitaddr}
  707. ss:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$1,64,32;'+
  708. '_PRIVATE:ar$1;1;32;$3,96,256;USERDATA:ar$1;1;32;$2,352,256;'+
  709. 'NAME:ar$1;0;255;$3,608,2048;;',[def_stab_number(s32inttype),
  710. def_stab_number(u8inttype),
  711. def_stab_number(cansichartype)]);
  712. {$endif cpu64bitaddr}
  713. write_def_stabstr(list,def,ss);
  714. end;
  715. procedure TDebugInfoStabs.appenddef_record(list:TAsmList;def:trecorddef);
  716. var
  717. ss : ansistring;
  718. begin
  719. ss:='s'+tostr(def.size);
  720. def.symtable.SymList.ForEachCall(@field_add_stabstr,@ss);
  721. ss[length(ss)]:=';';
  722. write_def_stabstr(list,def,ss);
  723. end;
  724. procedure TDebugInfoStabs.appenddef_object(list:TAsmList;def:tobjectdef);
  725. procedure do_write_object(list:TAsmList;def:tobjectdef);
  726. var
  727. ss : ansistring;
  728. anc : tobjectdef;
  729. begin
  730. ss:='';
  731. { Write the invisible pointer for the class? }
  732. if (def.objecttype=odt_class) and
  733. (not def.writing_class_record_dbginfo) then
  734. begin
  735. ss:='*'+def_stab_classnumber(def);
  736. write_def_stabstr(list,def,ss);
  737. exit;
  738. end;
  739. ss:='s'+tostr(tobjecTSymtable(def.symtable).datasize);
  740. if assigned(def.childof) then
  741. begin
  742. {only one ancestor not virtual, public, at base offset 0 }
  743. { !1 , 0 2 0 , }
  744. ss:=ss+'!1,020,'+def_stab_classnumber(def.childof)+';';
  745. end;
  746. {virtual table to implement yet}
  747. def.symtable.symList.ForEachCall(@field_add_stabstr,@ss);
  748. if (oo_has_vmt in def.objectoptions) and
  749. (
  750. not assigned(def.childof) or
  751. not(oo_has_vmt in def.childof.objectoptions)
  752. ) then
  753. ss:=ss+'$vf'+def_stab_classnumber(def)+':'+def_stab_number(vmtarraytype)+','+tostr(def.vmt_offset*8)+';';
  754. def.symtable.symList.ForEachCall(@method_add_stabstr,@ss);
  755. if (oo_has_vmt in def.objectoptions) then
  756. begin
  757. anc := def;
  758. while assigned(anc.childof) and (oo_has_vmt in anc.childof.objectoptions) do
  759. anc := anc.childof;
  760. { just in case anc = self }
  761. ss:=ss+';~%'+def_stab_classnumber(anc)+';';
  762. end
  763. else
  764. ss:=ss+';';
  765. write_def_stabstr(list,def,ss);
  766. end;
  767. var
  768. oldtypesym : tsym;
  769. begin
  770. tobjectdef(def).symtable.symList.ForEachCall(@field_write_defs,list);
  771. { classes require special code to write the record and the invisible pointer }
  772. if is_class(def) then
  773. begin
  774. { Write the record class itself }
  775. tobjectdef(def).writing_class_record_dbginfo:=true;
  776. do_write_object(list,def);
  777. tobjectdef(def).writing_class_record_dbginfo:=false;
  778. { Write the invisible pointer class }
  779. oldtypesym:=def.typesym;
  780. def.typesym:=nil;
  781. do_write_object(list,def);
  782. def.typesym:=oldtypesym;
  783. end
  784. else
  785. do_write_object(list,def);
  786. { VMT symbol }
  787. maybe_add_vmt_sym(list,def);
  788. end;
  789. procedure TDebugInfoStabs.appenddef_variant(list:TAsmList;def:tvariantdef);
  790. var
  791. ss : ansistring;
  792. begin
  793. if not assigned(vardatadef) then
  794. exit;
  795. ss:='s'+tostr(vardatadef.size);
  796. vardatadef.symtable.SymList.ForEachCall(@field_add_stabstr,@ss);
  797. ss[length(ss)]:=';';
  798. write_def_stabstr(list,def,ss);
  799. end;
  800. procedure TDebugInfoStabs.appenddef_pointer(list:TAsmList;def:tpointerdef);
  801. var
  802. ss : ansistring;
  803. begin
  804. ss:='*'+def_stab_number(tpointerdef(def).pointeddef);
  805. write_def_stabstr(list,def,ss);
  806. end;
  807. procedure TDebugInfoStabs.appenddef_set(list:TAsmList;def:tsetdef);
  808. var
  809. st,
  810. ss : ansistring;
  811. elementdefstabnr: string;
  812. begin
  813. { ugly hack: create a temporary subrange type if the lower bound of
  814. the set's element type is not a multiple of 8 (because we store them
  815. as if the lower bound is a multiple of 8) }
  816. if (def.setbase<>get_min_value(def.elementdef)) then
  817. begin
  818. { allocate a def number }
  819. inc(global_stab_number);
  820. elementdefstabnr:=tostr(global_stab_number);
  821. { anonymous subrange def }
  822. st:='":t'+elementdefstabnr+'=';
  823. if (def.elementdef.typ = enumdef) then
  824. st:=st+get_enum_defstr(tenumdef(def.elementdef),def.setbase)
  825. else
  826. st:=st+def_stabstr_evaluate(def.elementdef,'r'+elementdefstabnr+';$1;$2;',[tostr(longint(def.setbase)),tostr(longint(get_max_value(def.elementdef).svalue))]);
  827. st:=st+'",'+base_stabs_str(def_stab,'0','0','0');
  828. { add to list }
  829. list.concat(Tai_stab.create_ansistr(stabsdir,st));
  830. end
  831. else
  832. elementdefstabnr:=def_stab_number(def.elementdef);
  833. ss:=def_stabstr_evaluate(def,'@s$1;S$2',[tostr(def.size*8),elementdefstabnr]);
  834. write_def_stabstr(list,def,ss);
  835. end;
  836. procedure TDebugInfoStabs.appenddef_formal(list:TAsmList;def:tformaldef);
  837. var
  838. ss : ansistring;
  839. begin
  840. ss:=def_stabstr_evaluate(def,'${numberstring};',[]);
  841. write_def_stabstr(list,def,ss);
  842. end;
  843. procedure TDebugInfoStabs.appenddef_array(list:TAsmList;def:tarraydef);
  844. var
  845. tempstr: shortstring;
  846. ss : ansistring;
  847. begin
  848. if not is_packed_array(def) then
  849. begin
  850. { Try to used P if ememlent size is smaller than
  851. usual integer }
  852. if def.elesize <> std_param_align then
  853. tempstr:='ar@s'+tostr(def.elesize*8)+';$1;$2;$3;$4'
  854. else
  855. tempstr:='ar$1;$2;$3;$4';
  856. if is_dynamic_array(def) then
  857. tempstr:='*'+tempstr;
  858. ss:=def_stabstr_evaluate(def,tempstr,[def_stab_number(tarraydef(def).rangedef),
  859. tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementdef)])
  860. end
  861. else
  862. begin
  863. // the @P seems to be ignored by gdb
  864. tempstr:=def_stabstr_evaluate(tarraydef(def).rangedef,'r${numberstring};$1;$2;',
  865. [tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange)]);
  866. // will only show highrange-lowrange+1 bits in gdb
  867. ss:=def_stabstr_evaluate(def,'@s$1;@S;S$2',
  868. [tostr(TConstExprInt(tarraydef(def).elepackedbitsize) * tarraydef(def).elecount),tempstr]);
  869. end;
  870. write_def_stabstr(list,def,ss);
  871. end;
  872. procedure TDebugInfoStabs.appenddef_procvar(list:TAsmList;def:tprocvardef);
  873. var
  874. ss : ansistring;
  875. begin
  876. ss:='*f'+def_stab_number(tprocvardef(def).returndef);
  877. write_def_stabstr(list,def,ss);
  878. end;
  879. procedure TDebugInfoStabs.appenddef_undefined(list:TAsmList;def:tundefineddef);
  880. var
  881. ss : ansistring;
  882. begin
  883. ss:=def_stabstr_evaluate(def,'${numberstring};',[]);
  884. write_def_stabstr(list,def,ss);
  885. end;
  886. procedure TDebugInfoStabs.beforeappenddef(list:TAsmList;def:tdef);
  887. var
  888. anc : tobjectdef;
  889. i : longint;
  890. begin
  891. { write dependencies first }
  892. case def.typ of
  893. stringdef :
  894. begin
  895. if tstringdef(def).stringtype in [st_widestring,st_unicodestring] then
  896. appenddef(list,cwidechartype)
  897. else
  898. begin
  899. appenddef(list,cansichartype);
  900. appenddef(list,u8inttype);
  901. end;
  902. end;
  903. floatdef :
  904. appenddef(list,s32inttype);
  905. filedef :
  906. begin
  907. appenddef(list,s32inttype);
  908. {$ifdef cpu64bitaddr}
  909. appenddef(list,s64inttype);
  910. {$endif cpu64bitaddr}
  911. appenddef(list,u8inttype);
  912. appenddef(list,cansichartype);
  913. end;
  914. classrefdef :
  915. appenddef(list,pvmttype);
  916. pointerdef :
  917. appenddef(list,tpointerdef(def).pointeddef);
  918. setdef :
  919. appenddef(list,tsetdef(def).elementdef);
  920. procvardef :
  921. begin
  922. appenddef(list,tprocvardef(def).returndef);
  923. if assigned(tprocvardef(def).parast) then
  924. write_symtable_defs(list,tprocvardef(def).parast);
  925. end;
  926. procdef :
  927. begin
  928. appenddef(list,tprocdef(def).returndef);
  929. if assigned(tprocdef(def).parast) then
  930. write_symtable_defs(list,tprocdef(def).parast);
  931. if assigned(tprocdef(def).localst) and
  932. (tprocdef(def).localst.symtabletype=localsymtable) then
  933. write_symtable_defs(list,tprocdef(def).localst);
  934. end;
  935. arraydef :
  936. begin
  937. appenddef(list,tarraydef(def).rangedef);
  938. appenddef(list,tarraydef(def).elementdef);
  939. end;
  940. recorddef :
  941. trecorddef(def).symtable.symList.ForEachCall(@field_write_defs,list);
  942. enumdef :
  943. if assigned(tenumdef(def).basedef) then
  944. appenddef(list,tenumdef(def).basedef);
  945. objectdef :
  946. begin
  947. { make sure we don't write child classdefs before their parent }
  948. { classdefs, because this crashes gdb }
  949. anc:=tobjectdef(def);
  950. while assigned(anc.childof) do
  951. begin
  952. anc:=anc.childof;
  953. case anc.dbg_state of
  954. dbg_state_writing:
  955. { happens in case a field of a parent is of the (forward
  956. defined) child type
  957. }
  958. begin
  959. { We don't explicitly requeue it, but the fact that
  960. a child type was used in a parent before the child
  961. type was fully defined means that it was forward
  962. declared, and will still be encountered later.
  963. Setting the state to queued however allows us to
  964. get the def number already without an IE
  965. }
  966. def.dbg_state:=dbg_state_queued;
  967. break;
  968. end;
  969. end;
  970. end;
  971. appenddef(list,vmtarraytype);
  972. if assigned(tobjectdef(def).ImplementedInterfaces) then
  973. for i:=0 to tobjectdef(def).ImplementedInterfaces.Count-1 do
  974. appenddef(list,TImplementedInterface(tobjectdef(def).ImplementedInterfaces[i]).IntfDef);
  975. { first the parents }
  976. anc:=tobjectdef(def);
  977. while assigned(anc.childof) do
  978. begin
  979. anc:=anc.childof;
  980. { in case this is an object family declared in another unit
  981. that was compiled without debug info, this ancestor may not
  982. yet have a stabs number and not yet be added to defstowrite
  983. -> take care of that now, while its dbg_state is still
  984. dbg_state_unused in case the aforementioned things haven't
  985. happened yet (afterwards it will become dbg_state_writing,
  986. and then def_stab_number() won't do anything anymore because
  987. it assumes it's already happened
  988. }
  989. def_stab_number(anc);
  990. appenddef(list,anc);
  991. if assigned(anc.ImplementedInterfaces) then
  992. for i:=0 to anc.ImplementedInterfaces.Count-1 do
  993. appenddef(list,TImplementedInterface(anc.ImplementedInterfaces[i]).IntfDef);
  994. end;
  995. end;
  996. end;
  997. end;
  998. procedure TDebugInfoStabs.appendprocdef(list:TAsmList;def:tprocdef);
  999. var
  1000. hs : ansistring;
  1001. templist : TAsmList;
  1002. prev_procdef : tprocdef;
  1003. begin
  1004. if not(def.in_currentunit) or
  1005. { happens for init procdef of units without init section }
  1006. not assigned(def.procstarttai) then
  1007. exit;
  1008. { mark as used so the local type defs also be written }
  1009. def.dbg_state:=dbg_state_used;
  1010. prev_procdef:=current_procdef;
  1011. current_procdef:=def;
  1012. templist:=gen_procdef_endsym_stabs(def);
  1013. current_asmdata.asmlists[al_procedures].insertlistafter(def.procendtai,templist);
  1014. { FUNC stabs }
  1015. templist.free;
  1016. templist:=gen_procdef_startsym_stabs(def);
  1017. current_asmdata.asmlists[al_procedures].insertlistbefore(def.procstarttai,templist);
  1018. { para types }
  1019. if assigned(def.parast) then
  1020. write_symtable_syms(templist,def.parast);
  1021. { local type defs and vars should not be written
  1022. inside the main proc stab }
  1023. if assigned(def.localst) and
  1024. (def.localst.symtabletype=localsymtable) then
  1025. write_symtable_syms(templist,def.localst);
  1026. if assigned(def.funcretsym) and
  1027. (tabstractnormalvarsym(def.funcretsym).refs>0) then
  1028. begin
  1029. if tabstractnormalvarsym(def.funcretsym).localloc.loc=LOC_REFERENCE then
  1030. begin
  1031. { TODO: Need to add gdb support for ret in param register calling}
  1032. if paramanager.ret_in_param(def.returndef,def) then
  1033. hs:='X*'
  1034. else
  1035. hs:='X';
  1036. templist.concat(Tai_stab.create(stabsdir,strpnew(
  1037. '"'+GetSymName(def.procsym)+':'+hs+def_stab_number(def.returndef)+'",'+
  1038. base_stabs_str(localvarsymref_stab,'0','0',getoffsetstr(tabstractnormalvarsym(def.funcretsym).localloc.reference)))));
  1039. if (m_result in current_settings.modeswitches) then
  1040. templist.concat(Tai_stab.create(stabsdir,strpnew(
  1041. '"RESULT:'+hs+def_stab_number(def.returndef)+'",'+
  1042. base_stabs_str(localvarsymref_stab,'0','0',getoffsetstr(tabstractnormalvarsym(def.funcretsym).localloc.reference)))));
  1043. end;
  1044. end;
  1045. current_asmdata.asmlists[al_procedures].insertlistbefore(def.procstarttai,templist);
  1046. templist.free;
  1047. current_procdef:=prev_procdef;
  1048. end;
  1049. {****************************************************************************
  1050. TSym support
  1051. ****************************************************************************}
  1052. function TDebugInfoStabs.sym_var_value(const s:string;arg:pointer):string;
  1053. var
  1054. sym : tsym absolute arg;
  1055. begin
  1056. result:='';
  1057. if s='name' then
  1058. result:=GetSymName(sym)
  1059. else if s='mangledname' then
  1060. result:=ReplaceForbiddenAsmSymbolChars(sym.mangledname)
  1061. else if s='ownername' then
  1062. result:=GetSymTableName(sym.owner)
  1063. else if s='line' then
  1064. result:=tostr(sym.fileinfo.line)
  1065. else
  1066. internalerror(200401152);
  1067. end;
  1068. function TDebugInfoStabs.sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):ansistring;
  1069. begin
  1070. result:=string_evaluate(s,@sym_var_value,sym,vars);
  1071. end;
  1072. procedure TDebugInfoStabs.write_sym_stabstr(list:TAsmList;sym:tsym;const ss:ansistring);
  1073. begin
  1074. if ss='' then
  1075. exit;
  1076. { add to list }
  1077. list.concat(Tai_stab.create_ansistr(stabsdir,ss));
  1078. end;
  1079. function TDebugInfoStabs.staticvarsym_mangled_name(sym: tstaticvarsym): string;
  1080. begin
  1081. result:=ReplaceForbiddenAsmSymbolChars(sym.mangledname);
  1082. end;
  1083. procedure TDebugInfoStabs.maybe_add_vmt_sym(list: TAsmList; def: tobjectdef);
  1084. begin
  1085. if (oo_has_vmt in def.objectoptions) and
  1086. assigned(def.owner) and
  1087. assigned(def.owner.name) then
  1088. list.concat(Tai_stab.create_ansistr(stabsdir,ansistring('"vmt_')+GetSymTableName(def.owner)+tobjectdef(def).objname^+':S'+
  1089. def_stab_number(vmttype)+'",'+
  1090. base_stabs_str(globalvarsym_inited_stab,'0','0',ReplaceForbiddenAsmSymbolChars(tobjectdef(def).vmt_mangledname))));
  1091. end;
  1092. procedure TDebugInfoStabs.appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);
  1093. var
  1094. ss : ansistring;
  1095. begin
  1096. ss:='';
  1097. if (sym.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1098. (sp_static in sym.symoptions) then
  1099. ss:=sym_stabstr_evaluate(sym,'"${ownername}__${name}:S$1",'+base_stabs_str(globalvarsym_uninited_stab,'0','${line}','${mangledname}'),
  1100. [def_stab_number(sym.vardef)]);
  1101. write_sym_stabstr(list,sym,ss);
  1102. end;
  1103. procedure TDebugInfoStabs.appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);
  1104. var
  1105. ss : ansistring;
  1106. st : string;
  1107. threadvaroffset : string;
  1108. regidx : Tregisterindex;
  1109. nsym : byte;
  1110. begin
  1111. { external symbols can't be resolved at link time, so we
  1112. can't generate stabs for them }
  1113. if vo_is_external in sym.varoptions then
  1114. exit;
  1115. ss:='';
  1116. st:=def_stab_number(sym.vardef);
  1117. case sym.localloc.loc of
  1118. LOC_REGISTER,
  1119. LOC_CREGISTER,
  1120. LOC_MMREGISTER,
  1121. LOC_CMMREGISTER,
  1122. LOC_FPUREGISTER,
  1123. LOC_CFPUREGISTER :
  1124. begin
  1125. regidx:=findreg_by_number(sym.localloc.register);
  1126. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1127. { this is the register order for GDB}
  1128. if regidx<>0 then
  1129. ss:=sym_stabstr_evaluate(sym,'"${name}:r$1",'+base_stabs_str(regvar_stab,'0','${line}','$2'),[st,tostr(regstabs_table[regidx])]);
  1130. end;
  1131. else
  1132. begin
  1133. if (vo_is_thread_var in sym.varoptions) then
  1134. threadvaroffset:='+'+tostr(sizeof(pint))
  1135. else
  1136. threadvaroffset:='';
  1137. if (vo_is_typed_const in sym.varoptions) then
  1138. if vo_is_public in sym.varoptions then
  1139. nsym:=globalvarsym_inited_stab
  1140. else
  1141. nsym:=staticvarsym_inited_stab
  1142. else if vo_is_public in sym.varoptions then
  1143. nsym:=globalvarsym_uninited_stab
  1144. else
  1145. nsym:=staticvarsym_uninited_stab;
  1146. { Here we used S instead of
  1147. because with G GDB doesn't look at the address field
  1148. but searches the same name or with a leading underscore
  1149. but these names don't exist in pascal !}
  1150. st:='S'+st;
  1151. ss:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(nsym,'0','${line}','$2$3'),[st,staticvarsym_mangled_name(sym),threadvaroffset]);
  1152. end;
  1153. end;
  1154. write_sym_stabstr(list,sym,ss);
  1155. end;
  1156. procedure TDebugInfoStabs.appendsym_localvar(list:TAsmList;sym:tlocalvarsym);
  1157. var
  1158. ss : ansistring;
  1159. st : string;
  1160. regidx : Tregisterindex;
  1161. begin
  1162. { There is no space allocated for not referenced locals }
  1163. if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
  1164. exit;
  1165. ss:='';
  1166. st:=def_stab_number(sym.vardef);
  1167. case sym.localloc.loc of
  1168. LOC_REGISTER,
  1169. LOC_CREGISTER,
  1170. LOC_MMREGISTER,
  1171. LOC_CMMREGISTER,
  1172. LOC_FPUREGISTER,
  1173. LOC_CFPUREGISTER :
  1174. begin
  1175. regidx:=findreg_by_number(sym.localloc.register);
  1176. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1177. { this is the register order for GDB}
  1178. if regidx<>0 then
  1179. ss:=sym_stabstr_evaluate(sym,'"${name}:r$1",'+base_stabs_str(regvar_stab,'0','${line}','$2'),[st,tostr(regstabs_table[regidx])]);
  1180. end;
  1181. LOC_REFERENCE :
  1182. { offset to ebp => will not work if the framepointer is esp
  1183. so some optimizing will make things harder to debug }
  1184. ss:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(localvarsymref_stab,'0','${line}','$2'),[st,getoffsetstr(sym.localloc.reference)])
  1185. else
  1186. internalerror(2003091814);
  1187. end;
  1188. write_sym_stabstr(list,sym,ss);
  1189. end;
  1190. function TDebugInfoStabs.get_appendsym_paravar_reg(sym:tparavarsym;const typ,stabstr:string;reg: tregister): ansistring;
  1191. var
  1192. ltyp: string[1];
  1193. regidx : Tregisterindex;
  1194. begin
  1195. result:='';
  1196. if typ='p' then
  1197. ltyp:='R'
  1198. else
  1199. ltyp:='a';
  1200. regidx:=findreg_by_number(reg);
  1201. { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
  1202. { this is the register order for GDB}
  1203. if regidx<>0 then
  1204. result:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(regvar_stab,'0','${line}','$2'),[ltyp+stabstr,tostr(longint(regstabs_table[regidx]))]);
  1205. end;
  1206. function TDebugInfoStabs.base_stabs_str(typ: longint; const other, desc, value: ansistring): ansistring;
  1207. begin
  1208. result:=base_stabs_str(tostr(typ),other,desc,value);
  1209. end;
  1210. function TDebugInfoStabs.base_stabs_str(const typ, other, desc, value: ansistring): ansistring;
  1211. begin
  1212. result:=typ+','+other+','+desc+','+value
  1213. end;
  1214. function TDebugInfoStabs.gen_procdef_startsym_stabs(def: tprocdef): TAsmList;
  1215. var
  1216. RType : Char;
  1217. Obj,Info,
  1218. mangledname: ansistring;
  1219. begin
  1220. result:=TAsmList.create;
  1221. { "The stab representing a procedure is located immediately
  1222. following the code of the procedure. This stab is in turn
  1223. directly followed by a group of other stabs describing
  1224. elements of the procedure. These other stabs describe the
  1225. procedure's parameters, its block local variables, and its
  1226. block structure." (stab docs) }
  1227. { this is however incorrect in case "include source" statements }
  1228. { appear in the block, in that case the procedure stab must }
  1229. { appear before this include stabs (and we generate such an }
  1230. { stabs for all functions) (JM) }
  1231. obj := GetSymName(def.procsym);
  1232. info := '';
  1233. if (po_global in def.procoptions) then
  1234. RType := 'F'
  1235. else
  1236. RType := 'f';
  1237. if assigned(def.owner) then
  1238. begin
  1239. if (def.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
  1240. obj := GetSymTableName(def.owner)+'__'+GetSymName(def.procsym);
  1241. if not(cs_gdb_valgrind in current_settings.globalswitches) and
  1242. (def.owner.symtabletype=localsymtable) and
  1243. assigned(def.owner.defowner) and
  1244. assigned(tprocdef(def.owner.defowner).procsym) then
  1245. info := ','+GetSymName(def.procsym)+','+GetSymName(tprocdef(def.owner.defowner).procsym);
  1246. end;
  1247. mangledname:=ReplaceForbiddenAsmSymbolChars(def.mangledname);
  1248. if target_info.system in systems_dotted_function_names then
  1249. mangledname:='.'+mangledname;
  1250. result.concat(Tai_stab.Create_ansistr(stabsdir,'"'+obj+':'+RType+def_stab_number(def.returndef)+info+'",'+
  1251. base_stabs_str(procdef_stab,'0',tostr(def.fileinfo.line),mangledname)));
  1252. end;
  1253. function TDebugInfoStabs.gen_procdef_endsym_stabs(def: tprocdef): TAsmList;
  1254. var
  1255. ss, mangledname: ansistring;
  1256. stabsendlabel: tasmlabel;
  1257. begin
  1258. result:=TAsmList.create;
  1259. { end of procedure }
  1260. current_asmdata.getlabel(stabsendlabel,alt_dbgtype);
  1261. if dbgtype<>dbg_stabx then
  1262. begin
  1263. mangledname:=def.mangledname;
  1264. if target_info.system in systems_dotted_function_names then
  1265. mangledname:='.'+mangledname;
  1266. // LBRAC
  1267. ss:=tostr(STABS_N_LBRAC)+',0,0,'+mangledname;
  1268. if not(af_stabs_use_function_absolute_addresses in target_asm.flags) then
  1269. begin
  1270. ss:=ss+'-';
  1271. ss:=ss+mangledname;
  1272. end;
  1273. result.concat(Tai_stab.Create_ansistr(stab_stabn,ss));
  1274. // RBRAC
  1275. ss:=tostr(STABS_N_RBRAC)+',0,0,'+stabsendlabel.name;
  1276. if not(af_stabs_use_function_absolute_addresses in target_asm.flags) then
  1277. begin
  1278. ss:=ss+'-';
  1279. ss:=ss+mangledname;
  1280. end;
  1281. result.concat(Tai_stab.Create_ansistr(stab_stabn,ss));
  1282. { the stabsendlabel must come after all other stabs for this }
  1283. { function }
  1284. result.concat(tai_label.create(stabsendlabel));
  1285. { Add a "size" stab as described in the last paragraph of 2.5 at }
  1286. { http://sourceware.org/gdb/current/onlinedocs/stabs_2.html#SEC12 }
  1287. { This works at least on Darwin (and is needed on Darwin to get }
  1288. { correct smartlinking of stabs), but I don't know which binutils }
  1289. { version is required on other platforms }
  1290. { This stab must come after all other stabs for the procedure, }
  1291. { including the LBRAC/RBRAC ones }
  1292. if (target_info.system in systems_darwin) then
  1293. result.concat(Tai_stab.create(stabsdir,
  1294. strpnew('"",'+base_stabs_str(procdef_stab,'0','0',stabsendlabel.name+'-'+mangledname))));
  1295. end;
  1296. end;
  1297. procedure TDebugInfoStabs.appendsym_paravar(list:TAsmList;sym:tparavarsym);
  1298. var
  1299. ss : ansistring;
  1300. c : string[1];
  1301. st : string;
  1302. regidx : Tregisterindex;
  1303. begin
  1304. ss:='';
  1305. { set loc to LOC_REFERENCE to get somewhat usable debugging info for -Or }
  1306. { while stabs aren't adapted for regvars yet }
  1307. if (vo_is_self in sym.varoptions) then
  1308. begin
  1309. case sym.localloc.loc of
  1310. LOC_REGISTER,
  1311. LOC_CREGISTER:
  1312. regidx:=findreg_by_number(sym.localloc.register);
  1313. LOC_REFERENCE: ;
  1314. else
  1315. internalerror(2003091815);
  1316. end;
  1317. if (po_classmethod in tabstractprocdef(sym.owner.defowner).procoptions) or
  1318. (po_staticmethod in tabstractprocdef(sym.owner.defowner).procoptions) then
  1319. begin
  1320. if (sym.localloc.loc=LOC_REFERENCE) then
  1321. ss:=sym_stabstr_evaluate(sym,'"pvmt:p$1",'+base_stabs_str(localvarsymref_stab,'0','0','$2'),
  1322. [def_stab_number(pvmttype),getoffsetstr(sym.localloc.reference)])
  1323. else
  1324. begin
  1325. regidx:=findreg_by_number(sym.localloc.register);
  1326. ss:=sym_stabstr_evaluate(sym,'"pvmt:r$1",'+base_stabs_str(regvar_stab,'0','0','$2'),
  1327. [def_stab_number(pvmttype),tostr(regstabs_table[regidx])]);
  1328. end
  1329. end
  1330. else
  1331. begin
  1332. if not(is_class(tprocdef(sym.owner.defowner).struct)) then
  1333. c:='v'
  1334. else
  1335. c:='p';
  1336. if (sym.localloc.loc=LOC_REFERENCE) then
  1337. ss:=sym_stabstr_evaluate(sym,'"$$t:$1",'+base_stabs_str(localvarsymref_stab,'0','0','$2'),
  1338. [c+def_stab_number(tprocdef(sym.owner.defowner).struct),getoffsetstr(sym.localloc.reference)])
  1339. else
  1340. begin
  1341. if (c='p') then
  1342. c:='R'
  1343. else
  1344. c:='a';
  1345. regidx:=findreg_by_number(sym.localloc.register);
  1346. ss:=sym_stabstr_evaluate(sym,'"$$t:$1",'+base_stabs_str(regvar_stab,'0','0','$2'),
  1347. [c+def_stab_number(tprocdef(sym.owner.defowner).struct),tostr(regstabs_table[regidx])]);
  1348. end
  1349. end;
  1350. end
  1351. else
  1352. begin
  1353. st:=def_stab_number(sym.vardef);
  1354. if paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
  1355. not(vo_has_local_copy in sym.varoptions) and
  1356. not is_open_string(sym.vardef) then
  1357. c:='v' { should be 'i' but 'i' doesn't work }
  1358. else
  1359. c:='p';
  1360. case sym.localloc.loc of
  1361. LOC_REGISTER,
  1362. LOC_CREGISTER,
  1363. LOC_MMREGISTER,
  1364. LOC_CMMREGISTER,
  1365. LOC_FPUREGISTER,
  1366. LOC_CFPUREGISTER :
  1367. begin
  1368. ss:=get_appendsym_paravar_reg(sym,c,st,sym.localloc.register);
  1369. end;
  1370. LOC_REFERENCE :
  1371. begin
  1372. { When the *value* of a parameter (so not its address!) is
  1373. copied into a local variable, you have to generate two
  1374. stabs: one for the parmeter, and one for the local copy.
  1375. Not doing this breaks debugging under e.g. SPARC. Doc:
  1376. http://sourceware.org/gdb/current/onlinedocs/stabs_4.html#SEC26
  1377. }
  1378. if (target_dbg.id<>dbg_stabx) and
  1379. (c='p') and
  1380. not is_open_string(sym.vardef) and
  1381. ((sym.paraloc[calleeside].location^.loc<>sym.localloc.loc) or
  1382. ((sym.localloc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  1383. ((sym.paraloc[calleeside].location^.reference.index<>sym.localloc.reference.base) or
  1384. (sym.paraloc[calleeside].location^.reference.offset<>sym.localloc.reference.offset))) or
  1385. ((sym.localloc.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_MMREGISTER,LOC_CMMREGISTER,LOC_FPUREGISTER,LOC_CFPUREGISTER]) and
  1386. (sym.localloc.register<>sym.paraloc[calleeside].location^.register))) then
  1387. begin
  1388. if not(sym.paraloc[calleeside].location^.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1389. ss:=get_appendsym_paravar_reg(sym,c,st,sym.paraloc[calleeside].location^.register)
  1390. else
  1391. ss:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(localvarsymref_stab,'0','${line}','$2'),
  1392. [c+st,getparaoffsetstr(sym.paraloc[calleeside].location^.reference)]);
  1393. write_sym_stabstr(list,sym,ss);
  1394. { second stab has no parameter specifier }
  1395. c:='';
  1396. end;
  1397. { offset to ebp => will not work if the framepointer is esp
  1398. so some optimizing will make things harder to debug }
  1399. ss:=sym_stabstr_evaluate(sym,'"${name}:$1",'+base_stabs_str(paravarsymref_stab,'0','${line}','$2'),[c+st,getoffsetstr(sym.localloc.reference)])
  1400. end;
  1401. else
  1402. internalerror(2003091814);
  1403. end;
  1404. end;
  1405. write_sym_stabstr(list,sym,ss);
  1406. end;
  1407. function stabx_quote_const(const s: string): string;
  1408. var
  1409. i:byte;
  1410. begin
  1411. stabx_quote_const:='';
  1412. for i:=1 to length(s) do
  1413. begin
  1414. case s[i] of
  1415. #10:
  1416. stabx_quote_const:=stabx_quote_const+'\n';
  1417. #13:
  1418. stabx_quote_const:=stabx_quote_const+'\r';
  1419. { stabx strings cannot deal with embedded quotes }
  1420. '"':
  1421. stabx_quote_const:=stabx_quote_const+' ';
  1422. else
  1423. stabx_quote_const:=stabx_quote_const+s[i];
  1424. end;
  1425. end;
  1426. end;
  1427. procedure TDebugInfoStabs.appendsym_const(list:TAsmList;sym:tconstsym);
  1428. var
  1429. st : string;
  1430. ss : ansistring;
  1431. begin
  1432. ss:='';
  1433. { Don't write info for default parameter values, the N_Func breaks
  1434. the N_Func for the function itself.
  1435. Valgrind does not support constants }
  1436. if (sym.owner.symtabletype=parasymtable) or
  1437. (cs_gdb_valgrind in current_settings.globalswitches) then
  1438. exit;
  1439. case sym.consttyp of
  1440. conststring:
  1441. begin
  1442. if sym.value.len<200 then
  1443. if target_dbg.id=dbg_stabs then
  1444. st:='s'''+backspace_quote(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']),['"','\',#10,#13])+''''
  1445. else
  1446. st:='s'''+stabx_quote_const(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']))+''''
  1447. else
  1448. st:='<constant string too long>';
  1449. end;
  1450. constord:
  1451. st:='i'+tostr(sym.value.valueord);
  1452. constpointer:
  1453. st:='i'+tostr(sym.value.valueordptr);
  1454. constreal:
  1455. begin
  1456. system.str(pbestreal(sym.value.valueptr)^,st);
  1457. st := 'r'+st;
  1458. end;
  1459. else
  1460. begin
  1461. { if we don't know just put zero !! }
  1462. st:='i0';
  1463. end;
  1464. end;
  1465. ss:=sym_stabstr_evaluate(sym,'"${name}:c=$1;",'+base_stabs_str(constsym_stab,'0','${line}','0'),[st]);
  1466. write_sym_stabstr(list,sym,ss);
  1467. end;
  1468. procedure TDebugInfoStabs.appendsym_type(list:TAsmList;sym:ttypesym);
  1469. var
  1470. ss : ansistring;
  1471. stabchar : string[2];
  1472. begin
  1473. ss:='';
  1474. if not assigned(sym.typedef) then
  1475. internalerror(200509262);
  1476. if sym.typedef.typ in tagtypes then
  1477. stabchar:=tagtypeprefix
  1478. else
  1479. stabchar:='t';
  1480. ss:=sym_stabstr_evaluate(sym,'"${name}:$1$2",'+base_stabs_str(typesym_stab,'0','${line}','0'),[stabchar,def_stab_number(sym.typedef)]);
  1481. write_sym_stabstr(list,sym,ss);
  1482. end;
  1483. procedure TDebugInfoStabs.appendsym_label(list:TAsmList;sym:tlabelsym);
  1484. var
  1485. ss : ansistring;
  1486. begin
  1487. ss:=sym_stabstr_evaluate(sym,'"${name}",'+base_stabs_str(localvarsymref_stab,'0','${line}','0'),[]);
  1488. write_sym_stabstr(list,sym,ss);
  1489. end;
  1490. {****************************************************************************
  1491. Proc/Module support
  1492. ****************************************************************************}
  1493. procedure TDebugInfoStabs.inserttypeinfo;
  1494. var
  1495. stabsvarlist,
  1496. stabstypelist : TAsmList;
  1497. storefilepos : tfileposinfo;
  1498. i : longint;
  1499. vardatatype : ttypesym;
  1500. begin
  1501. storefilepos:=current_filepos;
  1502. current_filepos:=current_module.mainfilepos;
  1503. global_stab_number:=0;
  1504. defnumberlist:=TFPObjectlist.create(false);
  1505. deftowritelist:=TFPObjectlist.create(false);
  1506. stabsvarlist:=TAsmList.create;
  1507. stabstypelist:=TAsmList.create;
  1508. vardatatype:=try_search_system_type('TVARDATA');
  1509. if assigned(vardatatype) then
  1510. vardatadef:=trecorddef(vardatatype.typedef);
  1511. { include symbol that will be referenced from the main to be sure to
  1512. include this debuginfo .o file }
  1513. current_module.flags:=current_module.flags or uf_has_stabs_debuginfo;
  1514. if not(target_info.system in systems_darwin) then
  1515. begin
  1516. new_section(current_asmdata.asmlists[al_stabs],sec_data,GetSymTableName(current_module.localsymtable),sizeof(pint));
  1517. current_asmdata.asmlists[al_stabs].concat(tai_symbol.Createname_global(make_mangledname('DEBUGINFO',current_module.localsymtable,''),AT_DATA,0));
  1518. end
  1519. else
  1520. new_section(current_asmdata.asmlists[al_stabs],sec_code,GetSymTableName(current_module.localsymtable),sizeof(pint));
  1521. { write all global/local variables. This will flag all required tdefs }
  1522. if assigned(current_module.globalsymtable) then
  1523. write_symtable_syms(stabsvarlist,current_module.globalsymtable);
  1524. if assigned(current_module.localsymtable) then
  1525. write_symtable_syms(stabsvarlist,current_module.localsymtable);
  1526. { write all procedures and methods. This will flag all required tdefs }
  1527. if assigned(current_module.globalsymtable) then
  1528. write_symtable_procdefs(stabsvarlist,current_module.globalsymtable);
  1529. if assigned(current_module.localsymtable) then
  1530. write_symtable_procdefs(stabsvarlist,current_module.localsymtable);
  1531. { reset unit type info flag }
  1532. reset_unit_type_info;
  1533. { write used types from the used units }
  1534. write_used_unit_type_info(stabstypelist,current_module);
  1535. { last write the types from this unit }
  1536. if assigned(current_module.globalsymtable) then
  1537. write_symtable_defs(stabstypelist,current_module.globalsymtable);
  1538. if assigned(current_module.localsymtable) then
  1539. write_symtable_defs(stabstypelist,current_module.localsymtable);
  1540. write_remaining_defs_to_write(stabstypelist);
  1541. current_asmdata.asmlists[al_stabs].concatlist(stabstypelist);
  1542. current_asmdata.asmlists[al_stabs].concatlist(stabsvarlist);
  1543. { reset stab numbers }
  1544. for i:=0 to defnumberlist.count-1 do
  1545. begin
  1546. if assigned(defnumberlist[i]) then
  1547. begin
  1548. tdef(defnumberlist[i]).stab_number:=0;
  1549. tdef(defnumberlist[i]).dbg_state:=dbg_state_unused;
  1550. end;
  1551. end;
  1552. defnumberlist.free;
  1553. defnumberlist:=nil;
  1554. deftowritelist.free;
  1555. deftowritelist:=nil;
  1556. stabsvarlist.free;
  1557. stabstypelist.free;
  1558. current_filepos:=storefilepos;
  1559. end;
  1560. procedure TDebugInfoStabs.insertlineinfo(list: TAsmList);
  1561. var
  1562. currfileinfo,
  1563. lastfileinfo : tfileposinfo;
  1564. currfuncname : pshortstring;
  1565. currsectype : TAsmSectiontype;
  1566. hlabel : tasmlabel;
  1567. hp : tai;
  1568. infile : tinputfile;
  1569. begin
  1570. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  1571. currfuncname:=nil;
  1572. currsectype:=sec_code;
  1573. hp:=Tai(list.first);
  1574. while assigned(hp) do
  1575. begin
  1576. case hp.typ of
  1577. ait_section :
  1578. currsectype:=tai_section(hp).sectype;
  1579. ait_function_name :
  1580. currfuncname:=tai_function_name(hp).funcname;
  1581. ait_force_line :
  1582. lastfileinfo.line:=-1;
  1583. end;
  1584. if (currsectype=sec_code) and
  1585. (hp.typ=ait_instruction) then
  1586. begin
  1587. currfileinfo:=tailineinfo(hp).fileinfo;
  1588. { file changed ? (must be before line info) }
  1589. if (currfileinfo.fileindex<>0) and
  1590. ((lastfileinfo.fileindex<>currfileinfo.fileindex) or
  1591. (lastfileinfo.moduleindex<>currfileinfo.moduleindex)) then
  1592. begin
  1593. infile:=get_module(currfileinfo.moduleindex).sourcefiles.get_file(currfileinfo.fileindex);
  1594. if assigned(infile) then
  1595. begin
  1596. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1597. { emit stabs }
  1598. if not(ds_stabs_abs_include_files in current_settings.debugswitches) or
  1599. path_absolute(infile.path) then
  1600. list.insertbefore(Tai_stab.Create_str(stabsdir,'"'+BsToSlash(FixPath(infile.path,false))+FixFileName(infile.name)+'",'+tostr(stabs_n_includefile)+
  1601. ',0,0,'+hlabel.name),hp)
  1602. else
  1603. list.insertbefore(Tai_stab.Create_str(stabsdir,'"'+BsToSlash(FixPath(getcurrentdir,false)+FixPath(infile.path,false))+FixFileName(infile.name)+'",'+tostr(stabs_n_includefile)+
  1604. ',0,0,'+hlabel.name),hp);
  1605. list.insertbefore(tai_label.create(hlabel),hp);
  1606. { force new line info }
  1607. lastfileinfo.line:=-1;
  1608. end;
  1609. end;
  1610. { line changed ? }
  1611. if (currfileinfo.line>lastfileinfo.line) and (currfileinfo.line<>0) then
  1612. begin
  1613. if assigned(currfuncname) and
  1614. not(af_stabs_use_function_absolute_addresses in target_asm.flags) then
  1615. begin
  1616. current_asmdata.getlabel(hlabel,alt_dbgline);
  1617. list.insertbefore(Tai_stab.Create_str(stab_stabn,tostr(stabs_n_textline)+',0,'+tostr(currfileinfo.line)+','+
  1618. hlabel.name+' - '+{$IFDEF POWERPC64}'.'+{$ENDIF POWERPC64}currfuncname^),hp);
  1619. list.insertbefore(tai_label.create(hlabel),hp);
  1620. end
  1621. else
  1622. list.insertbefore(Tai_stab.Create_str(stab_stabd,tostr(stabs_n_textline)+',0,'+tostr(currfileinfo.line)),hp);
  1623. end;
  1624. lastfileinfo:=currfileinfo;
  1625. end;
  1626. hp:=tai(hp.next);
  1627. end;
  1628. end;
  1629. procedure TDebugInfoStabs.insertmoduleinfo;
  1630. var
  1631. hlabel : tasmlabel;
  1632. infile : tinputfile;
  1633. begin
  1634. { emit main source n_sourcefile for start of module }
  1635. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1636. infile:=current_module.sourcefiles.get_file(1);
  1637. new_section(current_asmdata.asmlists[al_start],sec_code,make_mangledname('DEBUGSTART',current_module.localsymtable,''),sizeof(pint),secorder_begin);
  1638. if not(target_info.system in systems_darwin) then
  1639. current_asmdata.asmlists[al_start].concat(tai_symbol.Createname_global(make_mangledname('DEBUGSTART',current_module.localsymtable,''),AT_DATA,0));
  1640. current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stabsdir,'"'+BsToSlash(FixPath(getcurrentdir,false))+'",'+
  1641. base_stabs_str(stabs_n_sourcefile,'0','0',hlabel.name)));
  1642. current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stabsdir,'"'+BsToSlash(FixPath(infile.path,false))+FixFileName(infile.name)+'",'+
  1643. base_stabs_str(stabs_n_sourcefile,'0','0',hlabel.name)));
  1644. current_asmdata.asmlists[al_start].concat(tai_label.create(hlabel));
  1645. { for darwin, you need a "module marker" too to work around }
  1646. { either some assembler or gdb bug (radar 4386531 according to a }
  1647. { comment in dbxout.c of Apple's gcc) }
  1648. if (target_info.system in systems_darwin) then
  1649. current_asmdata.asmlists[al_end].concat(Tai_stab.Create_str(stabsdir,'"",'+base_stabs_str(STABS_N_OSO,'0','0','0')));
  1650. { emit empty n_sourcefile for end of module }
  1651. current_asmdata.getlabel(hlabel,alt_dbgfile);
  1652. new_section(current_asmdata.asmlists[al_end],sec_code,make_mangledname('DEBUGEND',current_module.localsymtable,''),sizeof(pint),secorder_end);
  1653. if not(target_info.system in systems_darwin) then
  1654. current_asmdata.asmlists[al_end].concat(tai_symbol.Createname_global(make_mangledname('DEBUGEND',current_module.localsymtable,''),AT_DATA,0));
  1655. current_asmdata.asmlists[al_end].concat(Tai_stab.Create_str(stabsdir,'"",'+base_stabs_str(stabs_n_sourcefile,'0','0',hlabel.name)));
  1656. current_asmdata.asmlists[al_end].concat(tai_label.create(hlabel));
  1657. end;
  1658. procedure TDebugInfoStabs.referencesections(list: TAsmList);
  1659. var
  1660. hp : tmodule;
  1661. dbgtable : tai_symbol;
  1662. begin
  1663. { Reference all DEBUGINFO sections from the main .fpc section }
  1664. if (target_info.system in ([system_powerpc_macos]+systems_darwin)) then
  1665. exit;
  1666. new_section(list,sec_fpc,'links',0);
  1667. { make sure the debuginfo doesn't get stripped out }
  1668. if (target_info.system in systems_darwin) then
  1669. begin
  1670. dbgtable:=tai_symbol.createname('DEBUGINFOTABLE',AT_DATA,0);
  1671. list.concat(tai_directive.create(asd_no_dead_strip,dbgtable.sym.name));
  1672. list.concat(dbgtable);
  1673. end;
  1674. { include reference to all debuginfo sections of used units }
  1675. hp:=tmodule(loaded_units.first);
  1676. while assigned(hp) do
  1677. begin
  1678. If (hp.flags and uf_has_stabs_debuginfo)=uf_has_stabs_debuginfo then
  1679. begin
  1680. list.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',hp.localsymtable,''),0));
  1681. list.concat(Tai_const.Createname(make_mangledname('DEBUGSTART',hp.localsymtable,''),0));
  1682. list.concat(Tai_const.Createname(make_mangledname('DEBUGEND',hp.localsymtable,''),0));
  1683. end;
  1684. hp:=tmodule(hp.next);
  1685. end;
  1686. end;
  1687. constructor TDebugInfoStabs.Create;
  1688. begin
  1689. inherited Create;
  1690. dbgtype:=dbg_stabs;
  1691. stabsdir:=stab_stabs;
  1692. def_stab:=STABS_N_LSYM;
  1693. regvar_stab:=STABS_N_RSYM;
  1694. procdef_stab:=STABS_N_Function;
  1695. constsym_stab:=STABS_N_Function;
  1696. typesym_stab:=STABS_N_LSYM;
  1697. globalvarsym_uninited_stab:=STABS_N_STSYM;
  1698. globalvarsym_inited_stab:=STABS_N_LCSYM;
  1699. staticvarsym_uninited_stab:=STABS_N_STSYM;
  1700. staticvarsym_inited_stab:=STABS_N_LCSYM;
  1701. localvarsymref_stab:=STABS_N_TSYM;
  1702. paravarsymref_stab:=STABS_N_TSYM;
  1703. tagtypeprefix:='Tt';
  1704. vardatadef:=nil;
  1705. end;
  1706. const
  1707. dbg_stabs_info : tdbginfo =
  1708. (
  1709. id : dbg_stabs;
  1710. idtxt : 'STABS';
  1711. );
  1712. initialization
  1713. RegisterDebugInfo(dbg_stabs_info,TDebugInfoStabs);
  1714. end.