Reflection.Mod 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. MODULE Reflection;
  2. (** (c) Felix Friedrich, ETH Zurich, 2016 -- Reflection with more structured references section emitted by Fox Compiler *)
  3. IMPORT Modules, Streams, SYSTEM, Machine, Heaps, Objects, Trace, Kernel;
  4. CONST
  5. ShowAllProcs = TRUE;
  6. MaxFrames = 128;
  7. MaxString = 64;
  8. MaxArray = 8;
  9. MaxCols = 70;
  10. Sep = " ";
  11. SepLen = 2;
  12. LineDelay = 0;
  13. CONST
  14. sfTypeNone* = 0X;
  15. sfTypeCHAR* = 01X;
  16. sfTypeCHAR8* = 02X;
  17. sfTypeCHAR16* = 03X;
  18. sfTypeCHAR32* = 04X;
  19. sfTypeRANGE* = 05X;
  20. sfTypeSHORTINT* = 06X;
  21. sfTypeINTEGER* = 07X;
  22. sfTypeLONGINT* = 08X;
  23. sfTypeHUGEINT* = 09X;
  24. sfTypeWORD* = 0AX;
  25. sfTypeLONGWORD* = 0BX;
  26. sfTypeSIGNED8* = 0CX;
  27. sfTypeSIGNED16* = 0DX;
  28. sfTypeSIGNED32* = 0EX;
  29. sfTypeSIGNED64* = 0FX;
  30. sfTypeUNSIGNED8* = 10X;
  31. sfTypeUNSIGNED16* = 11X;
  32. sfTypeUNSIGNED32* = 12X;
  33. sfTypeUNSIGNED64* = 13X;
  34. sfTypeREAL* = 14X;
  35. sfTypeLONGREAL* = 15X;
  36. sfTypeCOMPLEX* = 16X;
  37. sfTypeLONGCOMPLEX* = 17X;
  38. sfTypeBOOLEAN* = 18X;
  39. sfTypeSET* = 19X;
  40. sfTypeANY* = 1AX;
  41. sfTypeOBJECT* = 1BX;
  42. sfTypeBYTE* = 1CX;
  43. sfTypeADDRESS* = 1DX;
  44. sfTypeSIZE* = 1EX;
  45. sfTypeIndirect*= 1FX;
  46. sfTypeRecord* = 20X;
  47. sfTypePointerToRecord* = 21X;
  48. sfTypePointerToArray* = 22X;
  49. sfTypeOpenArray* = 23X;
  50. sfTypeStaticArray* = 24X;
  51. sfTypeDynamicArray* = 25X;
  52. sfTypeMathStaticArray* = 26X;
  53. sfTypeMathOpenArray* = 27X;
  54. sfTypeMathTensor* = 28X;
  55. sfTypeProcedure* = 29X;
  56. sfTypeDelegate* = 2AX;
  57. sfTypeENUM* = 2BX;
  58. sfTypeCELL* = 2CX;
  59. sfTypePORT* = 2DX;
  60. sfIN* = 0X;
  61. sfOUT* = 1X;
  62. flagDelegate*=0;
  63. flagConstructor*=1;
  64. (* variable / parameter addressing modes *)
  65. sfAbsolute* = 0X; (* global vars *)
  66. sfRelative* = 1X; (* variables, value parameters *)
  67. sfIndirect* = 2X; (* var parameters *)
  68. sfScopeBegin* = 0F0X;
  69. sfScopeEnd* = 0F1X;
  70. sfProcedure* = 0F2X;
  71. sfVariable* = 0F3X;
  72. sfTypeDeclaration* = 0F4X;
  73. sfModule*= 0FFX;
  74. (*
  75. References section format:
  76. Scope = sfScopeBegin {variable:Variable} {procedure:Procedure} {typeDecl:TypeDeclaration} sfScopeEnd.
  77. Module = sfModule prevSymbolOffset:SIZE name:String Scope.
  78. Procedure = sfProcedure prevSymbolOffset:SIZE name:String start:ADR end:ADR flags:SET {parameter:Variable} returnType:Type Scope.
  79. Variable = sfVariable prevSymbolOffset:SIZE name:String (sfRelative offset: SIZE | sfIndirec offset: SIZE | sfAbsolute address:ADDRESS) type:Type.
  80. TypeDeclaration = sfTypeDeclaration prevSymbolOffset:SIZE name:String typeInfo:ADR Scope.
  81. Type =
  82. sfTypePointerToRecord
  83. | sfTypePointerToArray Type
  84. | sfTypeOpenArray Type
  85. | sfTypeDynamicArray Type
  86. | sfTypeStaticArray length:SIZE Type
  87. | sfTypeMathOpenArray Type
  88. | sfTypeMathStaticArray length:SIZE Type
  89. | sfTypeMathTensor Type
  90. | sfTypeRecord tdAdr:ADDRESS
  91. | sfTypeProcedure {Parameter} return:Type
  92. | sfTypeDelegate {Parameter} return:Type
  93. | sfTypePort (sfIN | sfOUT)
  94. | sfTypeBOOLEAN
  95. | sfTypeCHAR | sfTypeCHAR8 | sfTypeCHAR16 | sfTypeCHAR32
  96. | sfTypeSHORTINT | sfTypeINTEGER | sfTypeLONGINT | sfTypeHUGEINT
  97. | sfTypeSIGNED8 | sfTypeSIGNED16 | sfTypeSIGNED32 | sfTypeSIGNED64
  98. | sfTypeUNSIGNED8 | sfTypeUNSIGNED16 | sfTypeUNSIGNED32 | sfTypeUNSIGNED64
  99. | sfTypeWORD | sfTypeLONGWORD
  100. | sfTypeREAL | sfTypeLONGREAL
  101. | sfTypeCOMPLEX | sfTypeLONGCOMPLEX
  102. | sfTypeSET | sfTypeANY | sfTypeOBJECT | sfTypeBYTE | sfTypeADDRESS | sfTypeSIZE
  103. | sfTypeIndirect offset:SIZE.
  104. *)
  105. VAR
  106. modes: ARRAY 25 OF CHAR;
  107. TYPE
  108. Name = ARRAY 128 OF CHAR;
  109. Meta* = RECORD
  110. module-: Modules.Module;
  111. refs-: Modules.Bytes;
  112. offset*: SIZE;
  113. END;
  114. PROCEDURE CheckHeapAddress(address: ADDRESS): BOOLEAN;
  115. BEGIN
  116. RETURN Machine.ValidHeapAddress(address);
  117. END CheckHeapAddress;
  118. PROCEDURE Wait(w: Streams.Writer);
  119. VAR i: LONGINT;
  120. BEGIN
  121. IF LineDelay > 0 THEN
  122. FOR i := 0 TO LineDelay DO END;
  123. w.Update
  124. END;
  125. END Wait;
  126. PROCEDURE Expect(pos: SIZE; b: BOOLEAN): BOOLEAN;
  127. BEGIN
  128. IF ~b THEN Trace.String("Format error in references section @"); Trace.Int(pos,1); Trace.Ln END;
  129. RETURN b;
  130. END Expect;
  131. (* consume a char from the byte stream *)
  132. PROCEDURE GetChar*(refs: Modules.Bytes; VAR offset: SIZE): CHAR;
  133. VAR c: CHAR;
  134. BEGIN
  135. IF ~Expect(offset, offset < LEN(refs)) THEN RETURN 0X END;
  136. c := refs[offset];
  137. INC(offset);
  138. RETURN c;
  139. END GetChar;
  140. (* skip a char in the byte stream *)
  141. PROCEDURE SkipChar*(VAR offset: SIZE);
  142. BEGIN
  143. INC(offset, SIZEOF(CHAR));
  144. END SkipChar;
  145. (* consume an address in the byte stream *)
  146. PROCEDURE GetAddress*(refs: Modules.Bytes; VAR offset: SIZE): ADDRESS;
  147. VAR adr: ADDRESS; i: SIZE;
  148. BEGIN
  149. IF ~Expect(offset, offset < LEN(refs)) THEN RETURN 0 END;
  150. FOR i := 0 TO SIZEOF(ADDRESS)-1 DO
  151. SYSTEM.PUT8(ADDRESSOF(adr)+i, GetChar(refs, offset));
  152. END;
  153. RETURN adr;
  154. END GetAddress;
  155. (* skip an address in the byte stream *)
  156. PROCEDURE SkipAddress*(VAR offset: SIZE);
  157. BEGIN
  158. INC(offset, SIZEOF(ADDRESS));
  159. END SkipAddress;
  160. (* consume a size in the byte stream *)
  161. PROCEDURE GetSize*(refs: Modules.Bytes; VAR offset: SIZE): SIZE;
  162. VAR size: SIZE; i: SIZE;
  163. BEGIN
  164. IF ~Expect(offset, offset < LEN(refs)) THEN RETURN 0 END;
  165. FOR i := 0 TO SIZEOF(SIZE)-1 DO
  166. SYSTEM.PUT8(ADDRESSOF(size)+i, refs[offset]);
  167. INC(offset);
  168. END;
  169. RETURN size;
  170. END GetSize;
  171. (* skip a size in the byte stream *)
  172. PROCEDURE SkipSize*(VAR offset: SIZE);
  173. BEGIN
  174. INC(offset, SIZEOF(SIZE));
  175. END SkipSize;
  176. (* consume a set in the byte stream *)
  177. PROCEDURE GetSet*(refs: Modules.Bytes; VAR offset: SIZE): SET;
  178. VAR set: SET; i: SIZE;
  179. BEGIN
  180. IF ~Expect(offset, offset < LEN(refs)) THEN RETURN {} END;
  181. FOR i := 0 TO SIZEOF(SET)-1 DO
  182. SYSTEM.PUT8(ADDRESSOF(set)+i, refs[offset]);
  183. INC(offset);
  184. END;
  185. RETURN set;
  186. END GetSet;
  187. (* skip a set in the byte stream *)
  188. PROCEDURE SkipSet*(VAR offset: SIZE);
  189. BEGIN
  190. INC(offset, SIZEOF(SET));
  191. END SkipSet;
  192. (* consume a string in the byte stream *)
  193. PROCEDURE GetString*(refs: Modules.Bytes; VAR offset: SIZE; VAR string: ARRAY OF CHAR);
  194. VAR ch: CHAR; i: SIZE;
  195. BEGIN
  196. i := 0;
  197. REPEAT
  198. ch := GetChar(refs, offset);
  199. string[i] := ch;
  200. INC(i);
  201. UNTIL ch = 0X;
  202. END GetString;
  203. (* skip a string in the byte stream *)
  204. PROCEDURE SkipString*(refs: Modules.Bytes; VAR offset: SIZE);
  205. BEGIN
  206. WHILE(refs[offset] # 0X) DO INC(offset) END; INC(offset);
  207. END SkipString;
  208. (* extract a full name from the byte stream by traversing up the symbols in their scopes *)
  209. PROCEDURE GetFullName*(refs: Modules.Bytes; offset: SIZE; VAR name: ARRAY OF CHAR);
  210. VAR n: SIZE;
  211. PROCEDURE Traverse(offset: SIZE);
  212. VAR c: CHAR;
  213. BEGIN
  214. IF offset >= 0 THEN
  215. c := GetChar(refs, offset);
  216. IF (c = sfProcedure) OR (c=sfVariable) OR (c=sfTypeDeclaration) OR (c=sfModule) THEN
  217. Traverse(GetSize(refs, offset));
  218. END;
  219. IF (n > 0) & (n<LEN(name)) THEN name[n] := "."; INC(n); END;
  220. WHILE (n<LEN(name)) & (refs[offset] # 0X) DO
  221. name[n] := refs[offset];
  222. INC(n); INC(offset);
  223. END;
  224. END;
  225. END Traverse;
  226. BEGIN
  227. n := 0;
  228. Traverse(offset);
  229. name[n] := 0X;
  230. END GetFullName;
  231. (* "lock free" version of Modules.ThisTypeByAdr *)
  232. PROCEDURE ThisTypeByAdr(adr: ADDRESS; VAR m: Modules.Module; VAR t: Modules.TypeDesc);
  233. BEGIN
  234. IF adr # 0 THEN
  235. SYSTEM.GET (adr + Heaps.TypeDescOffset, adr);
  236. IF CheckHeapAddress(adr) THEN
  237. t := SYSTEM.VAL(Modules.TypeDesc, adr);
  238. m := t.mod;
  239. ELSE
  240. m := NIL; t := NIL
  241. END
  242. ELSE
  243. m := NIL; t := NIL
  244. END
  245. END ThisTypeByAdr;
  246. (* output type descriptor information *)
  247. PROCEDURE WriteType*(w: Streams.Writer; adr: ADDRESS);
  248. VAR module: Modules.Module; typeDesc: Modules.TypeDesc;
  249. BEGIN
  250. IF CheckHeapAddress(adr) THEN
  251. ThisTypeByAdr(adr, module, typeDesc);
  252. IF module # NIL THEN
  253. w.String(module.name);
  254. ELSE
  255. w.String("NIL"); RETURN
  256. END;
  257. w.String(".");
  258. IF typeDesc # NIL THEN
  259. IF typeDesc.name = "" THEN
  260. w.String("ANONYMOUS")
  261. ELSE
  262. w.String(typeDesc.name);
  263. END;
  264. ELSE
  265. w.String("NIL");
  266. END;
  267. ELSE
  268. w.String("UNKNOWN");
  269. END;
  270. END WriteType;
  271. (* Write the specified procedure name and returns parameters for use with Variables *)
  272. PROCEDURE WriteProc0(w: Streams.Writer; mod: Modules.Module; pc, fp: ADDRESS; VAR refs: Modules.Bytes; VAR refpos: SIZE; VAR base: ADDRESS);
  273. VAR ch: CHAR; startpc, end: ADDRESS; offset: SIZE; name: Name;
  274. BEGIN
  275. refpos := -1;
  276. IF mod = NIL THEN
  277. IF pc = 0 THEN w.String("NIL")
  278. ELSE
  279. w.String("Unknown PC="); w.Address(pc); w.Char("H")
  280. END;
  281. IF fp # -1 THEN
  282. w.String(" FP="); w.Address(fp); w.Char("H")
  283. END
  284. ELSE
  285. refs := mod.refs;
  286. refpos := FindByAdr(refs, 0, pc);
  287. IF refpos >= 0 THEN
  288. offset := refpos;
  289. IF GetChar(refs, offset) = sfProcedure THEN
  290. SkipSize(offset);
  291. SkipString(refs, offset);
  292. GetFullName(refs, refpos, name);
  293. startpc := GetAddress(refs, offset);
  294. end := GetAddress(refs, offset);
  295. SkipSet(offset);
  296. w.String(name);
  297. w.Char(":"); w.Int(pc-startpc,1);
  298. base := fp; (*! only for local !! *)
  299. refpos := offset;
  300. END;
  301. ELSE
  302. w.String("procedure not found in module "); w.String(mod.name);
  303. END;
  304. w.String(" pc="); w.Int(pc,1); w.String(" ["); w.Address (pc); w.String("H]");
  305. w.String(" = "); w.Int(startpc,1); w.String(" + "); w.Int(pc-startpc,1);
  306. w.String(" crc="); w.Hex(mod.crc,-8);
  307. (*Wait(w);*)
  308. END
  309. END WriteProc0;
  310. PROCEDURE WriteBasicValue*(w: Streams.Writer; type: CHAR; adr: ADDRESS; VAR size: SIZE);
  311. VAR
  312. b: BOOLEAN;
  313. c: CHAR; c8: CHAR8; c16: CHAR16; c32: CHAR32;
  314. s: SHORTINT; i: INTEGER; l: LONGINT; h: HUGEINT;
  315. sz: SIZE; a, pc: ADDRESS;
  316. word: WORD; lword: LONGWORD;
  317. s8: SIGNED8; s16: SIGNED16; s32: SIGNED32; s64: SIGNED64;
  318. u8: UNSIGNED8; u16: UNSIGNED16; u32: UNSIGNED32; u64: UNSIGNED64;
  319. r: REAL; x: LONGREAL;
  320. cplx {UNTRACED}: POINTER {UNSAFE} TO RECORD re,im: REAL END;
  321. lcplx {UNTRACED}: POINTER {UNSAFE} TO RECORD re,im: LONGREAL END;
  322. set: SET;
  323. byte: SYSTEM.BYTE;
  324. procedure: ARRAY 256 OF CHAR;
  325. PROCEDURE Signed(i: HUGEINT);
  326. BEGIN
  327. w.Int(i,1);
  328. END Signed;
  329. PROCEDURE Unsigned(i: HUGEINT; size: SIZE);
  330. BEGIN
  331. w.Hex(i,-2*size);
  332. END Unsigned;
  333. BEGIN
  334. CASE type OF
  335. | sfTypePointerToRecord, sfTypeANY, sfTypeOBJECT:
  336. size := SIZEOF(ADDRESS);
  337. SYSTEM.GET(adr, a); Unsigned(a, SIZEOF(ADDRESS));
  338. | sfTypeBOOLEAN:
  339. size := SIZEOF(BOOLEAN);
  340. SYSTEM.GET(adr, b); IF b THEN w.String("true") ELSE w.String("false") END;
  341. | sfTypeCHAR, sfTypeCHAR8:
  342. size := SIZEOF(CHAR);
  343. SYSTEM.GET(adr, c); IF (c > " ") & (c <= "~") THEN w.Char( c ); ELSE w.Hex( ORD( c ), -2 ); w.Char( "X" ) END;
  344. | sfTypeCHAR16:
  345. size := SIZEOF(CHAR16);
  346. SYSTEM.GET(adr, i); w.Hex(i,-4); w.Char("X");
  347. | sfTypeCHAR32:
  348. size := SIZEOF(CHAR32);
  349. SYSTEM.GET(adr, l); w.Hex(l,-8); w.Char("X");
  350. | sfTypeSHORTINT:
  351. size := SIZEOF(SHORTINT);
  352. SYSTEM.GET(adr, s); Signed(s);
  353. | sfTypeINTEGER:
  354. size := SIZEOF(INTEGER);
  355. SYSTEM.GET(adr, i); Signed(i);
  356. | sfTypeLONGINT:
  357. size := SIZEOF(LONGINT);
  358. SYSTEM.GET(adr, l); Signed(l);
  359. | sfTypeHUGEINT:
  360. size := SIZEOF(HUGEINT);
  361. SYSTEM.GET(adr, h); Signed(h);
  362. | sfTypeWORD:
  363. size := SIZEOF(WORD);
  364. SYSTEM.GET(adr, word); Signed(word);
  365. | sfTypeLONGWORD:
  366. size := SIZEOF(LONGWORD);
  367. SYSTEM.GET(adr, lword); Signed(lword);
  368. | sfTypeSIGNED8:
  369. size := SIZEOF(SIGNED8);
  370. SYSTEM.GET(adr, s8); Signed(s8);
  371. | sfTypeSIGNED16:
  372. size := SIZEOF(SIGNED16);
  373. SYSTEM.GET(adr, s16); Signed(s16);
  374. | sfTypeSIGNED32:
  375. size := SIZEOF(SIGNED32);
  376. SYSTEM.GET(adr, s32); Signed(s32);
  377. | sfTypeSIGNED64:
  378. size := SIZEOF(SIGNED64);
  379. SYSTEM.GET(adr, s64); Signed(s64);
  380. | sfTypeUNSIGNED8:
  381. size := SIZEOF(UNSIGNED8);
  382. SYSTEM.GET(adr, u8); Unsigned(u8, SIZEOF(UNSIGNED8));
  383. | sfTypeUNSIGNED16:
  384. size := SIZEOF(UNSIGNED16);
  385. SYSTEM.GET(adr, u16); Unsigned(u16, SIZEOF(UNSIGNED16));
  386. | sfTypeUNSIGNED32:
  387. size := SIZEOF(UNSIGNED32);
  388. SYSTEM.GET(adr, u32); Unsigned(u32, SIZEOF(UNSIGNED32));
  389. | sfTypeUNSIGNED64:
  390. size := SIZEOF(UNSIGNED64);
  391. SYSTEM.GET(adr, s64); Unsigned(s64, SIZEOF(UNSIGNED64));
  392. | sfTypeREAL:
  393. size := SIZEOF(REAL);
  394. SYSTEM.GET(adr, r); w.Float(r,7);
  395. w.String(" (");
  396. SYSTEM.GET(adr, u32); Unsigned(u32, SIZEOF(UNSIGNED32));
  397. w.String(")");
  398. | sfTypeLONGREAL:
  399. size := SIZEOF(LONGREAL);
  400. SYSTEM.GET(adr, x); w.Float(x,13);
  401. w.String(" (");
  402. SYSTEM.GET(adr, s64); Unsigned(s64, SIZEOF(UNSIGNED64));
  403. w.String(")");
  404. | sfTypeCOMPLEX:
  405. size := SIZEOF(COMPLEX);
  406. cplx := adr; w.Float(cplx.re,7); w.String("+ i*"); w.Float(cplx.im,7);
  407. | sfTypeLONGCOMPLEX:
  408. size := SIZEOF(LONGCOMPLEX);
  409. lcplx := adr;
  410. w.Float(lcplx.re,13); w.String("+ i*"); w.Float(lcplx.im,13);
  411. | sfTypeSET:
  412. size := SIZEOF(SET);
  413. SYSTEM.GET(adr, set); w.Set(set);
  414. | sfTypeBYTE:
  415. size := SIZEOF(SYSTEM.BYTE);
  416. SYSTEM.GET(adr, c); Unsigned(ORD(c), 1);
  417. | sfTypeRANGE:
  418. size := SIZEOF(RANGE);
  419. SYSTEM.GET(adr, sz); Unsigned(sz,SIZEOF(SIZE)); w.String(".."); Unsigned(sz, SIZEOF(SIZE));
  420. | sfTypeADDRESS:
  421. size := SIZEOF(ADDRESS);
  422. SYSTEM.GET(adr, a); Unsigned(a, SIZEOF(ADDRESS));
  423. | sfTypeSIZE:
  424. size := SIZEOF(SIZE);
  425. SYSTEM.GET(adr, sz); Signed(sz); w.String("["); Unsigned(sz, SIZEOF(SIZE)); w.String("]");
  426. | sfTypeENUM:
  427. SYSTEM.GET(adr, word); Signed(word);
  428. | sfTypePORT:
  429. SYSTEM.GET(adr, a); Unsigned(a, SIZEOF(ADDRESS));
  430. | sfTypeProcedure, sfTypeDelegate:
  431. size := SIZE OF ADDRESS;
  432. SYSTEM.GET(adr, a); pc := NIL; GetProcedureName(a, procedure, pc);
  433. IF pc # NIL THEN w.String(procedure) ELSE Unsigned(a, SIZE OF ADDRESS) END;
  434. IF type = sfTypeDelegate THEN
  435. SYSTEM.GET(adr + size, a); INC(size, SIZE OF ADDRESS);
  436. w.String(" {"); Unsigned(a, SIZE OF ADDRESS); w.String("}");
  437. END;
  438. ELSE
  439. w.String("UNKOWN TYPE "); Unsigned(ORD(type),1);
  440. END;
  441. w.Update;
  442. END WriteBasicValue;
  443. PROCEDURE OnHeapOrStack(adr: ADDRESS; low, high: ADDRESS): BOOLEAN;
  444. BEGIN
  445. RETURN (low <= adr) & (adr < high) OR CheckHeapAddress(adr);
  446. END OnHeapOrStack;
  447. PROCEDURE WriteValueString*(w: Streams.Writer; adr: ADDRESS; maxLen: SIZE; low, high: ADDRESS);
  448. CONST MaxString = 96;
  449. VAR ch: CHAR;
  450. BEGIN
  451. IF maxLen > MaxString THEN maxLen := MaxString END;
  452. w.Char('"');
  453. LOOP
  454. IF (maxLen <= 0) OR ~OnHeapOrStack(adr, low, high) THEN
  455. EXIT END;
  456. SYSTEM.GET(adr, ch);
  457. IF (ch < " ") OR (ch > "~") THEN EXIT END;
  458. w.Char(ch);
  459. INC(adr);
  460. DEC(maxLen);
  461. END;
  462. w.Char('"');
  463. IF maxLen = 0 THEN w.String("..."); END;
  464. END WriteValueString;
  465. PROCEDURE WriteMathArray*(w: Streams.Writer; adr: ADDRESS; low, high: ADDRESS);
  466. TYPE
  467. LenInc = RECORD
  468. len: SIZE;
  469. inc: SIZE
  470. END;
  471. UnsafeArray= POINTER {UNSAFE} TO RECORD
  472. ptr {UNTRACED}: ANY;
  473. adr: ADDRESS;
  474. flags: SET;
  475. dim: SIZE;
  476. elementSize: SIZE;
  477. lens: ARRAY 8 OF LenInc;
  478. END;
  479. VAR t {UNTRACED}: UnsafeArray; i: SIZE;
  480. BEGIN
  481. IF adr = NIL THEN w.String(" (NIL)");
  482. ELSIF OnHeapOrStack(adr, low, high) THEN
  483. t := adr;
  484. w.String(" len/inc=[ ");
  485. IF t.dim < 8 THEN
  486. FOR i := 0 TO t.dim-1 DO
  487. w.Int(t.lens[i].len,0);
  488. w.String("/");
  489. w.Int(t.lens[i].inc,0);
  490. IF i < t.dim-1 THEN w.String(" , ") END;
  491. END;
  492. END;
  493. w.String(" ]");
  494. w.String(" flags = "); w.Set(t.flags);
  495. w.String(" adr = "); w.Address(t.adr);
  496. w.String(" ptr = "); w.Address(t.ptr);
  497. w.String(" elementSize = "); w.Int(t.elementSize,0);
  498. ELSE
  499. w.String("(UNKNOWN)");
  500. END;
  501. END WriteMathArray;
  502. PROCEDURE WriteValue*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE; adr: ADDRESS; low, high: ADDRESS);
  503. VAR type: CHAR; a: ADDRESS; size, ofs: SIZE; len,i: SIZE;
  504. BEGIN
  505. IF ~OnHeapOrStack(adr, low, high) THEN
  506. SkipType(refs, offset);
  507. w.String("INVALID ADR:"); w.Address(adr);
  508. RETURN;
  509. END;
  510. type := GetChar(refs, offset);
  511. IF type = sfTypeIndirect THEN
  512. ofs := GetSize(refs, offset);
  513. WriteValue(w, refs, ofs, adr, low, high);
  514. ELSE
  515. CASE type OF
  516. sfTypeNone:
  517. w.String("NONE");
  518. | sfTypePointerToRecord, sfTypeANY, sfTypeOBJECT:
  519. WriteBasicValue(w,type, adr, size);
  520. SYSTEM.GET(adr, a);
  521. IF a = 0 THEN
  522. w.String(" NIL");
  523. ELSIF CheckHeapAddress(a) THEN
  524. SYSTEM.GET(a + Heaps.TypeDescOffset, a);
  525. w.String(" (");
  526. WriteType(w,a);
  527. w.String(")");
  528. ELSE
  529. w.String(" (UNKNOWN)");
  530. END;
  531. | sfTypePointerToArray:
  532. WriteBasicValue(w, sfTypeANY, adr, size);
  533. SYSTEM.GET(adr, a);
  534. IF ~OnHeapOrStack(a,low,high) THEN w.String(" (INVALID)") END;
  535. SkipType(refs, offset);
  536. | sfTypeOpenArray:
  537. IF (refs[offset] = sfTypeCHAR) OR (refs[offset] = sfTypeCHAR8) THEN (* ARRAY OF CHAR *)
  538. SYSTEM.GET(adr, a);
  539. WriteValueString(w, a, MaxString, low, high);
  540. ELSE
  541. w.String("... (NO STRING)")
  542. END;
  543. SkipType(refs, offset);
  544. | sfTypeStaticArray:
  545. len := GetSize(refs, offset);
  546. IF (refs[offset] = sfTypeCHAR) OR (refs[offset] = sfTypeCHAR8) THEN (* ARRAY x OF CHAR *)
  547. WriteValueString(w, adr, len, low, high);
  548. ELSE
  549. w.String("... (NO STRING)");
  550. END;
  551. SkipType(refs, offset);
  552. | sfTypeDynamicArray:
  553. w.String("... (DYNAMIC ARRAY)");
  554. SkipType(refs, offset);
  555. | sfTypeMathOpenArray:
  556. w.String(" OPEN MATH ARRAY ");
  557. SkipType(refs, offset);
  558. WriteMathArray(w, adr, low, high);
  559. | sfTypeMathStaticArray:
  560. w.String(" ... (MATH STATIC ARRAY)");
  561. SkipSize(offset); SkipType(refs, offset);
  562. | sfTypeMathTensor:
  563. w.String(" TENSOR ");
  564. SYSTEM.GET(adr, a);
  565. WriteBasicValue(w, sfTypeANY, adr, size);
  566. WriteMathArray(w, a, low, high);
  567. SkipType(refs, offset);
  568. | sfTypeRecord:
  569. w.String("...");
  570. w.String("(");
  571. a := GetAddress(refs, offset);
  572. WriteType(w,a);
  573. w.String(")");
  574. | sfTypeProcedure, sfTypeDelegate:
  575. WriteBasicValue(w, type, adr, size);
  576. WHILE refs[offset] = sfVariable DO SkipVariable(refs, offset) END;
  577. SkipType(refs, offset);
  578. | sfTypePORT:
  579. WriteBasicValue(w, type, adr, size);
  580. SkipChar(offset);
  581. ELSE
  582. WriteBasicValue(w, type, adr, size);
  583. END;
  584. w.Update;
  585. END;
  586. END WriteValue;
  587. PROCEDURE WriteVariable*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE; base: ADDRESS; low, high: ADDRESS);
  588. VAR name: ARRAY 128 OF CHAR; adr: ADDRESS; prevScope: SIZE; c: CHAR;
  589. BEGIN
  590. IF ~Expect(offset, GetChar(refs, offset) = sfVariable) THEN RETURN END;
  591. prevScope := GetSize(refs, offset);
  592. GetString(refs, offset, name);
  593. w.String(Sep); w.String(name); w.Char("=");
  594. c := GetChar(refs, offset);
  595. IF c = sfRelative THEN
  596. adr := base + GetSize(refs, offset)
  597. ELSIF c = sfIndirect THEN
  598. adr := base + GetSize(refs, offset);
  599. w.Address(adr); w.String("->");
  600. IF ~OnHeapOrStack(adr,low,high) THEN w.String(" (INVALID)");
  601. SkipType(refs,offset);
  602. RETURN;
  603. END;
  604. SYSTEM.GET(adr, adr);
  605. ELSE (* absolute *)
  606. adr := GetAddress(refs, offset);
  607. END;
  608. w.String(" [@");w.Int(adr-base,1); w.String("] ");
  609. WriteValue(w, refs, offset, adr, low, high);
  610. END WriteVariable;
  611. (* write variables taking meta information from stream in stream at offset, potentially stored at base address
  612. *)
  613. PROCEDURE WriteVariables*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE; base: ADDRESS; low, high: ADDRESS);
  614. VAR count: SIZE;
  615. BEGIN
  616. WHILE refs[offset] = sfVariable DO
  617. WriteVariable(w, refs, offset, base, low, high); w.Ln;
  618. (*INC(count); *)
  619. END;
  620. IF count > 0 THEN w.Ln; Wait(w); END;
  621. END WriteVariables;
  622. (* skip type metadata in stream *)
  623. PROCEDURE SkipType*(refs: Modules.Bytes; VAR offset: SIZE);
  624. VAR size: SIZE; adr: SIZE; c: CHAR;
  625. BEGIN
  626. c := GetChar(refs, offset);
  627. CASE c OF
  628. sfTypeNone .. sfTypeSIZE:
  629. | sfTypePointerToRecord:
  630. | sfTypePointerToArray:SkipType(refs, offset);
  631. | sfTypeOpenArray: SkipType(refs, offset);
  632. | sfTypeStaticArray: SkipSize(offset); SkipType(refs, offset);
  633. | sfTypeDynamicArray: SkipType(refs, offset);
  634. | sfTypeMathOpenArray: SkipType(refs, offset);
  635. | sfTypeMathStaticArray: SkipSize(offset); SkipType(refs, offset);
  636. | sfTypeMathTensor: SkipType(refs, offset);
  637. | sfTypeRecord: SkipSize(offset);
  638. | sfTypeProcedure, sfTypeDelegate:
  639. WHILE refs[offset] = sfVariable DO SkipVariable(refs, offset) END;
  640. SkipType(refs, offset);
  641. | sfTypeENUM:
  642. | sfTypePORT: SkipChar(offset);
  643. | sfTypeIndirect: SkipSize(offset);
  644. ELSE (* ?? *)
  645. END;
  646. END SkipType;
  647. (* skip procedure metadata in stream *)
  648. PROCEDURE SkipProcedure*(refs: Modules.Bytes; VAR offset: SIZE);
  649. BEGIN
  650. IF ~Expect(offset, GetChar(refs, offset) = sfProcedure) THEN RETURN END;
  651. SkipSize(offset);
  652. SkipString(refs, offset);
  653. SkipAddress(offset);
  654. SkipAddress(offset);
  655. SkipSet(offset);
  656. WHILE (refs[offset] = sfVariable) DO SkipVariable(refs, offset) END;
  657. SkipType(refs, offset);
  658. SkipScope(refs, offset);
  659. END SkipProcedure;
  660. (* skip variable metadata in stream *)
  661. PROCEDURE SkipVariable*(refs: Modules.Bytes; VAR offset: SIZE);
  662. BEGIN
  663. IF ~Expect(offset, GetChar(refs, offset) = sfVariable) THEN RETURN END;
  664. SkipSize(offset);
  665. SkipString(refs, offset);
  666. SkipChar(offset);
  667. SkipAddress(offset);
  668. SkipType(refs, offset);
  669. END SkipVariable;
  670. (* skip type declaration meta data in stream *)
  671. PROCEDURE SkipTypeDeclaration*(refs: Modules.Bytes; VAR offset: SIZE);
  672. BEGIN
  673. IF ~Expect(offset, GetChar(refs, offset) = sfTypeDeclaration) THEN RETURN END;
  674. SkipSize(offset);
  675. SkipString(refs, offset);
  676. SkipAddress(offset);
  677. IF refs[offset] = sfScopeBegin THEN SkipScope(refs, offset) END;
  678. END SkipTypeDeclaration;
  679. (* skip type declaration meta data in stream *)
  680. PROCEDURE SkipModule*(refs: Modules.Bytes; VAR offset: SIZE);
  681. BEGIN
  682. IF ~Expect(offset, GetChar(refs, offset) = sfModule) THEN RETURN END;
  683. SkipSize(offset);
  684. SkipString(refs, offset);
  685. IF refs[offset] = sfScopeBegin THEN SkipScope(refs, offset) END;
  686. END SkipModule;
  687. (* skip a scope in stream *)
  688. PROCEDURE SkipScope*(refs: Modules.Bytes; VAR offset: SIZE);
  689. BEGIN
  690. IF ~Expect(offset, GetChar(refs, offset) = sfScopeBegin) THEN RETURN END;
  691. WHILE (refs[offset] = sfVariable) DO SkipVariable(refs, offset) END;
  692. WHILE (refs[offset] = sfProcedure) DO SkipProcedure(refs, offset) END;
  693. WHILE (refs[offset] = sfTypeDeclaration) DO SkipTypeDeclaration(refs, offset) END;
  694. IF ~Expect(offset, GetChar(refs, offset) = sfScopeEnd) THEN RETURN END;
  695. END SkipScope;
  696. TYPE
  697. Search = RECORD
  698. name: ARRAY 256 OF CHAR; (* for search by name *)
  699. nameOffset: SIZE; (* to incrementally search through scopes *)
  700. minLevel: LONGINT; (* in order to stop scope search *)
  701. pc: ADDRESS; (* for search by address *)
  702. pos: SIZE; (* symbol position in stream, -1 if not found *)
  703. found: BOOLEAN; (* if found *)
  704. END;
  705. (* check if stream contains the string part stored in search record with respective offset *)
  706. PROCEDURE FindString(refs: Modules.Bytes; VAR offset: SIZE; level: LONGINT; VAR find: Search);
  707. VAR ofs: SIZE;
  708. BEGIN
  709. IF find.minLevel > level THEN
  710. SkipString(refs, offset)
  711. ELSE
  712. ofs := find.nameOffset;
  713. WHILE (refs[offset] # 0X) & (find.name[ofs] = refs[offset]) DO
  714. INC(offset); INC(ofs);
  715. END;
  716. IF (refs[offset] = 0X) THEN
  717. IF find.name[ofs] = 0X THEN
  718. find.found := TRUE;
  719. ELSIF find.name[ofs] = "." THEN
  720. find.minLevel := level+1;
  721. find.nameOffset := ofs+1;
  722. END;
  723. END;
  724. WHILE(refs[offset] # 0X) DO INC(offset) END;
  725. INC(offset);
  726. END;
  727. END FindString;
  728. (* find a symbol by name or pc starting from the procedure stream section *)
  729. PROCEDURE FindInProcedure(refs: Modules.Bytes; VAR offset: SIZE; level: LONGINT; VAR find: Search);
  730. VAR name: ARRAY 128 OF CHAR; start, end: ADDRESS; pos: SIZE;
  731. BEGIN
  732. pos := offset;
  733. IF ~Expect(offset, GetChar(refs, offset) = sfProcedure) THEN RETURN END;
  734. SkipSize(offset);
  735. FindString(refs, offset, level, find);
  736. start := GetAddress(refs, offset);
  737. end := GetAddress(refs, offset);
  738. SkipSet(offset);
  739. find.found := find.found OR (start <= find.pc) & (find.pc < end);
  740. IF find.found THEN
  741. find.pos := pos;
  742. RETURN;
  743. END;
  744. WHILE (refs[offset] = sfVariable) DO
  745. IF find.minLevel <= level+1 THEN
  746. FindInVariable(refs, offset, level+1, find);
  747. IF find.found THEN RETURN END;
  748. ELSE
  749. SkipVariable(refs, offset)
  750. END;
  751. END;
  752. SkipType(refs, offset);
  753. FindInScope(refs, offset, level+1, find);
  754. END FindInProcedure;
  755. (* find a symbol by name or pc starting from the variable stream section *)
  756. PROCEDURE FindInVariable(refs: Modules.Bytes; VAR offset: SIZE; level: LONGINT; VAR find: Search);
  757. VAR name: ARRAY 128 OF CHAR; pos: SIZE;
  758. BEGIN
  759. pos := offset;
  760. IF ~Expect(offset, GetChar(refs, offset) = sfVariable) THEN RETURN END;
  761. SkipSize(offset);
  762. FindString(refs, offset, level, find);
  763. IF find.found THEN
  764. find.pos := pos;
  765. RETURN;
  766. END;
  767. SkipChar(offset);
  768. SkipSize(offset);
  769. SkipType(refs, offset);
  770. END FindInVariable;
  771. (* find a symbol by name or pc starting from the type declaration stream section *)
  772. PROCEDURE FindInTypeDeclaration(refs: Modules.Bytes; VAR offset: SIZE; level: LONGINT; VAR find: Search);
  773. VAR name: ARRAY 128 OF CHAR; adr, pos: SIZE;
  774. BEGIN
  775. pos := offset;
  776. IF ~Expect(offset, GetChar(refs, offset) = sfTypeDeclaration) THEN RETURN END;
  777. SkipSize(offset);
  778. FindString(refs, offset, level, find);
  779. IF find.found THEN
  780. find.pos := pos;
  781. RETURN;
  782. END;
  783. SkipAddress(offset);
  784. IF refs[offset] = sfScopeBegin THEN FindInScope(refs, offset, level+1, find) END;
  785. END FindInTypeDeclaration;
  786. PROCEDURE FindInModule(refs: Modules.Bytes; VAR offset: SIZE; level: LONGINT; VAR find: Search);
  787. VAR pos: SIZE;
  788. BEGIN
  789. pos := offset;
  790. IF ~Expect(offset, GetChar(refs, offset) = sfModule) THEN RETURN END;
  791. SkipSize(offset);
  792. FindString(refs, offset, level, find);
  793. IF find.found THEN
  794. find.pos := pos;
  795. RETURN;
  796. END;
  797. FindInScope(refs, offset, level+1, find);
  798. END FindInModule;
  799. (* find a symbol by name or pc in a scope in the stream *)
  800. PROCEDURE FindInScope(refs: Modules.Bytes; VAR offset: SIZE; level: LONGINT; VAR find: Search);
  801. VAR no,i: SIZE;
  802. BEGIN
  803. IF ~Expect(offset, GetChar(refs, offset) = sfScopeBegin) THEN RETURN END;
  804. WHILE ~find.found &(refs[offset] = sfVariable) & (find.minLevel <= level) DO (* Variable *)
  805. FindInVariable(refs, offset, level, find);
  806. END;
  807. WHILE ~find.found & (refs[offset] = sfProcedure) & (find.minLevel <= level) DO (* Procedure *)
  808. FindInProcedure(refs, offset, level, find);
  809. END;
  810. WHILE ~find.found & (refs[offset] = sfTypeDeclaration) & (find.minLevel <= level) DO (* TypeDeclaration *)
  811. FindInTypeDeclaration(refs, offset,level, find);
  812. END;
  813. IF find.found OR (find.minLevel > level) THEN RETURN END;
  814. IF ~Expect(offset, GetChar(refs, offset) = sfScopeEnd) THEN RETURN END;
  815. END FindInScope;
  816. PROCEDURE InitSearch(VAR search: Search);
  817. BEGIN
  818. search.found := FALSE;
  819. search.pos := -1;
  820. search.name := "";
  821. search.nameOffset := 0;
  822. search.minLevel := 0;
  823. search.pc := 0;
  824. END InitSearch;
  825. (* Find a symbol in the stream starting at offset.
  826. If name is supposed to contain the referred to symbol, choose skipFirstSymbol = FALSE
  827. Example FindByName(m.refs, 0, "Reflection.FindByName", FALSE)
  828. otherwise choose skipFirstSymbol = TRUE
  829. Example FindByName(m.refs, 0, "FindByName", TRUE);
  830. *)
  831. PROCEDURE FindByName*(refs: Modules.Bytes; offset: SIZE; CONST name: ARRAY OF CHAR; skipFirstSymbol: BOOLEAN): SIZE;
  832. VAR search: Search;
  833. BEGIN
  834. InitSearch(search);
  835. COPY(name, search.name);
  836. IF skipFirstSymbol THEN search.minLevel := 1 END;
  837. CASE refs[offset] OF
  838. sfModule: FindInModule(refs, offset, 0, search);
  839. |sfVariable: FindInVariable(refs, offset, 0, search);
  840. |sfProcedure: FindInProcedure(refs, offset, 0, search);
  841. |sfTypeDeclaration: FindInTypeDeclaration(refs, offset, 0, search);
  842. ELSE (* wrong position in stream *)
  843. END;
  844. RETURN search.pos;
  845. END FindByName;
  846. PROCEDURE FindByAdr*(refs: Modules.Bytes; offset: SIZE; pc: ADDRESS): SIZE;
  847. VAR search: Search;
  848. BEGIN
  849. InitSearch(search);
  850. search.pc := pc;
  851. CASE refs[offset] OF
  852. sfModule: FindInModule(refs, offset, 0, search);
  853. |sfVariable: FindInVariable(refs, offset, 0, search);
  854. |sfProcedure: FindInProcedure(refs, offset, 0, search);
  855. |sfTypeDeclaration: FindInTypeDeclaration(refs, offset, 0, search);
  856. ELSE (* wrong position in stream *)
  857. END;
  858. RETURN search.pos;
  859. END FindByAdr;
  860. (** service procedures *)
  861. (** Find procedure name and write it. *)
  862. PROCEDURE WriteProc*(w: Streams.Writer; pc: ADDRESS);
  863. VAR refs: Modules.Bytes; refpos: SIZE; base: ADDRESS;
  864. BEGIN
  865. WriteProc0(w, Modules.ThisModuleByAdr0(pc), pc, -1, refs, refpos, base)
  866. END WriteProc;
  867. (** Write the state of the specified module. *)
  868. PROCEDURE ModuleState*(w: Streams.Writer; mod: Modules.Module);
  869. VAR offset: SIZE; base: ADDRESS; refs: Modules.Bytes;
  870. BEGIN
  871. IF mod = NIL THEN RETURN END;
  872. refs := mod.refs;
  873. offset := 0;
  874. w.String("State "); w.String(mod.name); w.Char(":");
  875. w.String(" (CRC = "); w.Hex(mod.crc,-8) ; w.String(")");
  876. w.Ln; Wait(w);
  877. IF (GetChar(refs, offset) = sfModule) THEN
  878. SkipSize(offset);
  879. SkipString(refs, offset);
  880. IF (GetChar(refs, offset) = sfScopeBegin) THEN
  881. WriteVariables(w, refs, offset, 0, 0, 0)
  882. END;
  883. END;
  884. END ModuleState;
  885. PROCEDURE CheckBP(bp: ADDRESS): ADDRESS;
  886. VAR n: ADDRESS;
  887. BEGIN
  888. IF bp # NIL THEN
  889. SYSTEM.GET(bp, n);
  890. IF ODD(n) THEN INC(bp, SIZEOF(ADDRESS)) END;
  891. END;
  892. RETURN bp;
  893. END CheckBP;
  894. (* Display call trackback. *)
  895. PROCEDURE StackTraceBack*(w: Streams.Writer; pc, bp: ADDRESS; low,high: ADDRESS; long, overflow: BOOLEAN);
  896. VAR count,offset: SIZE; stacklow: ADDRESS; base: ADDRESS; m: Modules.Module; refs: Modules.Bytes;
  897. BEGIN
  898. count := 0; (* frame count *)
  899. REPEAT
  900. m := Modules.ThisModuleByAdr0(pc);
  901. IF (ShowAllProcs OR (m # NIL) OR (count = 0)) & (bp # 0) & (bp >= low) & (bp < high) & (bp MOD SIZEOF(ADDRESS)=0) THEN
  902. IF CheckHeapAddress( pc ) THEN
  903. WriteProc0(w, m, pc, bp, refs, offset, base); w.Ln;Wait(w); w.Update;
  904. IF long & (~overflow OR (count > 0)) THEN (* show variables *)
  905. IF offset >= 0 THEN
  906. WriteVariables(w,refs,offset, base, low, high);
  907. SkipType(refs, offset);
  908. IF Expect(offset, GetChar(refs, offset) = sfScopeBegin) THEN
  909. WriteVariables(w,refs,offset, base, low, high);
  910. END;
  911. END;
  912. IF (m # NIL) & (base # m.sb) & (count = 0) THEN ModuleState(w, m) END
  913. END;
  914. ELSE
  915. w.String( "Unknown external procedure, pc = " ); w.Address( pc ); w.Ln; Wait(w);
  916. END;
  917. bp := CheckBP(bp);
  918. SYSTEM.GET(bp + SIZEOF(ADDRESS), pc); (* return addr from stack *)
  919. SYSTEM.GET(bp, bp); (* follow dynamic link *)
  920. INC(count)
  921. ELSE
  922. bp := 0
  923. END;
  924. UNTIL (bp = 0) OR (count = MaxFrames);
  925. IF bp # 0 THEN w.String("...") END
  926. END StackTraceBack;
  927. (** Write a process's state in one line. *)
  928. PROCEDURE WriteProcess*(w: Streams.Writer; p: Objects.Process);
  929. VAR adr: ADDRESS; mode: LONGINT; m: Modules.Module;
  930. BEGIN
  931. IF p # NIL THEN
  932. w.Int(p.id, 5);
  933. mode := p.mode;
  934. IF (mode >= Objects.Ready) & (mode <= Objects.Terminated) THEN
  935. adr := (mode-Objects.Ready)*4;
  936. FOR adr := adr TO adr+3 DO w.Char(modes[adr]) END
  937. ELSE
  938. w.Char(" "); w.Int(mode, 1)
  939. END;
  940. w.Int(p.procID, 2);
  941. w.Int(p.priority, 2);
  942. w.Update;
  943. w.Address (SYSTEM.VAL(ADDRESS, p.obj));
  944. IF p.obj # NIL THEN
  945. SYSTEM.GET(SYSTEM.VAL(ADDRESS, p.obj) - SIZEOF(ADDRESS), adr);
  946. w.Char(":"); WriteType(w, adr)
  947. END;
  948. w.Update;
  949. w.Char(" "); WriteProc(w, p.state.PC);
  950. IF p.mode = Objects.AwaitingLock THEN
  951. adr := SYSTEM.VAL(ADDRESS, p.waitingOn);
  952. w.Address (adr);
  953. w.Update;
  954. IF adr # 0 THEN (* can be 0 when snapshot is taken *)
  955. SYSTEM.GET(adr - SIZEOF(ADDRESS), adr);
  956. IF adr = SYSTEM.TYPECODE(Modules.Module) THEN
  957. w.Char("-");
  958. m := SYSTEM.VAL(Modules.Module, adr);
  959. w.String(m.name)
  960. ELSE
  961. w.Char(":"); WriteType(w, adr)
  962. END;
  963. w.Update;
  964. END
  965. ELSIF p.mode = Objects.AwaitingCond THEN
  966. w.Char(" "); WriteProc(w, SYSTEM.VAL(ADDRESS, p.condition));
  967. w.Address (p.condFP)
  968. END;
  969. w.Char(" "); w.Set(p.flags)
  970. END
  971. END WriteProcess;
  972. (* for interface compatibility *)
  973. PROCEDURE GetVariableAdr*(fp, pc: ADDRESS; CONST name: ARRAY OF CHAR): SIZE;
  974. BEGIN
  975. RETURN -1;
  976. END GetVariableAdr;
  977. PROCEDURE GetProcedureName*(pc: ADDRESS; VAR name: ARRAY OF CHAR; VAR startpc: ADDRESS);
  978. VAR m: Modules.Module; offset: SIZE;
  979. BEGIN
  980. name := "";
  981. m := Modules.ThisModuleByAdr0(pc);
  982. IF m # NIL THEN
  983. offset := FindByAdr(m.refs,0,pc);
  984. IF offset >= 0 THEN
  985. GetFullName(m.refs, offset, name);
  986. IF GetChar(m.refs, offset) = sfProcedure THEN
  987. SkipSize(offset);
  988. SkipString(m.refs,offset);
  989. startpc := GetAddress(m.refs, offset);
  990. END;
  991. END;
  992. END;
  993. END GetProcedureName;
  994. TYPE
  995. Variable* = RECORD
  996. adr-: ADDRESS;
  997. type-, size-, n-: SIZE;
  998. tdadr-: ADDRESS;
  999. END;
  1000. (* half-stub for module Info to work *)
  1001. PROCEDURE FindVar*(mod: Modules.Module; CONST name: ARRAY OF CHAR; VAR v: Variable): BOOLEAN;
  1002. VAR offset: SIZE; size: SIZE;adr: ADDRESS;
  1003. BEGIN
  1004. offset := FindByName(mod.refs, 0,name, TRUE);
  1005. IF offset < 0 THEN RETURN FALSE END;
  1006. IF ~Expect(offset, GetChar(mod.refs, offset) = sfVariable) THEN RETURN FALSE END;
  1007. SkipSize(offset);
  1008. SkipString(mod.refs, offset);
  1009. IF GetChar(mod.refs, offset) = sfRelative THEN
  1010. size := GetSize(mod.refs, offset);
  1011. ELSE (* absolute *)
  1012. adr := GetAddress(mod.refs, offset);
  1013. END;
  1014. v.adr := adr;
  1015. v.type := 0;
  1016. v.size := 0;
  1017. v.n := 0;
  1018. v.tdadr := 0;
  1019. RETURN TRUE;
  1020. END FindVar;
  1021. PROCEDURE WriteVar*(w: Streams.Writer; v: Variable; VAR col: LONGINT);
  1022. BEGIN
  1023. END WriteVar;
  1024. PROCEDURE ReportType*(w:Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE);
  1025. VAR size: SIZE; c: CHAR;
  1026. BEGIN
  1027. c := GetChar(refs, offset);
  1028. CASE c OF
  1029. sfTypeNone: w.String("no type");
  1030. | sfTypePointerToRecord: w.String("POINTER TO RECORD");
  1031. | sfTypePointerToArray: w.String("POINTER TO"); ReportType(w, refs, offset);
  1032. | sfTypeOpenArray: w.String("ARRAY OF "); ReportType(w, refs, offset);
  1033. | sfTypeStaticArray: w.String("ARRAY "); w.Int(GetSize(refs, offset),1 ); w.String(" OF "); ReportType(w, refs, offset);
  1034. | sfTypeDynamicArray: w.String("DARRAY OF "); ReportType(w,refs, offset);
  1035. | sfTypeMathOpenArray: w.String("ARRAY [*] OF "); ReportType(w, refs, offset);
  1036. | sfTypeMathStaticArray: w.String("ARRAY ["); w.Int(GetSize(refs, offset),1); w.String("] OF "); ReportType(w, refs, offset);
  1037. | sfTypeMathTensor: w.String("ARRAY [?] OF "); ReportType(w, refs, offset);
  1038. | sfTypeRecord: w.String("RECORD "); w.Address(GetAddress(refs, offset));
  1039. | sfTypeProcedure, sfTypeDelegate:
  1040. w.String("PROCEDURE"); IF c = sfTypeDelegate THEN w.String(" {DELEGATE}") END; w.String(" (");
  1041. WHILE refs[offset] = sfVariable DO ReportVariable(w, refs, offset) END;
  1042. w.String("):"); ReportType(w, refs, offset);
  1043. | sfTypeBOOLEAN: w.String("BOOLEAN");
  1044. | sfTypeCHAR: w.String("CHAR");
  1045. | sfTypeCHAR8: w.String("CHAR8");
  1046. | sfTypeCHAR16: w.String("CHAR16");
  1047. | sfTypeCHAR32: w.String("CHAR32");
  1048. | sfTypeSHORTINT: w.String("SHORTINT");
  1049. | sfTypeINTEGER: w.String("INTEGER");
  1050. | sfTypeLONGINT: w.String("LONGINT");
  1051. | sfTypeHUGEINT: w.String("HUGEINT");
  1052. | sfTypeWORD: w.String("WORD");
  1053. | sfTypeLONGWORD: w.String("LONGWORD");
  1054. | sfTypeSIGNED8: w.String("SIGNED8");
  1055. | sfTypeSIGNED16: w.String("SIGNED16");
  1056. | sfTypeSIGNED32: w.String("SIGNED32");
  1057. | sfTypeSIGNED64: w.String("SIGNED64");
  1058. | sfTypeUNSIGNED8: w.String("UNSIGNED8");
  1059. | sfTypeUNSIGNED16: w.String("UNSIGNED16");
  1060. | sfTypeUNSIGNED32: w.String("UNSIGNED32");
  1061. | sfTypeUNSIGNED64: w.String("UNSIGNED64");
  1062. | sfTypeREAL: w.String("REAL");
  1063. | sfTypeLONGREAL: w.String("LONGREAL");
  1064. | sfTypeCOMPLEX: w.String("COMPLEX");
  1065. | sfTypeLONGCOMPLEX: w.String("LONGCOMPLEX");
  1066. | sfTypeSET: w.String("SET");
  1067. | sfTypeANY: w.String("ANY");
  1068. | sfTypeOBJECT: w.String("OBJECT");
  1069. | sfTypeBYTE: w.String("BYTE");
  1070. | sfTypeRANGE: w.String("RANGE");
  1071. | sfTypeADDRESS: w.String("ADDRESS");
  1072. | sfTypeSIZE: w.String("SIZE");
  1073. | sfTypePORT: w.String("PORT"); IF GetChar(refs,offset) = sfIN THEN w.String("IN") ELSE w.String("OUT") END;
  1074. | sfTypeIndirect: w.String ("INDIRECT AT "); w.Int(GetSize(refs, offset),1);
  1075. ELSE w.String("????? TYPE ?????");
  1076. END;
  1077. END ReportType;
  1078. PROCEDURE ReportProcedure*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE);
  1079. VAR name: Name; start, end: ADDRESS; flags: SET;
  1080. BEGIN
  1081. w.Int(offset,1); w.String(":");
  1082. w.String("PROCEDURE ");
  1083. IF ~Expect(offset, GetChar(refs, offset) = sfProcedure) THEN RETURN END;
  1084. SkipSize(offset);
  1085. GetString(refs, offset, name);
  1086. w.String(name);
  1087. start := GetAddress(refs, offset);
  1088. end := GetAddress(refs, offset);
  1089. flags := GetSet(refs, offset);
  1090. IF flags # {} THEN
  1091. w.Set(flags);
  1092. END;
  1093. w.String("[@"); w.Address(start); w.String(" - "); w.Address(end); w.String("]");
  1094. w.String("("); w.Ln;
  1095. WHILE refs[offset] = sfVariable DO
  1096. ReportVariable(w, refs, offset);
  1097. END;
  1098. w.String(")");
  1099. w.String(":");
  1100. ReportType(w, refs, offset);
  1101. w.Ln;
  1102. ReportScope(w, refs, offset);
  1103. END ReportProcedure;
  1104. PROCEDURE ReportVariable*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE);
  1105. VAR name: ARRAY 128 OF CHAR; adr: ADDRESS; size: SIZE;
  1106. BEGIN
  1107. w.Int(offset,1); w.String(":");
  1108. w.String("VAR ");
  1109. IF ~Expect(offset, GetChar(refs, offset) = sfVariable) THEN RETURN END;
  1110. SkipSize(offset);
  1111. GetString(refs, offset, name);
  1112. w.String(name);
  1113. IF GetChar(refs, offset) = sfRelative THEN
  1114. size := GetSize(refs, offset);
  1115. w.String("[@"); w.Int(size,1); w.String("]");
  1116. ELSE (* absolute *)
  1117. adr := GetAddress(refs, offset);
  1118. w.String("[@"); w.Address(adr); w.String("]");
  1119. END;
  1120. w.String(":");
  1121. ReportType(w, refs, offset);
  1122. w.Ln;
  1123. END ReportVariable;
  1124. PROCEDURE ReportTypeDeclaration*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE);
  1125. VAR name: ARRAY 128 OF CHAR; adr: ADDRESS;
  1126. BEGIN
  1127. w.Int(offset,1); w.String(":");
  1128. w.String("TYPE ");
  1129. IF ~Expect(offset, GetChar(refs, offset) = sfTypeDeclaration) THEN RETURN END;
  1130. SkipSize(offset);
  1131. GetString(refs, offset, name);
  1132. w.String(name);
  1133. adr := GetAddress(refs, offset);
  1134. w.String(" ");
  1135. w.Address(adr);
  1136. w.Ln;
  1137. IF refs[offset] = sfScopeBegin THEN ReportScope(w, refs, offset) END;
  1138. END ReportTypeDeclaration;
  1139. PROCEDURE ReportScope*(w:Streams.Writer; refs: Modules.Bytes; VAR offset: SIZE);
  1140. BEGIN
  1141. IF ~Expect(offset, GetChar(refs, offset) = sfScopeBegin) THEN RETURN END;
  1142. w.Int(offset,1); w.String(": Scope"); w.Ln;
  1143. WHILE (refs[offset] = sfVariable) DO (* Variable *)
  1144. ReportVariable(w, refs, offset);
  1145. END;
  1146. WHILE (refs[offset] = sfProcedure) DO (* Procedure *)
  1147. ReportProcedure(w, refs, offset);
  1148. END;
  1149. WHILE (refs[offset] = sfTypeDeclaration) DO (* TypeDeclaration *)
  1150. ReportTypeDeclaration(w, refs, offset);
  1151. END;
  1152. IF ~Expect(offset, GetChar(refs, offset) = sfScopeEnd) THEN RETURN END;
  1153. w.String("END"); w.Ln;
  1154. END ReportScope;
  1155. PROCEDURE ReportModule*(w: Streams.Writer; refs: Modules.Bytes; offset: SIZE);
  1156. VAR name: Name;
  1157. BEGIN
  1158. w.String("MODULE ");
  1159. IF ~Expect(offset, GetChar(refs, offset) = sfModule) THEN RETURN END;
  1160. SkipSize(offset);
  1161. GetString(refs, offset, name);
  1162. w.String(name);
  1163. ReportScope(w, refs, offset);
  1164. END ReportModule;
  1165. PROCEDURE Report*(w:Streams.Writer; refs: Modules.Bytes; offset: SIZE);
  1166. BEGIN
  1167. CASE refs[offset] OF
  1168. sfModule: ReportModule(w, refs, offset);
  1169. |sfVariable: ReportVariable(w, refs, offset);
  1170. |sfProcedure: ReportProcedure(w, refs, offset);
  1171. |sfTypeDeclaration: ReportTypeDeclaration(w, refs, offset);
  1172. ELSE (* wrong position in stream *)
  1173. END;
  1174. END Report;
  1175. VAR trace: Streams.Writer;
  1176. PROCEDURE TraceH(process: Objects.Process; pc, bp: ADDRESS; stacklow, stackhigh: ADDRESS);
  1177. BEGIN
  1178. trace.String("----------- Process = ");
  1179. trace.Address(process);
  1180. trace.String(", Object = "); trace.Address(process.obj);
  1181. trace.Ln;
  1182. StackTraceBack(trace, pc, bp, stacklow ,stackhigh, TRUE, FALSE);
  1183. trace.Update;
  1184. END TraceH;
  1185. (* tracing the stacks of all processes during GC phase (needs to identify and stop all processes) *)
  1186. PROCEDURE TraceProcesses*;
  1187. BEGIN
  1188. Objects.TraceProcessHook := TraceH;
  1189. Kernel.GC;
  1190. Objects.TraceProcessHook := NIL;
  1191. END TraceProcesses;
  1192. PROCEDURE Test*;
  1193. VAR res: WORD; mod: Modules.Module; msg: ARRAY 32 OF CHAR; pos: SIZE;
  1194. BEGIN
  1195. mod := Modules.ThisModule("Reflection",res,msg);
  1196. ReportModule(trace, mod.refs, pos);
  1197. END Test;
  1198. BEGIN
  1199. NEW(trace, Trace.Send, 4 (*4096*) ); (* trace asap *)
  1200. modes := " rdy run awl awc awe rip"; (* 4 characters per mode from Objects.Ready to Objects.Terminated *)
  1201. END Reflection.
  1202. Linker.Link --fileFormat=PE32 --fileName=A2.exe --extension=GofW --displacement=401000H Builtins Trace Kernel32 Machine Heaps Modules Objects Kernel KernelLog Streams Commands Files WinFS Clock Dates Reals Strings Diagnostics BitSets StringPool ObjectFile GenericLinker Reflection Loader BootConsole ~