Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
utilities/pcsymb.mac
There are no other files named pcsymb.mac in the archive.
;<BEEBE.UTILITY>PCSYMB.MAC.18, 7-May-84 13:32:15, Edit by BEEBE
; [NHFB0031] If no symbol found, do not update SYMLST (SYMRET-1)
TITLE PCSYMB - Symbol Table Lookup Routine for PCLOOK
SEARCH MONSYM,MACSYM
SALL
.REQUIRE SYS:MACREL
.REQUEST SYS:FORLIB
ENTRY PCSYMB
COMMENT \
This routine accepts a numeric address and searches the symbol table of
the job or fork being watched and returns an ASCIZ string of the form
"modulename_closestsymbolname+offset<NUL>"
giving the name of the module in which the address is contained and the
offset from the closest symbol. It has been shamelessly lifted from
Ralph Gorin's excellent book "Introduction to DECSYSTEM-20 Assembly
Language Programming", Digital Press, Bedford, MA (1981), p. 424.
Gorin's version returned the closest symbol at or preceding the search
address, even if it was not inside the module. This version requires
the symbol to have a value at least as large as the module address.
It is used as follows:
CALL PCSYMB (ADDRESS, !address to find symbol for
X SYMPTR, !symbol table pointer (-count,,firstaddress)
X SYMSTRING, !symbol name area (returned)
X STRLEN, !symbol length (returned)
X SYMLST) !last module index (returned)
with the usual FORTRAN calling conventions for the argument list. The
SYMPTR argument is normally the contents of location .JBSYM (=116), and
this will be assumed if it is 0, but it can be set to any desired value.
It has the form of -count,,begadr, where begadr is the beginning address
of the symbol table in memory containing count/2 symbols. The table
grows downward in memory from location begadr+count-1.
The symbol table consists of word pairs of the form
0 3 4 35
|-----------------------|
n | Flags | RADIX-50 name |
|-----------------------|
n+1 | 36-bit symbol value |
| or if Flags = 00, LH =|
| negative length of |
| symbol table for |
| module, RH = first |
| address of code for |
| module |
|-----------------------|
The 4-bit flags are as follows:
00 Program name definition
04 Global symbol definition
10 Local symbol definition (different modules may have different
local symbols with the same name)
14 Block name (used by Algol, FAIL, SAIL, etc.)
44 Suppressed global definition. Like type 04, but DDT will not
use it in symbolic typeout.
50 Suppressed local definition. Like type 10, but DDT will not
use it in symbolic typeout.
Recent versions of TOPS-20 define the following new entries (found in
LNKOLD.MAC):
30 Global left half deferred symbol definition
34 Global both halves deferred symbol definition
70 Global left half deferred DDT suppressed symbol definition
74 Global both halves deferred DDT suppressed symbol definition
These are intended to replace the 44 and 64 codes for these functions.
The 44 and 64 blocks will mean:
44 Global DDT suppressed definition, not deferred
64 Global right half deferred DDT suppressed symbol definition
The fourth argument, STRLEN, is set on return to the number of
characters stored in the output string, SYMSTRING.
Although the symbol table is ordered by module, with the first loaded at
the top of memory, local symbols within the module can have any order.
A binary search is therefore not feasible except on module names. The
search is therefore sequential, but the index of the last module found
for which a symbol was accepted is returned in SYMLST and if non-zero on
entry, it will be used to restart the search for a new address value
which is assumed to be not less than the preceding one. If no symbol is
found, SYMLST is left unchanged. SYMLST will automatically be reset to
start the search at the top if the indexed module address is larger than
the search address.
For convenience of assembly-language callers, all registers are preserved.
\
A==1 ; Gorin's register
B==2 ; definitions A..E
C==3
D==4
E==5
Argptr==16
P==17
.JBSYM==116
MINOFF==10000 ; minimum acceptable offset
XVAL: 0
BPROG: 0
BSYM: 0
LINPTR: 0
INIPTR: 0
SIXBIT /PCSYMB/ ; Name for FORTRAN traceback
PCSYMB: ; entry point of symbol table
; lookup routine.
PUSH P,A ; Save registers A..E
PUSH P,B
PUSH P,C
PUSH P,D
PUSH P,E
MOVE A,@0(Argptr) ; Get numeric address
MOVEM A,XVAL ; Save it locally
MOVE A,2(Argptr) ; A(output string)
HLL A,[POINT 7,0]
MOVEM A,LINPTR ; Byte pointer to output string
SETZB C,BPROG ; No best program name yet
SETZM BSYM ; No best symbol
SKIPN D,@1(Argptr) ; SYMPTR = (-count,,first address)
MOVE D,.JBSYM ; SYMPTR = 0, so get default one
SETZM B ; SYMLEN = 0 initially
SKIPN D ; SYMPTR = 0?
JRST SYMRET ; Yes, symbols unavailable so quit.
HLRO A,D ; whole word copy of -count
SUB D,A ; -count,,ending address+1
MOVEM D,INIPTR ; save loop count
SKIPN D,@4(Argptr) ; Get SYMLST from caller
JRST SYMLK0 ; Start from beginning if SYMLST = 0
LDB A,[POINT 4,-2(D),3] ;Symbol type
SKIPE A ; Program name symbol?
JRST SYMLK0 ; No, start from beginning
HRRZ B,-1(D) ; -size,,symbol value
CAMGE B,XVAL ; Is search address in or after this module?
JRST SYMLK1 ; Yes, use previous index.
SYMLK0: MOVE D,INIPTR ; restore loop count
SYMLK1: LDB A,[POINT 4,-2(D),3] ;Symbol type
CAILE A,2 ; 0=program name, 1=global, 2=local
JRST SYMLK2 ; none of the kind we want
JUMPE A,SYML1Z ; this is a program name
MOVE A,-1(D) ; this is the value of the symbol
CAMN A,XVAL ; is this an exact match?
JRST SYML2A ; yes, select it. Leave loop
CAML A,XVAL ; is this smaller than value sought?
JRST SYMLK2 ; no. too large
SKIPN B,BSYM ; get best one so far
JRST SYML1A ; no previous best, remember this one
CAMG A,-1(B) ; compare to previous best
JRST SYMLK2 ; previous best was better
SYML1A: HRRZ A,-1(D) ; current symbol is best match so far
HRRZ E,-1(C) ; get symbol value and program value
CAMGE A,E ; symbol inside program?
JRST SYMLK2 ; no, do not save it.
MOVEM D,BSYM ;
MOVEM C,BPROG ; save it and look for a better one
JRST SYMLK2
SYML1Z: MOVE C,D ; save pointer to current program name
SYMLK2: ADD D,[2000000-2] ; add 2 in the left, sub 2 in the right
JUMPL D,SYMLK1
JRST SYMLK3
SYML2A: HRRZ A,-1(D) ; Here for an exact match.
HRRZ E,-1(C) ; get symbol value and program value
CAMGE A,E ; symbol inside program?
JRST SYMLK3 ; no, do not save it.
MOVEM D,BSYM ;
MOVEM C,BPROG ; Save values of C and D
SYMLK3: SKIPN D,BSYM ; did we find anything helpful?
JRST SYMDON ; no
MOVE A,XVAL ; desired value
SUB A,-1(D) ; less symbol's value = offset
CAIL A,MINOFF ; is offset small enough?
JRST SYMDON ; no, not a good enough match
MOVE D,BPROG ; pointer to the program name
MOVE A,-2(D) ; get the program name
CALL R50DOP ; copy program name to output string
MOVEI A, "_" ; add an underscore after the name
IDPB A,LINPTR
MOVE D,BSYM ; get the symbol's address
MOVE A,-2(D) ; symbol name
CALL R50DOP ; copy symbol name
MOVE B,XVAL ; desired value
SUB B,-1(D) ; less symbol's value = offset
JUMPE B,SYMDON ; if no offset, don't print "+0"
MOVE A,LINPTR ; destination
MOVX C,<NO%SGN!FLD(^D8,NO%RDX)>
NOUT% ; append "+offset" to string
ERJMP .+1 ; ignore error
MOVEM A,LINPTR ; store updated pointer to line
SYMDON: MOVEI A,.CHNUL
IDPB A,LINPTR ; insert trailing NUL
MOVE A,2(Argptr) ; A(output string)
HLL A,[POINT 7,0]
MOVEM A,LINPTR ; Byte pointer to output string
SETZ B,0 ; Zero byte count.
SYMCTB: ILDB A,LINPTR ; Pick up a byte
SKIPE A ; Skip out when NUL reached
AOJA B,SYMCTB ; Increment byte count and loop
MOVE A,BPROG
CAIE B,0 ; [NHFB0031] If no symbol, no SYMLST update
MOVEM A,@4(Argptr) ; Save module index
SYMRET: MOVEM B,@3(Argptr) ; Store string length
POP P,E ; restore A..E
POP P,D
POP P,C
POP P,B
POP P,A
RET ; return to caller
;
; Radix50 output routine. At entry, A = Radix50 symbol. At
; exit, the symbol has been converted to ASCII and appended
; to the string pointed to by LINPTR. Registers A..B are
; destroyed.
;
R50DOP: TLZ A,740000 ; clear any symbol flags
R50DP1: IDIVI A,50 ; divide by 50
PUSH P,B ; save remainder, a character
SKIPE A ; if A is now zero, unwind
; the stack
CALL R50DP1 ; call self again, reduce A
POP P,A ; pop one Radix50-coded character
ADJBP A,[POINT 7,R50TAB,6] ;convert Radix50 code to
; byte pointer
LDB A,A ; get ASCII decode of Radix50 character
IDPB A,LINPTR ; store ASCII in string
RET ; return to caller
R50TAB: ASCII / 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.$%/
END