2
0

dbgstabs.pas 63 KB

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