2
0

Decoder.Mod 54 KB

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