Reflection.Mod 40 KB

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