Decoder.Mod 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070
  1. (** AUTHOR "rg"; PURPOSE "Decoder for binary executable code"; *)
  2. MODULE Decoder;
  3. IMPORT SYSTEM, Modules, Streams, MemoryReader, Strings, Files, KernelLog, TextUtilities, Commands, WMGraphics,
  4. WMEditors, WMTextView, WMComponents, WMStandardComponents, WMDialogs, WMRestorable, WMTrees, WMMessages,
  5. WM := WMWindowManager, D:= Debugging;
  6. CONST
  7. maxDecoders = 5;
  8. MaxOpcodeSize = 20; (* enough for IA32 *)
  9. RepresentationModePlain = 0;
  10. RepresentationModeMeta = 1;
  11. OFFHdrRef = 8CX;
  12. OFFHdrBodyRef = 0F8X;
  13. OFFHdrProcRef = 0F9X;
  14. VarModeDirect = 1;
  15. VarModeIndirect = 3;
  16. VarRecord = 0;
  17. VarArray = 1;
  18. VarType = 2;
  19. AddressSize = SIZEOF(ADDRESS);
  20. TYPE
  21. Opcode* = OBJECT
  22. VAR
  23. instr* : LONGINT; (* instruction code *)
  24. offset* : ADDRESS;
  25. code* : Modules.Bytes;
  26. length- : LONGINT;
  27. decoder* : Decoder;
  28. next*: Opcode;
  29. stream : Streams.Writer;
  30. proc- : ProcedureInfo;
  31. PROCEDURE &New* (proc : ProcedureInfo; stream : Streams.Writer);
  32. BEGIN
  33. length := 0;
  34. SELF.proc := proc;
  35. SELF.stream := stream
  36. END New;
  37. PROCEDURE PrintOpcodeBytes* (w : Streams.Writer);
  38. END PrintOpcodeBytes;
  39. PROCEDURE PrintInstruction* (w : Streams.Writer);
  40. END PrintInstruction;
  41. PROCEDURE PrintArguments* (w : Streams.Writer);
  42. END PrintArguments;
  43. PROCEDURE PrintVariables* (w : Streams.Writer);
  44. END PrintVariables;
  45. PROCEDURE ToString* () : Strings.String;
  46. VAR
  47. str : ARRAY 255 OF CHAR;
  48. temp : ARRAY 10 OF CHAR;
  49. BEGIN
  50. Strings.IntToStr(instr, temp);
  51. Strings.Append(str, "Opcode: instr = "); Strings.Append(str, temp);
  52. Strings.IntToHexStr(offset, 0, temp);
  53. Strings.Append(str, ", offset = "); Strings.Append(str, temp);
  54. RETURN Strings.NewString(str)
  55. END ToString;
  56. PROCEDURE WriteHex8* (x : LONGINT; w : Streams.Writer);
  57. VAR result : ARRAY 3 OF CHAR;
  58. BEGIN
  59. IntToHex(x, 2, result); w.String(result)
  60. END WriteHex8;
  61. PROCEDURE WriteHex16* (x : LONGINT; w : Streams.Writer);
  62. VAR result : ARRAY 5 OF CHAR;
  63. BEGIN
  64. IntToHex(x, 4, result); w.String(result)
  65. END WriteHex16;
  66. PROCEDURE WriteHex32* (x : LONGINT; w : Streams.Writer);
  67. VAR result : ARRAY 10 OF CHAR;
  68. BEGIN
  69. IntToHex(x, 8, result); w.String(result)
  70. END WriteHex32;
  71. END Opcode;
  72. Decoder* = OBJECT
  73. VAR
  74. codeBuffer : Modules.Bytes;
  75. reader: Streams.Reader;
  76. outputStreamWriter* : Streams.Writer;
  77. firstOpcode, lastOpcode, currentOpcode: Opcode;
  78. completed : BOOLEAN;
  79. currentBufferPos, currentCodePos, opcodes, mode : LONGINT;
  80. currentProc* : ProcedureInfo;
  81. PROCEDURE &New* (reader : Streams.Reader);
  82. BEGIN
  83. SELF.reader := reader;
  84. SELF.mode := mode;
  85. NEW(codeBuffer, MaxOpcodeSize); (* limit: maximum # bytes per opcode *)
  86. currentCodePos := 0;
  87. opcodes := 0;
  88. completed := FALSE
  89. END New;
  90. PROCEDURE Bug* (op, no: LONGINT);
  91. BEGIN
  92. KernelLog.Ln; KernelLog.String("*** decode error ***; "); KernelLog.String("op = "); KernelLog.Hex(op, -1); KernelLog.String(", no = "); KernelLog.Int(no, 0); KernelLog.Ln;
  93. completed := TRUE
  94. END Bug;
  95. PROCEDURE NewOpcode* () : Opcode;
  96. VAR
  97. opcode : Opcode;
  98. BEGIN
  99. NEW(opcode, currentProc, outputStreamWriter);
  100. RETURN opcode
  101. END NewOpcode;
  102. PROCEDURE DecodeThis* (opcode : Opcode);
  103. END DecodeThis;
  104. PROCEDURE Decode* (proc : ProcedureInfo) : Opcode;
  105. (*
  106. VAR
  107. str : Strings.String;
  108. *)
  109. BEGIN
  110. currentProc := proc;
  111. WHILE ~completed DO
  112. currentBufferPos := 0;
  113. IF reader.Available() > 0 THEN
  114. currentOpcode := NewOpcode();
  115. BEGIN {EXCLUSIVE}
  116. DecodeThis(currentOpcode);
  117. IF reader.res = Streams.Ok THEN
  118. IF lastOpcode = NIL THEN
  119. lastOpcode := currentOpcode;
  120. firstOpcode := currentOpcode;
  121. ELSE
  122. lastOpcode.next := currentOpcode;
  123. lastOpcode := currentOpcode
  124. END;
  125. currentOpcode.offset := currentCodePos+proc.codeOffset;
  126. (*
  127. str := currentOpcode.ToString();
  128. KernelLog.String(str^); KernelLog.Ln;
  129. *)
  130. INC(currentOpcode.length);
  131. (* copy all buffered bytes to the opcode *)
  132. CopyBufferToOpcode(currentOpcode);
  133. INC(opcodes)
  134. END
  135. END
  136. ELSE
  137. completed := TRUE
  138. END;
  139. IF reader.res # Streams.Ok THEN completed := TRUE END;
  140. END;
  141. RETURN firstOpcode
  142. END Decode;
  143. PROCEDURE CopyBufferToOpcode(opcode : Opcode);
  144. VAR i : LONGINT;
  145. BEGIN
  146. NEW(opcode.code, currentBufferPos);
  147. FOR i := 0 TO currentBufferPos-1 DO
  148. opcode.code[i] := codeBuffer[i]
  149. END;
  150. opcode.length := currentBufferPos;
  151. INC(currentCodePos, currentBufferPos)
  152. END CopyBufferToOpcode;
  153. PROCEDURE InsertBytesAtBufferHead* (bytes : Modules.Bytes);
  154. VAR i, n : LONGINT;
  155. BEGIN
  156. n := LEN(bytes);
  157. FOR i := currentBufferPos-1 TO 0 BY -1 DO
  158. codeBuffer[i+n] := codeBuffer[i]
  159. END;
  160. FOR i := 0 TO n-1 DO
  161. codeBuffer[i] := bytes[i]
  162. END;
  163. INC(currentBufferPos, n)
  164. END InsertBytesAtBufferHead;
  165. PROCEDURE ReadChar* () : CHAR;
  166. VAR
  167. ch : CHAR;
  168. BEGIN
  169. reader.Char(ch);
  170. IF reader.res = Streams.Ok THEN
  171. codeBuffer[currentBufferPos] := ch;
  172. INC(currentBufferPos);
  173. END;
  174. RETURN ch
  175. END ReadChar;
  176. PROCEDURE ReadInt* () : INTEGER;
  177. VAR
  178. i : INTEGER;
  179. BEGIN
  180. reader.RawInt(i);
  181. IF reader.res = Streams.Ok THEN
  182. SYSTEM.MOVE(ADDRESSOF(i), ADDRESSOF(codeBuffer[currentBufferPos]), 2);
  183. INC(currentBufferPos, 2)
  184. END;
  185. RETURN i
  186. END ReadInt;
  187. PROCEDURE ReadLInt* () : LONGINT;
  188. VAR
  189. l, highByte, base : LONGINT;
  190. ch : CHAR;
  191. BEGIN
  192. ch := ReadChar();
  193. l := LONG(ORD(ch));
  194. ch := ReadChar();
  195. l := l + LONG(ORD(ch)) * 100H;
  196. ch := ReadChar();
  197. l := l + LONG(ORD(ch)) * 10000H;
  198. ch := ReadChar();
  199. highByte := ORD(ch);
  200. IF highByte >= 128 THEN base := MIN(LONGINT); DEC(highByte, 128) ELSE base := 0 END;
  201. l := base + highByte * 1000000H + l;
  202. RETURN l
  203. END ReadLInt;
  204. END Decoder;
  205. DecoderFactory = PROCEDURE {DELEGATE} (reader : Streams.Reader) : Decoder;
  206. Info = OBJECT
  207. VAR
  208. name-: ARRAY 256 OF CHAR;
  209. END Info;
  210. FieldInfo* = OBJECT (Info)
  211. VAR
  212. offset, mode, kind, type, dim, tdadr : LONGINT;
  213. markerPositions, temp : POINTER TO ARRAY OF RECORD
  214. pos : LONGINT;
  215. marker : WMTextView.PositionMarker
  216. END;
  217. nextMarker, markerSize : LONGINT;
  218. markersCreated : BOOLEAN;
  219. procedure : ProcedureInfo;
  220. PROCEDURE WriteType(w : Streams.Writer);
  221. BEGIN
  222. IF mode = VarModeIndirect THEN w.String("VAR ") END;
  223. IF kind = VarArray THEN w.String("ARRAY "); w.Int(dim, 0); w.String(" OF ") END;
  224. CASE type OF
  225. 1H : w.String("BYTE")
  226. | 2H : w.String("BOOLEAN")
  227. | 3H : w.String("CHAR")
  228. | 4H : w.String("SHORTINT")
  229. | 5H : w.String("INTEGER")
  230. | 6H : w.String("LONGINT")
  231. | 7H : w.String("REAL")
  232. | 8H : w.String("LONGREAL")
  233. | 9H : w.String("SET")
  234. | 0AH : w.String("?")
  235. | 0BH : w.String("?")
  236. | 0CH : w.String("?")
  237. | 0DH : w.String("PTR")
  238. | 0EH : w.String("PROC")
  239. | 0FH : w.String("STRING")
  240. | 10H : w.String("HUGEINT")
  241. | 16H : w.String("RECORD")
  242. | 1DH : w.String("OBJECT")
  243. ELSE
  244. END;
  245. END WriteType;
  246. PROCEDURE ToString(w : Streams.Writer);
  247. BEGIN
  248. w.String(name);
  249. w.String(" (");
  250. WriteType(w);
  251. w.String(") [");
  252. w.Int(offset, 0);
  253. w.String("]")
  254. END ToString;
  255. PROCEDURE AddMarkerPosition* (pos : LONGINT);
  256. VAR i : LONGINT;
  257. BEGIN
  258. markersCreated := FALSE;
  259. IF markerPositions = NIL THEN markerSize := 5; NEW(markerPositions, markerSize); nextMarker := 0 END;
  260. IF nextMarker >= LEN(markerPositions) THEN
  261. temp := markerPositions;
  262. markerSize := 2*markerSize;
  263. NEW(markerPositions, markerSize);
  264. FOR i := 0 TO nextMarker-1 DO
  265. markerPositions[i] := temp[i]
  266. END
  267. END;
  268. markerPositions[nextMarker].pos := pos;
  269. INC(nextMarker)
  270. END AddMarkerPosition;
  271. PROCEDURE CreateMarkers (tv : WMTextView.TextView);
  272. VAR i : LONGINT;
  273. BEGIN
  274. FOR i := 0 TO nextMarker-1 DO
  275. markerPositions[i].marker := tv.CreatePositionMarker();
  276. markerPositions[i].marker.SetPosition(markerPositions[i].pos);
  277. markerPositions[i].marker.SetVisible(FALSE);
  278. markerPositions[i].marker.Load("DecoderRes.zip://VariablePositionIcon.png")
  279. END;
  280. markersCreated := TRUE
  281. END CreateMarkers;
  282. PROCEDURE ToggleMarkers(enabled : BOOLEAN);
  283. VAR i : LONGINT;
  284. BEGIN
  285. IF markersCreated THEN
  286. FOR i := 0 TO nextMarker-1 DO
  287. markerPositions[i].marker.SetVisible(enabled)
  288. END
  289. END
  290. END ToggleMarkers
  291. END FieldInfo;
  292. FieldArray = POINTER TO ARRAY OF FieldInfo;
  293. ProcedureInfo* = OBJECT (Info)
  294. VAR
  295. codeOffset: ADDRESS; codeSize: LONGINT;
  296. retType, index : LONGINT;
  297. fields : FieldArray;
  298. fieldCount : LONGINT;
  299. method : BOOLEAN;
  300. gcInfo: GCInfo;
  301. PROCEDURE &New (CONST n : ARRAY OF CHAR; ofs: ADDRESS; idx : LONGINT);
  302. BEGIN
  303. COPY (n, name);
  304. codeOffset := ofs;
  305. index := idx;
  306. method := FALSE;
  307. NEW(fields, 5);
  308. gcInfo := NIL;
  309. END New;
  310. PROCEDURE AddField (fldInfo : FieldInfo);
  311. VAR
  312. oldFlds : FieldArray;
  313. i, len : LONGINT;
  314. BEGIN
  315. IF fieldCount = LEN(fields) THEN
  316. oldFlds := fields;
  317. len := LEN(fields);
  318. NEW(fields, 2 * len);
  319. FOR i := 0 TO len-1 DO fields[i] := oldFlds[i] END;
  320. END;
  321. fields[fieldCount] := fldInfo;
  322. INC(fieldCount)
  323. END AddField;
  324. PROCEDURE GetFieldAtOffset*(offset : LONGINT) : FieldInfo;
  325. VAR
  326. i : LONGINT;
  327. BEGIN
  328. i := 0;
  329. WHILE i < fieldCount DO
  330. IF fields[i].offset = offset THEN RETURN fields[i] END;
  331. INC(i)
  332. END;
  333. RETURN NIL
  334. END GetFieldAtOffset;
  335. END ProcedureInfo;
  336. ProcedureArray = POINTER TO ARRAY OF ProcedureInfo;
  337. TypeInfo* = OBJECT (Info)
  338. VAR
  339. procedures : ProcedureArray;
  340. fields : FieldArray;
  341. procedureCount, fieldCount : LONGINT;
  342. PROCEDURE &New (CONST n : ARRAY OF CHAR);
  343. BEGIN
  344. COPY (n, name);
  345. procedureCount := 0;
  346. fieldCount := 0;
  347. NEW(procedures, 5);
  348. NEW(fields, 5)
  349. END New;
  350. PROCEDURE AddProcedure (procInfo : ProcedureInfo);
  351. VAR
  352. oldProcs : ProcedureArray;
  353. i, len : LONGINT;
  354. BEGIN
  355. IF procedureCount = LEN(procedures) THEN
  356. oldProcs := procedures;
  357. len := LEN(procedures);
  358. NEW(procedures, 2 * len);
  359. FOR i := 0 TO len-1 DO procedures[i] := oldProcs[i] END;
  360. END;
  361. procedures[procedureCount] := procInfo;
  362. INC(procedureCount)
  363. END AddProcedure;
  364. END TypeInfo;
  365. TypeArray = POINTER TO ARRAY OF TypeInfo;
  366. Export*=POINTER TO RECORD
  367. next: Export;
  368. fp: LONGINT;
  369. type: LONGINT;
  370. val: LONGINT;
  371. name: ARRAY 256 OF CHAR;
  372. END;
  373. Use= POINTER TO RECORD
  374. next: Use;
  375. fp: LONGINT;
  376. type: LONGINT;
  377. val: LONGINT;
  378. name: ARRAY 256 OF CHAR;
  379. END;
  380. Import=OBJECT
  381. VAR
  382. next: Import;
  383. name: ARRAY 256 OF CHAR;
  384. uses: Use;
  385. PROCEDURE AddUse(u: Use);
  386. VAR x: Use;
  387. BEGIN
  388. IF uses = NIL THEN uses := u
  389. ELSE x := uses; WHILE x.next # NIL DO x := x.next; END;
  390. x.next := u;
  391. END;
  392. END AddUse;
  393. END Import;
  394. VarConstLink=RECORD
  395. num: LONGINT;
  396. ch: CHAR;
  397. links: POINTER TO ARRAY OF LONGINT;
  398. END;
  399. Link=RECORD
  400. num: LONGINT;
  401. END;
  402. Entry=RECORD
  403. num: LONGINT;
  404. END;
  405. GCInfo= POINTER TO RECORD
  406. codeOffset, beginOffset, endOffset: LONGINT;
  407. pointers: POINTER TO ARRAY OF LONGINT
  408. END;
  409. ObjHeader = RECORD (* data from object file header *)
  410. entries, commands, pointers, types, modules, links, dataLinks: LONGINT;
  411. codeSize, dataSize, refSize, constSize, exTableLen, procs, maxPtrs, crc: LONGINT;
  412. staticTdSize: LONGINT; (* ug *)
  413. name: Modules.Name
  414. END;
  415. ModuleInfo* = OBJECT (Info)
  416. VAR
  417. module : Modules.Module;
  418. header: ObjHeader;
  419. representationMode : LONGINT;
  420. procedures : ProcedureArray; (* references to all procedures, including methods *)
  421. procedureCount : LONGINT;
  422. types : TypeArray;
  423. typeCount : LONGINT;
  424. treeView : WMTrees.TreeView;
  425. tree : WMTrees.Tree;
  426. treePanel, lastDAssPanel : WMStandardComponents.Panel;
  427. resizerH : WMStandardComponents.Resizer;
  428. editor : WMEditors.Editor;
  429. textWriter : TextUtilities.TextWriter;
  430. currentProcInfo : ProcedureInfo;
  431. markPC : LONGINT;
  432. ext : Extension;
  433. codeScaleCallback: CodeScaleCallback;
  434. exports: Export;
  435. imports: Import;
  436. varConstLinks: POINTER TO ARRAY OF VarConstLink;
  437. links: POINTER TO ARRAY OF Link;
  438. entries: POINTER TO ARRAY OF Entry;
  439. gcInfo: POINTER TO ARRAY OF GCInfo;
  440. PROCEDURE AddExport(e: Export);
  441. VAR x: Export;
  442. BEGIN
  443. IF exports = NIL THEN exports := e
  444. ELSE
  445. x := exports;
  446. WHILE x.next # NIL DO x := x.next END;
  447. x.next := e;
  448. END;
  449. END AddExport;
  450. PROCEDURE AddImport(i: Import);
  451. VAR x: Import;
  452. BEGIN
  453. IF imports = NIL THEN imports := i
  454. ELSE
  455. x := imports;
  456. WHILE x.next # NIL DO x := x.next END;
  457. x.next := i;
  458. END;
  459. END AddImport;
  460. PROCEDURE IsExceptionHandled(pc: ADDRESS): BOOLEAN;
  461. VAR
  462. i: LONGINT;
  463. entry: Modules.ExceptionTableEntry;
  464. BEGIN
  465. IF (module # NIL) & (module.exTable # NIL) THEN
  466. FOR i := 0 TO LEN(module.exTable) - 1 DO
  467. entry := module.exTable[i];
  468. IF (entry.pcFrom <= pc) & (entry.pcTo > pc) THEN
  469. RETURN TRUE;
  470. END
  471. END
  472. END;
  473. RETURN FALSE;
  474. END IsExceptionHandled;
  475. PROCEDURE GetOpcodes (proc : ProcedureInfo) : Opcode;
  476. VAR
  477. reader : MemoryReader.Reader;
  478. ofs : ADDRESS;
  479. decoder : Decoder;
  480. BEGIN
  481. ofs := ADDRESSOF(module.code[proc.codeOffset]);
  482. NEW(reader, ofs, proc.codeSize);
  483. decoder := GetDecoder(ext, reader);
  484. RETURN decoder.Decode(proc)
  485. END GetOpcodes;
  486. PROCEDURE AddProcedure (procInfo : ProcedureInfo);
  487. VAR
  488. oldProcs : ProcedureArray;
  489. i, len : LONGINT;
  490. BEGIN
  491. IF procedureCount = LEN(procedures) THEN
  492. oldProcs := procedures;
  493. len := LEN(procedures);
  494. NEW(procedures, 2 * len);
  495. FOR i := 0 TO len-1 DO procedures[i] := oldProcs[i] END
  496. END;
  497. procedures[procedureCount] := procInfo;
  498. INC(procedureCount)
  499. END AddProcedure;
  500. PROCEDURE FindEntryByOffset (ofs : ADDRESS) : LONGINT;
  501. VAR
  502. i : LONGINT;
  503. BEGIN
  504. i := 0;
  505. WHILE i < header.entries DO
  506. IF ofs = module.entry[i] THEN RETURN i END;
  507. INC(i)
  508. END;
  509. RETURN -1
  510. END FindEntryByOffset;
  511. PROCEDURE GetProcedureByIndex (idx : LONGINT) : ProcedureInfo;
  512. VAR
  513. i : LONGINT;
  514. BEGIN
  515. i := 0;
  516. WHILE i < procedureCount DO
  517. IF idx = procedures[i].index THEN
  518. RETURN procedures[i]
  519. END;
  520. INC(i)
  521. END;
  522. RETURN NIL
  523. END GetProcedureByIndex;
  524. PROCEDURE DecodeRefs(reader : Streams.Reader);
  525. VAR idx, thisIdx : LONGINT;
  526. procInfo : ProcedureInfo;
  527. fldInfo : FieldInfo;
  528. ch : CHAR;
  529. ofs, prevOfs, retType, entry : LONGINT;
  530. name :ARRAY 256 OF CHAR;
  531. i: LONGINT;
  532. BEGIN
  533. ASSERT(header.codeSize > 0);
  534. (* body ref *)
  535. IF reader.Available() > 0 THEN
  536. ch := reader.Get();
  537. ASSERT(ch = OFFHdrBodyRef);
  538. reader.RawNum(ofs);
  539. reader.RawString(name);
  540. ASSERT(name = "$$");
  541. name := "@Body";
  542. NEW(procInfo, name, 0, header.entries); (* indexes below this are reserved by procedures/methods part of entries *)
  543. AddProcedure(procInfo);
  544. fldInfo := DecodeField(reader);
  545. WHILE fldInfo # NIL DO
  546. procInfo.AddField(fldInfo);
  547. fldInfo := DecodeField(reader);
  548. END
  549. END;
  550. idx := header.entries+1; (* start after entries and BODY *)
  551. ofs := 0;
  552. WHILE (reader.Available() > 0) & (reader.Peek() = OFFHdrProcRef) DO
  553. ch := reader.Get();
  554. prevOfs := ofs;
  555. reader.RawNum(ofs);
  556. IF (codeScaleCallback # NIL) THEN codeScaleCallback(ofs) END;
  557. ASSERT(procInfo # NIL);
  558. procInfo.codeSize := ofs - prevOfs; (* set size of previous procedure *)
  559. FOR i := 0 TO LEN(gcInfo)-1 DO
  560. IF (gcInfo[i]# NIL) & (prevOfs <=gcInfo[i].codeOffset) & (gcInfo[i].endOffset <= ofs) THEN
  561. procInfo.gcInfo := gcInfo[i]
  562. END;
  563. END;
  564. ch := reader.Get();
  565. retType := SYSTEM.VAL(LONGINT, reader.Get());
  566. ch := reader.Get(); ch := reader.Get();
  567. reader.RawString(name);
  568. entry := FindEntryByOffset(ofs);
  569. procInfo := NIL;
  570. IF entry >= 0 THEN
  571. procInfo := GetProcedureByIndex(entry);
  572. thisIdx := entry
  573. ELSE
  574. thisIdx := idx;
  575. INC(idx)
  576. END;
  577. IF procInfo = NIL THEN
  578. NEW(procInfo, name, ofs, thisIdx);
  579. AddProcedure(procInfo);
  580. ELSE
  581. COPY(name,procInfo.name);
  582. END;
  583. procInfo.retType := retType;
  584. fldInfo := DecodeField(reader);
  585. WHILE fldInfo # NIL DO
  586. procInfo.AddField(fldInfo);
  587. fldInfo := DecodeField(reader);
  588. END
  589. END;
  590. ASSERT(procInfo # NIL);
  591. procInfo.codeSize := header.codeSize - ofs; (* set size of last procedure *)
  592. FOR i := 0 TO LEN(gcInfo)-1 DO
  593. IF (gcInfo[i]# NIL) & (ofs <=gcInfo[i].codeOffset) & (gcInfo[i].endOffset <= header.codeSize) THEN
  594. procInfo.gcInfo := gcInfo[i]
  595. END;
  596. END;
  597. END DecodeRefs;
  598. PROCEDURE DecodeTypes;
  599. END DecodeTypes;
  600. PROCEDURE DecodeField(reader : Streams.Reader) : FieldInfo;
  601. VAR
  602. fieldInfo : FieldInfo;
  603. ch : CHAR;
  604. BEGIN
  605. NEW(fieldInfo);
  606. IF reader.Peek() = 1X THEN
  607. fieldInfo.mode := VarModeDirect
  608. ELSIF reader.Peek() = 3X THEN
  609. fieldInfo.mode := VarModeIndirect
  610. ELSE
  611. RETURN NIL (* not a field *)
  612. END;
  613. ch := reader.Get();
  614. fieldInfo.type := SYSTEM.VAL(LONGINT, reader.Get());
  615. IF fieldInfo.type <= 15H THEN
  616. fieldInfo.kind := VarType;
  617. ELSIF (fieldInfo.type >= 81H) & (fieldInfo.type <= 90H) THEN
  618. fieldInfo.kind := VarArray;
  619. DEC(fieldInfo.type, 80H);
  620. reader.RawNum(fieldInfo.dim)
  621. ELSE
  622. (*ASSERT((fieldInfo.type = 16H) OR (fieldInfo.type = 1DH));*)
  623. fieldInfo.kind := VarRecord;
  624. reader.RawNum(fieldInfo.tdadr)
  625. END;
  626. reader.RawNum(fieldInfo.offset);
  627. reader.RawString(fieldInfo.name);
  628. RETURN fieldInfo
  629. END DecodeField;
  630. PROCEDURE FindProcedureFromPC(pc : LONGINT) : ProcedureInfo;
  631. VAR
  632. i : LONGINT;
  633. BEGIN
  634. ASSERT(procedures # NIL);
  635. WHILE i < procedureCount DO
  636. IF (pc >= procedures[i].codeOffset) & (pc < procedures[i].codeOffset + procedures[i].codeSize) THEN
  637. RETURN procedures[i]
  638. END;
  639. INC(i)
  640. END;
  641. RETURN NIL
  642. END FindProcedureFromPC;
  643. PROCEDURE Init;
  644. BEGIN
  645. NEW(module);
  646. procedureCount := 0;
  647. markPC := -1;
  648. NEW(procedures, 5);
  649. codeScaleCallback := NIL;
  650. ext := ""
  651. END Init;
  652. PROCEDURE ClickNode(sender, data : ANY);
  653. VAR
  654. d: ANY;
  655. i : LONGINT;
  656. PROCEDURE ChangeProcedure(proc : ProcedureInfo);
  657. BEGIN
  658. IF editor # NIL THEN lastDAssPanel.RemoveContent(editor) END;
  659. OutlineProcedure(proc, lastDAssPanel)
  660. END ChangeProcedure;
  661. BEGIN
  662. lastDAssPanel.DisableUpdate;
  663. IF (data # NIL) & (data IS WMTrees.TreeNode) THEN
  664. tree.Acquire;
  665. d := tree.GetNodeData(data(WMTrees.TreeNode));
  666. tree.Release;
  667. IF d # NIL THEN
  668. IF d IS ProcedureInfo THEN ChangeProcedure(d(ProcedureInfo))
  669. ELSIF d IS FieldInfo THEN
  670. IF (currentProcInfo = NIL) OR (d(FieldInfo).procedure # currentProcInfo) THEN ChangeProcedure(d(FieldInfo).procedure)
  671. ELSE
  672. FOR i := 0 TO currentProcInfo.fieldCount-1 DO
  673. currentProcInfo.fields[i].ToggleMarkers(FALSE)
  674. END;
  675. END;
  676. d(FieldInfo).ToggleMarkers(TRUE);
  677. ELSIF d IS TypeInfo THEN
  678. IF editor # NIL THEN lastDAssPanel.RemoveContent(editor) END;
  679. OutlineType(d(TypeInfo), lastDAssPanel)
  680. ELSIF d IS ModuleInfo THEN
  681. IF editor # NIL THEN lastDAssPanel.RemoveContent(editor) END;
  682. OutlineModule(d(ModuleInfo), lastDAssPanel)
  683. ELSE
  684. HALT(99)
  685. END
  686. END
  687. END;
  688. lastDAssPanel.EnableUpdate;
  689. lastDAssPanel.Invalidate
  690. END ClickNode;
  691. PROCEDURE OutlineNamedProcedure(CONST name : ARRAY OF CHAR);
  692. VAR found : BOOLEAN;
  693. i : LONGINT;
  694. BEGIN
  695. i := 0; found := FALSE;
  696. WHILE ~found & (i < procedureCount) DO
  697. IF procedures[i].name = name THEN
  698. found := TRUE;
  699. OutlineProcedure(procedures[i], lastDAssPanel)
  700. END;
  701. INC(i)
  702. END;
  703. IF ~found THEN
  704. KernelLog.String("Decoder: ERROR: OutlineNamedProcedure: Procedure not found: "); KernelLog.String(name); KernelLog.Ln
  705. END
  706. END OutlineNamedProcedure;
  707. PROCEDURE OutlinePC (pc : LONGINT);
  708. VAR proc : ProcedureInfo;
  709. BEGIN
  710. proc := FindProcedureFromPC(pc);
  711. IF proc # NIL THEN
  712. markPC := pc;
  713. OutlineProcedure(proc, lastDAssPanel);
  714. markPC := -1;
  715. ELSE
  716. KernelLog.String("Decoder: ERROR: OutlinePC: Procedure not found at PC: "); KernelLog.Hex(pc, 0); KernelLog.Ln
  717. END
  718. END OutlinePC;
  719. PROCEDURE InitializeOutline (panel : WMStandardComponents.Panel) : Streams.Writer;
  720. VAR
  721. avgTabSize : LONGINT;
  722. tabStops : WMTextView.CustomTabStops;
  723. tabPositions : WMTextView.TabPositions;
  724. BEGIN
  725. NEW(editor); editor.alignment.Set(WMComponents.AlignClient);
  726. panel.AddContent(editor);
  727. panel.Reset(SELF, NIL);
  728. panel.AlignSubComponents;
  729. NEW(tabPositions, 4);
  730. avgTabSize := editor.bounds.GetWidth() DIV 14; (* 5 columns, 2 have double width *)
  731. tabPositions[0] := 2*avgTabSize; tabPositions[1] := 6*avgTabSize; tabPositions[2] := 8*avgTabSize; tabPositions[3] := 11*avgTabSize;
  732. NEW(tabStops, tabPositions);
  733. editor.tv.SetTabStops(tabStops);
  734. editor.tv.wrapMode.Set(WMTextView.NoWrap);
  735. NEW(textWriter, editor.text);
  736. RETURN textWriter
  737. END InitializeOutline;
  738. PROCEDURE OutlineProcedure (proc : ProcedureInfo; panel : WMStandardComponents.Panel);
  739. VAR
  740. s : Strings.String;
  741. opcodes : Opcode;
  742. w : Streams.Writer;
  743. i: LONGINT;
  744. opStart, opEnd: ADDRESS; pcPos : LONGINT;
  745. pcMarker : WMTextView.PositionMarker;
  746. (* ug *) s2: Strings.String;
  747. BEGIN
  748. currentProcInfo := proc;
  749. w := InitializeOutline(panel);
  750. textWriter.SetFontStyle({WMGraphics.FontBold});
  751. w.String(currentProcInfo.name);
  752. w.String(":");
  753. (* ug *) w.Ln; w.String("codeOffset = "); NEW(s2, 20); IntToHex(currentProcInfo.codeOffset, 8, s2^); Strings.Append(s2^, "H"); w.String(s2^);
  754. w.Ln; w.Ln;
  755. textWriter.SetFontStyle({});
  756. (* output data *)
  757. opcodes := GetOpcodes(currentProcInfo);
  758. WHILE opcodes # NIL DO
  759. IF IsExceptionHandled(opcodes.offset) THEN
  760. textWriter.SetBgColor(LONGINT(0C0D5FFFFH));
  761. ELSE
  762. textWriter.SetBgColor(WMGraphics.White);
  763. END;
  764. textWriter.SetFontColor(WMGraphics.Black);
  765. NEW(s, 20);
  766. IntToHex(opcodes.offset, 8, s^);
  767. Strings.Append(s^, "H");
  768. w.String(s^); w.Char(9X);
  769. (* insert marker for pc if selected *)
  770. IF markPC >= 0 THEN
  771. opStart := opcodes.offset;
  772. opEnd := opStart + opcodes.length - 1;
  773. IF (markPC >= opStart) & (markPC <= opEnd) THEN
  774. pcPos := w.Pos() + LONGINT((markPC-opStart)*3); (* text position within opcode bytes *)
  775. END
  776. END;
  777. opcodes.PrintOpcodeBytes(w); w.Char(9X);
  778. textWriter.SetFontColor(0000099FFH);
  779. opcodes.PrintInstruction(w); w.Char(9X);
  780. opcodes.PrintArguments(w); w.Char(9X);
  781. textWriter.SetFontColor(LONGINT(0999999FFH));
  782. opcodes.PrintVariables(w);
  783. w.Ln;
  784. opcodes := opcodes.next
  785. END;
  786. w.Update;
  787. IF proc.gcInfo # NIL THEN
  788. w.Ln;
  789. w.String("pcFrom="); w.Hex(proc.gcInfo.codeOffset,1);w.Ln;
  790. w.String("gcEnd="); w.Hex(proc.gcInfo.endOffset,1);w.Ln;
  791. w.String("gcBegin="); w.Hex(proc.gcInfo.beginOffset,1);w.Ln;
  792. FOR i := 0 TO LEN(proc.gcInfo.pointers)-1 DO
  793. w.String("ptr @ "); w.Int(proc.gcInfo.pointers[i],1); w.Ln;
  794. END;
  795. END;
  796. w.Update;
  797. IF markPC >= 0 THEN
  798. (* insert marker *)
  799. pcMarker := editor.tv.CreatePositionMarker();
  800. pcMarker.SetPosition(pcPos);
  801. pcMarker.SetVisible(TRUE);
  802. pcMarker.Load ("DecoderRes.zip://PCPositionIcon.png");
  803. editor.tv.cursor.SetPosition(pcPos);
  804. markPC := -1 (* forget this pc now *)
  805. ELSE
  806. editor.tv.cursor.SetPosition(0)
  807. END;
  808. (* set markers to highlight variables *)
  809. FOR i := 0 TO currentProcInfo.fieldCount-1 DO
  810. currentProcInfo.fields[i].CreateMarkers(editor.tv);
  811. END;
  812. END OutlineProcedure;
  813. PROCEDURE OutlineType (typeInfo : TypeInfo; panel : WMStandardComponents.Panel);
  814. VAR
  815. w : Streams.Writer;
  816. BEGIN
  817. w := InitializeOutline(panel);
  818. textWriter.SetFontStyle({WMGraphics.FontBold});
  819. w.String(typeInfo.name);
  820. w.String(":"); w.Ln; w.Ln;
  821. textWriter.SetFontStyle({});
  822. (*
  823. w.String("Fields: "); w.Int(typeInfo.fieldCount, 0); w.Ln;
  824. FOR i := 0 TO typeInfo.fieldCount-1 DO
  825. w.String(typeInfo.fields[i].name); w.Char(9X);
  826. typeInfo.fields[i].WriteType(w); w.Char(9X);
  827. w.String(") ["); w.Int(typeInfo.fields[i].offset, 0); w.String("]")
  828. END;
  829. *)
  830. w.Update
  831. END OutlineType;
  832. PROCEDURE OutlineModule (moduleInfo: ModuleInfo; panel : WMStandardComponents.Panel);
  833. VAR
  834. w : Streams.Writer;
  835. i,j : LONGINT;
  836. ch: CHAR;
  837. proc : ProcedureInfo;
  838. e: Export;
  839. import: Import;
  840. u: Use;
  841. PROCEDURE DataBlock(from,to: LONGINT);
  842. VAR i: LONGINT; ch: CHAR;
  843. BEGIN
  844. IF to >= LEN(module.data) THEN to := LEN(module.data)-1 END;
  845. FOR i := from TO to DO
  846. ch := module.data[i];
  847. w.Hex(ORD(ch),-2); w.String(" ");
  848. END;
  849. FOR i := from TO to DO
  850. ch := module.data[i];
  851. IF (ORD(ch)>20) & (ORD(ch)<127) THEN
  852. w.Char(ch)
  853. ELSE
  854. w.Char(".")
  855. END;
  856. END;
  857. w.Ln;
  858. END DataBlock;
  859. BEGIN
  860. w := InitializeOutline(panel);
  861. w.String(moduleInfo.name);
  862. w.String(":"); w.Ln; w.Ln;
  863. ASSERT(module # NIL);
  864. w.String("refSize:"); w.Char(9X); w.Int(header.refSize, 0); w.String(" ("); w.Hex(header.refSize, 0); w.String("H)"); w.Ln;
  865. w.String("# entries:"); w.Char(9X); w.Int(header.entries, 0); w.Ln;
  866. w.String("# commands:"); w.Char(9X); w.Int(header.commands, 0); w.Ln;
  867. w.String("# pointers:"); w.Char(9X); w.Int(header.pointers, 0); w.Ln;
  868. w.String("# types"); w.Char(9X); w.Int(header.types, 0); w.Ln;
  869. w.String("dataSize:"); w.Char(9X); w.Int(header.dataSize, 0); w.String(" ("); w.Hex(header.dataSize, 0); w.String("H)"); w.Ln;
  870. w.String("constSize:"); w.Char(9X); w.Int(header.constSize, 0); w.String(" ("); w.Hex(header.constSize, 0); w.String("H)"); w.Ln;
  871. w.String("codeSize:"); w.Char(9X); w.Int(header.codeSize, 0); w.String(" ("); w.Hex(header.codeSize, 0); w.String("H)"); w.Ln;
  872. w.String("crc:"); w.Char(9X); w.Hex(header.crc,-8); w.Ln;
  873. w.Ln;
  874. w.String("Constants:"); w.Ln;
  875. FOR i := 0 TO header.constSize-1 BY 16 DO
  876. DataBlock(i,i+15);
  877. END;
  878. IF (header.constSize-1) MOD 32 # 31 THEN w.Ln END;
  879. w.Ln;
  880. w.String("Entries:"); w.Ln;
  881. FOR i := 0 TO header.entries-1 DO
  882. proc := GetProcedureByIndex(FindEntryByOffset(module.entry[i]));
  883. w.Hex(module.entry[i], 0); w.Char(9X);
  884. IF proc # NIL THEN w.String(proc.name) END;
  885. w.Ln;
  886. END;
  887. w.Ln;
  888. w.String("Exception Handler Table"); w.Ln;
  889. FOR i := 0 TO header.exTableLen - 1 DO
  890. w.String("pcFrom= "); w.Hex(module.exTable[i].pcFrom, 0);
  891. w.String("H pcTo= "); w.Hex(module.exTable[i].pcTo, 0);
  892. w.String("H pcHandler= "); w.Hex(module.exTable[i].pcHandler, 0);
  893. w.String("H");
  894. w.Ln;
  895. END;
  896. w.Ln;
  897. w.String("Exports"); w.Ln;
  898. e := exports;
  899. WHILE e # NIL DO
  900. w.String("fp = "); w.Int(e.fp,1);
  901. w.String(", val = "); w.Int(e.val,1);
  902. w.String(", name= "); w.String(e.name);
  903. w.Ln;
  904. e := e.next;
  905. END;
  906. w.Ln;
  907. w.String("Imports"); w.Ln;
  908. import := imports;
  909. WHILE import # NIL DO
  910. w.String("module ="); w.String(import.name); w.Ln;
  911. u := import.uses;
  912. WHILE u # NIL DO
  913. w.String(" fp ="); w.Int(u.fp,1);
  914. w.String(", val = "); w.Int(u.val,1);
  915. w.String(", name ="); w.String(u.name);
  916. w.Ln;
  917. u := u.next;
  918. END;
  919. import := import.next;
  920. END;
  921. w.Ln;
  922. w.String("VarConstLinks"); w.Ln;
  923. FOR i := 0 TO LEN(varConstLinks)-1 DO
  924. w.String("num="); w.Int(varConstLinks[i].num,1);
  925. w.String(", no="); w.Int(ORD(varConstLinks[i].ch),1);
  926. w.Ln;
  927. FOR j := 0 TO LEN(varConstLinks[i].links)-1 DO
  928. w.String(" link="); w.Int(varConstLinks[i].links[j],1);
  929. w.String("(");
  930. w.Hex(varConstLinks[i].links[j],1);
  931. w.String("H)");
  932. w.Ln;
  933. END;
  934. END;
  935. w.Ln;
  936. w.String("Links"); w.Ln;
  937. FOR i := 0 TO LEN(links)-1 DO
  938. w.String("num="); w.Int(links[i].num,1);w.Ln;
  939. END;
  940. w.Ln;
  941. w.String("Link Entries"); w.Ln;
  942. FOR i := 0 TO LEN(entries)-1 DO
  943. w.String("num="); w.Int(entries[i].num,1);w.Ln;
  944. END;
  945. w.Ln;
  946. w.String("Pointers in Procs"); w.Ln;
  947. FOR i := 0 TO LEN(gcInfo)-1 DO
  948. w.String("code offset "); w.Hex(gcInfo[i].codeOffset,-8); w.Ln;
  949. w.String("begin offset "); w.Hex(gcInfo[i].beginOffset,-8); w.Ln;
  950. w.String("end offset "); w.Hex(gcInfo[i].endOffset,-8); w.Ln;
  951. w.String("pointers: "); w.Ln;
  952. FOR j := 0 TO LEN(gcInfo[i].pointers) - 1 DO
  953. w.Int(gcInfo[i].pointers[j],1); w.String(", ");
  954. END;
  955. w.Ln;
  956. END;
  957. w.Update
  958. END OutlineModule;
  959. PROCEDURE Outline (panel : WMStandardComponents.Panel);
  960. VAR
  961. moduleNode, fieldNode, typeNode : WMTrees.TreeNode;
  962. stringWriter : Strings.Buffer;
  963. w : Streams.Writer;
  964. i, j : LONGINT;
  965. PROCEDURE AddProcedureNode (parent : WMTrees.TreeNode; proc : ProcedureInfo; CONST typeName : ARRAY OF CHAR);
  966. VAR
  967. procedureNode : WMTrees.TreeNode;
  968. fieldCaption, procCaption : Strings.String;
  969. k : LONGINT;
  970. BEGIN
  971. NEW(procedureNode);
  972. tree.AddChildNode(parent, procedureNode);
  973. procCaption := Strings.NewString(proc.name);
  974. RemoveTypeName(procCaption^, typeName);
  975. tree.SetNodeCaption(procedureNode, procCaption);
  976. tree.SetNodeData(procedureNode, proc);
  977. tree.SetNodeImage(procedureNode, WMGraphics.LoadImage("DecoderRes.zip://ProcedureIcon.png", TRUE));
  978. k := 0;
  979. WHILE k < proc.fieldCount DO
  980. proc.fields[k].procedure := proc;
  981. NEW(fieldCaption, 40);
  982. NEW(fieldNode);
  983. tree.AddChildNode(procedureNode, fieldNode);
  984. proc.fields[k].ToString(w);
  985. fieldCaption := stringWriter.GetString();
  986. tree.SetNodeCaption(fieldNode, Strings.NewString(fieldCaption^));
  987. tree.SetNodeImage(fieldNode, WMGraphics.LoadImage("DecoderRes.zip://VariableIcon.png", TRUE));
  988. stringWriter.Clear;
  989. tree.SetNodeData(fieldNode, proc.fields[k]);
  990. INC(k)
  991. END
  992. END AddProcedureNode;
  993. BEGIN
  994. lastDAssPanel := panel;
  995. NEW(stringWriter, 0);
  996. w := stringWriter.GetWriter();
  997. NEW(treePanel);
  998. treePanel.alignment.Set(WMComponents.AlignLeft);
  999. treePanel.bounds.SetWidth(300);
  1000. panel.AddContent(treePanel);
  1001. NEW(resizerH);
  1002. resizerH.bounds.SetWidth(5); resizerH.alignment.Set(WMComponents.AlignRight);
  1003. resizerH.fillColor.Set(0808080FFH);
  1004. treePanel.AddContent(resizerH);
  1005. (* add a tree component *)
  1006. NEW(treeView); treeView.alignment.Set(WMComponents.AlignClient);
  1007. treePanel.AddContent(treeView);
  1008. tree := treeView.GetTree();
  1009. treeView.Initialize;
  1010. treeView.onClickNode.Add(ClickNode);
  1011. panel.Reset(SELF, NIL);
  1012. panel.AlignSubComponents;
  1013. tree.Acquire;
  1014. NEW(moduleNode);
  1015. tree.SetRoot(moduleNode);
  1016. tree.InclNodeState(moduleNode, WMTrees.NodeAlwaysExpanded);
  1017. tree.SetNodeCaption(moduleNode, Strings.NewString(name));
  1018. tree.SetNodeData(moduleNode, SELF);
  1019. i := 0;
  1020. WHILE i < typeCount DO
  1021. NEW(typeNode);
  1022. tree.AddChildNode(moduleNode, typeNode);
  1023. tree.SetNodeCaption(typeNode, Strings.NewString(types[i].name));
  1024. tree.SetNodeData(typeNode, types[i]);
  1025. tree.SetNodeImage(typeNode, WMGraphics.LoadImage("DecoderRes.zip://TypeIcon.png", TRUE));
  1026. j := 0;
  1027. WHILE j < types[i].procedureCount DO
  1028. AddProcedureNode(typeNode, types[i].procedures[j], types[i].name);
  1029. INC(j)
  1030. END;
  1031. INC(i)
  1032. END;
  1033. i := 0;
  1034. WHILE i < procedureCount DO
  1035. IF ~procedures[i].method THEN
  1036. AddProcedureNode(moduleNode, procedures[i], "")
  1037. END;
  1038. INC(i)
  1039. END;
  1040. tree.Release;
  1041. END Outline;
  1042. PROCEDURE Discard(panel : WMStandardComponents.Panel);
  1043. BEGIN
  1044. IF treePanel # NIL THEN
  1045. panel.RemoveContent(treePanel)
  1046. END;
  1047. IF editor # NIL THEN
  1048. panel.RemoveContent(editor)
  1049. END;
  1050. lastDAssPanel := NIL
  1051. END Discard;
  1052. END ModuleInfo;
  1053. ModuleInfoBytes = OBJECT (ModuleInfo)
  1054. PROCEDURE &New(bytes : Modules.Bytes);
  1055. BEGIN
  1056. Init;
  1057. name := "[UNKNOWN]";
  1058. representationMode := RepresentationModePlain;
  1059. NEW(procedures[0], "[UNKNOWN]", 0, 0);
  1060. procedureCount := 1;
  1061. procedures[0].codeSize := LEN(bytes);
  1062. module.code := bytes
  1063. END New;
  1064. PROCEDURE Outline (panel : WMStandardComponents.Panel);
  1065. BEGIN
  1066. ext := lastExt; (* allows to decode with the decoder the last file was decoded *)
  1067. OutlineProcedure(procedures[0], panel)
  1068. END Outline;
  1069. END ModuleInfoBytes;
  1070. CodeScaleCallback* = PROCEDURE(VAR size : LONGINT);
  1071. ModuleInfoObjectFile = OBJECT (ModuleInfo)
  1072. VAR
  1073. f: Files.File;
  1074. r : Files.Reader;
  1075. version : LONGINT;
  1076. nofLinks, nofVarConstLinks : LONGINT;
  1077. symSize : LONGINT;
  1078. noProcs : LONGINT; (* ug: temporary *)
  1079. PROCEDURE DecodeEntries;
  1080. VAR
  1081. ch : CHAR; i, e : LONGINT;
  1082. BEGIN
  1083. ch := r.Get();
  1084. ASSERT(ch = 82X);
  1085. NEW(module.entry, header.entries);
  1086. FOR i := 0 TO header.entries-1 DO
  1087. r.RawNum(e);
  1088. module.entry[i] := e
  1089. END
  1090. END DecodeEntries;
  1091. PROCEDURE SkipCommands;
  1092. VAR
  1093. ch : CHAR;
  1094. i, num : LONGINT;
  1095. n : Modules.Name;
  1096. BEGIN
  1097. ch := r.Get();
  1098. ASSERT(ch = 83X);
  1099. FOR i := 0 TO header.commands-1 DO
  1100. r.RawNum(num); r.RawNum(num); r.RawString(n); r.RawNum(num)
  1101. END
  1102. END SkipCommands;
  1103. PROCEDURE SkipPointers;
  1104. VAR
  1105. ch : CHAR;
  1106. i, num : LONGINT;
  1107. BEGIN
  1108. ch := r.Get();
  1109. ASSERT(ch = 84X);
  1110. FOR i := 0 TO header.pointers-1 DO
  1111. r.RawNum(num)
  1112. END
  1113. END SkipPointers;
  1114. PROCEDURE SkipImports;
  1115. VAR
  1116. ch : CHAR;
  1117. i : LONGINT;
  1118. n : Modules.Name;
  1119. BEGIN
  1120. ch := r.Get();
  1121. ASSERT(ch = 85X);
  1122. FOR i := 0 TO header.modules-1 DO
  1123. r.RawString(n)
  1124. END
  1125. END SkipImports;
  1126. PROCEDURE SkipVarConstLinks;
  1127. VAR
  1128. ch : CHAR;
  1129. i, j, num, count : LONGINT;
  1130. BEGIN
  1131. ch := r.Get();
  1132. ASSERT(ch = 8DX);
  1133. NEW(varConstLinks,nofVarConstLinks);
  1134. FOR i := 0 TO nofVarConstLinks-1 DO
  1135. ch := r.Get();
  1136. r.RawNum(num);
  1137. r.RawLInt(count);
  1138. varConstLinks[i].num := i;
  1139. varConstLinks[i].ch := ch;
  1140. NEW(varConstLinks[i].links,count);
  1141. FOR j := 0 TO count-1 DO
  1142. r.RawNum(num);
  1143. varConstLinks[i].links[j] := num;
  1144. END
  1145. END
  1146. END SkipVarConstLinks;
  1147. PROCEDURE SkipLinks;
  1148. VAR
  1149. ch : CHAR;
  1150. i, num : LONGINT;
  1151. BEGIN
  1152. ch := r.Get();
  1153. ASSERT(ch = 86X);
  1154. NEW(links,nofLinks);
  1155. FOR i := 0 TO nofLinks-1 DO
  1156. r.SkipBytes(2); (* skip 2 characters *)
  1157. r.RawNum(num);
  1158. links[i].num := num;
  1159. END;
  1160. NEW(entries,header.entries);
  1161. FOR i := 0 TO header.entries-1 DO
  1162. r.RawNum(num);
  1163. entries[i].num := num;
  1164. END;
  1165. r.RawNum(num)
  1166. END SkipLinks;
  1167. PROCEDURE SkipConsts;
  1168. VAR
  1169. ch : CHAR; i: LONGINT;
  1170. BEGIN
  1171. ch := r.Get();
  1172. ASSERT(ch = 87X);
  1173. NEW(module.data,header.constSize);
  1174. FOR i := 0 TO header.constSize-1 DO
  1175. r.Char(module.data[i]);
  1176. END;
  1177. END SkipConsts;
  1178. PROCEDURE SkipExports;
  1179. VAR count: LONGINT; name: Modules.Name; ch : CHAR;
  1180. PROCEDURE LoadScope (level: LONGINT);
  1181. VAR adr, fp, off, i, len, exp: LONGINT; check: POINTER TO ARRAY OF LONGINT;export: Export;
  1182. BEGIN
  1183. r.RawLInt(exp);
  1184. r.RawNum(fp);
  1185. len := 0;
  1186. IF fp # 0 THEN NEW(check, exp) END;
  1187. WHILE fp # 0 DO
  1188. D.Hex(fp,-8); D.Ln;
  1189. NEW(export);
  1190. export.fp := fp;
  1191. AddExport(export);
  1192. IF (fp = 1) THEN
  1193. r.RawNum(off);
  1194. export.val := off;
  1195. IF off >= 0 THEN
  1196. INC(count);
  1197. LoadScope (level+1(*1*))
  1198. END
  1199. ELSE
  1200. IF level = 0 THEN
  1201. r.RawNum(adr);
  1202. export.val := adr;
  1203. (*
  1204. i := 0;
  1205. WHILE i # len DO
  1206. IF check[i] = fp THEN
  1207. r.RawString(name);
  1208. COPY(name,export.name);
  1209. i := len
  1210. ELSE
  1211. INC(i)
  1212. END
  1213. END;
  1214. *)
  1215. check[len] := fp; INC(len)
  1216. END;
  1217. END;
  1218. r.RawNum(fp)
  1219. END
  1220. END LoadScope;
  1221. BEGIN
  1222. ch := r.Get();
  1223. ASSERT(ch = 88X);
  1224. LoadScope (0)
  1225. END SkipExports;
  1226. PROCEDURE SkipUse;
  1227. VAR ch : CHAR;
  1228. PROCEDURE ReadUsedModules;
  1229. VAR name : Modules.Name; import: Import;
  1230. PROCEDURE ReadEntry;
  1231. VAR
  1232. fp, arg : LONGINT;
  1233. name : ARRAY 256 OF CHAR;
  1234. use: Use;
  1235. BEGIN
  1236. r.RawNum(fp);
  1237. r.RawString(name);
  1238. r.RawNum(arg);
  1239. NEW(use);
  1240. use.fp := fp;
  1241. COPY(name,use.name);
  1242. use.val := arg;
  1243. import.AddUse(use);
  1244. IF arg > 0 THEN
  1245. IF r.Peek() = 1X THEN
  1246. ch := r.Get();
  1247. r.RawNum(arg)
  1248. END
  1249. ELSIF arg < 0 THEN
  1250. ELSE
  1251. IF r.Peek() = 1X THEN
  1252. (* read used record *)
  1253. ch := r.Get();
  1254. r.RawNum(arg); (* tdentry *)
  1255. IF r.Peek() # 0X THEN
  1256. r.RawNum(arg); (* FP *)
  1257. r.RawString(name);
  1258. ASSERT(name = "@");
  1259. END;
  1260. ch := r.Get();
  1261. ASSERT(ch = 0X)
  1262. END;
  1263. END
  1264. END ReadEntry;
  1265. BEGIN
  1266. WHILE r.Peek() # 0X DO
  1267. r.RawString(name);
  1268. NEW(import);
  1269. COPY(name,import.name);
  1270. AddImport(import);
  1271. WHILE r.Peek() # 0X DO
  1272. ReadEntry
  1273. END;
  1274. ch := r.Get();
  1275. ASSERT(ch = 0X)
  1276. END
  1277. END ReadUsedModules;
  1278. BEGIN
  1279. ch := r.Get();
  1280. ASSERT(ch = 08AX);
  1281. ReadUsedModules;
  1282. ch := r.Get();
  1283. ASSERT(ch = 0X)
  1284. END SkipUse;
  1285. PROCEDURE DecodeTypes;
  1286. VAR
  1287. i, j, size, entry, ptrOfs, tdaddr, moduleBase, nofMethods, nofInhMethods, nofNewMethods, nofPointers, tdSize (* ug *), methNr, entryNr : LONGINT;
  1288. name : ARRAY 256 OF CHAR; ch : CHAR;
  1289. type : TypeInfo;
  1290. procInfo : ProcedureInfo;
  1291. BEGIN
  1292. ch := r.Get();
  1293. ASSERT(ch = 08BX);
  1294. typeCount := header.types;
  1295. NEW(types, typeCount);
  1296. FOR i := 0 TO header.types-1 DO
  1297. r.RawNum(size);
  1298. r.RawNum(tdaddr);
  1299. (* read Base *)
  1300. r.RawNum(moduleBase); r.RawNum(entry);
  1301. (* read Count *)
  1302. r.RawNum(nofMethods); nofMethods := ABS (nofMethods);
  1303. r.RawNum(nofInhMethods); r.RawNum(nofNewMethods); r.RawLInt(nofPointers);
  1304. r.RawString(name);
  1305. r.RawLInt(tdSize); (* ug *)
  1306. NEW(type, name);
  1307. IF type.name = "" THEN type.name := "[anonymous]" END;
  1308. types[i] := type;
  1309. KernelLog.Ln;
  1310. KernelLog.String(" - name = "); KernelLog.String(type.name); KernelLog.Ln;
  1311. KernelLog.String(" - size = "); KernelLog.Int(size, 0); KernelLog.Ln;
  1312. KernelLog.String(" - tdaddr = "); KernelLog.Int(tdaddr, 0); KernelLog.Ln;
  1313. KernelLog.String(" - moduleBase = "); KernelLog.Int(moduleBase, 0); KernelLog.Ln;
  1314. KernelLog.String(" - entry = "); KernelLog.Int(entry, 0); KernelLog.Ln;
  1315. KernelLog.String(" - nofMethods = "); KernelLog.Int(nofMethods, 0); KernelLog.Ln;
  1316. KernelLog.String(" - nofInhMethods = "); KernelLog.Int(nofInhMethods, 0); KernelLog.Ln;
  1317. KernelLog.String(" - nofNewMethods = "); KernelLog.Int(nofNewMethods, 0); KernelLog.Ln;
  1318. KernelLog.String(" - nofPointers = "); KernelLog.Int(nofPointers, 0); KernelLog.Ln;
  1319. KernelLog.String(" - tdSize = "); KernelLog.Int(tdSize, 0); KernelLog.Ln; (* ug *)
  1320. KernelLog.String(" - Methods:"); KernelLog.Ln;
  1321. (* read Methods *)
  1322. type.procedureCount := nofNewMethods;
  1323. NEW(type.procedures, type.procedureCount);
  1324. FOR j := 0 TO type.procedureCount-1 DO
  1325. r.RawNum(methNr); r.RawNum(entryNr);
  1326. NEW(procInfo, "", module.entry[entryNr], entryNr);
  1327. procInfo.method := TRUE;
  1328. AddProcedure(procInfo);
  1329. type.procedures[j] := procInfo;
  1330. END;
  1331. KernelLog.String(" - PtrOfs: ");
  1332. (* read Pointers *)
  1333. FOR j := 0 TO nofPointers-1 DO
  1334. r.RawNum(ptrOfs);
  1335. KernelLog.Int(ptrOfs,1); KernelLog.String(" ");
  1336. END;
  1337. KernelLog.Ln;
  1338. END;
  1339. END DecodeTypes;
  1340. PROCEDURE DecodeExTable(r: Streams.Reader);
  1341. VAR
  1342. i: LONGINT;
  1343. tag: CHAR;
  1344. a: LONGINT;
  1345. BEGIN
  1346. NEW(module.exTable, header.exTableLen);
  1347. FOR i := 0 TO header.exTableLen -1 DO
  1348. r.Char(tag);
  1349. ASSERT(tag = 0FEX);
  1350. r.RawNum(a); module.exTable[i].pcFrom := a;
  1351. r.RawNum(a); module.exTable[i].pcTo := a;
  1352. r.RawNum(a); module.exTable[i].pcHandler := a;
  1353. END;
  1354. END DecodeExTable;
  1355. PROCEDURE SkipPointerInProc;
  1356. VAR ch : CHAR;
  1357. i, j, codeoffset, beginOffset, endOffset, p, nofptrs : LONGINT;
  1358. BEGIN
  1359. ch := r.Get();
  1360. ASSERT(ch = 8FX);
  1361. KernelLog.String(" - PointersInProc: "); KernelLog.Ln;
  1362. NEW(gcInfo,noProcs);
  1363. FOR i := 0 TO noProcs - 1 DO
  1364. NEW(gcInfo[i]);
  1365. r.RawNum(codeoffset);
  1366. r.RawNum(beginOffset);
  1367. r.RawNum(endOffset);
  1368. gcInfo[i].codeOffset := codeoffset;
  1369. gcInfo[i].beginOffset := beginOffset;
  1370. gcInfo[i].endOffset := endOffset;
  1371. r.RawLInt(nofptrs);
  1372. NEW(gcInfo[i].pointers,nofptrs);
  1373. FOR j := 0 TO nofptrs - 1 DO
  1374. r.RawNum(p);
  1375. gcInfo[i].pointers[j] := p;
  1376. END
  1377. END
  1378. END SkipPointerInProc;
  1379. PROCEDURE &New (CONST fileName : ARRAY OF CHAR);
  1380. VAR ch : CHAR; tmp : LONGINT; j, res : LONGINT; msg : ARRAY 255 OF CHAR; pos: LONGINT;
  1381. BEGIN
  1382. Init;
  1383. Strings.GetExtension (fileName, msg, ext);
  1384. lastExt := ext;
  1385. codeScaleCallback := GetCodeScaleCallback(ext);
  1386. f := Files.Old(fileName);
  1387. IF f # NIL THEN
  1388. Files.OpenReader(r, f, 0);
  1389. IF r.Get() = 0BBX THEN
  1390. version := ORD(r.Get());
  1391. IF version = 0ADH THEN version := ORD(r.Get()) END;
  1392. IF version = 0B1H THEN (* PACO object file *)
  1393. r.RawNum(symSize);
  1394. ELSIF (version >= 0B2H) THEN (*fof: OC object file *)
  1395. r.RawLInt(symSize);
  1396. END;
  1397. r.SkipBytes(symSize); (* skip symbol file *)
  1398. ELSE
  1399. KernelLog.String("Decoder: ERROR: Tag not supported or wrong file type!"); KernelLog.Ln;
  1400. RETURN
  1401. END;
  1402. r.RawLInt(header.refSize);
  1403. r.RawLInt(header.entries);
  1404. r.RawLInt(header.commands);
  1405. r.RawLInt(header.pointers);
  1406. r.RawLInt(header.types);
  1407. r.RawLInt(header.modules);
  1408. r.RawLInt(nofVarConstLinks);
  1409. r.RawLInt(nofLinks);
  1410. r.RawLInt(header.dataSize);
  1411. r.RawLInt(header.constSize);
  1412. r.RawLInt(header.codeSize);
  1413. IF (codeScaleCallback # NIL) THEN codeScaleCallback(header.codeSize) END;
  1414. (* Sz: Exception handling *)
  1415. r.RawLInt(header.exTableLen);
  1416. (* ug: Pointers in procedures, maxPtrs, staticTdSize: *)
  1417. r.RawLInt(noProcs);
  1418. r.RawLInt(tmp); (* ug: skip maxPtrs *)
  1419. r.RawLInt(tmp); (* ug: skip staticTdSize *)
  1420. IF version > 0B3H THEN r.RawLInt(header.crc) END;
  1421. r.RawString(name);
  1422. (* skip to code block *)
  1423. DecodeEntries;
  1424. SkipCommands;
  1425. SkipPointers;
  1426. SkipImports;
  1427. SkipVarConstLinks;
  1428. SkipLinks;
  1429. SkipConsts;
  1430. SkipExports;
  1431. ch := r.Get();
  1432. pos := r.Pos();
  1433. ASSERT(ch = 89X);
  1434. (* code section *)
  1435. NEW(module.code, header.codeSize);
  1436. FOR j := 0 TO header.codeSize-1 DO
  1437. module.code[j] := r.Get()
  1438. END;
  1439. SkipUse;
  1440. DecodeTypes;
  1441. (* Sz: read exception handling table *)
  1442. ch := r.Get();
  1443. ASSERT(ch = 8EX);
  1444. DecodeExTable(r);
  1445. SkipPointerInProc; (* ug *)
  1446. (* read ref header *)
  1447. ch := r.Get();
  1448. ASSERT(ch = OFFHdrRef);
  1449. DecodeRefs(r);
  1450. ELSE
  1451. msg := "Object file '"; Strings.Append(msg, fileName); Strings.Append(msg, "' could not be found.");
  1452. WMDialogs.Error("Decoder", msg)
  1453. END;
  1454. END New;
  1455. END ModuleInfoObjectFile;
  1456. ModuleInfoMemory = OBJECT (ModuleInfo)
  1457. VAR
  1458. reader : MemoryReader.Reader;
  1459. PROCEDURE &New (module : Modules.Module; header: ObjHeader);
  1460. BEGIN
  1461. Init;
  1462. COPY(module.name,name);
  1463. representationMode := RepresentationModeMeta;
  1464. NEW(reader, ADDRESSOF(module.refs[0]), header.refSize);
  1465. SELF.module := module;
  1466. SELF.header := header;
  1467. DecodeRefs(reader);
  1468. DecodeTypes
  1469. END New;
  1470. PROCEDURE DecodeTypes;
  1471. VAR
  1472. i, j : LONGINT;
  1473. type : TypeInfo;
  1474. typeDesc : Modules.TypeDesc;
  1475. adr : ADDRESS;
  1476. BEGIN
  1477. typeCount := header.types;
  1478. NEW(types, typeCount);
  1479. FOR i := 0 TO typeCount-1 DO
  1480. (* ug: for old heap DS *)
  1481. (*
  1482. adr := SYSTEM.VAL(ADDRESS, module.type[i]);
  1483. SYSTEM.GET(adr - AddressSize, typeDesc);
  1484. NEW(type, typeDesc.name);
  1485. *)
  1486. (* ug: for new heap DS *)
  1487. NEW(type, module.typeInfo[i].name);
  1488. types[i] := type;
  1489. (* check for methods of this type *)
  1490. IF type.name # "" THEN
  1491. (* silly way: name matching -> improve by reading typeDesc method block *)
  1492. FOR j := 0 TO procedureCount-1 DO
  1493. IF Strings.StartsWith(type.name, 0, procedures[j].name) THEN
  1494. type.AddProcedure(procedures[j]);
  1495. procedures[j].method := TRUE
  1496. END
  1497. END
  1498. ELSE
  1499. type.name := "[anonymous]"
  1500. END
  1501. END
  1502. END DecodeTypes;
  1503. END ModuleInfoMemory;
  1504. KillerMsg = OBJECT
  1505. END KillerMsg;
  1506. DecoderWindow = OBJECT (WMComponents.FormWindow)
  1507. VAR
  1508. panel : WMStandardComponents.Panel;
  1509. toolbar : WMStandardComponents.Panel;
  1510. decodeFile, decodeModule, decodeBytes: WMStandardComponents.Button;
  1511. stopped : BOOLEAN;
  1512. moduleInfo : ModuleInfo;
  1513. PROCEDURE CreateForm() : WMComponents.VisualComponent;
  1514. BEGIN
  1515. NEW(panel); panel.bounds.SetExtents(1024, 768); panel.fillColor.Set(WMGraphics.White); panel.takesFocus.Set(TRUE);
  1516. NEW(toolbar); toolbar.bounds.SetHeight(20); toolbar.alignment.Set(WMComponents.AlignTop);
  1517. panel.AddContent(toolbar);
  1518. NEW(decodeFile); decodeFile.caption.SetAOC("Decode File"); decodeFile.alignment.Set(WMComponents.AlignLeft);
  1519. decodeFile.bounds.SetWidth(2 * decodeFile.bounds.GetWidth());
  1520. decodeFile.onClick.Add(DecodeFileHandler);
  1521. toolbar.AddContent(decodeFile);
  1522. NEW(decodeModule); decodeModule.caption.SetAOC("Decode Module"); decodeModule.alignment.Set(WMComponents.AlignLeft);
  1523. decodeModule.bounds.SetWidth(2 * decodeModule.bounds.GetWidth());
  1524. decodeModule.onClick.Add(DecodeModuleHandler);
  1525. toolbar.AddContent(decodeModule);
  1526. NEW(decodeBytes); decodeBytes.caption.SetAOC("Decode Bytes"); decodeBytes.alignment.Set(WMComponents.AlignLeft);
  1527. decodeBytes.bounds.SetWidth(2 * decodeBytes.bounds.GetWidth());
  1528. decodeBytes.onClick.Add(DecodeBytesHandler);
  1529. toolbar.AddContent(decodeBytes);
  1530. RETURN panel
  1531. END CreateForm;
  1532. PROCEDURE &New(CONST fileName : ARRAY OF CHAR; c : WMRestorable.Context);
  1533. VAR
  1534. vc : WMComponents.VisualComponent;
  1535. moduleInfoObjectFile : ModuleInfoObjectFile;
  1536. moduleInfoMemory : ModuleInfoMemory;
  1537. msg : ARRAY 256 OF CHAR;
  1538. module : Modules.Module;
  1539. header: ObjHeader;
  1540. res: WORD; extPos : LONGINT;
  1541. BEGIN
  1542. vc := CreateForm();
  1543. Init(vc.bounds.GetWidth(), vc.bounds.GetHeight(), FALSE);
  1544. SetContent(vc);
  1545. WM.DefaultAddWindow(SELF);
  1546. stopped := FALSE;
  1547. IF fileName # "" THEN
  1548. extPos := Strings.Pos(".", fileName) + 1;
  1549. IF extPos # 0 THEN (* must be a file name *)
  1550. (* load the file and outline it *)
  1551. NEW(moduleInfoObjectFile, fileName);
  1552. moduleInfoObjectFile.Outline(panel);
  1553. moduleInfo := moduleInfoObjectFile;
  1554. ELSE
  1555. module := Modules.ThisModule(fileName, res, msg);
  1556. MakeHeader(module, header);
  1557. NEW(moduleInfoMemory, module, header);
  1558. moduleInfoMemory.Outline(panel);
  1559. moduleInfo := moduleInfoMemory;
  1560. END;
  1561. AdjustTitle(fileName);
  1562. ELSE
  1563. AdjustTitle("")
  1564. END;
  1565. IncCount;
  1566. END New;
  1567. PROCEDURE AdjustTitle (CONST str : ARRAY OF CHAR);
  1568. VAR
  1569. titleString : ARRAY Files.NameLength+10 OF CHAR;
  1570. BEGIN
  1571. titleString := "Decoder";
  1572. IF str # "" THEN
  1573. Strings.Append(titleString, " - ");
  1574. Strings.Append(titleString, str)
  1575. END;
  1576. SetTitle(Strings.NewString(titleString))
  1577. END AdjustTitle;
  1578. PROCEDURE DecodeFileHandler(sender, data : ANY);
  1579. VAR
  1580. fileNameStr : ARRAY Files.NameLength OF CHAR;
  1581. moduleInfoObjectFile : ModuleInfoObjectFile;
  1582. BEGIN
  1583. IF WMDialogs.QueryString("Enter file name", fileNameStr) = WMDialogs.ResOk THEN
  1584. IF moduleInfo # NIL THEN
  1585. moduleInfo.Discard(panel)
  1586. END;
  1587. NEW(moduleInfoObjectFile, fileNameStr);
  1588. moduleInfoObjectFile.Outline(panel);
  1589. moduleInfo := moduleInfoObjectFile;
  1590. AdjustTitle(fileNameStr)
  1591. END;
  1592. END DecodeFileHandler;
  1593. PROCEDURE DecodeModuleHandler(sender, data : ANY);
  1594. VAR moduleNameStr, msg : ARRAY 256 OF CHAR;
  1595. module : Modules.Module;
  1596. res : WORD;
  1597. moduleInfoMemory : ModuleInfoMemory;
  1598. header: ObjHeader;
  1599. BEGIN
  1600. IF WMDialogs.QueryString("Enter module name", moduleNameStr) = WMDialogs.ResOk THEN
  1601. module := Modules.ThisModule(moduleNameStr, res, msg);
  1602. IF res # 0 THEN
  1603. msg := "Module "; Strings.Append(msg, moduleNameStr); Strings.Append(msg, " not found in memory.");
  1604. WMDialogs.Error("Decoder", msg);
  1605. ELSE
  1606. IF moduleInfo # NIL THEN
  1607. moduleInfo.Discard(panel)
  1608. END;
  1609. MakeHeader(module,header);
  1610. NEW(moduleInfoMemory, module, header);
  1611. moduleInfoMemory.Outline(panel);
  1612. moduleInfo := moduleInfoMemory;
  1613. AdjustTitle(moduleNameStr)
  1614. END
  1615. END
  1616. END DecodeModuleHandler;
  1617. PROCEDURE DecodeBytesHandler(sender, data : ANY);
  1618. VAR hexByteStr : ARRAY 1024 OF CHAR;
  1619. moduleInfoBytes : ModuleInfoBytes;
  1620. BEGIN
  1621. IF WMDialogs.QueryString("Enter bytes in hex format (separated by spaces)", hexByteStr) = WMDialogs.ResOk THEN
  1622. IF moduleInfo # NIL THEN
  1623. moduleInfo.Discard(panel)
  1624. END;
  1625. NEW(moduleInfoBytes, HexBytes2Code(hexByteStr));
  1626. moduleInfoBytes.Outline(panel);
  1627. moduleInfo := moduleInfoBytes;
  1628. AdjustTitle("[byte array]")
  1629. END
  1630. END DecodeBytesHandler;
  1631. PROCEDURE Handle*(VAR x: WMMessages.Message);
  1632. BEGIN
  1633. IF (x.msgType = WMMessages.MsgExt) & (x.ext # NIL) & (x.ext IS KillerMsg) THEN Close
  1634. ELSE Handle^(x)
  1635. END
  1636. END Handle;
  1637. PROCEDURE OutlineProcedure (CONST name : ARRAY OF CHAR);
  1638. BEGIN
  1639. IF (moduleInfo # NIL) & ~(moduleInfo IS ModuleInfoBytes) THEN
  1640. moduleInfo.OutlineNamedProcedure(name)
  1641. END
  1642. END OutlineProcedure;
  1643. PROCEDURE OutlinePC (pc : LONGINT);
  1644. BEGIN
  1645. IF (moduleInfo # NIL) & ~(moduleInfo IS ModuleInfoBytes) THEN
  1646. moduleInfo.OutlinePC(pc)
  1647. END
  1648. END OutlinePC;
  1649. PROCEDURE Close*;
  1650. BEGIN
  1651. Close^;
  1652. BEGIN {EXCLUSIVE}
  1653. stopped := TRUE
  1654. END;
  1655. DecCount
  1656. END Close;
  1657. END DecoderWindow;
  1658. Extension = ARRAY 4 OF CHAR;
  1659. DecoderType = OBJECT
  1660. VAR
  1661. ext : Extension;
  1662. decoderFactory : DecoderFactory;
  1663. codeScaleCallback : CodeScaleCallback;
  1664. PROCEDURE &New (CONST ext : Extension; decoderFactory : DecoderFactory; codeScaleCallback : CodeScaleCallback);
  1665. BEGIN
  1666. SELF.ext := ext; SELF.decoderFactory := decoderFactory; SELF.codeScaleCallback := codeScaleCallback
  1667. END New;
  1668. END DecoderType;
  1669. VAR
  1670. nofWindows : LONGINT;
  1671. win : DecoderWindow;
  1672. decoderTypes : ARRAY maxDecoders OF DecoderType;
  1673. nofDecoders : LONGINT;
  1674. lastExt : Extension;
  1675. PROCEDURE OpenEmpty*;
  1676. BEGIN
  1677.  NEW(win, "", NIL);
  1678. END OpenEmpty;
  1679. PROCEDURE MakeHeader(module: Modules.Module; VAR header: ObjHeader);
  1680. BEGIN
  1681. header.entries := LEN(module.entry);
  1682. header.commands := LEN(module.command);
  1683. header.pointers := LEN(module.ptrAdr);
  1684. header.types := LEN(module.typeInfo);
  1685. header.modules := LEN(module.module);
  1686. header.codeSize := LEN(module.code);
  1687. header.dataSize := LEN(module.data);
  1688. header.refSize := LEN(module.refs);
  1689. header.constSize := 0;
  1690. header.exTableLen := LEN(module.exTable);
  1691. header.staticTdSize := LEN(module.typeInfo);
  1692. header.crc := module.crc;
  1693. header.name := module.name;
  1694. END MakeHeader;
  1695. PROCEDURE RemoveTypeName (VAR procName : ARRAY OF CHAR; CONST typeName : ARRAY OF CHAR);
  1696. VAR
  1697. i, j : LONGINT;
  1698. BEGIN
  1699. i := 0;
  1700. IF Strings.Length(typeName) > 0 THEN
  1701. WHILE procName[i] = typeName[i] DO INC(i) END;
  1702. IF (typeName[i] = 0X) & (procName[i] = '.') THEN
  1703. j := 0;
  1704. INC(i);
  1705. WHILE procName[i] # 0X DO
  1706. procName[j] := procName[i];
  1707. INC(i); INC(j)
  1708. END;
  1709. procName[j] := 0X
  1710. END
  1711. END
  1712. END RemoveTypeName;
  1713. PROCEDURE HexBytes2Code(CONST bytes : ARRAY OF CHAR) : Modules.Bytes;
  1714. VAR
  1715. buffer, result : Modules.Bytes;
  1716. byte : CHAR;
  1717. j, size : LONGINT;
  1718. PROCEDURE DecodeHexChar(ch : CHAR) : LONGINT;
  1719. BEGIN
  1720. IF (ORD(ch) >= 48) & (ORD(ch) <= 57) THEN RETURN ORD(ch) - 48 END;
  1721. IF (ORD(ch) >= 65) & (ORD(ch) <= 70) THEN RETURN ORD(ch) - 55 END;
  1722. IF (ORD(ch) >= 97) & (ORD(ch) <= 102) THEN RETURN ORD(ch) - 87 END;
  1723. RETURN 0
  1724. END DecodeHexChar;
  1725. BEGIN
  1726. NEW(buffer, LEN(bytes));
  1727. j := 0; size := 0;
  1728. WHILE j < Strings.Length(bytes)-1 DO
  1729. byte := CHR(DecodeHexChar(bytes[j])*16 + DecodeHexChar(bytes[j+1]));
  1730. INC(j, 2);
  1731. IF (j < LEN(bytes)) & (bytes[j] = 20X) THEN INC(j) END;
  1732. buffer[size] := byte;
  1733. INC(size)
  1734. END;
  1735. NEW(result, size);
  1736. j := 0;
  1737. WHILE j < size DO
  1738. result[j] := buffer[j]; INC(j)
  1739. END;
  1740. RETURN result
  1741. END HexBytes2Code;
  1742. PROCEDURE IntToHex(h: SIZE; width: LONGINT; VAR s: ARRAY OF CHAR);
  1743. VAR c: CHAR;
  1744. BEGIN
  1745. IF (width <= 0) THEN width := 8 END;
  1746. ASSERT(LEN(s) > width);
  1747. s[width] := 0X;
  1748. DEC(width);
  1749. WHILE (width >= 0) DO
  1750. c := CHR(h MOD 10H + ORD("0"));
  1751. IF (c > "9") THEN c := CHR((h MOD 10H - 10) + ORD("A")) END;
  1752. s[width] := c; h := h DIV 10H; DEC(width)
  1753. END
  1754. END IntToHex;
  1755. PROCEDURE IncCount;
  1756. BEGIN {EXCLUSIVE}
  1757. INC(nofWindows)
  1758. END IncCount;
  1759. PROCEDURE DecCount;
  1760. BEGIN {EXCLUSIVE}
  1761. DEC(nofWindows)
  1762. END DecCount;
  1763. PROCEDURE Cleanup;
  1764. VAR
  1765. die : KillerMsg;
  1766. msg : WMMessages.Message;
  1767. m : WM.WindowManager;
  1768. BEGIN {EXCLUSIVE}
  1769. NEW(die);
  1770. msg.ext := die;
  1771. msg.msgType := WMMessages.MsgExt;
  1772. m := WM.GetDefaultManager();
  1773. m.Broadcast(msg);
  1774. AWAIT(nofWindows = 0);
  1775. END Cleanup;
  1776. PROCEDURE Open* (context : Commands.Context);
  1777. VAR
  1778. name : ARRAY Files.NameLength OF CHAR;
  1779. pc : LONGINT;
  1780. BEGIN
  1781. context.arg.SkipWhitespace; context.arg.String(name);
  1782. NEW(win, name, NIL);
  1783. context.arg.SkipWhitespace();
  1784. IF (context.arg.Peek() < "0") OR (context.arg.Peek() > "9") THEN
  1785. context.arg.Token(name);
  1786. IF name # "" THEN win.OutlineProcedure (name) END
  1787. ELSIF (context.arg.Peek() >= "0") & (context.arg.Peek() <= "9") THEN
  1788. context.arg.Int(pc, FALSE);
  1789. IF pc > 0 THEN win.OutlinePC(pc) END
  1790. END;
  1791. END Open;
  1792. PROCEDURE OpenProcedure* (CONST moduleName, procedureName : ARRAY OF CHAR);
  1793. BEGIN
  1794. NEW(win, moduleName, NIL);
  1795. win.OutlineProcedure(procedureName)
  1796. END OpenProcedure;
  1797. PROCEDURE OpenPC* (CONST moduleName : ARRAY OF CHAR; pc : LONGINT);
  1798. BEGIN
  1799. NEW(win, moduleName, NIL);
  1800. win.OutlinePC(pc)
  1801. END OpenPC;
  1802. PROCEDURE GetDecoderType (CONST ext : Extension) : DecoderType;
  1803. VAR i : LONGINT;
  1804. BEGIN
  1805. IF nofDecoders < 1 THEN RETURN NIL END;
  1806. IF ext = "" THEN RETURN decoderTypes[0] END;
  1807. FOR i := 0 TO nofDecoders-1 DO
  1808. IF decoderTypes[i].ext = ext THEN
  1809. RETURN decoderTypes[i]
  1810. END
  1811. END;
  1812. RETURN NIL
  1813. END GetDecoderType;
  1814. PROCEDURE GetDecoder (CONST ext : Extension; reader : Streams.Reader) : Decoder;
  1815. VAR dec : DecoderType;
  1816. BEGIN
  1817. dec := GetDecoderType(ext);
  1818. IF dec # NIL THEN RETURN dec.decoderFactory(reader)
  1819. ELSE RETURN NIL
  1820. END
  1821. END GetDecoder;
  1822. PROCEDURE RegisterDecoder* (CONST ext : Extension; decFactory : DecoderFactory; csclCallback : CodeScaleCallback);
  1823. VAR dec : DecoderType;
  1824. BEGIN
  1825. ASSERT(nofDecoders < maxDecoders);
  1826. dec := GetDecoderType(ext);
  1827. IF dec = NIL THEN
  1828. NEW(decoderTypes[nofDecoders], ext, decFactory, csclCallback);
  1829. INC(nofDecoders)
  1830. END
  1831. END RegisterDecoder;
  1832. PROCEDURE GetCodeScaleCallback (CONST ext : Extension) : CodeScaleCallback;
  1833. VAR dec : DecoderType;
  1834. BEGIN
  1835. dec := GetDecoderType(ext);
  1836. IF dec # NIL THEN RETURN dec.codeScaleCallback
  1837. ELSE RETURN NIL
  1838. END
  1839. END GetCodeScaleCallback;
  1840. PROCEDURE Initialize (CONST decoder: ARRAY OF CHAR);
  1841. VAR initializer: PROCEDURE;
  1842. BEGIN
  1843. GETPROCEDURE (decoder, "Init", initializer);
  1844. IF initializer # NIL THEN initializer END;
  1845. END Initialize;
  1846. BEGIN
  1847. nofDecoders := 0;
  1848. Modules.InstallTermHandler(Cleanup);
  1849. Initialize ("I386Decoder");
  1850. Initialize ("ARMDecoder");
  1851. Initialize ("AMD64Decoder");
  1852. END Decoder.
  1853. System.FreeDownTo Decoder ~
  1854. WMProperties.Obw