dbgstabs.pas 66 KB

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