PageRenderTime 134ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Gedemin/jcl/source/windows/JclTD32.pas

http://gedemin.googlecode.com/
Pascal | 1700 lines | 1158 code | 149 blank | 393 comment | 45 complexity | 933a297e8fdcb110f16bf0f294c2e8fd MD5 | raw file
Possible License(s): AGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. {**************************************************************************************************}
  2. { }
  3. { Project JEDI Code Library (JCL) }
  4. { }
  5. { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
  6. { you may not use this file except in compliance with the License. You may obtain a copy of the }
  7. { License at http://www.mozilla.org/MPL/ }
  8. { }
  9. { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
  10. { ANY KIND, either express or implied. See the License for the specific language governing rights }
  11. { and limitations under the License. }
  12. { }
  13. { The Original Code is JclTD32.pas. }
  14. { }
  15. { The Initial Developer of the Original Code is Flier Lu (<flier_lu att yahoo dott com dott cn>). }
  16. { Portions created by Flier Lu are Copyright (C) Flier Lu. All Rights Reserved. }
  17. { }
  18. { Contributors: }
  19. { Flier Lu (flier) }
  20. { Olivier Sannier (obones) }
  21. { Petr Vones (pvones) }
  22. { Heinz Zastrau (heinzz) }
  23. { Andreas Hausladen (ahuser) }
  24. { }
  25. {**************************************************************************************************}
  26. { }
  27. { Borland TD32 symbolic debugging information support routines and classes. }
  28. { }
  29. { Unit owner: Flier Lu }
  30. { }
  31. {**************************************************************************************************}
  32. // Last modified: $Date: 2007-06-20 10:42:59 +0200 (mer., 20 juin 2007) $
  33. unit JclTD32;
  34. interface
  35. {$I jcl.inc}
  36. uses
  37. {$IFDEF UNITVERSIONING}
  38. JclUnitVersioning,
  39. {$ENDIF UNITVERSIONING}
  40. {$IFDEF MSWINDOWS}
  41. Windows,
  42. {$ENDIF MSWINDOWS}
  43. Classes, SysUtils, Contnrs,
  44. JclBase, JclFileUtils, JclPeImage;
  45. { TODO -cDOC : Original code: "Flier Lu" <flier_lu att yahoo dott com dott cn> }
  46. // TD32 constants and structures
  47. {*******************************************************************************
  48. [-----------------------------------------------------------------------]
  49. [ Symbol and Type OMF Format Borland Executable Files ]
  50. [-----------------------------------------------------------------------]
  51. Introduction
  52. This section describes the format used to embed debugging information into
  53. the executable file.
  54. Debug Information Format
  55. The format encompasses a block of data which goes at the end of the .EXE
  56. file, i.e., after the header plus load image, overlays, and
  57. Windows/Presentation Manager resource compiler information. The lower
  58. portion of the file is unaffected by the additional data.
  59. The last eight bytes of the file contain a signature and a long file offset
  60. from the end of the file (lfoBase). The signature is FBxx, where xx is the
  61. version number. The long offset indicates the position in the file
  62. (relative to the end of the file) of the base address. For the LX format
  63. executables, the base address is determined by looking at the executable
  64. header.
  65. The signatures have the following meanings:
  66. FB09 The signature for a Borland 32 bit symbol file.
  67. The value
  68. lfaBase=length of the file - lfoBase
  69. gives the base address of the start of the Symbol and Type OMF information
  70. relative to the beginning of the file. All other file offsets in the
  71. Symbol and Type OMF are relative to the lfaBase. At the base address the
  72. signature is repeated, followed by the long displacement to the subsection
  73. directory (lfoDir). All subsections start on a long word boundary and are
  74. designed to maintain natural alignment internally in each subsection and
  75. within the subsection directory.
  76. Subsection Directory
  77. The subsection directory has the format
  78. Directory header
  79. Directory entry 0
  80. Directory entry 1
  81. .
  82. .
  83. .
  84. Directory entry n
  85. There is no requirement for a particular subsection of a particular module to exist.
  86. The following is the layout of the FB09 debug information in the image:
  87. FB09 Header
  88. sstModule [1]
  89. .
  90. .
  91. .
  92. sstModule [n]
  93. sstAlignSym [1]
  94. sstSrcModule [1]
  95. .
  96. .
  97. .
  98. sstAlignSym [n]
  99. sstSrcModule [n]
  100. sstGlobalSym
  101. sstGlobalTypes
  102. sstNames
  103. SubSection Directory
  104. FB09 Trailer
  105. *******************************************************************************}
  106. const
  107. Borland32BitSymbolFileSignatureForDelphi = $39304246; // 'FB09'
  108. Borland32BitSymbolFileSignatureForBCB = $41304246; // 'FB0A'
  109. type
  110. { Signature structure }
  111. PJclTD32FileSignature = ^TJclTD32FileSignature;
  112. TJclTD32FileSignature = packed record
  113. Signature: DWORD;
  114. Offset: DWORD;
  115. end;
  116. const
  117. { Subsection Types }
  118. SUBSECTION_TYPE_MODULE = $120;
  119. SUBSECTION_TYPE_TYPES = $121;
  120. SUBSECTION_TYPE_SYMBOLS = $124;
  121. SUBSECTION_TYPE_ALIGN_SYMBOLS = $125;
  122. SUBSECTION_TYPE_SOURCE_MODULE = $127;
  123. SUBSECTION_TYPE_GLOBAL_SYMBOLS = $129;
  124. SUBSECTION_TYPE_GLOBAL_TYPES = $12B;
  125. SUBSECTION_TYPE_NAMES = $130;
  126. type
  127. { Subsection directory header structure }
  128. { The directory header structure is followed by the directory entries
  129. which specify the subsection type, module index, file offset, and size.
  130. The subsection directory gives the location (LFO) and size of each subsection,
  131. as well as its type and module number if applicable. }
  132. PDirectoryEntry = ^TDirectoryEntry;
  133. TDirectoryEntry = packed record
  134. SubsectionType: Word; // Subdirectory type
  135. ModuleIndex: Word; // Module index
  136. Offset: DWORD; // Offset from the base offset lfoBase
  137. Size: DWORD; // Number of bytes in subsection
  138. end;
  139. { The subsection directory is prefixed with a directory header structure
  140. indicating size and number of subsection directory entries that follow. }
  141. PDirectoryHeader = ^TDirectoryHeader;
  142. TDirectoryHeader = packed record
  143. Size: Word; // Length of this structure
  144. DirEntrySize: Word; // Length of each directory entry
  145. DirEntryCount: DWORD; // Number of directory entries
  146. lfoNextDir: DWORD; // Offset from lfoBase of next directory.
  147. Flags: DWORD; // Flags describing directory and subsection tables.
  148. DirEntries: array [0..0] of TDirectoryEntry;
  149. end;
  150. {*******************************************************************************
  151. SUBSECTION_TYPE_MODULE $120
  152. This describes the basic information about an object module including code
  153. segments, module name, and the number of segments for the modules that
  154. follow. Directory entries for sstModules precede all other subsection
  155. directory entries.
  156. *******************************************************************************}
  157. type
  158. PSegmentInfo = ^TSegmentInfo;
  159. TSegmentInfo = packed record
  160. Segment: Word; // Segment that this structure describes
  161. Flags: Word; // Attributes for the logical segment.
  162. // The following attributes are defined:
  163. // $0000 Data segment
  164. // $0001 Code segment
  165. Offset: DWORD; // Offset in segment where the code starts
  166. Size: DWORD; // Count of the number of bytes of code in the segment
  167. end;
  168. PSegmentInfoArray = ^TSegmentInfoArray;
  169. TSegmentInfoArray = array [0..32767] of TSegmentInfo;
  170. PModuleInfo = ^TModuleInfo;
  171. TModuleInfo = packed record
  172. OverlayNumber: Word; // Overlay number
  173. LibraryIndex: Word; // Index into sstLibraries subsection
  174. // if this module was linked from a library
  175. SegmentCount: Word; // Count of the number of code segments
  176. // this module contributes to
  177. DebuggingStyle: Word; // Debugging style for this module.
  178. NameIndex: DWORD; // Name index of module.
  179. TimeStamp: DWORD; // Time stamp from the OBJ file.
  180. Reserved: array [0..2] of DWORD; // Set to 0.
  181. Segments: array [0..0] of TSegmentInfo;
  182. // Detailed information about each segment
  183. // that code is contributed to.
  184. // This is an array of cSeg count segment
  185. // information descriptor structures.
  186. end;
  187. {*******************************************************************************
  188. SUBSECTION_TYPE_SOURCE_MODULE $0127
  189. This table describes the source line number to addressing mapping
  190. information for a module. The table permits the description of a module
  191. containing multiple source files with each source file contributing code to
  192. one or more code segments. The base addresses of the tables described
  193. below are all relative to the beginning of the sstSrcModule table.
  194. Module header
  195. Information for source file 1
  196. Information for segment 1
  197. .
  198. .
  199. .
  200. Information for segment n
  201. .
  202. .
  203. .
  204. Information for source file n
  205. Information for segment 1
  206. .
  207. .
  208. .
  209. Information for segment n
  210. *******************************************************************************}
  211. type
  212. { The line number to address mapping information is contained in a table with
  213. the following format: }
  214. PLineMappingEntry = ^TLineMappingEntry;
  215. TLineMappingEntry = packed record
  216. SegmentIndex: Word; // Segment index for this table
  217. PairCount: Word; // Count of the number of source line pairs to follow
  218. Offsets: array [0..0] of DWORD;
  219. // An array of 32-bit offsets for the offset
  220. // within the code segment ofthe start of ine contained
  221. // in the parallel array linenumber.
  222. (*
  223. { This is an array of 16-bit line numbers of the lines in the source file
  224. that cause code to be emitted to the code segment.
  225. This array is parallel to the offset array.
  226. If cPair is not even, then a zero word is emitted to
  227. maintain natural alignment in the sstSrcModule table. }
  228. LineNumbers: array [0..PairCount - 1] of Word;
  229. *)
  230. end;
  231. TOffsetPair = packed record
  232. StartOffset: DWORD;
  233. EndOffset: DWORD;
  234. end;
  235. POffsetPairArray = ^TOffsetPairArray;
  236. TOffsetPairArray = array [0..32767] of TOffsetPair;
  237. { The file table describes the code segments that receive code from this
  238. source file. Source file entries have the following format: }
  239. PSourceFileEntry = ^TSourceFileEntry;
  240. TSourceFileEntry = packed record
  241. SegmentCount: Word; // Number of segments that receive code from this source file.
  242. NameIndex: DWORD; // Name index of Source file name.
  243. BaseSrcLines: array [0..0] of DWORD;
  244. // An array of offsets for the line/address mapping
  245. // tables for each of the segments that receive code
  246. // from this source file.
  247. (*
  248. { An array of two 32-bit offsets per segment that
  249. receives code from this module. The first offset
  250. is the offset within the segment of the first byte
  251. of code from this module. The second offset is the
  252. ending address of the code from this module. The
  253. order of these pairs corresponds to the ordering of
  254. the segments in the seg array. Zeros in these
  255. entries means that the information is not known and
  256. the file and line tables described below need to be
  257. examined to determine if an address of interest is
  258. contained within the code from this module. }
  259. SegmentAddress: array [0..SegmentCount - 1] of TOffsetPair;
  260. Name: ShortString; // Count of the number of bytes in source file name
  261. *)
  262. end;
  263. { The module header structure describes the source file and code segment
  264. organization of the module. Each module header has the following format: }
  265. PSourceModuleInfo = ^TSourceModuleInfo;
  266. TSourceModuleInfo = packed record
  267. FileCount: Word; // The number of source file scontributing code to segments
  268. SegmentCount: Word; // The number of code segments receiving code from this module
  269. BaseSrcFiles: array [0..0] of DWORD;
  270. (*
  271. // This is an array of base offsets from the beginning of the sstSrcModule table
  272. BaseSrcFiles: array [0..FileCount - 1] of DWORD;
  273. { An array of two 32-bit offsets per segment that
  274. receives code from this module. The first offset
  275. is the offset within the segment of the first byte
  276. of code from this module. The second offset is the
  277. ending address of the code from this module. The
  278. order of these pairs corresponds to the ordering of
  279. the segments in the seg array. Zeros in these
  280. entries means that the information is not known and
  281. the file and line tables described below need to be
  282. examined to determine if an address of interest is
  283. contained within the code from this module. }
  284. SegmentAddress: array [0..SegmentCount - 1] of TOffsetPair;
  285. { An array of segment indices that receive code from
  286. this module. If the number of segments is not
  287. even, a pad word is inserted to maintain natural
  288. alignment. }
  289. SegmentIndexes: array [0..SegmentCount - 1] of Word;
  290. *)
  291. end;
  292. {*******************************************************************************
  293. SUBSECTION_TYPE_GLOBAL_TYPES $12b
  294. This subsection contains the packed type records for the executable file.
  295. The first long word of the subsection contains the number of types in the
  296. table. This count is followed by a count-sized array of long offsets to
  297. the corresponding type record. As the sstGlobalTypes subsection is
  298. written, each type record is forced to start on a long word boundary.
  299. However, the length of the type string is NOT adjusted by the pad count.
  300. The remainder of the subsection contains the type records.
  301. *******************************************************************************}
  302. type
  303. PGlobalTypeInfo = ^TGlobalTypeInfo;
  304. TGlobalTypeInfo = packed record
  305. Count: DWORD; // count of the number of types
  306. // offset of each type string from the beginning of table
  307. Offsets: array [0..0] of DWORD;
  308. end;
  309. const
  310. { Symbol type defines }
  311. SYMBOL_TYPE_COMPILE = $0001; // Compile flags symbol
  312. SYMBOL_TYPE_REGISTER = $0002; // Register variable
  313. SYMBOL_TYPE_CONST = $0003; // Constant symbol
  314. SYMBOL_TYPE_UDT = $0004; // User-defined Type
  315. SYMBOL_TYPE_SSEARCH = $0005; // Start search
  316. SYMBOL_TYPE_END = $0006; // End block, procedure, with, or thunk
  317. SYMBOL_TYPE_SKIP = $0007; // Skip - Reserve symbol space
  318. SYMBOL_TYPE_CVRESERVE = $0008; // Reserved for Code View internal use
  319. SYMBOL_TYPE_OBJNAME = $0009; // Specify name of object file
  320. SYMBOL_TYPE_BPREL16 = $0100; // BP relative 16:16
  321. SYMBOL_TYPE_LDATA16 = $0101; // Local data 16:16
  322. SYMBOL_TYPE_GDATA16 = $0102; // Global data 16:16
  323. SYMBOL_TYPE_PUB16 = $0103; // Public symbol 16:16
  324. SYMBOL_TYPE_LPROC16 = $0104; // Local procedure start 16:16
  325. SYMBOL_TYPE_GPROC16 = $0105; // Global procedure start 16:16
  326. SYMBOL_TYPE_THUNK16 = $0106; // Thunk start 16:16
  327. SYMBOL_TYPE_BLOCK16 = $0107; // Block start 16:16
  328. SYMBOL_TYPE_WITH16 = $0108; // With start 16:16
  329. SYMBOL_TYPE_LABEL16 = $0109; // Code label 16:16
  330. SYMBOL_TYPE_CEXMODEL16 = $010A; // Change execution model 16:16
  331. SYMBOL_TYPE_VFTPATH16 = $010B; // Virtual function table path descriptor 16:16
  332. SYMBOL_TYPE_BPREL32 = $0200; // BP relative 16:32
  333. SYMBOL_TYPE_LDATA32 = $0201; // Local data 16:32
  334. SYMBOL_TYPE_GDATA32 = $0202; // Global data 16:32
  335. SYMBOL_TYPE_PUB32 = $0203; // Public symbol 16:32
  336. SYMBOL_TYPE_LPROC32 = $0204; // Local procedure start 16:32
  337. SYMBOL_TYPE_GPROC32 = $0205; // Global procedure start 16:32
  338. SYMBOL_TYPE_THUNK32 = $0206; // Thunk start 16:32
  339. SYMBOL_TYPE_BLOCK32 = $0207; // Block start 16:32
  340. SYMBOL_TYPE_WITH32 = $0208; // With start 16:32
  341. SYMBOL_TYPE_LABEL32 = $0209; // Label 16:32
  342. SYMBOL_TYPE_CEXMODEL32 = $020A; // Change execution model 16:32
  343. SYMBOL_TYPE_VFTPATH32 = $020B; // Virtual function table path descriptor 16:32
  344. {*******************************************************************************
  345. Global and Local Procedure Start 16:32
  346. SYMBOL_TYPE_LPROC32 $0204
  347. SYMBOL_TYPE_GPROC32 $0205
  348. The symbol records define local (file static) and global procedure
  349. definition. For C/C++, functions that are declared static to a module are
  350. emitted as Local Procedure symbols. Functions not specifically declared
  351. static are emitted as Global Procedures.
  352. For each SYMBOL_TYPE_GPROC32 emitted, an SYMBOL_TYPE_GPROCREF symbol
  353. must be fabricated and emitted to the SUBSECTION_TYPE_GLOBAL_SYMBOLS section.
  354. *******************************************************************************}
  355. type
  356. TSymbolProcInfo = packed record
  357. pParent: DWORD;
  358. pEnd: DWORD;
  359. pNext: DWORD;
  360. Size: DWORD; // Length in bytes of this procedure
  361. DebugStart: DWORD; // Offset in bytes from the start of the procedure to
  362. // the point where the stack frame has been set up.
  363. DebugEnd: DWORD; // Offset in bytes from the start of the procedure to
  364. // the point where the procedure is ready to return
  365. // and has calculated its return value, if any.
  366. // Frame and register variables an still be viewed.
  367. Offset: DWORD; // Offset portion of the segmented address of
  368. // the start of the procedure in the code segment
  369. Segment: Word; // Segment portion of the segmented address of
  370. // the start of the procedure in the code segment
  371. ProcType: DWORD; // Type of the procedure type record
  372. NearFar: Byte; // Type of return the procedure makes:
  373. // 0 near
  374. // 4 far
  375. Reserved: Byte;
  376. NameIndex: DWORD; // Name index of procedure
  377. end;
  378. TSymbolObjNameInfo = packed record
  379. Signature: DWORD; // Signature for the CodeView information contained in
  380. // this module
  381. NameIndex: DWORD; // Name index of the object file
  382. end;
  383. TSymbolDataInfo = packed record
  384. Offset: DWORD; // Offset portion of the segmented address of
  385. // the start of the data in the code segment
  386. Segment: Word; // Segment portion of the segmented address of
  387. // the start of the data in the code segment
  388. Reserved: Word;
  389. TypeIndex: DWORD; // Type index of the symbol
  390. NameIndex: DWORD; // Name index of the symbol
  391. end;
  392. TSymbolWithInfo = packed record
  393. pParent: DWORD;
  394. pEnd: DWORD;
  395. Size: DWORD; // Length in bytes of this "with"
  396. Offset: DWORD; // Offset portion of the segmented address of
  397. // the start of the "with" in the code segment
  398. Segment: Word; // Segment portion of the segmented address of
  399. // the start of the "with" in the code segment
  400. Reserved: Word;
  401. NameIndex: DWORD; // Name index of the "with"
  402. end;
  403. TSymbolLabelInfo = packed record
  404. Offset: DWORD; // Offset portion of the segmented address of
  405. // the start of the label in the code segment
  406. Segment: Word; // Segment portion of the segmented address of
  407. // the start of the label in the code segment
  408. NearFar: Byte; // Address mode of the label:
  409. // 0 near
  410. // 4 far
  411. Reserved: Byte;
  412. NameIndex: DWORD; // Name index of the label
  413. end;
  414. TSymbolConstantInfo = packed record
  415. TypeIndex: DWORD; // Type index of the constant (for enums)
  416. NameIndex: DWORD; // Name index of the constant
  417. Reserved: DWORD;
  418. Value: DWORD; // value of the constant
  419. end;
  420. TSymbolUdtInfo = packed record
  421. TypeIndex: DWORD; // Type index of the type
  422. Properties: Word; // isTag:1 True if this is a tag (not a typedef)
  423. // isNest:1 True if the type is a nested type (its name
  424. // will be 'class_name::type_name' in that case)
  425. NameIndex: DWORD; // Name index of the type
  426. Reserved: DWORD;
  427. end;
  428. TSymbolVftPathInfo = packed record
  429. Offset: DWORD; // Offset portion of start of the virtual function table
  430. Segment: Word; // Segment portion of the virtual function table
  431. Reserved: Word;
  432. RootIndex: DWORD; // The type index of the class at the root of the path
  433. PathIndex: DWORD; // Type index of the record describing the base class
  434. // path from the root to the leaf class for the virtual
  435. // function table
  436. end;
  437. type
  438. { Symbol Information Records }
  439. PSymbolInfo = ^TSymbolInfo;
  440. TSymbolInfo = packed record
  441. Size: Word;
  442. SymbolType: Word;
  443. case Word of
  444. SYMBOL_TYPE_LPROC32, SYMBOL_TYPE_GPROC32:
  445. (Proc: TSymbolProcInfo);
  446. SYMBOL_TYPE_OBJNAME:
  447. (ObjName: TSymbolObjNameInfo);
  448. SYMBOL_TYPE_LDATA32, SYMBOL_TYPE_GDATA32, SYMBOL_TYPE_PUB32:
  449. (Data: TSymbolDataInfo);
  450. SYMBOL_TYPE_WITH32:
  451. (With32: TSymbolWithInfo);
  452. SYMBOL_TYPE_LABEL32:
  453. (Label32: TSymbolLabelInfo);
  454. SYMBOL_TYPE_CONST:
  455. (Constant: TSymbolConstantInfo);
  456. SYMBOL_TYPE_UDT:
  457. (Udt: TSymbolUdtInfo);
  458. SYMBOL_TYPE_VFTPATH32:
  459. (VftPath: TSymbolVftPathInfo);
  460. end;
  461. PSymbolInfos = ^TSymbolInfos;
  462. TSymbolInfos = packed record
  463. Signature: DWORD;
  464. Symbols: array [0..0] of TSymbolInfo;
  465. end;
  466. {$IFDEF SUPPORTS_EXTSYM}
  467. {$EXTERNALSYM Borland32BitSymbolFileSignatureForDelphi}
  468. {$EXTERNALSYM Borland32BitSymbolFileSignatureForBCB}
  469. {$EXTERNALSYM SUBSECTION_TYPE_MODULE}
  470. {$EXTERNALSYM SUBSECTION_TYPE_TYPES}
  471. {$EXTERNALSYM SUBSECTION_TYPE_SYMBOLS}
  472. {$EXTERNALSYM SUBSECTION_TYPE_ALIGN_SYMBOLS}
  473. {$EXTERNALSYM SUBSECTION_TYPE_SOURCE_MODULE}
  474. {$EXTERNALSYM SUBSECTION_TYPE_GLOBAL_SYMBOLS}
  475. {$EXTERNALSYM SUBSECTION_TYPE_GLOBAL_TYPES}
  476. {$EXTERNALSYM SUBSECTION_TYPE_NAMES}
  477. {$EXTERNALSYM SYMBOL_TYPE_COMPILE}
  478. {$EXTERNALSYM SYMBOL_TYPE_REGISTER}
  479. {$EXTERNALSYM SYMBOL_TYPE_CONST}
  480. {$EXTERNALSYM SYMBOL_TYPE_UDT}
  481. {$EXTERNALSYM SYMBOL_TYPE_SSEARCH}
  482. {$EXTERNALSYM SYMBOL_TYPE_END}
  483. {$EXTERNALSYM SYMBOL_TYPE_SKIP}
  484. {$EXTERNALSYM SYMBOL_TYPE_CVRESERVE}
  485. {$EXTERNALSYM SYMBOL_TYPE_OBJNAME}
  486. {$EXTERNALSYM SYMBOL_TYPE_BPREL16}
  487. {$EXTERNALSYM SYMBOL_TYPE_LDATA16}
  488. {$EXTERNALSYM SYMBOL_TYPE_GDATA16}
  489. {$EXTERNALSYM SYMBOL_TYPE_PUB16}
  490. {$EXTERNALSYM SYMBOL_TYPE_LPROC16}
  491. {$EXTERNALSYM SYMBOL_TYPE_GPROC16}
  492. {$EXTERNALSYM SYMBOL_TYPE_THUNK16}
  493. {$EXTERNALSYM SYMBOL_TYPE_BLOCK16}
  494. {$EXTERNALSYM SYMBOL_TYPE_WITH16}
  495. {$EXTERNALSYM SYMBOL_TYPE_LABEL16}
  496. {$EXTERNALSYM SYMBOL_TYPE_CEXMODEL16}
  497. {$EXTERNALSYM SYMBOL_TYPE_VFTPATH16}
  498. {$EXTERNALSYM SYMBOL_TYPE_BPREL32}
  499. {$EXTERNALSYM SYMBOL_TYPE_LDATA32}
  500. {$EXTERNALSYM SYMBOL_TYPE_GDATA32}
  501. {$EXTERNALSYM SYMBOL_TYPE_PUB32}
  502. {$EXTERNALSYM SYMBOL_TYPE_LPROC32}
  503. {$EXTERNALSYM SYMBOL_TYPE_GPROC32}
  504. {$EXTERNALSYM SYMBOL_TYPE_THUNK32}
  505. {$EXTERNALSYM SYMBOL_TYPE_BLOCK32}
  506. {$EXTERNALSYM SYMBOL_TYPE_WITH32}
  507. {$EXTERNALSYM SYMBOL_TYPE_LABEL32}
  508. {$EXTERNALSYM SYMBOL_TYPE_CEXMODEL32}
  509. {$EXTERNALSYM SYMBOL_TYPE_VFTPATH32}
  510. {$ENDIF SUPPORTS_EXTSYM}
  511. // TD32 information related classes
  512. type
  513. TJclModuleInfo = class(TObject)
  514. private
  515. FNameIndex: DWORD;
  516. FSegments: PSegmentInfoArray;
  517. FSegmentCount: Integer;
  518. function GetSegment(const Idx: Integer): TSegmentInfo;
  519. protected
  520. constructor Create(pModInfo: PModuleInfo);
  521. public
  522. property NameIndex: DWORD read FNameIndex;
  523. property SegmentCount: Integer read FSegmentCount; //GetSegmentCount;
  524. property Segment[const Idx: Integer]: TSegmentInfo read GetSegment; default;
  525. end;
  526. TJclLineInfo = class(TObject)
  527. private
  528. FLineNo: DWORD;
  529. FOffset: DWORD;
  530. protected
  531. constructor Create(ALineNo, AOffset: DWORD);
  532. public
  533. property LineNo: DWORD read FLineNo;
  534. property Offset: DWORD read FOffset;
  535. end;
  536. TJclSourceModuleInfo = class(TObject)
  537. private
  538. FLines: TObjectList;
  539. FSegments: POffsetPairArray;
  540. FSegmentCount: Integer;
  541. FNameIndex: DWORD;
  542. function GetLine(const Idx: Integer): TJclLineInfo;
  543. function GetLineCount: Integer;
  544. function GetSegment(const Idx: Integer): TOffsetPair;
  545. protected
  546. constructor Create(pSrcFile: PSourceFileEntry; Base: DWORD);
  547. public
  548. destructor Destroy; override;
  549. function FindLine(const AAddr: DWORD; var ALine: TJclLineInfo): Boolean;
  550. property NameIndex: DWORD read FNameIndex;
  551. property LineCount: Integer read GetLineCount;
  552. property Line[const Idx: Integer]: TJclLineInfo read GetLine; default;
  553. property SegmentCount: Integer read FSegmentCount; //GetSegmentCount;
  554. property Segment[const Idx: Integer]: TOffsetPair read GetSegment;
  555. end;
  556. TJclSymbolInfo = class(TObject)
  557. private
  558. FSymbolType: Word;
  559. protected
  560. constructor Create(pSymInfo: PSymbolInfo); virtual;
  561. property SymbolType: Word read FSymbolType;
  562. end;
  563. TJclProcSymbolInfo = class(TJclSymbolInfo)
  564. private
  565. FNameIndex: DWORD;
  566. FOffset: DWORD;
  567. FSize: DWORD;
  568. protected
  569. constructor Create(pSymInfo: PSymbolInfo); override;
  570. public
  571. property NameIndex: DWORD read FNameIndex;
  572. property Offset: DWORD read FOffset;
  573. property Size: DWORD read FSize;
  574. end;
  575. TJclLocalProcSymbolInfo = class(TJclProcSymbolInfo);
  576. TJclGlobalProcSymbolInfo = class(TJclProcSymbolInfo);
  577. { not used by Delphi }
  578. TJclObjNameSymbolInfo = class(TJclSymbolInfo)
  579. private
  580. FSignature: DWORD;
  581. FNameIndex: DWORD;
  582. protected
  583. constructor Create(pSymInfo: PSymbolInfo); override;
  584. public
  585. property NameIndex: DWORD read FNameIndex;
  586. property Signature: DWORD read FSignature;
  587. end;
  588. TJclDataSymbolInfo = class(TJclSymbolInfo)
  589. private
  590. FOffset: DWORD;
  591. FTypeIndex: DWORD;
  592. FNameIndex: DWORD;
  593. protected
  594. constructor Create(pSymInfo: PSymbolInfo); override;
  595. public
  596. property NameIndex: DWORD read FNameIndex;
  597. property TypeIndex: DWORD read FTypeIndex;
  598. property Offset: DWORD read FOffset;
  599. end;
  600. TJclLDataSymbolInfo = class(TJclDataSymbolInfo);
  601. TJclGDataSymbolInfo = class(TJclDataSymbolInfo);
  602. TJclPublicSymbolInfo = class(TJclDataSymbolInfo);
  603. TJclWithSymbolInfo = class(TJclSymbolInfo)
  604. private
  605. FOffset: DWORD;
  606. FSize: DWORD;
  607. FNameIndex: DWORD;
  608. protected
  609. constructor Create(pSymInfo: PSymbolInfo); override;
  610. public
  611. property NameIndex: DWORD read FNameIndex;
  612. property Offset: DWORD read FOffset;
  613. property Size: DWORD read FSize;
  614. end;
  615. { not used by Delphi }
  616. TJclLabelSymbolInfo = class(TJclSymbolInfo)
  617. private
  618. FOffset: DWORD;
  619. FNameIndex: DWORD;
  620. protected
  621. constructor Create(pSymInfo: PSymbolInfo); override;
  622. public
  623. property NameIndex: DWORD read FNameIndex;
  624. property Offset: DWORD read FOffset;
  625. end;
  626. { not used by Delphi }
  627. TJclConstantSymbolInfo = class(TJclSymbolInfo)
  628. private
  629. FValue: DWORD;
  630. FTypeIndex: DWORD;
  631. FNameIndex: DWORD;
  632. protected
  633. constructor Create(pSymInfo: PSymbolInfo); override;
  634. public
  635. property NameIndex: DWORD read FNameIndex;
  636. property TypeIndex: DWORD read FTypeIndex; // for enums
  637. property Value: DWORD read FValue;
  638. end;
  639. TJclUdtSymbolInfo = class(TJclSymbolInfo)
  640. private
  641. FTypeIndex: DWORD;
  642. FNameIndex: DWORD;
  643. FProperties: Word;
  644. protected
  645. constructor Create(pSymInfo: PSymbolInfo); override;
  646. public
  647. property NameIndex: DWORD read FNameIndex;
  648. property TypeIndex: DWORD read FTypeIndex;
  649. property Properties: Word read FProperties;
  650. end;
  651. { not used by Delphi }
  652. TJclVftPathSymbolInfo = class(TJclSymbolInfo)
  653. private
  654. FRootIndex: DWORD;
  655. FPathIndex: DWORD;
  656. FOffset: DWORD;
  657. protected
  658. constructor Create(pSymInfo: PSymbolInfo); override;
  659. public
  660. property RootIndex: DWORD read FRootIndex;
  661. property PathIndex: DWORD read FPathIndex;
  662. property Offset: DWORD read FOffset;
  663. end;
  664. // TD32 parser
  665. TJclTD32InfoParser = class(TObject)
  666. private
  667. FBase: Pointer;
  668. FData: TCustomMemoryStream;
  669. FNames: TList;
  670. FModules: TObjectList;
  671. FSourceModules: TObjectList;
  672. FSymbols: TObjectList;
  673. FProcSymbols: TList;
  674. FValidData: Boolean;
  675. function GetName(const Idx: Integer): string;
  676. function GetNameCount: Integer;
  677. function GetSymbol(const Idx: Integer): TJclSymbolInfo;
  678. function GetSymbolCount: Integer;
  679. function GetProcSymbol(const Idx: Integer): TJclProcSymbolInfo;
  680. function GetProcSymbolCount: Integer;
  681. function GetModule(const Idx: Integer): TJclModuleInfo;
  682. function GetModuleCount: Integer;
  683. function GetSourceModule(const Idx: Integer): TJclSourceModuleInfo;
  684. function GetSourceModuleCount: Integer;
  685. protected
  686. procedure Analyse;
  687. procedure AnalyseNames(const pSubsection: Pointer; const Size: DWORD); virtual;
  688. procedure AnalyseGlobalTypes(const pTypes: Pointer; const Size: DWORD); virtual;
  689. procedure AnalyseAlignSymbols(pSymbols: PSymbolInfos; const Size: DWORD); virtual;
  690. procedure AnalyseModules(pModInfo: PModuleInfo; const Size: DWORD); virtual;
  691. procedure AnalyseSourceModules(pSrcModInfo: PSourceModuleInfo; const Size: DWORD); virtual;
  692. procedure AnalyseUnknownSubSection(const pSubsection: Pointer; const Size: DWORD); virtual;
  693. function LfaToVa(Lfa: DWORD): Pointer;
  694. public
  695. constructor Create(const ATD32Data: TCustomMemoryStream); // Data mustn't be freed before the class is destroyed
  696. destructor Destroy; override;
  697. function FindModule(const AAddr: DWORD; var AMod: TJclModuleInfo): Boolean;
  698. function FindSourceModule(const AAddr: DWORD; var ASrcMod: TJclSourceModuleInfo): Boolean;
  699. function FindProc(const AAddr: DWORD; var AProc: TJclProcSymbolInfo): Boolean;
  700. class function IsTD32Sign(const Sign: TJclTD32FileSignature): Boolean;
  701. class function IsTD32DebugInfoValid(const DebugData: Pointer; const DebugDataSize: LongWord): Boolean;
  702. property Data: TCustomMemoryStream read FData;
  703. property Names[const Idx: Integer]: string read GetName;
  704. property NameCount: Integer read GetNameCount;
  705. property Symbols[const Idx: Integer]: TJclSymbolInfo read GetSymbol;
  706. property SymbolCount: Integer read GetSymbolCount;
  707. property ProcSymbols[const Idx: Integer]: TJclProcSymbolInfo read GetProcSymbol;
  708. property ProcSymbolCount: Integer read GetProcSymbolCount;
  709. property Modules[const Idx: Integer]: TJclModuleInfo read GetModule;
  710. property ModuleCount: Integer read GetModuleCount;
  711. property SourceModules[const Idx: Integer]: TJclSourceModuleInfo read GetSourceModule;
  712. property SourceModuleCount: Integer read GetSourceModuleCount;
  713. property ValidData: Boolean read FValidData;
  714. end;
  715. // TD32 scanner with source location methods
  716. TJclTD32InfoScanner = class(TJclTD32InfoParser)
  717. public
  718. function LineNumberFromAddr(AAddr: DWORD; var Offset: Integer): Integer; overload;
  719. function LineNumberFromAddr(AAddr: DWORD): Integer; overload;
  720. function ProcNameFromAddr(AAddr: DWORD): string; overload;
  721. function ProcNameFromAddr(AAddr: DWORD; var Offset: Integer): string; overload;
  722. function ModuleNameFromAddr(AAddr: DWORD): string;
  723. function SourceNameFromAddr(AAddr: DWORD): string;
  724. end;
  725. // PE Image with TD32 information and source location support
  726. TJclPeBorTD32Image = class(TJclPeBorImage)
  727. private
  728. FIsTD32DebugPresent: Boolean;
  729. FTD32DebugData: TCustomMemoryStream;
  730. FTD32Scanner: TJclTD32InfoScanner;
  731. protected
  732. procedure AfterOpen; override;
  733. procedure Clear; override;
  734. procedure ClearDebugData;
  735. procedure CheckDebugData;
  736. function IsDebugInfoInImage(var DataStream: TCustomMemoryStream): Boolean;
  737. function IsDebugInfoInTds(var DataStream: TCustomMemoryStream): Boolean;
  738. public
  739. property IsTD32DebugPresent: Boolean read FIsTD32DebugPresent;
  740. property TD32DebugData: TCustomMemoryStream read FTD32DebugData;
  741. property TD32Scanner: TJclTD32InfoScanner read FTD32Scanner;
  742. end;
  743. {$IFDEF UNITVERSIONING}
  744. const
  745. UnitVersioning: TUnitVersionInfo = (
  746. RCSfile: '$URL: https://jcl.svn.sourceforge.net:443/svnroot/jcl/tags/JCL-1.101-Build2725/jcl/source/windows/JclTD32.pas $';
  747. Revision: '$Revision: 2048 $';
  748. Date: '$Date: 2007-06-20 10:42:59 +0200 (mer., 20 juin 2007) $';
  749. LogPath: 'JCL\source\windows'
  750. );
  751. {$ENDIF UNITVERSIONING}
  752. implementation
  753. uses
  754. JclResources, JclSysUtils;
  755. const
  756. TurboDebuggerSymbolExt = '.tds';
  757. //=== { TJclModuleInfo } =====================================================
  758. constructor TJclModuleInfo.Create(pModInfo: PModuleInfo);
  759. begin
  760. Assert(Assigned(pModInfo));
  761. inherited Create;
  762. FNameIndex := pModInfo.NameIndex;
  763. FSegments := @pModInfo.Segments[0];
  764. FSegmentCount := pModInfo.SegmentCount;
  765. end;
  766. function TJclModuleInfo.GetSegment(const Idx: Integer): TSegmentInfo;
  767. begin
  768. Assert((0 <= Idx) and (Idx < FSegmentCount));
  769. Result := FSegments[Idx];
  770. end;
  771. //=== { TJclLineInfo } =======================================================
  772. constructor TJclLineInfo.Create(ALineNo, AOffset: DWORD);
  773. begin
  774. inherited Create;
  775. FLineNo := ALineNo;
  776. FOffset := AOffset;
  777. end;
  778. //=== { TJclSourceModuleInfo } ===============================================
  779. constructor TJclSourceModuleInfo.Create(pSrcFile: PSourceFileEntry; Base: DWORD);
  780. type
  781. PArrayOfWord = ^TArrayOfWord;
  782. TArrayOfWord = array [0..0] of Word;
  783. var
  784. I, J: Integer;
  785. pLineEntry: PLineMappingEntry;
  786. begin
  787. Assert(Assigned(pSrcFile));
  788. inherited Create;
  789. FNameIndex := pSrcFile.NameIndex;
  790. FLines := TObjectList.Create;
  791. {$RANGECHECKS OFF}
  792. for I := 0 to pSrcFile.SegmentCount - 1 do
  793. begin
  794. pLineEntry := PLineMappingEntry(Base + pSrcFile.BaseSrcLines[I]);
  795. for J := 0 to pLineEntry.PairCount - 1 do
  796. FLines.Add(TJclLineInfo.Create(
  797. PArrayOfWord(@pLineEntry.Offsets[pLineEntry.PairCount])^[J],
  798. pLineEntry.Offsets[J]));
  799. end;
  800. FSegments := @pSrcFile.BaseSrcLines[pSrcFile.SegmentCount];
  801. FSegmentCount := pSrcFile.SegmentCount;
  802. {$IFDEF RANGECHECKS_ON}
  803. {$RANGECHECKS ON}
  804. {$ENDIF RANGECHECKS_ON}
  805. end;
  806. destructor TJclSourceModuleInfo.Destroy;
  807. begin
  808. FreeAndNil(FLines);
  809. inherited Destroy;
  810. end;
  811. function TJclSourceModuleInfo.GetLine(const Idx: Integer): TJclLineInfo;
  812. begin
  813. Result := TJclLineInfo(FLines.Items[Idx]);
  814. end;
  815. function TJclSourceModuleInfo.GetLineCount: Integer;
  816. begin
  817. Result := FLines.Count;
  818. end;
  819. function TJclSourceModuleInfo.GetSegment(const Idx: Integer): TOffsetPair;
  820. begin
  821. Assert((0 <= Idx) and (Idx < FSegmentCount));
  822. Result := FSegments[Idx];
  823. end;
  824. function TJclSourceModuleInfo.FindLine(const AAddr: DWORD; var ALine: TJclLineInfo): Boolean;
  825. var
  826. I: Integer;
  827. begin
  828. for I := 0 to LineCount - 1 do
  829. with Line[I] do
  830. begin
  831. if AAddr = Offset then
  832. begin
  833. Result := True;
  834. ALine := Line[I];
  835. Exit;
  836. end
  837. else
  838. if (I > 1) and (Line[I - 1].Offset < AAddr) and (AAddr < Offset) then
  839. begin
  840. Result := True;
  841. ALine := Line[I-1];
  842. Exit;
  843. end;
  844. end;
  845. Result := False;
  846. ALine := nil;
  847. end;
  848. //=== { TJclSymbolInfo } =====================================================
  849. constructor TJclSymbolInfo.Create(pSymInfo: PSymbolInfo);
  850. begin
  851. Assert(Assigned(pSymInfo));
  852. inherited Create;
  853. FSymbolType := pSymInfo.SymbolType;
  854. end;
  855. //=== { TJclProcSymbolInfo } =================================================
  856. constructor TJclProcSymbolInfo.Create(pSymInfo: PSymbolInfo);
  857. begin
  858. Assert(Assigned(pSymInfo));
  859. inherited Create(pSymInfo);
  860. with pSymInfo^ do
  861. begin
  862. FNameIndex := Proc.NameIndex;
  863. FOffset := Proc.Offset;
  864. FSize := Proc.Size;
  865. end;
  866. end;
  867. //=== { TJclObjNameSymbolInfo } ==============================================
  868. constructor TJclObjNameSymbolInfo.Create(pSymInfo: PSymbolInfo);
  869. begin
  870. Assert(Assigned(pSymInfo));
  871. inherited Create(pSymInfo);
  872. with pSymInfo^ do
  873. begin
  874. FNameIndex := ObjName.NameIndex;
  875. FSignature := ObjName.Signature;
  876. end;
  877. end;
  878. //=== { TJclDataSymbolInfo } =================================================
  879. constructor TJclDataSymbolInfo.Create(pSymInfo: PSymbolInfo);
  880. begin
  881. Assert(Assigned(pSymInfo));
  882. inherited Create(pSymInfo);
  883. with pSymInfo^ do
  884. begin
  885. FTypeIndex := Data.TypeIndex;
  886. FNameIndex := Data.NameIndex;
  887. FOffset := Data.Offset;
  888. end;
  889. end;
  890. //=== { TJclWithSymbolInfo } =================================================
  891. constructor TJclWithSymbolInfo.Create(pSymInfo: PSymbolInfo);
  892. begin
  893. Assert(Assigned(pSymInfo));
  894. inherited Create(pSymInfo);
  895. with pSymInfo^ do
  896. begin
  897. FNameIndex := With32.NameIndex;
  898. FOffset := With32.Offset;
  899. FSize := With32.Size;
  900. end;
  901. end;
  902. //=== { TJclLabelSymbolInfo } ================================================
  903. constructor TJclLabelSymbolInfo.Create(pSymInfo: PSymbolInfo);
  904. begin
  905. Assert(Assigned(pSymInfo));
  906. inherited Create(pSymInfo);
  907. with pSymInfo^ do
  908. begin
  909. FNameIndex := Label32.NameIndex;
  910. FOffset := Label32.Offset;
  911. end;
  912. end;
  913. //=== { TJclConstantSymbolInfo } =============================================
  914. constructor TJclConstantSymbolInfo.Create(pSymInfo: PSymbolInfo);
  915. begin
  916. Assert(Assigned(pSymInfo));
  917. inherited Create(pSymInfo);
  918. with pSymInfo^ do
  919. begin
  920. FNameIndex := Constant.NameIndex;
  921. FTypeIndex := Constant.TypeIndex;
  922. FValue := Constant.Value;
  923. end;
  924. end;
  925. //=== { TJclUdtSymbolInfo } ==================================================
  926. constructor TJclUdtSymbolInfo.Create(pSymInfo: PSymbolInfo);
  927. begin
  928. Assert(Assigned(pSymInfo));
  929. inherited Create(pSymInfo);
  930. with pSymInfo^ do
  931. begin
  932. FNameIndex := Udt.NameIndex;
  933. FTypeIndex := Udt.TypeIndex;
  934. FProperties := Udt.Properties;
  935. end;
  936. end;
  937. //=== { TJclVftPathSymbolInfo } ==============================================
  938. constructor TJclVftPathSymbolInfo.Create(pSymInfo: PSymbolInfo);
  939. begin
  940. Assert(Assigned(pSymInfo));
  941. inherited Create(pSymInfo);
  942. with pSymInfo^ do
  943. begin
  944. FRootIndex := VftPath.RootIndex;
  945. FPathIndex := VftPath.PathIndex;
  946. FOffset := VftPath.Offset;
  947. end;
  948. end;
  949. //=== { TJclTD32InfoParser } =================================================
  950. constructor TJclTD32InfoParser.Create(const ATD32Data: TCustomMemoryStream);
  951. begin
  952. Assert(Assigned(ATD32Data));
  953. inherited Create;
  954. FNames := TList.Create;
  955. FModules := TObjectList.Create;
  956. FSourceModules := TObjectList.Create;
  957. FSymbols := TObjectList.Create;
  958. FProcSymbols := TList.Create;
  959. FNames.Add(nil);
  960. FData := ATD32Data;
  961. FBase := FData.Memory;
  962. FValidData := IsTD32DebugInfoValid(FBase, FData.Size);
  963. if FValidData then
  964. Analyse;
  965. end;
  966. destructor TJclTD32InfoParser.Destroy;
  967. begin
  968. FreeAndNil(FProcSymbols);
  969. FreeAndNil(FSymbols);
  970. FreeAndNil(FSourceModules);
  971. FreeAndNil(FModules);
  972. FreeAndNil(FNames);
  973. inherited Destroy;
  974. end;
  975. procedure TJclTD32InfoParser.Analyse;
  976. var
  977. I: Integer;
  978. pDirHeader: PDirectoryHeader;
  979. pSubsection: Pointer;
  980. begin
  981. pDirHeader := PDirectoryHeader(LfaToVa(PJclTD32FileSignature(LfaToVa(0)).Offset));
  982. while True do
  983. begin
  984. Assert(pDirHeader.DirEntrySize = SizeOf(TDirectoryEntry));
  985. {$RANGECHECKS OFF}
  986. for I := 0 to pDirHeader.DirEntryCount - 1 do
  987. with pDirHeader.DirEntries[I] do
  988. begin
  989. pSubsection := LfaToVa(Offset);
  990. case SubsectionType of
  991. SUBSECTION_TYPE_MODULE:
  992. AnalyseModules(pSubsection, Size);
  993. SUBSECTION_TYPE_ALIGN_SYMBOLS:
  994. AnalyseAlignSymbols(pSubsection, Size);
  995. SUBSECTION_TYPE_SOURCE_MODULE:
  996. AnalyseSourceModules(pSubsection, Size);
  997. SUBSECTION_TYPE_NAMES:
  998. AnalyseNames(pSubsection, Size);
  999. SUBSECTION_TYPE_GLOBAL_TYPES:
  1000. AnalyseGlobalTypes(pSubsection, Size);
  1001. else
  1002. AnalyseUnknownSubSection(pSubsection, Size);
  1003. end;
  1004. end;
  1005. {$IFDEF RANGECHECKS_ON}
  1006. {$RANGECHECKS ON}
  1007. {$ENDIF RANGECHECKS_ON}
  1008. if pDirHeader.lfoNextDir <> 0 then
  1009. pDirHeader := PDirectoryHeader(LfaToVa(pDirHeader.lfoNextDir))
  1010. else
  1011. Break;
  1012. end;
  1013. end;
  1014. procedure TJclTD32InfoParser.AnalyseNames(const pSubsection: Pointer; const Size: DWORD);
  1015. var
  1016. I, Count, Len: Integer;
  1017. pszName: PChar;
  1018. begin
  1019. Count := PDWORD(pSubsection)^;
  1020. pszName := PChar(DWORD(pSubsection) + SizeOf(DWORD));
  1021. if Count > 0 then
  1022. begin
  1023. FNames.Capacity := FNames.Capacity + Count;
  1024. for I := 0 to Count - 1 do
  1025. begin
  1026. // Get the length of the name
  1027. Len := Ord(pszName^);
  1028. Inc(pszName);
  1029. // Get the name
  1030. FNames.Add(pszName);
  1031. // skip the length of name and a NULL at the end
  1032. Inc(pszName, Len + 1);
  1033. end;
  1034. end;
  1035. end;
  1036. const
  1037. // Leaf indices for type records that can be referenced from symbols
  1038. LF_MODIFIER = $0001;
  1039. LF_POINTER = $0002;
  1040. LF_ARRAY = $0003;
  1041. LF_CLASS = $0004;
  1042. LF_STRUCTURE = $0005;
  1043. LF_UNION = $0006;
  1044. LF_ENUM = $0007;
  1045. LF_PROCEDURE = $0008;
  1046. LF_MFUNCTION = $0009;
  1047. LF_VTSHAPE = $000a;
  1048. LF_COBOL0 = $000b;
  1049. LF_COBOL1 = $000c;
  1050. LF_BARRAY = $000d;
  1051. LF_LABEL = $000e;
  1052. LF_NULL = $000f;
  1053. LF_NOTTRAN = $0010;
  1054. LF_DIMARRAY = $0011;
  1055. LF_VFTPATH = $0012;
  1056. // Leaf indices for type records that can be referenced from other type records
  1057. LF_SKIP = $0200;
  1058. LF_ARGLIST = $0201;
  1059. LF_DEFARG = $0202;
  1060. LF_LIST = $0203;
  1061. LF_FIELDLIST = $0204;
  1062. LF_DERIVED = $0205;
  1063. LF_BITFIELD = $0206;
  1064. LF_METHODLIST = $0207;
  1065. LF_DIMCONU = $0208;
  1066. LF_DIMCONLU = $0209;
  1067. LF_DIMVARU = $020a;
  1068. LF_DIMVARLU = $020b;
  1069. LF_REFSYM = $020c;
  1070. // Leaf indices for fields of complex lists:
  1071. LF_BCLASS = $0400;
  1072. LF_VBCLASS = $0401;
  1073. LF_IVBCLASS = $0402;
  1074. LF_ENUMERATE = $0403;
  1075. LF_FRIENDFCN = $0404;
  1076. LF_INDEX = $0405;
  1077. LF_MEMBER = $0406;
  1078. LF_STMEMBER = $0407;
  1079. LF_METHOD = $0408;
  1080. LF_NESTTYPE = $0409;
  1081. LF_VFUNCTAB = $040a;
  1082. LF_FRIENDCLS = $040b;
  1083. // Leaf indices for numeric fields of symbols and type records:
  1084. LF_NUMERIC = $8000;
  1085. LF_CHAR = $8001;
  1086. LF_SHORT = $8002;
  1087. LF_USHORT = $8003;
  1088. LF_LONG = $8004;
  1089. LF_ULONG = $8005;
  1090. LF_REAL32 = $8006;
  1091. LF_REAL64 = $8007;
  1092. LF_REAL80 = $8008;
  1093. LF_REAL128 = $8009;
  1094. LF_QUADWORD = $800a;
  1095. LF_UQUADWORD = $800b;
  1096. LF_REAL48 = $800c;
  1097. LF_PAD0 = $f0;
  1098. LF_PAD1 = $f1;
  1099. LF_PAD2 = $f2;
  1100. LF_PAD3 = $f3;
  1101. LF_PAD4 = $f4;
  1102. LF_PAD5 = $f5;
  1103. LF_PAD6 = $f6;
  1104. LF_PAD7 = $f7;
  1105. LF_PAD8 = $f8;
  1106. LF_PAD9 = $f9;
  1107. LF_PAD10 = $fa;
  1108. LF_PAD11 = $fb;
  1109. LF_PAD12 = $fc;
  1110. LF_PAD13 = $fd;
  1111. LF_PAD14 = $fe;
  1112. LF_PAD15 = $ff;
  1113. type
  1114. PSymbolTypeInfo = ^TSymbolTypeInfo;
  1115. TSymbolTypeInfo = packed record
  1116. TypeId: DWORD;
  1117. NameIndex: DWORD; // 0 if unnamed
  1118. Size: Word; // size in bytes of the object
  1119. MaxSize: Byte;
  1120. ParentIndex: DWORD;
  1121. end;
  1122. const
  1123. TID_VOID = $00; // Unknown or no type
  1124. TID_LSTR = $01; // Basic Literal string
  1125. TID_DSTR = $02; // Basic Dynamic string
  1126. TID_PSTR = $03; // Pascal style string
  1127. procedure TJclTD32InfoParser.AnalyseGlobalTypes(const pTypes: Pointer; const Size: DWORD);
  1128. var
  1129. pTyp: PSymbolTypeInfo;
  1130. begin
  1131. pTyp := PSymbolTypeInfo(pTypes);
  1132. repeat
  1133. {case pTyp.TypeId of
  1134. TID_VOID: ;
  1135. end;}
  1136. pTyp := PSymbolTypeInfo(DWORD(pTyp) + pTyp.Size + SizeOf(pTyp^));
  1137. until DWORD(pTyp) >= DWORD(pTypes) + Size;
  1138. end;
  1139. procedure TJclTD32InfoParser.AnalyseAlignSymbols(pSymbols: PSymbolInfos; const Size: DWORD);
  1140. var
  1141. Offset: DWORD;
  1142. pInfo: PSymbolInfo;
  1143. Symbol: TJclSymbolInfo;
  1144. begin
  1145. Offset := DWORD(@pSymbols.Symbols[0]) - DWORD(pSymbols);
  1146. while Offset < Size do
  1147. begin
  1148. pInfo := PSymbolInfo(DWORD(pSymbols) + Offset);
  1149. case pInfo.SymbolType of
  1150. SYMBOL_TYPE_LPROC32:
  1151. begin
  1152. Symbol := TJclLocalProcSymbolInfo.Create(pInfo);
  1153. FProcSymbols.Add(Symbol);
  1154. end;
  1155. SYMBOL_TYPE_GPROC32:
  1156. begin
  1157. Symbol := TJclGlobalProcSymbolInfo.Create(pInfo);
  1158. FProcSymbols.Add(Symbol);
  1159. end;
  1160. SYMBOL_TYPE_OBJNAME:
  1161. Symbol := TJclObjNameSymbolInfo.Create(pInfo);
  1162. SYMBOL_TYPE_LDATA32:
  1163. Symbol := TJclLDataSymbolInfo.Create(pInfo);
  1164. SYMBOL_TYPE_GDATA32:
  1165. Symbol := TJclGDataSymbolInfo.Create(pInfo);
  1166. SYMBOL_TYPE_PUB32:
  1167. Symbol := TJclPublicSymbolInfo.Create(pInfo);
  1168. SYMBOL_TYPE_WITH32:
  1169. Symbol := TJclWithSymbolInfo.Create(pInfo);
  1170. SYMBOL_TYPE_LABEL32:
  1171. Symbol := TJclLabelSymbolInfo.Create(pInfo);
  1172. SYMBOL_TYPE_CONST:
  1173. Symbol := TJclConstantSymbolInfo.Create(pInfo);
  1174. SYMBOL_TYPE_UDT:
  1175. Symbol := TJclUdtSymbolInfo.Create(pInfo);
  1176. SYMBOL_TYPE_VFTPATH32:
  1177. Symbol := TJclVftPathSymbolInfo.Create(pInfo);
  1178. else
  1179. Symbol := nil;
  1180. end;
  1181. if Assigned(Symbol) then
  1182. FSymbols.Add(Symbol);
  1183. Inc(Offset, pInfo.Size + SizeOf(pInfo.Size));
  1184. end;
  1185. end;
  1186. procedure TJclTD32InfoParser.AnalyseModules(pModInfo: PModuleInfo; const Size: DWORD);
  1187. begin
  1188. FModules.Add(TJclModuleInfo.Create(pModInfo));
  1189. end;
  1190. procedure TJclTD32InfoParser.AnalyseSourceModules(pSrcModInfo: PSourceModuleInfo; const Size: DWORD);
  1191. var
  1192. I: Integer;
  1193. pSrcFile: PSourceFileEntry;
  1194. begin
  1195. {$RANGECHECKS OFF}
  1196. for I := 0 to pSrcModInfo.FileCount - 1 do
  1197. begin
  1198. pSrcFile := PSourceFileEntry(DWORD(pSrcModInfo) + pSrcModInfo.BaseSrcFiles[I]);
  1199. if pSrcFile.NameIndex > 0 then
  1200. FSourceModules.Add(TJclSourceModuleInfo.Create(pSrcFile, DWORD(pSrcModInfo)));
  1201. end;
  1202. {$IFDEF RANGECHECKS_ON}
  1203. {$RANGECHECKS ON}
  1204. {$ENDIF RANGECHECKS_ON}
  1205. end;
  1206. procedure TJclTD32InfoParser.AnalyseUnknownSubSection(const pSubsection: Pointer; const Size: DWORD);
  1207. begin
  1208. // do nothing
  1209. end;
  1210. function TJclTD32InfoParser.GetModule(const Idx: Integer): TJclModuleInfo;
  1211. begin
  1212. Result := TJclModuleInfo(FModules.Items[Idx]);
  1213. end;
  1214. function TJclTD32InfoParser.GetModuleCount: Integer;
  1215. begin
  1216. Result := FModules.Count;
  1217. end;
  1218. function TJclTD32InfoParser.GetName(const Idx: Integer): string;
  1219. begin
  1220. Result := PChar(FNames.Items[Idx]);
  1221. end;
  1222. function TJclTD32InfoParser.GetNameCount: Integer;
  1223. begin
  1224. Result := FNames.Count;
  1225. end;
  1226. function TJclTD32InfoParser.GetSourceModule(const Idx: Integer): TJclSourceModuleInfo;
  1227. begin
  1228. Result := TJclSourceModuleInfo(FSourceModules.Items[Idx]);
  1229. end;
  1230. function TJclTD32InfoParser.GetSourceModuleCount: Integer;
  1231. begin
  1232. Result := FSourceModules.Count;
  1233. end;
  1234. function TJclTD32InfoParser.GetSymbol(const Idx: Integer): TJclSymbolInfo;
  1235. begin
  1236. Result := TJclSymbolInfo(FSymbols.Items[Idx]);
  1237. end;
  1238. function TJclTD32InfoParser.GetSymbolCount: Integer;
  1239. begin
  1240. Result := FSymbols.Count;
  1241. end;
  1242. function TJclTD32InfoParser.GetProcSy

Large files files are truncated, but you can click here to view the full file