wasmtoolutils.pas 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. unit wasmtoolutils;
  2. interface
  3. uses
  4. Classes,SysUtils, wasmbin, lebutils,
  5. //wasmbindebug,
  6. wasmlink, wasmlinkchange;
  7. function ChangeSymbolFlagStream(st: TStream; syms: TStrings): Boolean;
  8. procedure ChangeSymbolFlag(const fn, symfn: string);
  9. function ExportRenameSym(var x: TExportSection; syms: TStrings): Integer;
  10. function ExportRenameProcess(st, dst: TStream; syms: TStrings; doVerbose: Boolean): Boolean;
  11. function ExportNameGather(const wasmfile: string; syms: TStrings; doVerbose: Boolean = false): Boolean;
  12. procedure ExportRename(const fn, symfn: string; doVerbose: Boolean);
  13. implementation
  14. function ChangeSymbolFlagStream(st: TStream; syms: TStrings): Boolean;
  15. var
  16. dw : LongWord;
  17. ofs : int64;
  18. sc : TSection;
  19. ps : int64;
  20. nm : string;
  21. begin
  22. dw := st.ReadDWord;
  23. Result := dw = WasmId_Int;
  24. if not Result then Exit;
  25. dw := st.ReadDWord;
  26. while st.Position<st.Size do begin
  27. ofs := st.Position;
  28. sc.id := st.ReadByte;
  29. sc.Size := ReadU(st);
  30. ps := st.Position+sc.size;
  31. if sc.id=0 then begin
  32. nm := GetName(st);
  33. if nm = SectionName_Linking then begin
  34. ProcessLinkingSection(st, syms);
  35. break;
  36. end;
  37. //DumpLinking(st, sc.size - (st.Position - ofs));
  38. end;
  39. //if sc.id= 1 then DumpTypes(st);
  40. if st.Position <> ps then
  41. begin
  42. //writeln('adjust stream targ=',ps,' actual: ', st.position);
  43. st.Position := ps;
  44. end;
  45. end;
  46. end;
  47. procedure ChangeSymbolFlag(const fn, symfn: string);
  48. var
  49. fs :TFileStream;
  50. syms: TStringList;
  51. begin
  52. syms:=TStringList.Create;
  53. fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone);
  54. try
  55. if (symfn<>'') then
  56. ReadSymbolsConf(symfn, syms);
  57. ChangeSymbolFlagStream(fs, syms);
  58. finally
  59. fs.Free;
  60. syms.Free;
  61. end;
  62. end;
  63. function ExportRenameSym(var x: TExportSection; syms: TStrings): integer;
  64. var
  65. i : integer;
  66. v : string;
  67. begin
  68. Result := 0;
  69. for i:=0 to length(x.entries)-1 do begin
  70. v := syms.Values[x.entries[i].name];
  71. if v <> '' then begin
  72. x.entries[i].name := v;
  73. inc(Result);
  74. end;
  75. end;
  76. end;
  77. function ExportRenameProcess(st, dst: TStream; syms: TStrings; doVerbose: Boolean): Boolean;
  78. var
  79. dw : LongWord;
  80. ofs : int64;
  81. sc : TSection;
  82. ps : int64;
  83. x : TExportSection;
  84. mem : TMemoryStream;
  85. cnt : integer;
  86. begin
  87. dw := st.ReadDWord;
  88. Result := dw = WasmId_Int;
  89. if not Result then begin
  90. Exit;
  91. end;
  92. dw := st.ReadDWord;
  93. while st.Position<st.Size do begin
  94. ofs := st.Position;
  95. sc.id := st.ReadByte;
  96. sc.Size := ReadU(st);
  97. ps := st.Position+sc.size;
  98. if sc.id = SECT_EXPORT then begin
  99. if doVerbose then writeln(' export section found');
  100. ReadExport(st, x);
  101. cnt := ExportRenameSym(x, syms);
  102. writeln(' renamings: ', cnt);
  103. st.Position:=0;
  104. dst.CopyFrom(st, ofs);
  105. st.Position:=ps;
  106. mem := TMemoryStream.Create;
  107. WriteExport(x, mem);
  108. mem.Position:=0;
  109. dst.WriteByte(SECT_EXPORT);
  110. WriteU32(dst, mem.Size);
  111. dst.CopyFrom(mem, mem.Size);
  112. dst.CopyFrom(st, st.Size-st.Position);
  113. break;
  114. end;
  115. if st.Position <> ps then
  116. st.Position := ps;
  117. end;
  118. end;
  119. // match between exported function names and symbol names
  120. procedure MatchExportNameToSymName(const x: TExportSection; const l: TLinkingSection; dst: TStrings);
  121. var
  122. expname : string;
  123. i,j : integer;
  124. begin
  125. for i:=0 to length(x.entries)-1 do begin
  126. // gathering only function names for now
  127. if x.entries[i].desc <> EXPDESC_FUNC then continue;
  128. expname := x.entries[i].name;
  129. for j:=0 to length(l.symbols)-1 do begin
  130. if (l.symbols[j].kind = SYMTAB_FUNCTION)
  131. and (l.symbols[j].symindex = x.entries[i].index)
  132. and (l.symbols[j].hasSymName)
  133. then
  134. dst.Values[ l.symbols[j].symname ] := expname;
  135. end;
  136. end;
  137. end;
  138. function ExportNameGather(const wasmfile: string; syms: TStrings; doVerbose: Boolean = false): Boolean;
  139. var
  140. dw : LongWord;
  141. ofs : int64;
  142. sc : TSection;
  143. ps : int64;
  144. mem : TMemoryStream;
  145. cnt : integer;
  146. st : TFileStream;
  147. nm : string;
  148. x : TExportSection;
  149. foundExport: Boolean;
  150. l : TLinkingSection;
  151. foundLink: Boolean;
  152. begin
  153. st := TFileStream.Create(wasmfile, fmOpenRead or fmShareDenyNone);
  154. try
  155. dw := st.ReadDWord;
  156. Result := dw = WasmId_Int;
  157. if not Result then begin
  158. Exit;
  159. end;
  160. dw := st.ReadDWord;
  161. foundExport:=false;
  162. foundLink:=false;
  163. while st.Position<st.Size do begin
  164. ofs := st.Position;
  165. sc.id := st.ReadByte;
  166. sc.Size := ReadU(st);
  167. ps := st.Position+sc.size;
  168. if sc.id = SECT_EXPORT then begin
  169. if doVerbose then writeln(' export section found');
  170. ReadExport(st, x);
  171. cnt := ExportRenameSym(x, syms);
  172. foundExport:=true;
  173. end else if sc.id = SECT_CUSTOM then begin
  174. nm := ReadName(st);
  175. if nm = SectionName_Linking then begin
  176. foundLink := true;
  177. ReadLinkingSection(st, sc.size, l);
  178. end;
  179. end;
  180. if st.Position <> ps then
  181. st.Position := ps;
  182. end;
  183. Result := foundLink and foundExport;
  184. if Result then
  185. MatchExportNameToSymName(x, l, syms);
  186. finally
  187. st.Free;
  188. end;
  189. end;
  190. procedure ExportRename(const fn, symfn: string; doVerbose: Boolean);
  191. var
  192. fs : TFileStream;
  193. syms : TStringList;
  194. dst : TMemoryStream;
  195. begin
  196. if doVerbose then writeln('Export symbols renaming');
  197. syms:=TStringList.Create;
  198. fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone);
  199. dst := TMemoryStream.Create;
  200. try
  201. if (symfn <> '') and fileExists(symfn) then
  202. begin
  203. if doVerbose then writeln('reading symbols: ', symfn);
  204. if isWasmFile(symfn) then
  205. ExportNameGather(symfn, syms, doVerbose)
  206. else
  207. syms.LoadFromFile(symfn);
  208. if doVerbose then write(syms.Text);
  209. end;
  210. ExportRenameProcess(fs, dst, syms, doVerbose);
  211. fs.Position:=0;
  212. dst.Position:=0;
  213. fs.CopyFrom(dst, dst.Size);
  214. fs.Size:=dst.Size;
  215. finally
  216. dst.Free;
  217. fs.Free;
  218. syms.Free;
  219. end;
  220. end;
  221. end.