dbgstabs.pas 61 KB

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