home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TPU55A.ZIP / TPUDOC1.TXT < prev    next >
Encoding:
Text File  |  1990-08-11  |  130.2 KB  |  2,836 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.                            -----------------------------
  18.  
  19.  
  20.  
  21.                            INSIDE TURBO PASCAL 5.5 UNITS
  22.  
  23.  
  24.  
  25.                            -----------------------------
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.                                          by
  50.  
  51.                                   William L. Peavy
  52.  
  53.                                  -----------------
  54.  
  55.                               Revised: August 11, 1990
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.                                       ABSTRACT
  63.  
  64.             This document  provides a  revised report on researches into
  65.             the structure  and content  of Unit (.TPU) files produced by
  66.             Turbo Pascal  (version 5.5)  from Borland International.  No
  67.             assurances are  possible regarding  when (if  ever)  further
  68.             updates will be available so the material is released to the
  69.             Turbo Pascal  user community  in its  admittedly  imcomplete
  70.             state since  very little of consequence really remains to be
  71.             done.
  72.  
  73.  
  74.  
  75.                                       COMMENTS
  76.  
  77.             Comments  and   feed-back  are  welcome  --  especially  new
  78.             contributions.  I can be reached via the following services:
  79.  
  80.                  CompuServ           (70042,2310)
  81.  
  82.                  HalPC Telecom-1     (William;Peavy)
  83.  
  84.                  HalPC Telecom-2     (Wm;Peavy)
  85.  
  86.  
  87.  
  88.                                   Table Of Contents
  89.  
  90.  
  91.  
  92.            Introduction ................................................ 3
  93.  
  94.            1. Gross File Structure ..................................... 3
  95.                1.1 User Units .......................................... 4
  96.  
  97.            2. Locators ................................................. 5
  98.                2.1 Local Links ......................................... 5
  99.                2.2 Global Links ........................................ 5
  100.                2.3 Table Offsets ....................................... 5
  101.  
  102.            3. Unit Header .............................................. 6
  103.                3.1 Description ......................................... 6
  104.                3.2 File Size ........................................... 9
  105.  
  106.            4. Symbol Dictionaries ...................................... 9
  107.                4.1 Organization ........................................ 9
  108.                4.2 Interface Dictionary ............................... 10
  109.                4.3 DEBUG Dictionary ................................... 10
  110.  
  111.                4.4 Dictionary Elements ................................ 10
  112.                    4.4.1 Hash Tables .................................. 10
  113.                        4.4.1.1 Size ................................... 11
  114.                        4.4.1.2 Scope .................................. 12
  115.                        4.4.1.3 Special Cases .......................... 12
  116.  
  117.                    4.4.2 Dictionary Headers ........................... 13
  118.  
  119.                    4.4.3 Dictionary Stubs ............................. 13
  120.                        4.4.3.1 Label Declaratives ("O") ............... 13
  121.                        4.4.3.2 Un-Typed Constants ("P") ............... 14
  122.                        4.4.3.3 Named Types ("Q") ...................... 14
  123.                        4.4.3.4 Variables, Fields, Typed Cons ("R") .... 15
  124.                        4.4.3.5 Subprograms & Methods ("S") ............ 16
  125.                        4.4.3.6 Turbo Std Procedures ("T") ............. 17
  126.                        4.4.3.7 Turbo Std Functions ("U") .............. 17
  127.                        4.4.3.8 Turbo Std "NEW" Routine ("V") .......... 17
  128.                        4.4.3.9 Turbo Std Port Arrays ("W") ............ 17
  129.                        4.4.3.10 Turbo Std External Variables ("X") .... 17
  130.                        4.4.3.11 Units ("Y") ........................... 18
  131.  
  132.                    4.4.4 Type Descriptors ............................. 19
  133.                        4.4.4.1 Scope .................................. 19
  134.                        4.4.4.2 Prefix Part ............................ 20
  135.  
  136.                        4.4.4.3 Suffix Parts ........................... 21
  137.                            4.4.4.3.1 Un-Typed ......................... 21
  138.                            4.4.4.3.2 Structured Types ................. 22
  139.                                4.4.4.3.2.1 ARRAY Types ................ 22
  140.                                4.4.4.3.2.2 RECORD Types ............... 22
  141.                                4.4.4.3.2.3 OBJECT Types ............... 23
  142.                                4.4.4.3.2.4 FILE (non-TEXT) Types ...... 23
  143.                                4.4.4.3.2.5 TEXT File Types ............ 23
  144.                                4.4.4.3.2.6 SET Types .................. 24
  145.  
  146.  
  147.  
  148.                                         - i -
  149.  
  150.  
  151.  
  152.                                   Table Of Contents
  153.  
  154.  
  155.                                4.4.4.3.2.7 POINTER Types .............. 24
  156.                                4.4.4.3.2.8 STRING Types ............... 24
  157.  
  158.                            4.4.4.3.3 Floating-Point Types ............. 24
  159.  
  160.                            4.4.4.3.4 Ordinal Types .................... 24
  161.                                4.4.4.3.4.1 "Integers" ................. 25
  162.                                4.4.4.3.4.2 BOOLEANs ................... 25
  163.                                4.4.4.3.4.3 CHARs ...................... 25
  164.                                4.4.4.3.4.4 ENUMERATions ............... 26
  165.  
  166.                            4.4.4.3.5 SUBPROGRAM Types ................. 26
  167.  
  168.            5. Maps and Lists .......................................... 27
  169.                5.1 PROC Map ........................................... 27
  170.                5.2 CSeg Map ........................................... 28
  171.                5.3 Typed CONST DSeg Map ............................... 28
  172.                5.4 Global VAR DSeg Map ................................ 29
  173.                5.5 Donor Unit List .................................... 29
  174.                5.6 Source File List ................................... 30
  175.                5.7 DEBUG Trace Table .................................. 31
  176.  
  177.            6. Code, Data, Relocation Info ............................. 32
  178.                6.1 Object CSegs ....................................... 32
  179.                6.2 CONST DSegs ........................................ 32
  180.                6.3 Relocation Data Table .............................. 33
  181.  
  182.            7. Supplied Program ........................................ 34
  183.                7.1 TPUNEW ............................................. 35
  184.                                                                            |
  185.                7.2 TPURPT1 ............................................ 35
  186.                7.3 TPUAMS1 ............................................ 35
  187.                7.4 TPUUNA1 ............................................ 35
  188.                7.5 Modifications ...................................... 36
  189.  
  190.                7.6 Notes on Program Logic ............................. 36
  191.                                                                            |
  192.                    7.6.1 Formatting the Dictionary .................... 37
  193.                                                                            |
  194.                    7.6.2 The Disassembler ............................. 38
  195.                                                                            |
  196.  
  197.            8. Unit Libraries .......................................... 41
  198.                8.1 Library Structure .................................. 41
  199.                8.2 The TPUMOVER Utility ............................... 41
  200.  
  201.            9. Application Notes ....................................... 41
  202.  
  203.            10. Acknowledgements ....................................... 42
  204.  
  205.            11. References ............................................. 43
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.                                        - ii -
  217.  
  218.  
  219.  
  220.                            Inside TURBO Pascal 5.5 Units           
  221.        ----------------------------------------------------------------------
  222.  
  223.        INTRODUCTION
  224.  
  225.  
  226.        This document  is  the  outcome  of  an  inquiry  conducted  into  the
  227.        structure and  content of  Borland Turbo  Pascal  (Version  5.5)  Unit
  228.        files.   The original  purpose of the inquiry was to provide a body of
  229.        theory enabling  Cross-Reference programs  to  resolve  references  to
  230.        symbols defined  in .TPU  files where qualification was not explicitly
  231.        provided.   As is  so often the case, one thing led to another and the
  232.        scope of  the inquiry  was expanded dramatically.  While this document
  233.        should not be regarded as definitive, the author feels that the entire
  234.        Turbo Pascal  User community might gain from the information extracted
  235.        from these files at the cost of so much time and effort.
  236.  
  237.        The  material   contained   herein   represents   the   findings   and
  238.        interpretations of  the author.    A  great  deal  of  guess-work  was
  239.        required and  no assurances are given as to the accuracy of either the
  240.        findings of fact or the inferences contained herein which are the sole
  241.        work-product of the author.  In particular, the author had access only
  242.        to materials  or information  that any  normal  Borland  customer  has
  243.        access to.   Further,  no Borland  source-codes were  available as the
  244.        Library Routine source is not licensed to the author.  In short, there
  245.        was nothing irregular about how these findings were achieved.
  246.  
  247.        The material  contained herein  is placed in the public domain free of
  248.        copyright for  use of  the general public at its own risk.  The author
  249.        assumes no  liability for  any damages  arising from  the use  of this
  250.        material by  others.   If you make use of this information and you get
  251.        burned, TOUGH!   The  author accepts no obligation to correct any such
  252.        errors as  may exist  in the  supplied programs  or in the findings of
  253.        fact or  opinion contained  herein.   On the other hand, this is not a
  254.        "complete" work in that a great many questions remain open, especially
  255.        as regards  fine details.   (The author is not a practitioner of Intel
  256.        80xxx Assembly  Language and  several open  questions  might  best  be
  257.        addressed by persons competent in this area.)  The author welcomes the
  258.        input of  interested readers  who might be able to "flesh-out" some of
  259.        these open questions with "hard" answers.
  260.  
  261.  
  262.        1. GROSS FILE STRUCTURE
  263.  
  264.  
  265.        A Turbo  Pascal Unit  file (Version  5.5 only) consists of an array of
  266.        bytes that  is some  exact multiple  of  sixteen  (16).    "Signature"
  267.        information allows  the compiler  to verify  that the  .TPU  file  was
  268.        compiled with the correct compiler version and to verify that the file
  269.        is of  the correct  size.   The fine  structure of  the file  will  be
  270.        addressed in later sections at ever increasing levels of detail.
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.        ----------------------------------------------------------------------
  280.        Rev: August 11, 1990                                            Page 3
  281.  
  282.  
  283.  
  284.                            Inside TURBO Pascal 5.5 Units           
  285.        ----------------------------------------------------------------------
  286.  
  287.        Graphically, the  file may be regarded as having the following general
  288.        layout:
  289.  
  290.              +-------------------+
  291.              | Unit Header       |        Main Index to Unit File
  292.              +-------------------+
  293.              | Dictionaries:     |
  294.              |   a) Interface    |
  295.              |   b) Debugger   * |        For Local Symbol Access
  296.              +-------------------+
  297.              | PROC Map          |
  298.              +-------------------+
  299.              | CSeg Map        * |        May be Empty
  300.              +-------------------+
  301.              | CONST DSeg Map  * |        May be Empty
  302.              +-------------------+
  303.              | VAR DSeg Map    * |        May be Empty
  304.              +-------------------+
  305.              | Donor Units     * |        May be Empty
  306.              +-------------------+
  307.              | Source Files      |
  308.              +-------------------+
  309.              | Trace Table     * |        May be Empty
  310.              +-------------------+
  311.              | CODE Segment(s) * |        May be Empty
  312.              +-------------------+
  313.              | DATA Segment(s) * |        May be Empty
  314.              +-------------------+
  315.              | RELO Data       * |        May be Empty
  316.              +-------------------+
  317.  
  318.  
  319.        1.1 USER UNITS
  320.  
  321.  
  322.        Units prepared by the compiler available to ordinary users have a very
  323.        straight-forward appearance  and content.   There may even be a little
  324.        "wasted" space  that might  be removed  if the  compiler were  just  a
  325.        little cleverer.  The SYSTEM.TPU file is quite another thing however.
  326.  
  327.        The SYSTEM.TPU  file (found  in TURBO.TPL)  is extraordinary  in  that
  328.        great pains  seem to  have been  taken to  compact it.    Further,  it
  329.        contains a  great many  types of  entries that  just don't  seem to be
  330.        achievable by  ordinary users  and I suspect that much (if not all) of
  331.        it was "hand-coded" in Assembler Language.
  332.  
  333.        In the  following sections, the details of these optimizations will be
  334.        explained  in  the  context  of  the  structural  element  then  under
  335.        discussion.
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.  
  343.        ----------------------------------------------------------------------
  344.        Rev: August 11, 1990                                            Page 4
  345.  
  346.  
  347.  
  348.                            Inside TURBO Pascal 5.5 Units           
  349.        ----------------------------------------------------------------------
  350.  
  351.        2. LOCATORS
  352.  
  353.  
  354.        The data  in these  files has  need of  structure and  organization to
  355.        support efficient access by the various programs such as the compiler,
  356.        the linker  and the  debugger.   This organization is built on a solid
  357.        foundation of locators employed in the unit's data structures.
  358.  
  359.  
  360.  
  361.        2.1 LOCAL LINKS
  362.  
  363.  
  364.        Local Links  (LL's) are  items of type WORD (2 bytes) which contain an
  365.        offset which  is relative to the origin of the unit file itself.  This
  366.        implies that  a unit must be somewhat less than 64K bytes in size.  If
  367.        the .TPU file is loaded into the heap, then LL's can be used to locate
  368.        any byte in the segment beginning with the load point of the file.
  369.  
  370.  
  371.  
  372.        2.2 GLOBAL LINKS
  373.  
  374.  
  375.        Global Links  (LG's) are  used to  locate type  descriptors which  may
  376.        reside in  other Units  (i.e., units  external to  the present  unit).
  377.        LG's are  structured items  consisting of two (2) words.  The first of
  378.        these is  an LL  that is  relative to  the origin  of  the  (possibly)
  379.        external unit.  The second word is an LL which locates the stub of the
  380.        unit entry  in the current unit dictionary for the (possibly) external
  381.        unit.   This dictionary  entry provides  the name  of  the  unit  that
  382.        contains the item the LG points to.
  383.  
  384.        This provides  a handy  mechanism for  locating type descriptors which
  385.        are defined in other separately compiled units.
  386.  
  387.  
  388.  
  389.        2.3 TABLE OFFSETS
  390.  
  391.  
  392.        Finally, various  data-structures within  a .TPU file are organized as
  393.        arrays of fixed-length records or as lists of variable-length records.
  394.        Efficient access  to such  records is  achieved by  means  of  offsets
  395.        rather than subscripts (an addressing technique denied Pascal).  These
  396.        offsets are  relative to  the  origin  of  the  array  or  list  being
  397.        referenced rather than the origin of the unit.
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.        ----------------------------------------------------------------------
  408.        Rev: August 11, 1990                                            Page 5
  409.  
  410.  
  411.  
  412.                            Inside TURBO Pascal 5.5 Units           
  413.        ----------------------------------------------------------------------
  414.  
  415.        3. UNIT HEADER
  416.  
  417.  
  418.        The Unit  Header comprises  the first  64 bytes  of the .TPU file.  It
  419.        contains LL's  that effectively  locate all other sections of the .TPU
  420.        file plus  statistics  that  enable  a  little  cross-checking  to  be
  421.        performed.   Some parts  of the  Unit Header appear to be reserved for
  422.        future use  since no  unit examined  by this author has ever contained
  423.        non-zero data in these apparently reserved fields.
  424.  
  425.  
  426.  
  427.        3.1 DESCRIPTION
  428.  
  429.  
  430.        The Unit Header provides a high-level locator table whereby each major
  431.        structure in the unit file can be addressed.  The following provides a
  432.        Pascal-like explanation  of the  layout  of  the  header  followed  by
  433.        further narrative  discussion of the contents of the individual fields
  434.        in the Unit Header.
  435.  
  436.              Type HdrAry = Array[0..3] of Char; LL = Word;
  437.  
  438.              UnitHeader = Record
  439.  
  440.               FilHd : HdrAry;  { +00 : = 'TPU6'                       }
  441.               Fillr : HdrAry;  { +04 : = $00000000                    }
  442.               UDirE : LL;      { +08 : to Dictionary Head-This Unit   }
  443.               UGHsh : LL;      { +0A : to Interface Hash Header       }
  444.               UHPrc : LL;      { +0C : to PROC Map                    }
  445.               UHCsg : LL;      { +0E : to CSeg Map                    }
  446.               UHDsT : LL;      { +10 : to DSeg Map-Typed CONST's      }
  447.               UHDsV : LL;      { +12 : to DSeg Map-GLOBAL Variables   }
  448.               URULt : LL;      { +14 : to Donor Unit List             }
  449.               USRCF : LL;      { +16 : to Source file List            }
  450.               UDBTS : LL;      { +18 : to Debug Trace Step Controls   }
  451.               UndNC : LL;      { +1A : to end non-code part of Unit   }
  452.               ULCod : Word;    { +1C : Size of Code                   }
  453.               ULTCon: Word;    { +1E : Size of Typed Constant Data    }
  454.               ULPtch: Word;    { +20 : Size of Relo Patch List        }
  455.               Unknx : Word;    { +22 : Number of Virtual Objects???   }
  456.               ULVars: Word;    { +24 : Size of GLOBAL VAR Data        }
  457.               UHash2: LL;      { +26 : to Debug Hash Header           }
  458.               UOvrly: Word;    { +28 : Number of Procs to Overlay??   }
  459.               UVTPad: Array[0..10]
  460.                       of Word; { +2A : Reserved for Future Expansion? }
  461.  
  462.              End; { UnitHeader }
  463.  
  464.          FilHd   contains the  characters "TPU6"  in that  order.   This is
  465.                  clear evidence that this unit was compiled by Turbo Pascal
  466.                  Version 5.5.
  467.  
  468.          Fillr   is apparently reserved and contains binary zeros.
  469.  
  470.  
  471.        ----------------------------------------------------------------------
  472.        Rev: August 11, 1990                                            Page 6
  473.  
  474.  
  475.  
  476.                            Inside TURBO Pascal 5.5 Units           
  477.        ----------------------------------------------------------------------
  478.  
  479.          UDirE   contains an  LL (WORD)  which  points  to  the  Dictionary
  480.                  Header in which the name of this unit is found.
  481.  
  482.          UGHsh   contains an LL (WORD) which points to a Hash table that is
  483.                  the root of the Interface Dictionary tree.
  484.  
  485.          UHPrc   contains an  LL (WORD)  which points  to the  PROC Map for
  486.                  this unit.   The  PROC Map  contains  an  entry  for  each
  487.                  Procedure or  Function declared  in the  unit (except  for
  488.                  INLINE types),  plus an  entry for the Unit Initialization
  489.                  section.   The length  of  the  PROC  Map  (in  bytes)  is
  490.                  determined by subtracting this LL (at 000C) from the LL at
  491.                  offset 000E.
  492.  
  493.          UHCsg   contains an  LL (WORD)  which points  to  the  CSeg  (CODE
  494.                  Segment) Map  for this  unit.   The CSeg  Map contains  an
  495.                  entry for  each CODE Segment produced by the compiler plus
  496.                  an entry  for each  of the  CODE Segments included via the
  497.                  {$L filename.OBJ}  compiler directive.  The length of this
  498.                  Map (in  bytes) is  obtained by  subtracting this  LL  (at
  499.                  000E) from  the word  at 0010.   The result may be zero in
  500.                  which case the CSeg Map is empty.
  501.  
  502.          UHDsT   contains an  LL (WORD)  which points  to  the  DSeg  (DATA
  503.                  Segment) Map  that maps  the initializing  data for  Typed
  504.                  CONST items  plus  templates  for  VMT's  (Virtual  Method
  505.                  Tables) that  are associated  with  OBJECTS  which  employ
  506.                  Virtual Methods.   The  length of  this Map  (in bytes) is
  507.                  obtained by subtracting this LL (at 0010) from the word at
  508.                  0012.   The result may be zero in which case this DSeg Map
  509.                  is empty.
  510.  
  511.          UHDsV   contains an  LL (WORD)  which points  to  the  DSeg  (DATA
  512.                  Segment) Map  that contains  the specifications  for  DSeg
  513.                  storage required  by VARiables whose scope is GLOBAL.  The
  514.                  length of  this Map  (in bytes) is obtained by subtracting
  515.                  this LL  (at 0012)  from the word at 0014.  The result may
  516.                  be zero in which case this DSeg Map is empty.
  517.  
  518.          URULt   contains an  LL (WORD)  which points  to a  table of units
  519.                  which contribute  either CODE or DATA Segments to the .EXE
  520.                  file for  a program  using this  Unit.  This is called the
  521.                  "Donor Unit  Table".   The length of this table (in bytes)
  522.                  is obtained by subtracting this LL (at 0014) from the word
  523.                  at 0016.   The result may be zero in which case this table
  524.                  is empty.
  525.  
  526.          USRCF   contains an  LL (WORD)  which points to a list of "source"
  527.                  files.   These are  the files  whose CODE or DATA Segments
  528.                  are included  in this  Unit by the compiler.  Examples are
  529.                  the Pascal Source for the Unit itself, plus the .OBJ files
  530.                  included via  the {$L  filename.OBJ}  compiler  directive.
  531.                  The length  of  this  table  (in  bytes)  is  obtained  by
  532.                  subtracting this  LL (at 0016) from the word at 0018.  The
  533.                  result may be zero in which case this table is empty.
  534.  
  535.        ----------------------------------------------------------------------
  536.        Rev: August 11, 1990                                            Page 7
  537.  
  538.  
  539.  
  540.                            Inside TURBO Pascal 5.5 Units           
  541.        ----------------------------------------------------------------------
  542.  
  543.          UDBTS   contains an  LL (WORD)  which points to a Trace Table used
  544.                  by the  DEBUGGER for  "stepping"  through  a  Function  or
  545.                  Procedure contained  in this  Unit.   The length  of  this
  546.                  table (in  bytes) is  obtained by  subtracting this LL (at
  547.                  0018) from  the word  at 001A.   The result may be zero in
  548.                  which case this table is empty.
  549.  
  550.          UndNC   contains an  LL (WORD) which points to the first free byte
  551.                  which follows  the Trace  Table (if  any).  It serves as a
  552.                  delimiter for  determinimg the  size of  the Trace  Table.
  553.                  This LL  (when rounded up to the next integral multiple of
  554.                  16) serves to locate the start of the code/data segments.
  555.  
  556.          ULCod   is a  WORD that  contains the total byte count of all CODE
  557.                  Segments compiled into this Unit.
  558.  
  559.          ULTCon  is a  WORD that contains the total byte count of all Typed
  560.                  CONST and VMT DATA Segments compiled into this unit.
  561.  
  562.          ULPtch  is a  WORD that  contains the  total  byte  count  of  the
  563.                  Relocation Data Table for this unit.
  564.  
  565.          Unknx   is a  WORD whose  usage is  poorly understood.  It appears
  566.                  always to  be zero  except when  the Unit contains OBJECTs
  567.                  which employ Virtual Methods.
  568.  
  569.          ULVars  is a WORD that contains the total byte count of all GLOBAL
  570.                  VAR DATA Segments compiled into this unit.
  571.  
  572.          UHash2  contains an  LL (WORD)  which points to a Hash Table which
  573.                  is the  root of the DEBUGGER Dictionary.  If Local Symbols
  574.                  were generated  by the compiler (directive {$L+}) then ALL
  575.                  symbols declared  in the  unit can  be accessed  from this
  576.                  Hash Table.   In  the SYSTEM.TPU  file, there  is no  such
  577.                  Dictionary and  the LL stored here points to the INTERFACE
  578.                  Dictionary.  This is an example of Hash Table "Folding" to
  579.                  save space which has been observed only in SYSTEM.TPU.
  580.  
  581.          UOvrly  is a  WORD whose usage is poorly understood.  This word is
  582.                  usually zero unless the Unit was compiled with the Overlay
  583.                  Directive {$O+}.
  584.  
  585.          UVTPad  begins a  series of  eleven (11) words that are apparently
  586.                  reserved for future use.  Nothing but zeros have ever been
  587.                  seen here by this author.
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.        ----------------------------------------------------------------------
  600.        Rev: August 11, 1990                                            Page 8
  601.  
  602.  
  603.  
  604.                            Inside TURBO Pascal 5.5 Units           
  605.        ----------------------------------------------------------------------
  606.  
  607.        3.2 FILE SIZE
  608.  
  609.  
  610.        An independent  check on  the size of the .TPU file is available using
  611.        information contained  in the Unit Header.  This is also important for
  612.        .TPL (Unit  Library) organization.  To compute the file size, refer to
  613.        the four  (4) words  at offsets  001A, 001C, 001E and 0020.  Round the
  614.        contents of  each of  these words to the lowest multiple of 16 that is
  615.        greater than  or equal to the content of that word.  Then form the sum
  616.        of the rounded words.  This is the .TPU file size in bytes.
  617.  
  618.  
  619.  
  620.        4. SYMBOL DICTIONARIES
  621.  
  622.  
  623.        This area contains all available documentation of declared symbols and
  624.        procedure blocks  defined within  the unit.    Depending  on  compiler
  625.        options in  effect when  the unit  was  compiled,  this  section  will
  626.        contain at  a minimum,  the INTERFACE  declarations, and at a maximum,
  627.        ALL declarations.   The information stored in the dictionary is highly
  628.        dependent on  the context  of the  symbol declared.   We defer further
  629.        explanation to the appropriate section which follows.
  630.  
  631.  
  632.  
  633.        4.1 ORGANIZATION
  634.  
  635.  
  636.        The dictionary  is organized  with a Hash Table as its root.  The hash
  637.        table is  used to  provide rapid  access to  arbitrary symbols.  Since
  638.        Turbo Pascal  compiles very rapidly, I presume the hash function to be
  639.        worthwhile to say the least.
  640.  
  641.        The dictionary  itself may  be thought  of as  an n-way  tree.    Each
  642.        subtree has its roots in a hash table.  There may be a great many hash
  643.        tables in  a given unit and their number depends on unit complexity as
  644.        well as  the options  chosen when  the unit  was compiled.  Use of the
  645.        {$L+} directive  produces the  densest trees.   The  hash  tables  are
  646.        explained in detail a few sections further on.
  647.  
  648.        Hash tables  point to  Dictionary Headers.   When  two or more symbols
  649.        produce the  same hash  function result, a collision is said to occur.
  650.        Collisions  are  resolved  by  the  time-honored  method  of  chaining
  651.        together the  Dictionary Headers of those symbols having the same hash
  652.        function result.   Dictionary supersetting is accomplished using these
  653.        chains.
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.        ----------------------------------------------------------------------
  664.        Rev: August 11, 1990                                            Page 9
  665.  
  666.  
  667.  
  668.                            Inside TURBO Pascal 5.5 Units           
  669.        ----------------------------------------------------------------------
  670.  
  671.        4.2 INTERFACE DICTIONARY
  672.  
  673.  
  674.        The INTERFACE  dictionary  contains  all  symbols  and  the  necessary
  675.        explanatory data  for the  INTERFACE section  of a  Unit.  Symbols get
  676.        added to  the  Unit  using  increasing  storage  addresses  until  the
  677.        IMPLEMENTATION section is encountered.
  678.  
  679.  
  680.  
  681.        4.3 DEBUG DICTIONARY
  682.  
  683.  
  684.        The DEBUG  dictionary (if  present) is  a superset  of  the  INTERFACE
  685.        dictionary.   It is  used by  the Turbo  Debugger to  support its many
  686.        features when  tracing through a unit.  If present, this dictionary is
  687.        rooted in  its  own  hash  table.    The  hash  table  is  effectively
  688.        initialized when  the  IMPLEMENTATION  keyword  is  processed  by  the
  689.        compiler.   This takes  the form  (initially) of an unmodified copy of
  690.        the INTERFACE  hash table,  to which  symbols are  added in  the usual
  691.        fashion.   Thus, the  hash chains constructed or extended at this time
  692.        lead naturally to the INTERFACE chains and this is how the superset is
  693.        effectively implemented.
  694.  
  695.  
  696.  
  697.        4.4 DICTIONARY ELEMENTS
  698.  
  699.  
  700.        The dictionary contains four major elements.  These are:  hash tables,
  701.        Dictionary Headers,  Dictionary  Stubs  and  Type  Descriptors.    The
  702.        distinction  between  Dictionary  Headers  and  Stubs  is  essentially
  703.        arbitrary and  is made in this document to assist in exposition.  They
  704.        might just  as easily  be regarded as a single element (such as symbol
  705.        entry).
  706.  
  707.  
  708.  
  709.        4.4.1 HASH TABLES
  710.  
  711.  
  712.        As has  been intimated,  Hash Tables  are  the  glue  that  binds  the
  713.        dictionary entries  together and  gives the  dictionary  its  "shape".
  714.        They effectively  implement the  scope rules of the language and speed
  715.        access to essential information.
  716.  
  717.        Each Hash table begins with a 2-byte size descriptor.  This descriptor
  718.        contains the  number of bytes in the table proper (less 2).  Thus, the
  719.        descriptor directly  points to the last bucket in the hash table.  For
  720.        a hash  table of  128 bytes,  the size  descriptor contains  126.  The
  721.        first bucket in the table immediately follows the size descriptor.
  722.  
  723.  
  724.  
  725.  
  726.  
  727.        ----------------------------------------------------------------------
  728.        Rev: August 11, 1990                                           Page 10
  729.  
  730.  
  731.  
  732.                            Inside TURBO Pascal 5.5 Units           
  733.        ----------------------------------------------------------------------
  734.  
  735.        4.4.1.1 SIZE
  736.  
  737.  
  738.        So far,  three different  hash table  sizes have  been observed.   The
  739.        INTERFACE and  DEBUG hash tables are usually 128 bytes (64 entries) in
  740.        size plus  2 bytes  of size  description, but the SYSTEM.TPU unit is a
  741.        special case,  containing only  16 entries.   Hash tables which anchor
  742.        subtrees whose  scope is  relatively local  usually contain  four  (4)
  743.        entries (8 bytes).
  744.  
  745.        Graphically, a Hash Table with four slots has the following layout:
  746.  
  747.              +--------------------+
  748.              |       0006h        |      Size Descriptor
  749.              +====================+
  750.              |       slot 0       |      an LL or zero
  751.              +--------------------+
  752.              |       slot 1       |      an LL or zero
  753.              +--------------------+
  754.              |       slot 2       |      an LL or zero
  755.              +--------------------+
  756.              |       slot 3       |      an LL or zero
  757.              +--------------------+
  758.  
  759.        It should  be noted  that the Size Descriptor furnishes an upper bound
  760.        for the  hash function  itself.  Thus, it seems possible that a single
  761.        hash function is used for all hash tables and that its result is ANDed
  762.        with the  Size Descriptor  to get the final result.  Because the sizes
  763.        are chosen  as they  are (powers of 2) this is feasible.  Note that in
  764.        the above  example, 6  = 2 * (n - 1) where n = 4 {slot count}.  All of
  765.        the hash tables observed so far have this property.  What you get is a
  766.        really efficient MOD function.
  767.  
  768.        Suppose that the hash of a given symbol is 13 and the proper slot must
  769.        be located for a hash table of four entries.  If we let "h" be the raw
  770.        result of 13, then our final hash is (h SHL 1) AND ((4-1) SHL 1) or   
  771.  
  772.                                 (13 SHL 1) AND 6 = 2 !
  773.  
  774.        One final  note on this subject.  Given these properties, "Folding" of
  775.        sparse hash  tables is  a rather  trivial exercise  so long as the new
  776.        hash table also contains a number of slots that is a power of 2.  This
  777.        point is  intriguing when  one recalls  that the SYSTEM.TPU hash table
  778.        has only 16 slots rather than the usual 64.
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.        ----------------------------------------------------------------------
  792.        Rev: August 11, 1990                                           Page 11
  793.  
  794.  
  795.  
  796.                            Inside TURBO Pascal 5.5 Units           
  797.        ----------------------------------------------------------------------
  798.  
  799.        4.4.1.2 SCOPE
  800.  
  801.  
  802.        The INTERFACE  and DEBUG  dictionary hash  tables are  Global in Scope
  803.        even though the symbols accessed directly via the DEBUG hash table may
  804.        be private.   On the other hand, other hash tables are purely local in
  805.        scope.   For example,  the fields declared within a record are reached
  806.        via a  small local  hash  table,  as  are  the  parameters  and  local
  807.        variables declared  within procedures and functions.  Even OBJECTS use
  808.        this technique to provide access to Methods and Object Fields.
  809.  
  810.        Access to  such local  scope fields/methods  requires use of qualified
  811.        names which  ensures conformity  to Pascal scope rules.  The method is
  812.        truly simple and elegant.
  813.  
  814.  
  815.  
  816.        4.4.1.3 SPECIAL CASES
  817.  
  818.  
  819.        The SYSTEM.TPU  Unit is  a special case.  Its INTERFACE and DEBUG hash
  820.        tables have  apparently  been  "hand-tuned"  for  small  size.    Each
  821.        contains only sixteen (16) entries.  In addition, the DEBUG hash table
  822.        is empty  since there  is no  local symbol  generation in  this  unit.
  823.        Therefore, the  DEBUG hash  table does not exist as a separate entity,
  824.        its function being served by the INTERFACE hash table.  The pointer to
  825.        the DEBUG  hash table  (in the  Unit Header) has the same value as the
  826.        pointer to the INTERFACE hash table (SYSTEM unit ONLY).
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.        ----------------------------------------------------------------------
  856.        Rev: August 11, 1990                                           Page 12
  857.  
  858.  
  859.  
  860.                            Inside TURBO Pascal 5.5 Units           
  861.        ----------------------------------------------------------------------
  862.  
  863.        4.4.2 DICTIONARY HEADERS
  864.  
  865.  
  866.        This is  the structure  that anchors  all  information  known  by  the
  867.        compiler about any symbol.  The format is as follows:
  868.  
  869.          +00:    An LL  which points  to the  next (previous) symbol in the
  870.                  same scope which had the same hash function value.
  871.  
  872.          +02:    A character  that defines  the category the symbol belongs
  873.                  to and  defines the  format of  the Dictionary  Stub which
  874.                  follows the Dictionary Header.
  875.  
  876.          +03:    A String  (in the  Pascal sense)  of  variable  size  that
  877.                  contains the  text of  the symbol  (in UPPER-CASE  letters
  878.                  only).   The SizeOf  function is  not  defined  for  these
  879.                  strings since they are truncated to match the symbol size.
  880.                  The "value"  of the  SizeOf function  can be determined by
  881.                  adding  1  to  the  first  byte  in  the  string.    Thus,
  882.                  Ord(Symbol[0])+1 is  the expression  that defines the Size
  883.                  of the  symbol string.  Turbo Pascal defines a symbol as a
  884.                  string of  relatively arbitrary size, the most significant
  885.                  63 characters  of which  will be stored in the dictionary.
  886.                  Thus, we  conclude that  the maximum size of such a string
  887.                  is 64 bytes.
  888.  
  889.  
  890.  
  891.        4.4.3 DICTIONARY STUBS
  892.  
  893.  
  894.        Dictionary Stubs immediately follow their respective headers and their
  895.        format is  determined by  the category  character  in  the  Dictionary
  896.        Header.   The function  of the  stub is  to organize  the  information
  897.        appropriate to  the symbol and provide a means of accessing additional
  898.        information such as type descriptors, constant values, parameter lists
  899.        and nested  scopes.   The format  of each  Stub is  presented  in  the
  900.        following sub-sections.
  901.  
  902.  
  903.  
  904.        4.4.3.1 LABEL DECLARATIVES ("O")
  905.  
  906.  
  907.        This Stub consists of a WORD whose function is (as yet) unknown.
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.        ----------------------------------------------------------------------
  920.        Rev: August 11, 1990                                           Page 13
  921.  
  922.  
  923.  
  924.                            Inside TURBO Pascal 5.5 Units           
  925.        ----------------------------------------------------------------------
  926.  
  927.        4.4.3.2 UN-TYPED CONSTANTS ("P")
  928.  
  929.  
  930.        This Stub consists of (2) two fields:
  931.  
  932.          +00:    An LG  which points  to  a  Type  Descriptor  (usually  in
  933.                  SYSTEM.TPU).     This  establishes   the  minimum  storage
  934.                  requirement for  the constant.   The  rules vary  with the
  935.                  type, but  the size  of the  constant  data  field  (which
  936.                  follows) is defined using the Type Descriptor(s).
  937.  
  938.          +04:    The value  of the constant.  For ordinal types, this value
  939.                  is stored as a LONGINT (size=4 bytes).  For Floating-Point
  940.                  types, the  size is  implicit in  the type  itself.    For
  941.                  String types,  the size  is determined  from the length of
  942.                  the string  which is  stored in  the initial  byte of  the
  943.                  constant.
  944.  
  945.  
  946.  
  947.        4.4.3.3 NAMED TYPES ("Q")
  948.  
  949.  
  950.        This Stub  consists of  an  LG  (4-bytes)  that  points  to  the  Type
  951.        Descriptor for this symbol.
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.        ----------------------------------------------------------------------
  984.        Rev: August 11, 1990                                           Page 14
  985.  
  986.  
  987.  
  988.                            Inside TURBO Pascal 5.5 Units           
  989.        ----------------------------------------------------------------------
  990.  
  991.        4.4.3.4 VARIABLES, FIELDS, TYPED CONS ("R")
  992.  
  993.  
  994.        This Stub contains information required to allocate and describe these
  995.        types of entities.  The format and content is as follows:
  996.  
  997.          +00:    A one-byte flag that precisely identifies the class of the
  998.                  item being  described.   The known values and their proper
  999.                  interpretation is as follows:
  1000.  
  1001.                  0 -> Global Variables Allocated in DS;  
  1002.                  1 -> Typed Constants Allocated in DS;   
  1003.                  2 -> LOCAL Variables & VALUE Parameters on STACK; 
  1004.                  6 -> ADDRESS Parameters allocated on STACK;  
  1005.                  8 -> Fields suballocated in RECORDS and OBJECTS, plus  
  1006.                       METHODS declared for OBJECTS.
  1007.  
  1008.          +01:    A WORD containing the allocation offset in bytes;
  1009.  
  1010.          +03:    A WORD  whose content  depends on  the one-byte  flag that
  1011.                  this stub  begins  with.    The  context-dependent  values
  1012.                  observed thus far are:
  1013.  
  1014.                  If the  flag is  0, 2  or 6,  then this word is an LL that
  1015.                  locates the containing scope or zero if none;
  1016.  
  1017.                  If the flag is 8, then this word is an LL that locates the
  1018.                  Dictionary Header  for the  next field  or method  defined
  1019.                  within the Record or Object;
  1020.  
  1021.                  If the  flag is  1, then this word is an offset within the
  1022.                  CONST DSeg Map that locates the text of the Typed Constant
  1023.                  Data.
  1024.  
  1025.          +05:    An LG  that locates  the proper  Type Descriptor  for this
  1026.                  symbol.
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.        ----------------------------------------------------------------------
  1048.        Rev: August 11, 1990                                           Page 15
  1049.  
  1050.  
  1051.  
  1052.                            Inside TURBO Pascal 5.5 Units           
  1053.        ----------------------------------------------------------------------
  1054.  
  1055.        4.4.3.5 SUBPROGRAMS & METHODS ("S")
  1056.  
  1057.  
  1058.        Subprograms, especially  since Object  Methods are  supported, have  a
  1059.        rather involved stub.  Its format is as follows:
  1060.  
  1061.          +00:    A byte  that contains  bit-switches.   These bit  switches
  1062.                  have a  great deal  to do  with the  size of this stub and
  1063.                  with the  proper interpretation  of  what  follows.    The
  1064.                  observed values of the bit-switches are as follows:
  1065.  
  1066.                  xxxxxxx1 -> Symbol declared in INTERFACE;    
  1067.                  xxxxxx1x -> Symbol is an INLINE Declarative; 
  1068.                  xxxx1x0x -> Symbol has EXTERNAL attribute;   
  1069.                  x001xxxx -> Symbol is an ordinary Object Method;  
  1070.                  x011xxxx -> Symbol is a CONSTRUCTOR Method;  
  1071.                  x101xxxx -> Symbol is a DESTRUCTOR Method;
  1072.  
  1073.          +01:    A Word  whose interpretation depends on whether we have an
  1074.                  INLINE Declarative  Subprogram or  not.   If  this  is  an
  1075.                  INLINE Declarative Subprogram, then this word contains the
  1076.                  byte-count of  the INLINE  code text  at the  end of  this
  1077.                  stub.   Otherwise, this word is the offset within the PROC
  1078.                  Map that locates the object code for this Subprogram.
  1079.  
  1080.          +03:    A Word  that contains  an LL  which locates the containing
  1081.                  scope in the dictionary, or zero if none.
  1082.  
  1083.          +05:    A Word  that contains  an LL  which locates the local Hash
  1084.                  Table for  this scope.  A local hash table provides access
  1085.                  to all  formal parameters of the Subprogram as well as all
  1086.                  Symbols whose  declarations are local to the scope of this
  1087.                  Subprogram.
  1088.  
  1089.          +07:    A Word that is zero unless the symbol is a Virtual Method.
  1090.                  In this  case, then  the content  is the offset within the
  1091.                  VMT for  the owning  object that  defines  where  the  FAR
  1092.                  POINTER to this Virtual Method is stored.
  1093.  
  1094.          +09:    A Word  that is  zero unless  the symbol  is a Method.  In
  1095.                  this case,  then the  content is  an LL  which locates the
  1096.                  next METHOD for this Object.
  1097.  
  1098.          +0B:    A complete  Type-Descriptor  for  this  Subprogram.    The
  1099.                  length is  variable and  depends upon the number of Formal
  1100.                  Parameters declared in the header.  A complete description
  1101.                  of  this   subfield  is   found   in   a   later   section
  1102.                  (4.4.4.3.2.6).
  1103.  
  1104.          +??:    If  this   Symbol   represents   an   INLINE   Declarative
  1105.                  Subprogram, then  the object-code  text begins  here.  The
  1106.                  byte-count of  the text  occurs at  offset 0001h  in  this
  1107.                  stub.
  1108.  
  1109.  
  1110.  
  1111.        ----------------------------------------------------------------------
  1112.        Rev: August 11, 1990                                           Page 16
  1113.  
  1114.  
  1115.  
  1116.                            Inside TURBO Pascal 5.5 Units           
  1117.        ----------------------------------------------------------------------
  1118.  
  1119.        4.4.3.6 TURBO STD PROCEDURES ("T")
  1120.  
  1121.  
  1122.        This Stub consists of two bytes, the first of which is unique for each
  1123.                                                                               |
  1124.        procedure and  increments by  4.   I have  found nothing in the SYSTEM
  1125.                                                                               |
  1126.        unit (which  is where  this entry  appears) that  this seems  directly
  1127.                                                                               |
  1128.        related to.  The second byte is always zero.
  1129.                                                                               |
  1130.  
  1131.  
  1132.  
  1133.        4.4.3.7 TURBO STD FUNCTIONS ("U")
  1134.  
  1135.  
  1136.        This Stub consists of two bytes, the first of which is unique for each
  1137.                                                                               |
  1138.        function and increments by 4.  I have found nothing in the SYSTEM unit
  1139.                                                                               |
  1140.        (which is  where this  entry appears) that this seems directly related
  1141.                                                                               |
  1142.        to.   I wouldn't  be surprised if this byte were an index into a TURBO
  1143.                                                                               |
  1144.        compiler table that points to specialized parse tables/action routines
  1145.                                                                               |
  1146.        for handling these functions and their non-standard parameter lists.
  1147.                                                                               |
  1148.  
  1149.        The second byte seems to be a flag having the values $00, $40 and $C0.
  1150.                                                                               |
  1151.        I strongly  suspect that  the flag  $C0 marks  exactly those functions
  1152.                                                                               |
  1153.        which may  be evaluated at compile-time.  The meaning behind the other
  1154.                                                                               |
  1155.        values is not known to me.
  1156.                                                                               |
  1157.  
  1158.  
  1159.  
  1160.        4.4.3.8 TURBO STD "NEW" ROUTINE ("V")
  1161.  
  1162.  
  1163.        This Stub consists of a WORD whose function is (as yet) unknown.  This
  1164.                                                                               |
  1165.        is the  only Standard  Turbo routine that can behave as a procedure as
  1166.                                                                               |
  1167.        well as a function (returning a pointer value).
  1168.                                                                               |
  1169.  
  1170.  
  1171.  
  1172.        4.4.3.9 TURBO STD PORT ARRAYS ("W")
  1173.  
  1174.  
  1175.        This Stub  consists of  a byte whose value is 0 for byte arrays, and 1
  1176.        for word arrays.
  1177.  
  1178.  
  1179.  
  1180.        4.4.3.10 TURBO STD EXTERNAL VARIABLES ("X")
  1181.  
  1182.  
  1183.        This Stub  consists of  an  LG  (4-bytes)  that  points  to  the  Type
  1184.        Descriptor for this symbol.
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.        ----------------------------------------------------------------------
  1193.        Rev: August 11, 1990                                           Page 17
  1194.  
  1195.  
  1196.  
  1197.                            Inside TURBO Pascal 5.5 Units           
  1198.        ----------------------------------------------------------------------
  1199.  
  1200.        4.4.3.11 UNITS ("Y")
  1201.  
  1202.  
  1203.        Unit Stubs have the following content:
  1204.  
  1205.          +00:    A Word  whose apparently  reserved for use by the Compiler
  1206.                  or Linker.
  1207.  
  1208.          +02:    A Word that seems to contain some kind of "signature" used
  1209.                  to  detect   inconsistent  Unit  Versions.    This  author
  1210.                  suspects that  this consists  of some kind of sum-check or
  1211.                  hash total  but has not yet identified the algorithm which
  1212.                  computes the value stored in this word.
  1213.  
  1214.          +04:    A Word  that contains  an LL  which locates  the Successor
  1215.                  Unit in  the "Uses"  list.   In fact,  the "Uses" lists of
  1216.                  both the INTERFACE and IMPLEMENTATION sections of the Unit
  1217.                  are merged  by this  Word into  a single list.  A value of
  1218.                  zero is used to indicate no successor.
  1219.  
  1220.          +06:    A Word  that contains  an LL which locates the Predecessor
  1221.                  Unit in  the "Uses" list.  For the SYSTEM unit entry, this
  1222.                  value is  always zero to indicate no predecessor.  For the
  1223.                  Unit being compiled, this LL locates the final Unit in the
  1224.                  combined "Uses" list.
  1225.  
  1226.        In effect,  the two  LL's at  offsets 0004 and 0006 organize the units
  1227.        into both  forward and backward linked chains.  The entry for the unit
  1228.        being compiled  is effectively  the head  of both  the forward and the
  1229.        backward chains.  The final unit in the merged "Uses" list is the tail
  1230.        of the  forward chain, and the SYSTEM unit is the tail of the backward
  1231.        chain.
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.        ----------------------------------------------------------------------
  1257.        Rev: August 11, 1990                                           Page 18
  1258.  
  1259.  
  1260.  
  1261.                            Inside TURBO Pascal 5.5 Units           
  1262.        ----------------------------------------------------------------------
  1263.  
  1264.        4.4.4 TYPE DESCRIPTORS
  1265.  
  1266.  
  1267.        Type Descriptors  store much  of the semantic information that applies
  1268.        to the  symbols declared  in the  unit.  Implementation details can be
  1269.        managed using  high-level abstractions  and these  abstractions can be
  1270.        shared.
  1271.  
  1272.  
  1273.  
  1274.        4.4.4.1 SCOPE
  1275.  
  1276.  
  1277.        Type Descriptor  sharing can  occur across  the boundaries  which  are
  1278.        implicit in  unit modules.   Thus,  a type  defined in one unit may be
  1279.        "imported" by  some other  module.  Also, the pre-defined Pascal Types
  1280.        (plus the  Turbo Pascal extensions) are defined in the SYSTEM.TPU unit
  1281.        and there  needs to  be a  means of  "importing" such Type Descriptors
  1282.        during compilation.  This is precisely the objective of the LG locator
  1283.        which was  described in  section 2.2  (above).   Type Descriptors  are
  1284.        NEVER copied between units.  The binding always occurs by reference at
  1285.        compile time  and this helps support the technique of modifying a unit
  1286.        and compiling  it to a .TPU file, then re-compiling all units/programs
  1287.        that "USE" it.
  1288.  
  1289.        Type Descriptors  have many  roles so  their format  varies.   We have
  1290.        divided these  structures into  two parts:   The PREFIX Part (which is
  1291.        always present  and) whose  format is  fairly constant  and the SUFFIX
  1292.        Part whose  content and format depends on the attributes that are part
  1293.        of the type definition.
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.        ----------------------------------------------------------------------
  1321.        Rev: August 11, 1990                                           Page 19
  1322.  
  1323.  
  1324.  
  1325.                            Inside TURBO Pascal 5.5 Units           
  1326.        ----------------------------------------------------------------------
  1327.  
  1328.        4.4.4.2 PREFIX PART
  1329.  
  1330.  
  1331.        The Prefix  Part of  every Type Descriptor consists of four (4) bytes.
  1332.        The usage  is consistent for all types observed by this author and the
  1333.        format is as follows:
  1334.  
  1335.          +00:    A Byte  that identifies  the format  of the  Suffix  part.
  1336.                  This is essentially based on several high-level categories
  1337.                  which the Suffix Parts support directly.  The observed set
  1338.                  of values is as follows:
  1339.  
  1340.                  00h -> an un-typed entity;    
  1341.                  01h -> an ARRAY type;    
  1342.                  02h -> a RECORD type;    
  1343.                  03h -> an OBJECT type;   
  1344.                  04h -> a FILE type (other than TEXT);   
  1345.                  05h -> a TEXT File type; 
  1346.                  06h -> a SUBPROGRAM type;     
  1347.                  07h -> a SET type;  
  1348.                  08h -> a POINTER type;   
  1349.                  09h -> a STRING type;    
  1350.                  0Ah -> an 8087 Floating-Point type;     
  1351.                  0Bh -> a REAL type; 
  1352.                  0Ch -> a Fixed-Point ordinal type; 
  1353.                  0Dh -> a BOOLEAN type;   
  1354.                  0Eh -> a CHAR type; 
  1355.                  0Fh -> an Enumerated ordinal type.
  1356.  
  1357.          +01:    A Byte  used as a modifier.  Since the above scheme is too
  1358.                  general for  machine-dependent  details  such  as  storage
  1359.                  width  and  sign  control,  this  modifier  byte  supplies
  1360.                  additional data  as required.   The  author has identified
  1361.                  several cases  in which  this information is vital but has
  1362.                  not spent  very much time on the subject.  The chief areas
  1363.                  of importance seem to be in the 8087 Floating-Point types,
  1364.                  and the  Fixed-Point ordinal types.  The semantics seem to
  1365.                  be as follows:
  1366.  
  1367.                  0A 00 -> The type "SINGLE"    
  1368.                  0A 02 -> The type "EXTENDED"  
  1369.                  0A 04 -> The type "DOUBLE"    
  1370.                  0A 06 -> The type "COMP" 
  1371.  
  1372.                  0C 00 -> an un-named BYTE integer  
  1373.                  0C 01 -> The type "SHORTINT"  
  1374.                  0C 02 -> The type "BYTE" 
  1375.                  0C 04 -> an un-named WORD integer  
  1376.                  0C 05 -> The type "INTEGER"   
  1377.                  0C 06 -> The type "WORD" 
  1378.                  0C 0C -> an un-named double-word integer     
  1379.                  0C 0D -> The type "LONGINT"
  1380.  
  1381.  
  1382.  
  1383.  
  1384.        ----------------------------------------------------------------------
  1385.        Rev: August 11, 1990                                           Page 20
  1386.  
  1387.  
  1388.  
  1389.                            Inside TURBO Pascal 5.5 Units           
  1390.        ----------------------------------------------------------------------
  1391.  
  1392.                  One important  feature of  the above semantics is the fact
  1393.                  that an un-typed CONST declaration refers to the above two
  1394.                  bytes  to  determine  the  storage  space  needed  in  the
  1395.                  dictionary for  the data  value of the constant.  This can
  1396.                  be a  little involved  however as the constant may contain
  1397.                  its own  length descriptor  (as in the case of a character
  1398.                  string)   in which  case it  may be sufficient to identify
  1399.                  the high-level type category without any modifier byte.
  1400.  
  1401.          +02:    A Word  that contains  the number of bytes of storage that
  1402.                  are required  to contain  an object/entity  of this  type.
  1403.                  For types  that represent variable-length objects/entities
  1404.                  such as  strings, this  word may define the value returned
  1405.                  by the SIZEOF function as applied to the type.
  1406.  
  1407.  
  1408.  
  1409.        4.4.4.3 SUFFIX PARTS
  1410.  
  1411.  
  1412.        Suffix Parts further refine the implementation details of the type and
  1413.        also provide  subrange constraints  where appropriate.   In some cases
  1414.        the Suffix  part is  empty since  all semantic  data for  the type  is
  1415.        contained in the Prefix part.
  1416.  
  1417.  
  1418.  
  1419.        4.4.4.3.1 UN-TYPED
  1420.  
  1421.  
  1422.        This Suffix Part is empty.  Nothing is known about an un-typed entity.
  1423.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.        ----------------------------------------------------------------------
  1449.        Rev: August 11, 1990                                           Page 21
  1450.  
  1451.  
  1452.  
  1453.                            Inside TURBO Pascal 5.5 Units           
  1454.        ----------------------------------------------------------------------
  1455.  
  1456.        4.4.4.3.2 STRUCTURED TYPES
  1457.  
  1458.  
  1459.        The structured  types represent  aggregates of  lower-level types.  We
  1460.        include ARRAY,  RECORD, OBJECT,  FILE, TEXT,  SET, POINTER  and STRING
  1461.        types in this category.
  1462.  
  1463.  
  1464.  
  1465.        4.4.4.3.2.1 ARRAY TYPES
  1466.  
  1467.  
  1468.        The Suffix  Part of  the ARRAY type is so constructed as to be able to
  1469.        support recursive  or nested  definition of arrays.  The suffix format
  1470.        is as follows:
  1471.  
  1472.          +00:    An LG that locates the Type Descriptor for the "base-type"
  1473.                  of the  array.   This is  the type  of  the  entity  being
  1474.                  arrayed and may itself be an array.
  1475.  
  1476.          +04:    An LG  that locates  the Type  Descriptor  for  the  array
  1477.                  bounds which is a constrained ordinal type or subrange.
  1478.  
  1479.  
  1480.  
  1481.        4.4.4.3.2.2 RECORD TYPES
  1482.  
  1483.  
  1484.        RECORD types  have nested  scopes.   The Suffix  part provides  a base
  1485.        structure by  which to  locate the  fields local  to the  scope of the
  1486.        Record type itself.  The format is as follows:
  1487.  
  1488.          +00:    A Word containing an LL which locates the local Hash Table
  1489.                  that provides access to the fields in the nested scope.
  1490.  
  1491.          +02:    A Word  containing an  LL  which  locates  the  Dictionary
  1492.                  Header of  the initial  field in  the nested  scope.  This
  1493.                  supports a  "left-to-right" traversal  of the  fields in a
  1494.                  record.
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502.  
  1503.  
  1504.  
  1505.  
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.        ----------------------------------------------------------------------
  1513.        Rev: August 11, 1990                                           Page 22
  1514.  
  1515.  
  1516.  
  1517.                            Inside TURBO Pascal 5.5 Units           
  1518.        ----------------------------------------------------------------------
  1519.  
  1520.        4.4.4.3.2.3 OBJECT TYPES
  1521.  
  1522.  
  1523.        OBJECT types also have nested scopes.  The Suffix part provides a base
  1524.        structure by which to locate the fields and METHODS local to the scope
  1525.        of  the  OBJECT  type  itself.    In  addition,  inheritance  and  VMT
  1526.        particulars are stored.  The format is as follows:
  1527.  
  1528.          +00:    A Word containing an LL which locates the local Hash Table
  1529.                  that provides  access to  the fields  and METHODS local to
  1530.                  the nested scope.
  1531.  
  1532.          +02:    A Word  containing an  LL  which  locates  the  Dictionary
  1533.                  Header of the initial field or METHOD in the nested scope.
  1534.                  This supports  a "left-to-right"  traversal of  the fields
  1535.                  and METHODS in an OBJECT.
  1536.  
  1537.          +04:    An LG  which locates  the Type  Descriptor of  the  Parent
  1538.                  Object.  This field is zero if there is no such Parent.
  1539.  
  1540.          +08:    A Word  which contains  the size  in bytes  of the VMT for
  1541.                  this Object.   This field is zero if the object employs no
  1542.                  Virtual Methods.
  1543.  
  1544.          +0A:    A Word which contains the offset within the CONST DSeg Map
  1545.                  that locates  the VMT  skeleton or template segment.  This
  1546.                  field equals  FFFFh  if  the  object  employs  no  Virtual
  1547.                  Methods.
  1548.  
  1549.          +0C:    A Word which contains the offset within an Object instance
  1550.                  where the NEAR POINTER to the VMT for the object is stored
  1551.                  (within the DATA SEGMENT).  This field equals FFFFh if the
  1552.                  object employs no Virtual Methods.
  1553.  
  1554.          +0E:    A Word  which contains  an LL which locates the Dictionary
  1555.                  Header for the name of the OBJECT itself.
  1556.  
  1557.  
  1558.  
  1559.        4.4.4.3.2.4 FILE (NON-TEXT) TYPES
  1560.  
  1561.  
  1562.        This Suffix  consists of an LG that locates the Type Descriptor of the
  1563.        base type  of the  file.  Note that the Type Descriptor may be that of
  1564.        an un-typed entity (for un-typed files).
  1565.  
  1566.  
  1567.  
  1568.        4.4.4.3.2.5 TEXT FILE TYPES
  1569.  
  1570.  
  1571.        This Suffix  consists of an LG that locates the Type Descriptor of the
  1572.        base type of the file -- in this case SYSTEM.CHAR.
  1573.  
  1574.  
  1575.  
  1576.        ----------------------------------------------------------------------
  1577.        Rev: August 11, 1990                                           Page 23
  1578.  
  1579.  
  1580.  
  1581.                            Inside TURBO Pascal 5.5 Units           
  1582.        ----------------------------------------------------------------------
  1583.  
  1584.        4.4.4.3.2.6 SET TYPES
  1585.  
  1586.  
  1587.        This Suffix  consists of  an LG  that locates the base-type of the set
  1588.        itself.    Pascal  limits  such  entities  to  simple  ordinals  whose
  1589.        cardinality is limited to 256.
  1590.  
  1591.  
  1592.  
  1593.        4.4.4.3.2.7 POINTER TYPES
  1594.  
  1595.  
  1596.        This Suffix consists of an LG that locates the base-type of the entity
  1597.        pointed at.
  1598.  
  1599.  
  1600.  
  1601.        4.4.4.3.2.8 STRING TYPES
  1602.  
  1603.  
  1604.        This is a special case of an ARRAY type.  The format is as follows:
  1605.  
  1606.          +00:    An LG to the Type Descriptor SYSTEM.CHAR which is the base
  1607.                  type of all Turbo Pascal Strings.
  1608.  
  1609.          +04:    An  LG  to  the  Type  Descriptor  for  the  array  bounds
  1610.                  constraints for the string.
  1611.  
  1612.  
  1613.  
  1614.        4.4.4.3.3 FLOATING-POINT TYPES
  1615.  
  1616.  
  1617.        The Suffix  part for  all Floating-Point  types is  EMPTY.   All  data
  1618.        needed to  specify these  approximate number types is contained in the
  1619.        Prefix part.   The  Types included  in this  class are SINGLE, DOUBLE,
  1620.        EXTENDED, COMP and REAL.
  1621.  
  1622.  
  1623.  
  1624.        4.4.4.3.4 ORDINAL TYPES
  1625.  
  1626.  
  1627.        The Ordinal  Types consist  of the  various "integer"  types plus  the
  1628.        BOOLEAN, CHAR and Enumerated types.
  1629.  
  1630.  
  1631.  
  1632.  
  1633.  
  1634.  
  1635.  
  1636.  
  1637.  
  1638.  
  1639.  
  1640.        ----------------------------------------------------------------------
  1641.        Rev: August 11, 1990                                           Page 24
  1642.  
  1643.  
  1644.  
  1645.                            Inside TURBO Pascal 5.5 Units           
  1646.        ----------------------------------------------------------------------
  1647.  
  1648.        4.4.4.3.4.1 "INTEGERS"
  1649.  
  1650.  
  1651.        These types  include BYTE, SMALLINT, WORD, INTEGER and LONGINT.  Their
  1652.        Suffix parts are identical in format:
  1653.  
  1654.          +00:    A double-word  containing the  LOWER bound of the subrange
  1655.                  constraint on the type;
  1656.  
  1657.          +04:    A double-word  containing the  UPPER bound of the subrange
  1658.                  constraint on the type;
  1659.  
  1660.          +08:    An LG  that locates  the Type  Descriptor of  the  largest
  1661.                  upward compatible  type.  This is the Type Descriptor that
  1662.                  is used  to control  the width  of an un-typed constant in
  1663.                  the dictionary  stub.  For the "integer" types, this is an
  1664.                  LG to SYSTEM.LONGINT.
  1665.  
  1666.  
  1667.  
  1668.        4.4.4.3.4.2 BOOLEANS
  1669.  
  1670.  
  1671.        This type Suffix has the following format:
  1672.  
  1673.          +00:    A double-word  containing the  LOWER bound of the subrange
  1674.                  constraint on the type;
  1675.  
  1676.          +04:    A double-word  containing the  UPPER bound of the subrange
  1677.                  constraint on the type;
  1678.  
  1679.          +08:    An LG  that locates  the Type  Descriptor  SYSTEM.BOOLEAN.
  1680.                  There is no "upward compatible" type.
  1681.  
  1682.  
  1683.  
  1684.        4.4.4.3.4.3 CHARS
  1685.  
  1686.  
  1687.        This type Suffix has the following format:
  1688.  
  1689.          +00:    A double-word  containing the  LOWER bound of the subrange
  1690.                  constraint on the type;
  1691.  
  1692.          +04:    A double-word  containing the  UPPER bound of the subrange
  1693.                  constraint on the type;
  1694.  
  1695.          +08:    An LG that locates the Type Descriptor SYSTEM.CHAR.  There
  1696.                  is no "upward compatible" type.
  1697.  
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.        ----------------------------------------------------------------------
  1705.        Rev: August 11, 1990                                           Page 25
  1706.  
  1707.  
  1708.  
  1709.                            Inside TURBO Pascal 5.5 Units           
  1710.        ----------------------------------------------------------------------
  1711.  
  1712.        4.4.4.3.4.4 ENUMERATIONS
  1713.  
  1714.  
  1715.        This type Suffix is unusual and has the following format:
  1716.  
  1717.          +00:    A double-word  containing the  LOWER bound of the subrange
  1718.                  constraint on the type;
  1719.  
  1720.          +04:    A double-word  containing the  UPPER bound of the subrange
  1721.                  constraint on the type;
  1722.  
  1723.          +08:    An  LG  that  locates  the  Prefix  of  the  current  Type
  1724.                  Descriptor.  There is no upward compatible type.
  1725.  
  1726.        What follows  is a full-fledged SET Type Descriptor whose base type is
  1727.        the Type Descriptor of the Enumerated Type itself.  The author has not
  1728.        yet discovered the reason for this.
  1729.  
  1730.  
  1731.  
  1732.        4.4.4.3.5 SUBPROGRAM TYPES
  1733.  
  1734.  
  1735.        The length of this Suffix is variable.  The format is as follows:
  1736.  
  1737.          +00:    An LG  that locates  the Type  Descriptor of  the FUNCTION
  1738.                  result returned  by the Subprogram.  This field is zero if
  1739.                  the Subprogram is a PROCEDURE.
  1740.  
  1741.          +04:    A Word  that contains  the number  of Formal Parameters in
  1742.                  the Function/Procedure  header.   If non-zero,  then  this
  1743.                  word is  followed by the parameter list itself as a simple
  1744.                  array of parameter descriptors.
  1745.  
  1746.                  The format of a parameter descriptor is as follows:
  1747.  
  1748.                  0000: An LG that locates the Type Descriptor of the    
  1749.                        corresponding parameter;
  1750.  
  1751.                  0004: A Byte that identifies the parameter passing     
  1752.                        mechanism used for this entry as follows:
  1753.  
  1754.                        02h -> VALUE of parameter is passed on STACK,    
  1755.                        06h -> ADDRESS of parameter is passed on STACK.
  1756.  
  1757.  
  1758.  
  1759.  
  1760.  
  1761.  
  1762.  
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.        ----------------------------------------------------------------------
  1769.        Rev: August 11, 1990                                           Page 26
  1770.  
  1771.  
  1772.  
  1773.                            Inside TURBO Pascal 5.5 Units           
  1774.        ----------------------------------------------------------------------
  1775.  
  1776.        5. MAPS AND LISTS
  1777.  
  1778.  
  1779.        The "MAPS  and LISTS"  are not part of the symbol dictionary.  Rather,
  1780.        these structures provide access to the Code and Data Segments produced
  1781.        by the  compiler or  included via  the {$L  name.OBJ} directive.   The
  1782.        format and  purpose (as  understood by  this author)  of each of these
  1783.        tables is explained in the following sections.
  1784.  
  1785.  
  1786.  
  1787.        5.1 PROC MAP
  1788.  
  1789.  
  1790.        The PROC  Map provides a means of associating the various Function and
  1791.        Procedure declarations with the Code Segments.  There is some evidence
  1792.        that the  Compiler produces  CODE (and  DATA) Segments for EACH of the
  1793.        Subprograms defined  in the  Unit as  well as  for the  un-named  Unit
  1794.        Initialization code block.  There is also evidence that EXTERNAL PROCs
  1795.                                                                               |
  1796.        must be  assembled separately  in order  to exploit  fully  the  Turbo
  1797.        "Smart Linker" since Turbo Pascal places some significant restrictions
  1798.        on  EXTERNAL  routines  in  the  area  of  Segment  Names  and  Types.
  1799.        Specifically, only  code segments named "CODE" and data segments named
  1800.        "DATA" will  be used by the "Smart Linker" as sources of code and data
  1801.        for inclusion in a Turbo Pascal .EXE file.
  1802.  
  1803.        The first  entry in  the PROC  Map is reserved for Unit Initialization
  1804.        block.   If there  is no Unit Initialization block, this entry will be
  1805.                                                                               |
  1806.        filled with  $FF.  In addition, each and every PROC in the Unit has an
  1807.                                                                               |
  1808.        entry in this table.
  1809.  
  1810.        If an  EXTERNAL routine  is included, then ALL PUBLIC PROC definitions
  1811.        in that  routine must  be declared  in the  Unit Source  Code with the
  1812.        EXTERNAL attribute.
  1813.  
  1814.        The size  of the  PROC Map  Table (in  Bytes) is  implied in  the Unit
  1815.        Header by the LL's that occur at offsets +0C and +0E.
  1816.  
  1817.        The Format of a single PROC Map Entry is as follows:
  1818.  
  1819.          +00:    A Word  that contains an offset within the CSeg Map.  This
  1820.                  is used to locate the code segment containing the PROC.
  1821.  
  1822.          +02:    A Word  that contains  an offset  within the  CODE Segment
  1823.                  that defines  the PROC  entry point  relative to  the load
  1824.                  point of the referenced CODE Segment.
  1825.  
  1826.  
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.  
  1833.  
  1834.  
  1835.        ----------------------------------------------------------------------
  1836.        Rev: August 11, 1990                                           Page 27
  1837.  
  1838.  
  1839.  
  1840.                            Inside TURBO Pascal 5.5 Units           
  1841.        ----------------------------------------------------------------------
  1842.  
  1843.        5.2 CSEG MAP
  1844.  
  1845.  
  1846.        The CSeg  Map provides  a convenient  descriptor table  for each  CODE
  1847.        Segment present  in the  Unit and serves to relate these segments with
  1848.        the Segment  Relocation Data  and the  Segment Trace  Table.  It seems
  1849.        reasonable to infer that the "Smart Linker" is able to include/exclude
  1850.        code/data at the SEGMENT level only.
  1851.  
  1852.        The CSeg  Map is  an array  of fixed-length records whose format is as
  1853.        follows:
  1854.  
  1855.          +00:    A Word apparently reserved for use by TURBO.
  1856.  
  1857.          +02:    A Word that contains the Segment Length (in bytes).
  1858.  
  1859.          +04:    A Word  that contains  the Length  of the  Relocation Data
  1860.                  Table for this Code Segment (in bytes).
  1861.  
  1862.          +06:    A Word  that contains  the offset of the Trace Table Entry
  1863.                  for this  Segment (if it was compiled with DEBUG Support).
  1864.                  If there  is no  Trace Table  for this  segment, then this
  1865.                  Word contains FFFFh.
  1866.  
  1867.  
  1868.  
  1869.        5.3 TYPED CONST DSEG MAP
  1870.  
  1871.  
  1872.        The CONST  DSeg Map  provides a  convenient descriptor  table for each
  1873.        DATA Segment  present in the Unit which was spawned by the presence of
  1874.        Typed Constants  or VMT's  in the  Pascal Code.   It  serves to relate
  1875.        these segments  with the  Segment Relocation  Data and  with the  Code
  1876.        Segments that refer to these DATA elements.
  1877.  
  1878.        The CONST DSeg Map is an array of fixed-length records whose format is
  1879.        as follows:
  1880.  
  1881.          +00:    A Word apparently reserved for use by TURBO.
  1882.  
  1883.          +02:    A Word that contains the Segment Length (in bytes).
  1884.  
  1885.          +04:    A Word  that contains  the Length  of the  Relocation Data
  1886.                  Table for this DATA Segment (in bytes).
  1887.  
  1888.          +06:    A Word  that contains  an LL which locates the OBJECT that
  1889.                  owns this VMT skeleton or zero if the segment is not a VMT
  1890.                  skeleton.
  1891.  
  1892.        It is  possible to determine the containing scope for a Typed Constant
  1893.        declaration but -- unless it is for a VMT -- the job is a bit tedious.
  1894.        Essentially, one has to search the Symbol Dictionary for a declaration
  1895.        whose offset  points to  a given  entry and  the complete path to that
  1896.        symbol must  be recorded.   Our  program doesn't do this but it can be
  1897.        done if the required dictionary entries are present.
  1898.  
  1899.        ----------------------------------------------------------------------
  1900.        Rev: August 11, 1990                                           Page 28
  1901.  
  1902.  
  1903.  
  1904.                            Inside TURBO Pascal 5.5 Units           
  1905.        ----------------------------------------------------------------------
  1906.  
  1907.  
  1908.  
  1909.        5.4 GLOBAL VAR DSEG MAP
  1910.  
  1911.  
  1912.        The VAR  DSeg Map provides a convenient descriptor table for each DATA
  1913.        Segment present in the Unit.
  1914.  
  1915.        One entry  exists for  each CODE  segment which refers to GLOBAL VAR's
  1916.        allocated in  the DATA  Segment.   These references may be seen in the
  1917.        Relocation Data Table.  Each EXTERNAL CSeg having a segment named DATA
  1918.        also spawns  an entry in this table.  Only the Code Segments that meet
  1919.        these criteria cause entries to be generated in the VAR Dseg Map.
  1920.  
  1921.        The VAR  DSeg Map  is an array of fixed-length records whose format is
  1922.        as follows:
  1923.  
  1924.          +00:    A Word apparently reserved for use by TURBO.
  1925.  
  1926.          +02:    A Word  that contains the Segment Length (in bytes).  This
  1927.                  may be zero, especially if the EXTERNAL routine contains a
  1928.                  DATA segment  whose sole purpose is to declare one or more
  1929.                  EXTRN symbols  that  are  defined  in  some  DATA  segment
  1930.                  external to the Assembly.
  1931.  
  1932.          +04:    A Word apparently reserved for use by TURBO.
  1933.  
  1934.          +06:    A Word apparently reserved for use by TURBO.
  1935.  
  1936.        To determine  the identity of the CSeg that owns some particular entry
  1937.        in this  table, examine  the Relocation Data for ALL CSegs.  Each CSeg
  1938.        which makes reference to a DATA segment has an entry in this table.
  1939.  
  1940.  
  1941.  
  1942.        5.5 DONOR UNIT LIST
  1943.  
  1944.  
  1945.        This list contains an entry for each Unit (taken from the "USES" list)
  1946.        which MAY  contribute either CODE or DATA to the executable file.  Not
  1947.        all units do make such a contribution as some exist merely to define a
  1948.        collection of  Types, etc.  A Unit gets into this list if there exists
  1949.        a single  Relocation Data  Entry that  references CODE or DATA in that
  1950.        Unit.
  1951.  
  1952.        The list  is comprised  of elements  whose SIZE  is variable and whose
  1953.        format is as follows:
  1954.  
  1955.          +00:    A WORD apparently reserved for use by TURBO.
  1956.  
  1957.          +02:    A variable-length String containing the unit name.
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.        ----------------------------------------------------------------------
  1964.        Rev: August 11, 1990                                           Page 29
  1965.  
  1966.  
  1967.  
  1968.                            Inside TURBO Pascal 5.5 Units           
  1969.        ----------------------------------------------------------------------
  1970.  
  1971.        5.6 SOURCE FILE LIST
  1972.  
  1973.  
  1974.        This list contains an entry for each "source" file used to compile the
  1975.        Unit.   This includes the Primary Pascal file, files containing Pascal
  1976.        code included  by means  of the  {$I filename.xxx} compiler directive,
  1977.        and .OBJ files included by the {$L filename.OBJ} compiler directive.
  1978.  
  1979.        The order  of entries  in this list is critical since it maps the CODE
  1980.        segments stored in the unit.  The order of the entries is as follows:
  1981.  
  1982.          1)      The Primary Pascal file;
  1983.  
  1984.          2)      All Included Pascal files;
  1985.  
  1986.          3)      All Included .OBJ files.
  1987.  
  1988.        Mapping of CSegs to files is done as follows:
  1989.  
  1990.          a)      Each .OBJ file contributes a SINGLE Code Segment (if any).
  1991.                  Note that this author has not observed an .OBJ module that
  1992.                  contains only  a DATA  Segment (but  that seems a distinct
  1993.                  possibility).
  1994.  
  1995.          b)      The Primary  Pascal file (augmented by all included Pascal
  1996.                  Files) contributes zero or more CODE Segments.
  1997.  
  1998.        Therefore, there  are at least as many CSeg entries as .OBJ files.  If
  1999.        more, then  the excess entries (those at the front of the list) belong
  2000.        to the Pascal files that make up the Pascal source for the unit.
  2001.  
  2002.        The format of an entry in this list is as follows:
  2003.  
  2004.          +00:    A flag byte that indicates the type of file represented;    
  2005.  
  2006.                  04h -> the Primary Pascal Source File,  
  2007.                  03h -> an Included Pascal Source File,  
  2008.                  05h -> an .OBJ file that contains a CODE segment.
  2009.  
  2010.          +01:    A Word apparently reserved for use by the Compiler/Linker.
  2011.  
  2012.          +03:    A Word  that is zero for .OBJ files and which contains the
  2013.                  file directory time-stamp for Pascal Files.
  2014.  
  2015.          +05:    A Word  that is zero for .OBJ files and which contains the
  2016.                  file directory date-stamp for Pascal Files.
  2017.  
  2018.          +07:    A  variable-sized   string  containing  the  filename  and
  2019.                  extension of the file used during compilation.
  2020.  
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026.  
  2027.        ----------------------------------------------------------------------
  2028.        Rev: August 11, 1990                                           Page 30
  2029.  
  2030.  
  2031.  
  2032.                            Inside TURBO Pascal 5.5 Units           
  2033.        ----------------------------------------------------------------------
  2034.  
  2035.        5.7 DEBUG TRACE TABLE
  2036.  
  2037.  
  2038.        If Debug  support was  selected at  compile time, then all Pascal code
  2039.        which supports  Debugging produces  an entry in this table.  The table
  2040.        entries themselves are variable in size and have the following format:
  2041.  
  2042.          +00:    A Word  which contains  an LL  that locates  the Directory
  2043.                  Header of the Symbol (a PROC name) this entry represents.
  2044.  
  2045.          +02:    A Word  which contains  the offset (within the Source File
  2046.                  List) of  the entry that names the file that generated the
  2047.                  CSeg being traced.  This allows the file included by means
  2048.                  of the  {$I filename} directive to be identified for DEBUG
  2049.                  purposes, as well as code produced from the Primary File.
  2050.  
  2051.          +04:    A Word containing the number of bytes of data that precede
  2052.                  the BEGIN statement code in the segment.  For Pascal PROCS
  2053.                  these  bytes   consist  of   literal  constants,  un-typed
  2054.                                                                               |
  2055.                  constants, and  other data  such as range-checking limits,
  2056.                                                                               |
  2057.                  etc.
  2058.  
  2059.          +06:    A Word  containing the  Line Number of the BEGIN statement
  2060.                  for the PROC.
  2061.  
  2062.          +08:    A Word  containing the  number of  lines of Source Code to
  2063.                  Trace in this Segment.
  2064.  
  2065.          +0A:    An array  of bytes  whose size   is at least the number of
  2066.                  source code  lines in  the PROC.   Each  byte contains the
  2067.                  number of bytes of object code in the corresponding source
  2068.                  line.   This appears to be an array of SHORTINT since if a
  2069.                  "line" contains more than 127 bytes, then a single byte of
  2070.                  $80 precedes  the actual  byte count as a sort of "escape"
  2071.                  and the  next byte  records the  up to  255 bytes  for the
  2072.                                                                               |
  2073.                  line.  This situation has not yet been fully explored.  We
  2074.                                                                               |
  2075.                  do not  yet know  what happens  in the  event  a  line  is
  2076.                                                                               |
  2077.                  credited with spawning more than 255 bytes of code.
  2078.                                                                               |
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.        ----------------------------------------------------------------------
  2098.        Rev: August 11, 1990                                           Page 31
  2099.  
  2100.  
  2101.  
  2102.                            Inside TURBO Pascal 5.5 Units           
  2103.        ----------------------------------------------------------------------
  2104.  
  2105.        6. CODE, DATA, RELOCATION INFO
  2106.  
  2107.  
  2108.        This area  begins at the start of the next free PARAGRAPH.  This means
  2109.        that its  offset from  the beginning  of the  Unit ALWAYS  ends in the
  2110.        digit zero.
  2111.  
  2112.        This area  contains the  CODE segments,  CONST DATA  segments, and the
  2113.        Relocation Data required for linking.
  2114.  
  2115.  
  2116.  
  2117.        6.1 OBJECT CSEGS
  2118.  
  2119.  
  2120.        Each CODE  segment included  in the  unit appears here as specified by
  2121.        the CSeg  Map Table.  Depending on usage, these segments may appear in
  2122.        the executable file.  There are no filler bytes between segments.
  2123.  
  2124.  
  2125.  
  2126.        6.2 CONST DSEGS
  2127.  
  2128.  
  2129.        This section begins at the start of the first free PARAGRAPH following
  2130.        the end  of the  Object CSegs.   This  means that  its offset from the
  2131.        beginning of the Unit ALWAYS ends in the digit zero.
  2132.  
  2133.        A DATA  segment fragment  appears here  for each  CSeg that declares a
  2134.        typed constant,  and for  each OBJECT  which employs  Virtual Methods.
  2135.        There are no filler bytes between segments.
  2136.  
  2137.        If local symbols were generated, there is always enough information to
  2138.        allow documenting the scope of the declaration as well as interpreting
  2139.        the data  in the display since the needed type declarations would also
  2140.        be available.  Our program doesn't go to this extreme however.
  2141.  
  2142.  
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.  
  2160.  
  2161.        ----------------------------------------------------------------------
  2162.        Rev: August 11, 1990                                           Page 32
  2163.  
  2164.  
  2165.  
  2166.                            Inside TURBO Pascal 5.5 Units           
  2167.        ----------------------------------------------------------------------
  2168.  
  2169.        6.3 RELOCATION DATA TABLE
  2170.  
  2171.  
  2172.        This table  begins at  the start of the first free PARAGRAPH following
  2173.        the end  of the  CONST DSegs.   This  means that  its offset  from the
  2174.        beginning of  the Unit  ALWAYS ends  in the digit zero.  There are two
  2175.                                                                               |
  2176.        sections in  this table:   one  for code,  and one  for  data.    Both
  2177.                                                                               |
  2178.        sections are  aligned on  paragraph boundaries.   This may result in a
  2179.                                                                               |
  2180.        "slack" entry  between the  code and data sub-sections, but this entry
  2181.                                                                               |
  2182.        is included  in the  byte tally  for the  section stored  in the  Unit
  2183.                                                                               |
  2184.        Header Table at ULPtch (offset +20).
  2185.                                                                               |
  2186.  
  2187.        The table  begins with  entries for the CSeg Map and ends with entries
  2188.        for the  CONST DSeg  Map.   The appropriate  Map entry  specifies  the
  2189.        number of  bytes of  Relocation Data  for the  corresponding  segment.
  2190.        This number  may be zero in which case there is no Relocation Data for
  2191.        the given segment.
  2192.                                                                               |
  2193.  
  2194.        The Table  consists of an array of eight (8) byte entries whose format
  2195.        is as follows:
  2196.  
  2197.          +00:    A Byte containing the offset within the Donor Unit List of
  2198.                  the Unit  name that this entry refers to.  This can be the
  2199.                  compiled Unit or some previously compiled external unit.
  2200.  
  2201.          +01:    A Byte  that defines  the type of reference being made and
  2202.                  implies the  size of  the pointer  needed (WORD or DWORD).
  2203.                  The known and/or observed values are as follows:
  2204.  
  2205.                  00h -> a WORD refers to a PROC Map.     
  2206.                  10h -> a WORD refers to a PROC Map.     
  2207.                  20h -> a WORD refers to a PROC Map.     
  2208.                  30h -> a DWORD pointer refers to a PROC Map. 
  2209.                  50h -> a WORD refers to a CSeg Map.     
  2210.                  60h -> a WORD refers to an unknown Map. 
  2211.                  70h -> a DWORD pointer refers to a CSeg Map. 
  2212.                  90h -> a WORD refers to a VAR DSeg Map. 
  2213.                  A0h -> a WORD refers to a DSeg Map for SEG address.    
  2214.                                                                               |
  2215.                  D0h -> a WORD refers to a CONST DSeg Map.
  2216.  
  2217.          +02:    A  Word   containing  the  offset  within  the  Map  table
  2218.                  referenced according to the above code scheme.
  2219.  
  2220.          +04:    A Word  containing an  offset within  the  target  segment
  2221.                  which will  be  added  to  the  effective  address.    For
  2222.                  example, a  reference to  the VAR  DSeg Map will require a
  2223.                  final offset to locate the item (variable) within the DATA
  2224.                  SEGMENT being  referenced here.   This  may also be needed
  2225.                  for references to LITERAL DATA embedded in a CODE SEGMENT.
  2226.  
  2227.          +06:    A Word  containing the  offset within  the  CODE  or  DATA
  2228.                  segment owning  this entry  that contains  the area  to be
  2229.                                                                               |
  2230.                  patched with the value of the final effective address.
  2231.                                                                               |
  2232.  
  2233.  
  2234.  
  2235.        ----------------------------------------------------------------------
  2236.        Rev: August 11, 1990                                           Page 33
  2237.  
  2238.  
  2239.  
  2240.                            Inside TURBO Pascal 5.5 Units           
  2241.        ----------------------------------------------------------------------
  2242.  
  2243.        For some  truly wild guessing about the flag byte above, the following
  2244.                                                                               |
  2245.        pattern seems  to be  emerging.   Look at  bits 7-4  of this byte.  It
  2246.                                                                               |
  2247.        appears that  the type of Map reference may be coded into bits 7-6 and
  2248.                                                                               |
  2249.        that the  size or  type of reference may be coded into bits 5-4.  Note
  2250.                                                                               |
  2251.        that bits  7-6 are  "00" for  PROC Map items, "01" for CSeg Map items,
  2252.                                                                               |
  2253.        "10" for Global DSeg Map items, and "11" for Const DSeg Map items.  It
  2254.                                                                               |
  2255.        appears that the size or type of reference may be coded into bits 5-4.
  2256.                                                                               |
  2257.        Note that  all FAR  (DWORD) pointer references show these bits as "11"
  2258.                                                                               |
  2259.        and that a SEGMENT Register value appears as "10" and that WORD values
  2260.                                                                               |
  2261.        otherwise appear  as "01" or "00".  Further, no type 00h item has been
  2262.                                                                               |
  2263.        seen which  has a  non-zero effective  address adjustment.   This  all
  2264.                                                                               |
  2265.        seems to suggest the following code structure:
  2266.                                                                               |
  2267.  
  2268.          7654 3210    (bits 3-0 don't seem to be used)
  2269.                                                                               |
  2270.  
  2271.          00-- ----    Locate item via a PROC Map,
  2272.                                                                               |
  2273.          01-- ----    Locate item via a CSeg Map,
  2274.                                                                               |
  2275.          10-- ----    Locate item via a Global DSeg Map,
  2276.                                                                               |
  2277.          11-- ----    Locate item via a Const  DSeg Map,
  2278.                                                                               |
  2279.          --00 ----    WORD offset has NO effective address adjustment,
  2280.                                                                               |
  2281.          --01 ----    WORD offset HAS an effective address adjustment,
  2282.                                                                               |
  2283.          --10 ----    WORD is content of a SEGMENT Register such as DS
  2284.                                                                               |
  2285.                       or CS.
  2286.                                                                               |
  2287.          --11 ----    DWORD (FAR) pointer is supplied with possible
  2288.                                                                               |
  2289.                       effective address adjustment.
  2290.                                                                               |
  2291.  
  2292.        The evidence  in support of this conjecture is both slim and vast.  It
  2293.                                                                               |
  2294.        all depends  on how much data one looks at.  I have looked at a lot of
  2295.                                                                               |
  2296.        data from  the Borland  supplied units and I haven't found anything to
  2297.                                                                               |
  2298.        refute the  above.   Accordingly, the supplied program interprets this
  2299.                                                                               |
  2300.        flag byte according to this scheme.
  2301.                                                                               |
  2302.  
  2303.  
  2304.  
  2305.        7. SUPPLIED PROGRAM
  2306.  
  2307.  
  2308.        In order that the above information be made constructively useful, the
  2309.        author has designed a program that automates the process of discovery.
  2310.        It is  not a  "handsome" program and it is not a work of art.  It does
  2311.        give useful results provided your PC has enough available memory.
  2312.  
  2313.        It should  be obvious  that the  program was  not designed "top-down".
  2314.        Rather, it  just evolved as each new discovery was made.  Later on, it
  2315.        seemed reasonable to try to document some of the relations between the
  2316.        various lists  and tables  and the program tries to make some of these
  2317.        relations clear, albeit with varying degrees of success.
  2318.  
  2319.  
  2320.  
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.        ----------------------------------------------------------------------
  2328.        Rev: August 11, 1990                                           Page 34
  2329.  
  2330.  
  2331.  
  2332.                            Inside TURBO Pascal 5.5 Units           
  2333.        ----------------------------------------------------------------------
  2334.  
  2335.        7.1 TPUNEW
  2336.                                                                               |
  2337.  
  2338.  
  2339.        This is  the main program.  It will ask for the name of the unit to be
  2340.        documented.   Reply with  the unit name only.  The program will append
  2341.        the ".TPU" extension and will search for the proper file.
  2342.  
  2343.        The program  will then ask if Dis-Assembly is desired and will require
  2344.        a "y" or "n" answer.
  2345.  
  2346.        The  current  directory  will  be  searched  first,  followed  by  all
  2347.        directories in the current PATH.  The program will NOT search a ".TPL"
  2348.        (Turbo Pascal Library) file.
  2349.  
  2350.        If the  desired unit  is found, the program will write a report to the
  2351.        current directory  named "unitname.lst"  which contains  its analysis.
  2352.        The format of the report is such that it may be copied to a printer if
  2353.        that printer supports TTY control codes with form-feeds.  Be judicious
  2354.        in doing  this however  since there  can be a lot of information.  The
  2355.        Turbo SYSTEM.TPU  unit file  produces almost ninety (90) pages without
  2356.                                                                               |
  2357.        the disassembly  option.  When disassembly is requested for the SYSTEM
  2358.                                                                               |
  2359.        unit, the size of the output file exceeds 700K bytes.
  2360.                                                                               |
  2361.  
  2362.  
  2363.  
  2364.        7.2 TPURPT1
  2365.  
  2366.  
  2367.        This is  a Unit that contains the text-file output primitives required
  2368.        by the main program.  It's not very pretty but it does work.
  2369.  
  2370.  
  2371.  
  2372.        7.3 TPUAMS1
  2373.  
  2374.  
  2375.        This Unit  contains all  Type Definitions,  Structures,  and  "Canned"
  2376.        Functions and Procedures required by the main program.  All structures
  2377.        documented in  this report  are also documented in TPUAMS1 by means of
  2378.        the TYPE  mechanism.   Some of  the structures  are difficult  if  not
  2379.        impossible to  handle using  ISO Pascal  but Turbo Pascal provides the
  2380.        means for getting the job done.
  2381.  
  2382.  
  2383.  
  2384.        7.4 TPUUNA1
  2385.  
  2386.  
  2387.        This unit is a rudimentary disassembler.  The output will not assemble
  2388.        and may  look strange to a real assembler programmer since this author
  2389.        is not  so-qualified.   However, the basis for support of 80286, 80386
  2390.        etc. processors is present as well as coprocessor support.  Of perhaps
  2391.        the greatest  interest is  that it  does appear to decode the emulated
  2392.        coprocessor instructions that are implemented via INT 34-3D.
  2393.  
  2394.  
  2395.        ----------------------------------------------------------------------
  2396.        Rev: August 11, 1990                                           Page 35
  2397.  
  2398.  
  2399.  
  2400.                            Inside TURBO Pascal 5.5 Units           
  2401.        ----------------------------------------------------------------------
  2402.  
  2403.        Be warned  however.  The output is not guaranteed since this was coded
  2404.        by myself  and I  am perhaps  the rankest amateur that ever approached
  2405.        this quite  awful assembler  language.   For convenience,  the operand
  2406.        coding mimics TASM "Ideal" mode.
  2407.  
  2408.        As is  usual with programs of this type, error-recovery is minimal and
  2409.        no context  checking is  performed.  If the operation code is found to
  2410.        be valid,  then a  valid instruction  is assumed  -- even  if  invalid
  2411.        operands are present.
  2412.  
  2413.        The only positives that apply to this program are that it doesn't slow
  2414.        the cpu down (although a lot more output is produced), and it does let
  2415.        one "tune" code for compactness by letting one view the results of the
  2416.        coding directly.   Also,  incomplete instructions  are handled as data
  2417.                                                                               |
  2418.        rather than overrunning into the next proc.
  2419.                                                                               |
  2420.  
  2421.  
  2422.  
  2423.        7.5 MODIFICATIONS
  2424.  
  2425.  
  2426.        It was intended from the beginning that this program should be able to
  2427.        be enhanced  to permit  external units  to be  referenced  during  the
  2428.        analysis of any given unit, even if they were library components.  The
  2429.        author hopes  that users so-inclined will find the code pliable enough
  2430.        to engineer  such enhancements.   No small amount of care was expended
  2431.        to make  pointer references flexible enough so that more than one unit
  2432.        could be  addressed at  one time.   However, none of the references to
  2433.        external units are resolved by the program as it now stands.
  2434.  
  2435.        This program  was NOT intended as a pilot for some future product.  It
  2436.                                                                               |
  2437.        WAS intended as a rather "ersatz" tool for myself.
  2438.                                                                               |
  2439.  
  2440.  
  2441.  
  2442.        7.6 NOTES ON PROGRAM LOGIC
  2443.                                                                               |
  2444.  
  2445.  
  2446.        The following  sections discuss  a few  of the methods employed by the
  2447.        supplied program.
  2448.  
  2449.  
  2450.  
  2451.  
  2452.  
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.  
  2460.  
  2461.  
  2462.  
  2463.  
  2464.        ----------------------------------------------------------------------
  2465.        Rev: August 11, 1990                                           Page 36
  2466.  
  2467.  
  2468.  
  2469.                            Inside TURBO Pascal 5.5 Units           
  2470.        ----------------------------------------------------------------------
  2471.  
  2472.        7.6.1 FORMATTING THE DICTIONARY
  2473.                                                                               |
  2474.  
  2475.  
  2476.        Printing the unit dictionary area in a way that exposes its underlying
  2477.                                                                               |
  2478.        semantics is  no small  task.   The unit  dictionary area  itself is a
  2479.                                                                               |
  2480.        rather  amorphous-looking  mass  of  data  composed  of  hash  tables,
  2481.                                                                               |
  2482.        dictionary headers  and stubs,  type descriptors,  etc.   In order  to
  2483.                                                                               |
  2484.        present all  this information  in a  meaningful way, we have to reveal
  2485.                                                                               |
  2486.        its structure  and this  cannot be  done  by  means  of  a  sequential
  2487.                                                                               |
  2488.        "browse" technique.   Rather,  we have  to  visit  all  nodes  in  the
  2489.                                                                               |
  2490.        dictionary area  so that  each may  be formatted in a way that exposes
  2491.                                                                               |
  2492.        their function  and meaning.   This is made necessary by the fact that
  2493.                                                                               |
  2494.        items are  added to  the dictionary  as encountered  and no convenient
  2495.                                                                               |
  2496.        ordering of  entry types  exists.  What we have here is the problem of
  2497.                                                                               |
  2498.        finding a  minimal "cover"  for  the  dictionary  area  that  properly
  2499.                                                                               |
  2500.        exposes the content and structure of the dictionary area.
  2501.                                                                               |
  2502.  
  2503.        To do  this, we  construct (in  the heap) a stack and a queue, both of
  2504.                                                                               |
  2505.        which are  initially empty.   The entries we put in the stack identify
  2506.                                                                               |
  2507.        the class  of entry (Hash Table, Dictionary Header, Type Descriptor or
  2508.                                                                               |
  2509.        In-Line Code  group), the  location of the structure, and the location
  2510.                                                                               |
  2511.        of its  immediate "owner"  or "parent"  dictionary entry (which allows
  2512.                                                                               |
  2513.        some limited information about scope to be printed).
  2514.                                                                               |
  2515.  
  2516.        To the  empty stack,  we add  an entry  for the  unit name  dictionary
  2517.                                                                               |
  2518.        entry, the  INTERFACE hash table, and the DEBUG hash table.  All these
  2519.                                                                               |
  2520.        are located  via direct  pointers (LL's) in the Unit Header Table.  We
  2521.                                                                               |
  2522.        then pop one entry off the stack and begin our analysis.
  2523.                                                                               |
  2524.  
  2525.        a)    If the  entry we  popped off  the stack  is not  present in  the
  2526.                                                                               |
  2527.              queue, we add it and call a routine that can interpret the entry
  2528.                                                                               |
  2529.              (aka, "cover")  for a  Dictionary Header,  Hash Table,  or  Type
  2530.                                                                               |
  2531.              Descriptor.  (This may lead to additional entries being added to
  2532.                                                                               |
  2533.              the stack  such as nested-scope hash tables, Dictionary Headers,
  2534.                                                                               |
  2535.              Type Descriptors or In-Line Code group entries.)
  2536.                                                                               |
  2537.  
  2538.        b)    While the  stack is  not empty,  we pop another entry and repeat
  2539.                                                                               |
  2540.              step "a" (above) until no more entries are available.
  2541.                                                                               |
  2542.  
  2543.        The result  is a  queue containing one entry for each structure in the
  2544.                                                                               |
  2545.        unit  dictionary  area  that  is  identifiable  via  traversal.    (In
  2546.                                                                               |
  2547.        practice, the  method we use is similar to a "breadth-first" traversal
  2548.                                                                               |
  2549.        of an  n-way tree that is implemented in non-recursive fashion.)  Each
  2550.                                                                               |
  2551.        entry in  the queue  contains the  information described above and the
  2552.                                                                               |
  2553.        queue itself thus forms a set of descriptors that drive the process of
  2554.                                                                               |
  2555.        formatting the  dictionary area  for display.    The  process  may  be
  2556.                                                                               |
  2557.        likened to  "painting by  the numbers" or to finding a way to lay tile
  2558.                                                                               |
  2559.        on a flat surface using tiles of four different irregular shapes until
  2560.                                                                               |
  2561.        the floor is exactly covered.
  2562.                                                                               |
  2563.  
  2564.        There is  one significant limitation that needs to be pointed out.  It
  2565.                                                                               |
  2566.        is not  always possible to determine the "parent" or "owner" of a node
  2567.                                                                               |
  2568.        with certainty.   The  following discussion illustrates the problem of
  2569.                                                                               |
  2570.        finding the "real" parent of a Type Descriptor.
  2571.                                                                               |
  2572.  
  2573.  
  2574.        ----------------------------------------------------------------------
  2575.        Rev: August 11, 1990                                           Page 37
  2576.  
  2577.  
  2578.  
  2579.                            Inside TURBO Pascal 5.5 Units           
  2580.        ----------------------------------------------------------------------
  2581.  
  2582.        Almost every "type" in Pascal is actually derived from the basic types
  2583.                                                                               |
  2584.        that are  (in Turbo  Pascal) defined  in the  SYSTEM.TPU unit  -- e.g.
  2585.                                                                               |
  2586.        "INTEGER", "BYTE",  etc.  In addition, several of the Type Descriptors
  2587.                                                                               |
  2588.        in the  SYSTEM unit  are referenced by more than one Dictionary Entry.
  2589.                                                                               |
  2590.        Thus, we  find that  a "many-to-one"  relationship may  exist  between
  2591.                                                                               |
  2592.        Dictionary Entries  and Type Descriptors.  How does one find out which
  2593.                                                                               |
  2594.        is the entry that actually gave rise to the Type Descriptor?
  2595.                                                                               |
  2596.  
  2597.        The Dictionary  Area of  a unit  has some  special properties,  one of
  2598.                                                                               |
  2599.        which is  the fact  that the  Dictionary Entries  for named  Types are
  2600.                                                                               |
  2601.        often  located  quite  near  their  primary  type  descriptors.    The
  2602.                                                                               |
  2603.        Dictionary Area seems to be treated as an upward growing heap with the
  2604.                                                                               |
  2605.        various structures  being added  by Turbo  as needed.   This  makes it
  2606.                                                                               |
  2607.        likely that  the Type "Q" header which gives rise to a type descriptor
  2608.                                                                               |
  2609.        is quite likely to occur earlier in the Dictionary Area than any other
  2610.                                                                               |
  2611.        header which refers to the same descriptor.  We take advantage of this
  2612.                                                                               |
  2613.        property to allocate "ownership" but it may not be "fool-proof".  Some
  2614.                                                                               |
  2615.        type descriptors are spawned by other type descriptors, especially for
  2616.                                                                               |
  2617.        structured types.   We  don't attempt to allocate "ownership" to these
  2618.                                                                               |
  2619.        "lower-level" descriptors.
  2620.                                                                               |
  2621.  
  2622.  
  2623.  
  2624.        7.6.2 THE DISASSEMBLER
  2625.                                                                               |
  2626.  
  2627.  
  2628.        To start with, I apologize up front for mistakes which are bound to be
  2629.                                                                               |
  2630.        present in  this routine.   I  am not  a MASM or TASM programmer and I
  2631.                                                                               |
  2632.        will not  pretend otherwise.   This  being the  case, the formatting I
  2633.                                                                               |
  2634.        have chosen  for the operands may be erroneous or misleading and might
  2635.                                                                               |
  2636.        (if submitted  to one  of the  "real" assemblers)  produce object code
  2637.                                                                               |
  2638.        quite different  from what  is expected.   I  hope not,  but I have to
  2639.                                                                               |
  2640.        admit it's possible.
  2641.                                                                               |
  2642.  
  2643.        My intention  in adding  this unit was to permit tuning of object code
  2644.                                                                               |
  2645.        to be  made possible.   With practice and some effort, one can observe
  2646.                                                                               |
  2647.        the effect  on the  object module  caused by  specific Pascal  coding.
  2648.                                                                               |
  2649.        Thus, where  compactness is  an issue of paramount importance, TPUUNA1
  2650.                                                                               |
  2651.        can be  of help.   In some cases, a simple re-arrangement of the local
  2652.                                                                               |
  2653.        variable declarations  in a procedure can have a significant effect of
  2654.                                                                               |
  2655.        the size  of the  code if it means the difference between 1 and 2-byte
  2656.                                                                               |
  2657.        displacements for  each instruction  that references  a specific local
  2658.                                                                               |
  2659.        variable.   Potential  applications  along  these  lines  seem  almost
  2660.                                                                               |
  2661.        unlimited.
  2662.                                                                               |
  2663.  
  2664.  
  2665.  
  2666.  
  2667.  
  2668.  
  2669.  
  2670.  
  2671.  
  2672.  
  2673.  
  2674.  
  2675.        ----------------------------------------------------------------------
  2676.        Rev: August 11, 1990                                           Page 38
  2677.  
  2678.  
  2679.  
  2680.                            Inside TURBO Pascal 5.5 Units           
  2681.        ----------------------------------------------------------------------
  2682.  
  2683.        I adopted an operand format not unlike that of TASM "Ideal" mode since
  2684.                                                                               |
  2685.        it was  more convenient  to do  so and  looked more readable to me.  I
  2686.                                                                               |
  2687.        relied on  several reference books for guidance in decoding the entire
  2688.                                                                               |
  2689.        mess and  I found  that there were several flaws (read ERRORS) in some
  2690.                                                                               |
  2691.        of them  which made  the  job  that  much  more  difficult.    I  then
  2692.                                                                               |
  2693.        compounded my  problems  by  attempting  to  handle  80286  and  80386
  2694.                                                                               |
  2695.        specific code even though Turbo Pascal does not generate code specific
  2696.                                                                               |
  2697.        to these  processors.   I simply  felt that  the  effort  involved  in
  2698.                                                                               |
  2699.        writing any sort of Dis-Assembly program for Turbo Pascal units was an
  2700.                                                                               |
  2701.        effort best  experienced not  more than  once.   With all  this  self-
  2702.                                                                               |
  2703.        flagellation out of my system once and for all, I will try to show the
  2704.                                                                               |
  2705.        basic strategy  of the program and to explain the limitations and some
  2706.                                                                               |
  2707.        of the discoveries I made.
  2708.                                                                               |
  2709.  
  2710.        The routine  is intended  to be  idiotically simple - i.e., no smarter
  2711.                                                                               |
  2712.        than the  DEBUG command  in principle.   The basic idea is:  pass some
  2713.                                                                               |
  2714.        text to  the routine and get back ONE line derived from some prefix of
  2715.                                                                               |
  2716.        that text.   Repeat  as necessary until all text is gone.  Thus, there
  2717.                                                                               |
  2718.        is no attempt to check the context of the text being processed.  Also,
  2719.                                                                               |
  2720.        some configurations  of the  "modR/M" byte  may invalid  for  selected
  2721.                                                                               |
  2722.        instructions.  I don't try to screen these out since the intent was to
  2723.                                                                               |
  2724.        look at  the presumably  correct code  produced by TURBO Pascal -- not
  2725.                                                                               |
  2726.        devious assembly language.  Also, this program regards WAIT operations
  2727.                                                                               |
  2728.        as "stand-alone"  -- i.e.,  it doesn't  check to  see if a coprocessor
  2729.                                                                               |
  2730.        operation follows for which the WAIT might be regarded as a prefix.
  2731.                                                                               |
  2732.  
  2733.        One area  of real  difficulty  was  figuring  out  the  Floating-Point
  2734.                                                                               |
  2735.        emulations used  by Turbo  Pascal that  are implemented  by  means  of
  2736.                                                                               |
  2737.        interrupts $34  through $3D.   I don't know if I got it right, but the
  2738.                                                                               |
  2739.        results seem reasonable and consistent.  In the listing, the Interrupt
  2740.                                                                               |
  2741.        is produced  on one line, followed by its parameters on the next line.
  2742.                                                                               |
  2743.        The parameter line is given the op-code "EMU_xxxx" where "xxxx" is the
  2744.                                                                               |
  2745.        coprocessor op-code  I felt  was being  emulated.  Interrupt $3C was a
  2746.                                                                               |
  2747.        real puzzler  but after  seeing a lot of code in context, I think that
  2748.                                                                               |
  2749.        the segment  override is  communicated to the emulator by means of the
  2750.                                                                               |
  2751.        first byte after the $3C.
  2752.                                                                               |
  2753.  
  2754.        Normally, in  a non-emulator  environment, all  coprocessor operations
  2755.                                                                               |
  2756.        (ignoring any  WAIT prefixes)  begin with  $D8-$DF.  What Borland (and
  2757.                                                                               |
  2758.        maybe Microsoft)  seem to  have done  here is to change the $D8-$DF so
  2759.                                                                               |
  2760.        that bits  7 and 6 of this byte are replaced with the one's complement
  2761.                                                                               |
  2762.        of  the   2-bit  segment   register  number   found  in  various  8086
  2763.                                                                               |
  2764.        instructions.  This seems to be how an override for the DS register is
  2765.                                                                               |
  2766.        passed to  the emulator.    I  don't  KNOW  this  to  be  the  correct
  2767.                                                                               |
  2768.        interpretation, but  the code I have examined in context seems to work
  2769.                                                                               |
  2770.        under this  scheme,  so  TPUUNA  uses  it  to  interpret  the  operand
  2771.                                                                               |
  2772.        accordingly.
  2773.                                                                               |
  2774.  
  2775.        For 80x86  machines, the problem was somewhat simpler.  TPUUNA takes a
  2776.                                                                               |
  2777.        quick look at the first byte of the text.  Almost any byte is valid as
  2778.                                                                               |
  2779.        the initial byte of an instruction, but some instructions require more
  2780.                                                                               |
  2781.        than one  byte to  hold the  complete operation  code.   Thus, step  1
  2782.                                                                               |
  2783.        classifies bytes in several ways that lead to efficient recognition of
  2784.                                                                               |
  2785.        valid operation codes.
  2786.                                                                               |
  2787.  
  2788.  
  2789.        ----------------------------------------------------------------------
  2790.        Rev: August 11, 1990                                           Page 39
  2791.  
  2792.  
  2793.  
  2794.                            Inside TURBO Pascal 5.5 Units           
  2795.        ----------------------------------------------------------------------
  2796.  
  2797.        Once the  instruction has  been identified  in this way, it is more or
  2798.                                                                               |
  2799.        less easy  to link  to supplemental  information that provides operand
  2800.                                                                               |
  2801.        editing guidance, etc.
  2802.                                                                               |
  2803.  
  2804.        The tables  that embody  the recognition scheme were constructed using
  2805.                                                                               |
  2806.        PARADOX 3.0  (another fine Borland product) and suitably coded queries
  2807.                                                                               |
  2808.        were used to generate the actual Turbo Pascal code for compilation.
  2809.                                                                               |
  2810.  
  2811.        For those  that are  interested, TPUUNA  supports the address-size and
  2812.                                                                               |
  2813.        operand-size prefixes  of the  80386 as  well as  32-bit operands  and
  2814.                                                                               |
  2815.        addresses but  remember that  Turbo Pascal  doesn't generate these.  A
  2816.                                                                               |
  2817.        trivial change  is provided for which allows segments which default to
  2818.                                                                               |
  2819.        32-bit mode to be handled as well.
  2820.                                                                               |
  2821.  
  2822.        There is  a simple  mode variable  that gets  passed to  TPUUNA by its
  2823.                                                                               |
  2824.        caller which  specifies the most-capable processor whose code is to be
  2825.                                                                               |
  2826.        handled.   Codes are  provided for  the 8086 (8088 is the same), 80186
  2827.                                                                               |
  2828.        (same as  80286 except  no protected  mode instructions), 80286 (80186
  2829.                                                                               |
  2830.        plus protected mode operation), and 80386.
  2831.                                                                               |
  2832.  
  2833.        No such  specifier is provided for coprocessor support.  What is there
  2834.                                                                               |
  2835.        is what  I think an 80387 supports.  I don't think that this is really
  2836.                                                                               |
  2837.        a problem if you don't try to use TPUUNA for anything but Turbo Pascal
  2838.                                                                               |
  2839.        code.
  2840.                                                                               |
  2841.  
  2842.        Error recovery is predictably simple.  The initial text byte is output
  2843.                                                                               |
  2844.        as the  operand of a DB pseudo-op and provision is made to resume work
  2845.                                                                               |
  2846.        at the next byte of text.
  2847.                                                                               |
  2848.  
  2849.        I hope  this program  is found  to be useful in spite of the errors it
  2850.                                                                               |
  2851.        must surely  contain.   I have yet to make much sense of the rules for
  2852.                                                                               |
  2853.        MASM or  TASM operand  coding and I found very little of value in many
  2854.                                                                               |
  2855.        of the  so-called "texts"  on the  subject.   I found  myself  in  the
  2856.                                                                               |
  2857.        position of  that legendary  American  watching  a  Cricket  match  in
  2858.                                                                               |
  2859.        England for the first time ("You mean it has RULES?").
  2860.                                                                               |
  2861.  
  2862.  
  2863.  
  2864.  
  2865.  
  2866.  
  2867.  
  2868.  
  2869.  
  2870.  
  2871.  
  2872.  
  2873.  
  2874.  
  2875.  
  2876.  
  2877.  
  2878.  
  2879.  
  2880.  
  2881.  
  2882.        ----------------------------------------------------------------------
  2883.        Rev: August 11, 1990                                           Page 40
  2884.  
  2885.  
  2886.  
  2887.                            Inside TURBO Pascal 5.5 Units           
  2888.        ----------------------------------------------------------------------
  2889.  
  2890.        8. UNIT LIBRARIES
  2891.  
  2892.  
  2893.        This author  has examined  .TPL files  in passing  and concludes  that
  2894.        their structure is trivial in the extreme.  The following notes should
  2895.        be of some help.
  2896.  
  2897.  
  2898.  
  2899.        8.1 LIBRARY STRUCTURE
  2900.  
  2901.  
  2902.        A Turbo  Pascal Library  (.TPL) file appears to be a simple catenation
  2903.        of Turbo  Pascal Unit (.TPU) files.  Since the length of a Unit may be
  2904.        determined from the Unit Header (see section 3.2), it is simple to see
  2905.        that one may "browse" through a .TPL file looking for an external unit
  2906.        such as  SYSTEM.TPU.   If this seems to be too much effort, then there
  2907.        is always the TPUMOVER Utility program supplied by Borland.
  2908.  
  2909.  
  2910.  
  2911.        8.2 THE TPUMOVER UTILITY
  2912.  
  2913.  
  2914.        Quite simply, this Utility allows one to extract units from .TPL files
  2915.        in order  to subject  them to the analysis performed by TPUMAIN.  Read
  2916.        your Turbo  Pascal User's  Guide for instructions on the operation and
  2917.        use of this utility.
  2918.  
  2919.  
  2920.  
  2921.        9. APPLICATION NOTES
  2922.  
  2923.  
  2924.        One of the more obvious applications of this information would seem to
  2925.        be in the area of a Cross-Reference Generator.
  2926.  
  2927.        There is  a very  fine example  of such a program in the public domain
  2928.        that was  written by  Mr. R. N. Wisan called  "PXL".  This program has
  2929.        been around since the days of Turbo Pascal Version 1.  The program has
  2930.        been continually enhanced by the author in the way of features and for
  2931.        support of the newer Turbo Pascal versions.  It does not however solve
  2932.        the problem  of telling  one which  unit contains  the definition of a
  2933.        given symbol.   In fairness to "PXL" however, this is no small problem
  2934.        since the  format of  .TPU files  keeps changing  (Turbo 5.5 Units are
  2935.        not object-code  compatible with  Turbo 5.0  Units, and  so on...) and
  2936.        Mr. Wisan probably has more than enough other projects to keep himself
  2937.        occupied.
  2938.  
  2939.        However, for  the user who is willing to work a little (maybe a lot?),
  2940.        this document would seem to provide the information needed to add such
  2941.        a function to his own pet cross-reference generator.
  2942.  
  2943.  
  2944.  
  2945.  
  2946.        ----------------------------------------------------------------------
  2947.        Rev: August 11, 1990                                           Page 41
  2948.  
  2949.  
  2950.  
  2951.                            Inside TURBO Pascal 5.5 Units           
  2952.        ----------------------------------------------------------------------
  2953.  
  2954.        10. ACKNOWLEDGEMENTS
  2955.  
  2956.  
  2957.        This project  would have  been totally  infeasible without  the aid of
  2958.        some very  fine tools.  As it was, several hundred man hours have been
  2959.        expended on  it and  as you can see, there are a few unresolved issues
  2960.        that have  been (graciously)  left for  others to  address.  The tools
  2961.        used by this author consisted of:
  2962.  
  2963.        1)    Turbo Pascal 5.5 Professional by Borland International
  2964.  
  2965.        2)    Microsoft WORD (version 5.0)
  2966.  
  2967.        3)    LIST (version 6.4a) by Vernon D. Buerg
  2968.  
  2969.        4)    the DEBUG utility in MS-DOS Version 3.3.
  2970.  
  2971.        5)    PARADOX 3.0 by Borland International
  2972.                                                                               |
  2973.  
  2974.        6)    QUATTRO PRO by Borland International
  2975.                                                                               |
  2976.  
  2977.        7)    TURBO ASSEMBLER 1.1 by Borland International
  2978.                                                                               |
  2979.  
  2980.        (PARADOX and QUATTRO PRO were used for data collection and analysis in
  2981.                                                                               |
  2982.        the course of coding the recognizer tables for the disassembler unit.)
  2983.                                                                               |
  2984.  
  2985.        The references  listed were of great value in this project.  [Intel85]
  2986.                                                                               |
  2987.        was a valuable source of information about coprocessor instructions as
  2988.                                                                               |
  2989.        well as offering hints about the differences between the 8086/8088 and
  2990.                                                                               |
  2991.        the 80286.   The  [Borland] TASM  manuals offered  further info on the
  2992.                                                                               |
  2993.        80186.     [Nelson]  provided  presentations  of  well-organized  data
  2994.                                                                               |
  2995.        directed at the problem of disassembly but the tables were flawed by a
  2996.                                                                               |
  2997.        number of  errors which  crept into my databases and which caused much
  2998.                                                                               |
  2999.        of the extra debugging effort.  [Intel89] offered valuable insights on
  3000.                                                                               |
  3001.        the 80386  addressing schemes  as well  as the 32-bit data extensions.
  3002.                                                                               |
  3003.        Finally,  [Brown]   provided  valuable  clues  on  the  Floating-Point
  3004.                                                                               |
  3005.        emulators used  by Borland  (and Microsoft?).   As  you can  see,  the
  3006.                                                                               |
  3007.        amount of  hard information  available to me on this project was quite
  3008.                                                                               |
  3009.        limited since I am unaware of any other existing body of literature on
  3010.                                                                               |
  3011.        this subject.
  3012.                                                                               |
  3013.  
  3014.        That's it  folks.   Does anyone wonder why it took several hundred man
  3015.        hours to  get to  this point?   It  took a  lot of  hard (and at times
  3016.        tedious) work  coupled with a great many lucky guesses to achieve what
  3017.        you see here.
  3018.  
  3019.  
  3020.  
  3021.  
  3022.  
  3023.  
  3024.  
  3025.  
  3026.  
  3027.  
  3028.  
  3029.        ----------------------------------------------------------------------
  3030.        Rev: August 11, 1990                                           Page 42
  3031.  
  3032.  
  3033.  
  3034.                            Inside TURBO Pascal 5.5 Units           
  3035.        ----------------------------------------------------------------------
  3036.  
  3037.        11. REFERENCES
  3038.  
  3039.  
  3040.        [Bor88a],  TURBO ASSEMBLER  REFERENCE  GUIDE,  Borland  International,
  3041.                                                                               |
  3042.                   1988.
  3043.                                                                               |
  3044.  
  3045.        [Bor88b],  TURBO ASSEMBLER USER'S GUIDE, Borland International, 1988.
  3046.                                                                               |
  3047.  
  3048.        [Bor88c],  TURBO  PASCAL   REFERENCE  GUIDE   Version   5.0,   Borland
  3049.                                                                               |
  3050.                   International, 1988.
  3051.                                                                               |
  3052.  
  3053.        [Bor88d],  TURBO   PASCAL    USER'S   GUIDE   Version   5.0,   Borland
  3054.                                                                               |
  3055.                   International, 1988.
  3056.                                                                               |
  3057.  
  3058.        [Bor89],   TURBO PASCAL 5.5 OBJECT-ORIENTED PROGRAMMING GUIDE, Borland
  3059.                                                                               |
  3060.                   International, 1989.
  3061.                                                                               |
  3062.  
  3063.        [Brown],   INTER489.ARC, Ralf Brown, 1989
  3064.                                                                               |
  3065.  
  3066.        [Intel85], iAPX 286  PROGRAMMER'S REFERENCE  MANUAL INCLUDING THE iAPX
  3067.                                                                               |
  3068.                   286 NUMERIC  SUPPLEMENT, Intel  Corporation,  1985,  (order
  3069.                                                                               |
  3070.                   number 210498-003).
  3071.                                                                               |
  3072.  
  3073.        [Intel89], 386  SX MICROPROCESSOR PROGRAMMER'S REFERENCE MANUAL, Intel
  3074.                                                                               |
  3075.                   Corporation, 1989, (order number 240331-001).
  3076.                                                                               |
  3077.  
  3078.        [Nelson],  THE 80386  BOOK:   ASSEMBLY LANGUAGE PROGRAMMER'S GUIDE FOR
  3079.                                                                               |
  3080.                   THE 80386, Ross P. Nelson, Microsoft Press, 1988.
  3081.                                                                               |
  3082.  
  3083.        [Scanlon], 80286  ASSEMBLY   LANGUAGE  ON  MS-DOS  COMPUTERS,  Leo  J.
  3084.                                                                               |
  3085.                   Scanlon, Brady 1986.
  3086.                                                                               |
  3087.  
  3088.  
  3089.  
  3090.  
  3091.  
  3092.  
  3093.  
  3094.  
  3095.  
  3096.  
  3097.  
  3098.  
  3099.  
  3100.  
  3101.  
  3102.  
  3103.  
  3104.  
  3105.  
  3106.  
  3107.  
  3108.  
  3109.  
  3110.  
  3111.  
  3112.        ----------------------------------------------------------------------
  3113.        Rev: August 11, 1990                                           Page 43