2
0

Generic.Reflection.Mod 39 KB

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