Reflection.Mod 40 KB

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