dbgcodeview.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. {
  2. Copyright (c) 2018 by Nikolay Nikolov
  3. This units contains support for Microsoft CodeView 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. { documentation for the format, available on the internet:
  18. earlier versions:
  19. http://pagesperso-orange.fr/pierrelib/exec_formats/MS_Symbol_Type_v1.0.pdf
  20. http://ftp.openwatcom.org/devel/docs/CodeView.pdf
  21. modern versions:
  22. https://llvm.org/docs/PDB/index.html
  23. https://llvm.org/devmtg/2016-11/Slides/Kleckner-CodeViewInLLVM.pdf
  24. }
  25. unit dbgcodeview;
  26. {$i fpcdefs.inc}
  27. interface
  28. uses
  29. aasmdata,
  30. dbgbase;
  31. type
  32. TSymbolIndex = (
  33. S_COMPILE = $0001, { Compile flags symbol }
  34. S_REGISTER = $0002, { Register variable }
  35. S_CONSTANT = $0003, { Constant symbol }
  36. S_UDT = $0004, { User-defined Type }
  37. S_SSEARCH = $0005, { Start search }
  38. S_END = $0006, { End block, procedure, with, or thunk }
  39. S_SKIP = $0007, { Skip - Reserve symbol space }
  40. S_CVRESERVE = $0008, { Reserved for internal use by the Microsoft debugger }
  41. S_OBJNAME = $0009, { Specify name of object file }
  42. S_ENDARG = $000a, { Specify end of arguments in function symbols }
  43. S_COBOLUDT = $000b, { Microfocus COBOL user-defined type }
  44. S_MANYREG = $000c, { Many register symbol }
  45. S_RETURN = $000d, { Function return description }
  46. S_ENTRYTHIS = $000e, { Description of this pointer at entry }
  47. S_BPREL16 = $0100, { BP relative 16:16 }
  48. S_LDATA16 = $0101, { Local data 16:16 }
  49. S_GDATA16 = $0102, { Global data 16:16 }
  50. S_PUB16 = $0103, { Public symbol 16:16 }
  51. S_LPROC16 = $0104, { Local procedure start 16:16 }
  52. S_GPROC16 = $0105, { Global procedure start 16:16 }
  53. S_THUNK16 = $0106, { Thunk start 16:16 }
  54. S_BLOCK16 = $0107, { Block start 16:16 }
  55. S_WITH16 = $0108, { With start 16:16 }
  56. S_LABEL16 = $0109, { Code label 16:16 }
  57. S_CEXMODEL16 = $010a, { Change execution model 16:16 }
  58. S_VFTPATH16 = $010b, { Virtual function table path descriptor 16:16 }
  59. S_REGREL16 = $010c, { Specify 16:16 offset relative to arbitrary register }
  60. S_BPREL32 = $0200, { BP relative 16:32 }
  61. S_LDATA32 = $0201, { Local data 16:32 }
  62. S_GDATA32 = $0202, { Global data 16:32 }
  63. S_PUB32 = $0203, { Public symbol 16:32 }
  64. S_LPROC32 = $0204, { Local procedure start 16:32 }
  65. S_GPROC32 = $0205, { Global procedure start 16:32 }
  66. S_THUNK32 = $0206, { Thunk start 16:32 }
  67. S_BLOCK32 = $0207, { Block start 16:32 }
  68. S_VFTPATH32 = $020b, { Virtual function table path descriptor 16:32 }
  69. S_REGREL32 = $020c, { 16:32 offset relative to arbitrary register }
  70. S_LTHREAD32 = $020d, { Local Thread Storage data }
  71. S_GTHREAD32 = $020e, { Global Thread Storage data }
  72. S_LPROCMIPS = $0300, { Local procedure start MIPS }
  73. S_GPROCMIPS = $0301, { Global procedure start MIPS }
  74. S_PROCREF = $0400, { Reference to a procedure }
  75. S_DATAREF = $0401, { Reference to data }
  76. S_ALIGN = $0402 { Page align symbols }
  77. );
  78. TLeafIndex=(
  79. LF_MODIFIER = $0001, { Type Modifier (const, volatile, unaligned) }
  80. LF_POINTER = $0002, { Pointer }
  81. LF_ARRAY = $0003, { Simple Array }
  82. LF_CLASS = $0004, { Class (C++ class declaration) }
  83. LF_STRUCTURE = $0005, { Structure (C and C++ struct declaration) }
  84. LF_UNION = $0006, { Union }
  85. LF_ENUM = $0007, { Enumeration }
  86. LF_PROCEDURE = $0008, { Procedure }
  87. LF_MFUNCTION = $0009, { Member Function }
  88. LF_VTSHAPE = $000a, { Virtual Function Table Shape }
  89. LF_COBOL0 = $000b, { reserved for Microfocus COBOL }
  90. LF_COBOL1 = $000c, { reserved for Microfocus COBOL }
  91. LF_BARRAY = $000d, { Basic Array }
  92. LF_LABEL = $000e, { Label }
  93. LF_NULL = $000f, { Null }
  94. LF_NOTTRAN = $0010, { Not Translated }
  95. LF_DIMARRAY = $0011, { Multiply Dimensioned Array }
  96. LF_VFTPATH = $0012, { Path to Virtual Function Table }
  97. LF_PRECOMP = $0013, { Reference Precompiled Types }
  98. LF_ENDPRECOMP = $0014, { End of Precompiled Types }
  99. LF_OEM = $0015, { OEM Generic Type }
  100. LF_Reserved = $0016, { Reserved }
  101. LF_PAD0 = $f0,
  102. LF_PAD1 = $f1,
  103. LF_PAD2 = $f2,
  104. LF_PAD3 = $f3,
  105. LF_PAD4 = $f4,
  106. LF_PAD5 = $f5,
  107. LF_PAD6 = $f6,
  108. LF_PAD7 = $f7,
  109. LF_PAD8 = $f8,
  110. LF_PAD9 = $f9,
  111. LF_PAD10 = $fa,
  112. LF_PAD11 = $fb,
  113. LF_PAD12 = $fc,
  114. LF_PAD13 = $fc,
  115. LF_PAD14 = $fe,
  116. LF_PAD15 = $ff,
  117. LF_SKIP = $0200, { Skip (used by incremental compilers to reserve space for future indexes) }
  118. LF_ARGLIST = $0201, { Argument List }
  119. LF_DEFARG = $0202, { Default Argument }
  120. LF_LIST = $0203, { Arbitrary List }
  121. LF_FIELDLIST = $0204, { Field List }
  122. LF_DERIVED = $0205, { Derived Classes }
  123. LF_BITFIELD = $0206, { Bit Fields }
  124. LF_METHODLIST = $0207, { Method List }
  125. LF_DIMCONU = $0208, { Dimensioned Array with Constant Upper Bound }
  126. LF_DIMCONLU = $0209, { Dimensioned Array with Constant Lower and Upper Bounds }
  127. LF_DIMVARU = $020a, { Dimensioned Array with Variable Upper Bound }
  128. LF_DIMVARLU = $020b, { Dimensioned Array with Variable Lower and Upper Bounds }
  129. LF_REFSYM = $020c, { Referenced Symbol }
  130. LF_BCLASS = $0400, { Real Base Class }
  131. LF_VBCLASS = $0401, { Direct Virtual Base Class }
  132. LF_IVBCLASS = $0402, { Indirect Virtual Base Class }
  133. LF_ENUMERATE = $0403, { Enumeration Name and Value }
  134. LF_FRIENDFCN = $0404, { Friend Function }
  135. LF_INDEX = $0405, { Index to Another Type Record }
  136. LF_MEMBER = $0406, { Data Member }
  137. LF_STMEMBER = $0407, { Static Data Member }
  138. LF_METHOD = $0408, { Method }
  139. LF_NESTTYPE = $0409, { Nested Type Definition }
  140. LF_VFUNCTAB = $040a, { Virtual Function Table Pointer }
  141. LF_FRIENDCLS = $040b, { Friend Class }
  142. LF_ONEMETHOD = $040c, { One Method }
  143. LF_VFUNCOFF = $040d, { Virtual Function Offset }
  144. LF_CHAR = $8000, { Signed Char (8-bit value) }
  145. LF_SHORT = $8001, { Signed Short (16-bit signed value) }
  146. LF_USHORT = $8002, { Unsigned Short (16-bit unsigned value) }
  147. LF_LONG = $8003, { Signed Long (32-bit signed value) }
  148. LF_ULONG = $8004, { Unsigned Long (32-bit unsigned value) }
  149. LF_REAL32 = $8005, { 32-bit Float }
  150. LF_REAL64 = $8006, { 64-bit Float }
  151. LF_REAL80 = $8007, { 80-bit Float }
  152. LF_REAL128 = $8008, { 128-bit Float }
  153. LF_QUADWORD = $8009, { Signed Quad Word (64-bit signed value) }
  154. LF_UQUADWORD = $800a, { Unsigned Quad Word (64-bit unsigned value) }
  155. LF_REAL48 = $800b, { 48-bit Float }
  156. LF_COMPLEX32 = $800c, { 32-bit Complex }
  157. LF_COMPLEX64 = $800d, { 64-bit Complex }
  158. LF_COMPLEX80 = $800e, { 80-bit Complex }
  159. LF_COMPLEX128 = $800f, { 128-bit Complex }
  160. LF_VARSTRING = $8010 { Variable-length String }
  161. );
  162. const
  163. LF_NUMERIC = LF_CHAR;
  164. type
  165. { TDebugInfoCodeView }
  166. TDebugInfoCodeView = class(TDebugInfo)
  167. public
  168. procedure insertlineinfo(list:TAsmList);override;
  169. end;
  170. procedure InsertLineInfo_OMF_LINNUM_MsLink(list: TAsmList);
  171. implementation
  172. uses
  173. globtype,
  174. cutils,
  175. aasmtai,
  176. fmodule,
  177. systems;
  178. procedure InsertLineInfo_OMF_LINNUM_MsLink(list: TAsmList);
  179. var
  180. currfileinfo,
  181. lastfileinfo : tfileposinfo;
  182. nolineinfolevel : Integer;
  183. currfuncname : pshortstring;
  184. hp : tai;
  185. begin
  186. FillChar(lastfileinfo,sizeof(lastfileinfo),0);
  187. hp:=Tai(list.first);
  188. nolineinfolevel:=0;
  189. while assigned(hp) do
  190. begin
  191. case hp.typ of
  192. ait_function_name :
  193. begin
  194. currfuncname:=tai_function_name(hp).funcname;
  195. list.concat(tai_comment.Create(strpnew('function: '+currfuncname^)));
  196. end;
  197. ait_force_line :
  198. begin
  199. lastfileinfo.line:=-1;
  200. end;
  201. ait_marker :
  202. begin
  203. case tai_marker(hp).kind of
  204. mark_NoLineInfoStart:
  205. inc(nolineinfolevel);
  206. mark_NoLineInfoEnd:
  207. dec(nolineinfolevel);
  208. end;
  209. end;
  210. end;
  211. { OMF LINNUM records do not support multiple source files }
  212. if (hp.typ=ait_instruction) and
  213. (nolineinfolevel=0) and
  214. (tailineinfo(hp).fileinfo.fileindex=main_module.unit_index) then
  215. begin
  216. currfileinfo:=tailineinfo(hp).fileinfo;
  217. { line changed ? }
  218. if (lastfileinfo.line<>currfileinfo.line) and (currfileinfo.line<>0) then
  219. begin
  220. { line directive }
  221. list.insertbefore(tai_directive.Create(asd_omf_linnum_line,tostr(currfileinfo.line)),hp);
  222. end;
  223. lastfileinfo:=currfileinfo;
  224. end;
  225. hp:=tai(hp.next);
  226. end;
  227. end;
  228. {****************************************************************************
  229. TDebugInfoCodeView
  230. ****************************************************************************}
  231. procedure TDebugInfoCodeView.insertlineinfo(list: TAsmList);
  232. begin
  233. InsertLineInfo_OMF_LINNUM_MsLink(list);
  234. end;
  235. {****************************************************************************
  236. ****************************************************************************}
  237. const
  238. dbg_codeview_info : tdbginfo =
  239. (
  240. id : dbg_codeview;
  241. idtxt : 'CODEVIEW';
  242. );
  243. initialization
  244. RegisterDebugInfo(dbg_codeview_info,TDebugInfoCodeView);
  245. end.