1
(*******************************************************************
5
* This unit is only used by the debugger.
7
* Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg
9
* This file is part of the FreeType project, and may only be used
10
* modified and distributed under the terms of the FreeType project
11
* license, LICENSE.TXT. By continuing to use, modify or distribute
12
* this file you indicate that you have read the license and
13
* understand and accept it fully.
15
******************************************************************)
21
uses TTTypes, TTTables, TTObjs, TTInterp;
25
ByteHexStr = string[2]; (* hex representation of a byte *)
26
ShortHexStr = string[4]; (* " " " short *)
27
LongHexStr = string[8]; (* " " " long *)
28
DebugStr = string[128]; (* disassembled line output *)
32
{ A simple record to hold breakpoint information }
33
{ it may be completed later with pass count, etc.. }
34
{ They must be in a sorted linked list }
36
PBreakPoint = ^TBreakPoint;
45
{ a record to store line number information and breakpoints list }
47
PRangeRec = ^TRangeRec;
53
Disassembled : PUShort;
58
{ Generate_Range : Generate Line Number information specific to }
61
procedure Generate_Range( CR : PCodeRange;
65
{ Throw_Range : Discard Line Number Information }
67
procedure Throw_Range( var RR : TRangeRec );
69
{ Toggle_Break : Toggle a breakpoint }
71
procedure Toggle_Break( var Head : PBreakPoint; Range, Adr : Int );
73
{ Set_Break : Set a breakpoint on a given address }
75
procedure Set_Break ( var Head : PBreakPoint; Range, Adr : Int );
77
{ Clear_Break : Clear one specific breakpoint }
79
procedure Clear_Break( var Head : PBreakPoint; Bp : PBreakPoint );
81
{ Clear_All_Breaks : Clear breakpoint list }
83
procedure Clear_All_Breaks( var Head : PBreakPoint );
85
{ Find_Breakpoint : find one breakpoint at a given address }
87
function Find_BreakPoint( Head : PBreakPoint; Range, IP : Int ) : PBreakPoint;
89
{ Cur_U_Line : returns the current disassembled line at Code(IP) }
91
function Cur_U_Line( Code : PByte; IP : Int ) : DebugStr;
93
{ Get_Length : returns the length of the current opcode at Code(IP) }
95
function Get_Length( Code : PByte; IP : Int ) : Int;
97
function Get_Dis_Line( var cr : TRangeRec; addr : Int ) : Int;
100
{ Hex_N : returns an hexadecimal string }
102
function Hex8 ( B : Byte ) : ByteHexStr;
103
function Hex16( W : word ) : ShortHexStr;
104
function Hex32( L : Long ) : LongHexStr;
110
PStorageLong = ^TStorageLong;
111
TStorageLong = record (* do-it-all union record type *)
114
1 : ( S1, S2 : Integer );
115
2 : ( W1, W2 : Word );
125
OpStr : array[ 0..255 ] of String[10]
127
'SVTCA y', (* Set vectors to coordinate axis y *)
128
'SVTCA x', (* Set vectors to coordinate axis x *)
129
'SPvTCA y', (* Set Proj. vec. to coord. axis y *)
130
'SPvTCA x', (* Set Proj. vec. to coord. axis x *)
131
'SFvTCA y', (* Set Free. vec. to coord. axis y *)
132
'SFvTCA x', (* Set Free. vec. to coord. axis x *)
133
'SPvTL //', (* Set Proj. vec. parallel to segment *)
134
'SPvTL +', (* Set Proj. vec. normal to segment *)
135
'SFvTL //', (* Set Free. vec. parallel to segment *)
136
'SFvTL +', (* Set Free. vec. normal to segment *)
137
'SPvFS', (* Set Proj. vec. from stack *)
138
'SFvFS', (* Set Free. vec. from stack *)
139
'GPV', (* Get projection vector *)
140
'GFV', (* Get freedom vector *)
141
'SFvTPv', (* Set free. vec. to proj. vec. *)
142
'ISECT', (* compute intersection *)
144
'SRP0', (* Set reference point 0 *)
145
'SRP1', (* Set reference point 1 *)
146
'SRP2', (* Set reference point 2 *)
147
'SZP0', (* Set Zone Pointer 0 *)
148
'SZP1', (* Set Zone Pointer 1 *)
149
'SZP2', (* Set Zone Pointer 2 *)
150
'SZPS', (* Set all zone pointers *)
151
'SLOOP', (* Set loop counter *)
152
'RTG', (* Round to Grid *)
153
'RTHG', (* Round to Half-Grid *)
154
'SMD', (* Set Minimum Distance *)
156
'JMPR', (* Jump Relative *)
157
'SCvTCi', (* Set CVT *)
401
HexStr : string[16] = '0123456789abcdef';
403
(*******************************************************************
407
* Description : Returns the string hexadecimal representation
412
* Output : two-chars string
414
*****************************************************************)
416
function Hex8( B : Byte ) : ByteHexStr;
421
S[1] := HexStr[ 1+( B shr 4 ) ];
422
S[2] := HexStr[ 1+( B and 15 )];
426
(*******************************************************************
430
* Description : Returns the string hexadecimal representation
435
* Output : four-chars string
437
*****************************************************************)
439
function Hex16( W : word ) : ShortHexStr;
441
Hex16 := Hex8( Hi(w) )+Hex8( Lo(w) );
444
(*******************************************************************
448
* Description : Returns the string hexadecimal representation
453
* Output : eight-chars string
455
*****************************************************************)
457
function Hex32( L : Long ) : LongHexStr;
459
Hex32 := Hex16( TStorageLong(L).W2 )+Hex16( TStorageLong(L).W1 );
462
(*******************************************************************
464
* Function : Cur_U_Line
466
* Description : Returns a string of the current unassembled
469
* Input : Code base code range
470
* IP current instruction pointer
472
* Output : line string
474
*****************************************************************)
476
function Cur_U_Line( Code : PByte; IP : Int ) : DebugStr;
484
S := Hex16(IP)+': '+Hex8(Op)+' '+OpStr[Op];
490
S := S+'('+Hex8(n)+')';
492
S := S+' $'+Hex8( Code^[Ip+i+1] );
497
S := S+'('+Hex8(n)+')';
499
S := S+' $'+Hex8( Code^[Ip+i*2+1] )+Hex8( Code^[Ip+i*2+2] );
505
S := S+' $'+Hex8( Code^[Ip+i+1] );
511
S := S+' $'+Hex8( Code^[IP+i*2+1] )+Hex8( Code^[Ip+i*2+2] );
519
(*******************************************************************
521
* Function : Get_Length
523
* Description : Returns the length in bytes of the instruction at
524
* current instruction pointer.
526
* Input : Code base code range
527
* IP current instruction pointer
529
* Output : Length in bytes
531
*****************************************************************)
533
function Get_Length( Code : PByte; IP : Int ) : Int;
543
$40 : N := 2 + Code^[IP+1];
544
$41 : N := 2 + Code^[IP+1]*2;
546
$B0..$B7 : N := 2 + ( Op-$B0 );
547
$B8..$BF : N := 3 + ( Op-$B8 )*2
557
(*******************************************************************
559
* Function : Generate_Range
561
* Description : Create a list of unassembled lines for a
568
*****************************************************************)
570
procedure Generate_Range( CR : PCodeRange;
572
var RR : TRangeRec );
580
RR.Code := PByte( CR^.Base );
588
GetMem( RR.Disassembled, sizeof(Short) * N );
592
RR.Disassembled^[Line] := Adr;
594
inc( Adr, Get_Length( RR.Code, Adr ));
603
(*******************************************************************
605
* Function : Get_Dis_Line
607
* Description : Returns the line index of address 'addr'
608
* in the coderange 'cr'
610
*****************************************************************)
612
function Get_Dis_Line( var cr : TRangeRec; addr : Int ) : Int;
616
if (cr.NLines = 0) or
617
(addr > cr.Disassembled^[cr.Nlines-1] ) then
628
if cr.Disassembled^[l] = addr then
634
if cr.Disassembled^[r] = addr then
641
if cr.Disassembled^[m] = addr then
647
if cr.Disassembled^[m] < addr then
653
if cr.Disassembled^[r] = addr then
663
(*******************************************************************
665
* Function : Throw_Range
667
* Description : Destroys a list of unassembled lines for a
674
*****************************************************************)
676
procedure Throw_Range( var RR : TRangeRec );
678
B, Bnext : PBreakPoint;
682
FreeMem( RR.Disassembled, RR.Size * sizeof(Short) );
684
RR.Disassembled := nil;
700
(*******************************************************************
702
* Function : Set_Break
704
* Description : Sets a Breakpoint ON
710
*****************************************************************)
712
procedure Set_Break( var Head : PBreakPoint;
723
while (Cur <> nil) and (Cur^.Address < Adr) do
731
if (Cur^.Address = Adr) and (Cur^.Range = Range) then exit;
744
(*******************************************************************
746
* Function : Clear_Break
748
* Description : Clears a breakpoint OFF
754
*****************************************************************)
756
procedure Clear_Break( var Head : PBreakPoint; Bp : PBreakPoint );
764
while (Cur <> nil) and (Cur <> Bp) do
770
if Cur = nil then exit;
775
Old^.Next := Cur^.Next;
780
procedure Toggle_Break( var Head : PBreakPoint; Range, Adr : Int );
784
Bp := Find_BreakPoint( Head, Range, Adr );
785
if Bp <> nil then Clear_Break( Head, Bp )
786
else Set_Break( Head, Range, Adr );
789
(*******************************************************************
791
* Function : Clear_All_Breaks
793
* Description : Clears all breakpoints
799
*****************************************************************)
801
procedure Clear_All_Breaks( var Head : PBreakPoint );
817
(*******************************************************************
819
* Function : Find_BreakPoint
821
* Description : Find a breakpoint at address IP
823
* Input : Head break points sorted linked list
824
* IP address of expected breakpoint
826
* Output : pointer to breakpoint if found
829
*****************************************************************)
831
function Find_BreakPoint( Head : PBreakPoint; Range, IP : Int ) : PBreakPoint;
841
if (Cur^.Address = IP ) and
842
(Cur^.Range = Range) then Res := Cur;
844
if (Cur^.Address >= IP) then Cur := nil
845
else Cur := Cur^.Next;
848
Find_BreakPoint := Res;