dbgstabs.pas 66 KB

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