SparcSymbolsImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
written by Ch. Le Cocq, September 15, 1988
Christian Le Cocq September 21, 1988 11:17:56 am PDT
Understands the symbol information of the sparc executables.
DIRECTORY
Basics USING [Card32FromF, CompareCard, FWORD],
IO,
RedBlackTree,
Rope,
SparcSymbols;
SparcSymbolsImpl: CEDAR PROGRAM
IMPORTS Basics, IO, RedBlackTree, Rope
EXPORTS SparcSymbols
~ BEGIN
Tables: TYPE ~ SparcSymbols.Tables;
Symbol: TYPE ~ REF SymbolRec;
SymbolRec: TYPE ~ RECORD[
txt: Rope.ROPENIL,
type: Basics.FWORD ← [[0, 0], [0, 0]],
val: CARD32 ← 0
];
Symbols Input
GetUnsigned: PROC [s: IO.STREAM] RETURNS [u: CARD32] ~ {
RETURN[Basics.Card32FromF[IO.GetFWord[s]]];
};
GetLocAndSize: PROC [s: IO.STREAM] RETURNS [off, size: INT] ~ {
text, data, trsize, drsize: CARD32;
[] ← GetUnsigned[s]; --machine flags etc
text ← GetUnsigned[s];
data ← GetUnsigned[s];
[] ← GetUnsigned[s]; --bss not actually present in the file
size ← GetUnsigned[s];
[] ← GetUnsigned[s]; --entry point: don't care
trsize ← GetUnsigned[s];
drsize ← GetUnsigned[s];
off ← text+data+trsize+drsize;
};
StopOnZero: IO.BreakProc ~ {RETURN[IF char='\000 THEN break ELSE other]};
GetOneSymbol: PROC [s: IO.STREAM, strOff: INT] RETURNS [sym: Symbol] ~ {
index: INT;
txtOff: INT ← GetUnsigned[s];
sym ← NEW[SymbolRec];
sym.type ← IO.GetFWord[s];
sym.val ← GetUnsigned[s];
index ← IO.GetIndex[s];
IF txtOff=0 THEN RETURN;
IO.SetIndex[s, strOff+txtOff];
sym.txt ← IO.GetTokenRope[stream: s, breakProc: StopOnZero].token;
IO.SetIndex[s, index];
};
XtractAddr: RedBlackTree.GetKey ~ {RETURN[data]};
XtractName: RedBlackTree.GetKey ~ {RETURN[NARROW[data, Symbol].txt]};
CompareAddr: RedBlackTree.Compare ~ {RETURN[Basics.CompareCard[
NARROW[k, Symbol].val,
NARROW[data, Symbol].val
]]};
CompareName: RedBlackTree.Compare ~ {RETURN[Rope.Compare[
NARROW[k],
NARROW[data, Symbol].txt
]]};
GetSymbols: PUBLIC PROC [s: IO.STREAM] RETURNS [tables: Tables] ~ {
reads the symbols in from the a.out format. see man a.out.
symOff, strOff, symSize, strSize: INT;
IO.SetIndex[s, 0]; -- just in case the stream has already been red
[symOff, symSize] ← GetLocAndSize[s];
strOff ← symOff+symSize;
IO.SetIndex[s, strOff];
strSize ← GetUnsigned[s];
IO.SetIndex[s, symOff];
tables ← NEW[SparcSymbols.TablesRec ← [
byAddr: RedBlackTree.Create[XtractAddr, CompareAddr],
byName: RedBlackTree.Create[XtractName, CompareName]
]];
WHILE IO.GetIndex[s]<strOff DO
sym: Symbol ← GetOneSymbol[s, strOff];
IF sym.type.hi.hi=05h THEN RedBlackTree.Insert[tables.byAddr, sym, sym];
IF sym.txt#NIL THEN RedBlackTree.Insert[tables.byName, sym, sym.txt ! RedBlackTree.DuplicateKey => CONTINUE];
ENDLOOP;
};
Table Access
GetClosestName: PUBLIC PROC [addr: CARD32, tables: Tables] RETURNS [name: Rope.ROPE] ~ {
lookupSym: Symbol ← NEW[SymbolRec ← [val: addr]];
sym: Symbol ← NARROW[RedBlackTree.Lookup[tables.byAddr, lookupSym]];
IF sym=NIL THEN sym ← NARROW[RedBlackTree.LookupNextSmaller[tables.byAddr, lookupSym]];
RETURN[sym.txt];
};
GetAddress: PUBLIC PROC [name: Rope.ROPE, tables: Tables] RETURNS [addr: CARD32] ~ {
sym: Symbol ← NARROW[RedBlackTree.Lookup[tables.byName, name]];
RETURN[IF sym=NIL THEN 0 ELSE sym.val];
};
Tests
ListTable: PROC [out: IO.STREAM, table: RedBlackTree.Table] ~ {
PrintEachEntry: RedBlackTree.EachNode ~ {
sym: Symbol ← NARROW[data];
IO.PutF[out, "%g\t\t(%8x) =\t%d\n", IO.rope[sym.txt], IO.card[LOOPHOLE[sym.type]], IO.card[sym.val]];
};
RedBlackTree.EnumerateIncreasing[table, PrintEachEntry];
};
ListTables: PUBLIC PROC [out: IO.STREAM, tables: Tables] ~ {
IO.PutRope[out, "\nMap by address: \n"];
ListTable[out, tables.byAddr];
IO.PutRope[out, "\nMap by name: \n"];
ListTable[out, tables.byName];
};
END.