Browse Source

[PATCH 010/188] starting wasmtool

From 8bc85f8323cf0fc24a838a0dcc8cde90b91dabee Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <[email protected]>
Date: Thu, 26 Sep 2019 09:24:27 -0400

git-svn-id: branches/wasm@46006 -
nickysn 5 years ago
parent
commit
d4f8da8112
4 changed files with 353 additions and 0 deletions
  1. 3 0
      .gitattributes
  2. 68 0
      utils/wasmbin/wasmtool.lpi
  3. 39 0
      utils/wasmbin/wasmtool.lpr
  4. 243 0
      utils/wasmbin/wasmtoolutils.pas

+ 3 - 0
.gitattributes

@@ -18983,3 +18983,6 @@ utils/wasmbin/wasmld.lpi svneol=native#text/plain
 utils/wasmbin/wasmld.lpr svneol=native#text/plain
 utils/wasmbin/wasmlink.pas svneol=native#text/plain
 utils/wasmbin/wasmlinkchange.pas svneol=native#text/plain
+utils/wasmbin/wasmtool.lpi svneol=native#text/plain
+utils/wasmbin/wasmtool.lpr svneol=native#text/plain
+utils/wasmbin/wasmtoolutils.pas svneol=native#text/plain

+ 68 - 0
utils/wasmbin/wasmtool.lpi

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="wasmtool"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <UseFileFilters Value="True"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="wasmtool.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="wasmbin.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="wasmbindebug.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="wasmtool"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 39 - 0
utils/wasmbin/wasmtool.lpr

@@ -0,0 +1,39 @@
+program wasmtool;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  { you can add units after this }
+  Classes, SysUtils, wasmbin, lebutils,
+  wasmbindebug, wasmlink, wasmlinkchange,
+  wasmtoolutils;
+
+procedure PrintHelp;
+begin
+  writeln('wasmtool [options] .wasm file...');
+  writeln();
+  writeln('options:');
+  writeln('  --exportrename @inputfile');
+  writeln('  --symbolflag @inputfile');
+end;
+
+
+var
+  symfn : string;
+begin
+  if ParamCount=0 then begin
+    PrintHelp;
+
+    exit;
+  end;
+  symfn:='';
+  if ParamCount>1 then symfn:=ParamStr(2);
+
+  //ReadWasmFile(ParamStr(1));
+  //ProcessWasmFile(ParamStr(1), symfn);
+  ProcessWasmSection(ParamStr(1), symfn);
+end.
+

+ 243 - 0
utils/wasmbin/wasmtoolutils.pas

@@ -0,0 +1,243 @@
+unit wasmtoolutils;
+
+interface
+
+uses
+  Classes,SysUtils, wasmbin, lebutils,
+  //wasmbindebug,
+  wasmlink, wasmlinkchange;
+
+function ReadStream(st: TStream): Boolean;
+procedure ReadWasmFile(const fn: string);
+function WriteStream(st: TStream; syms: TStrings): Boolean;
+procedure ProcessWasmFile(const fn, symfn: string);
+procedure RenameExport(var x: TExportSection; syms: TStrings);
+function ProcessSections(st, dst: TStream; syms: TStrings): Boolean;
+procedure ProcessWasmSection(const fn, {%H-}symfn: string);
+
+implementation
+
+function ReadStream(st: TStream): Boolean;
+var
+  dw  : LongWord;
+  ofs : int64;
+  sc  : TSection;
+  ps  : int64;
+  nm  : string;
+begin
+  dw := st.ReadDWord;
+  Result := dw = WasmId_Int;
+  if not Result then begin
+    writeln('not a wasm file');
+    Exit;
+  end;
+  dw := st.ReadDWord;
+  writeln('version: ', dw);
+  while st.Position<st.Size do begin
+    ofs := st.Position;
+    sc.id := st.ReadByte;
+    sc.Size := ReadU(st);
+    writeln(ofs,': id=', sc.id,'(', SectionIdToStr(sc.id),') sz=', sc.size);
+
+    ps := st.Position+sc.size;
+    if sc.id=0 then begin
+      nm := GetName(st);
+      writeln(nm);
+      if nm = SectionName_Linking then
+        DumpLinking(st, sc.size - (st.Position - ofs));
+    end;
+    //if sc.id= 1 then DumpTypes(st);
+
+    if st.Position <> ps then
+    begin
+      //writeln('adjust stream targ=',ps,' actual: ', st.position);
+      st.Position := ps;
+    end;
+  end;
+end;
+
+
+procedure ReadWasmFile(const fn: string);
+var
+  fs :TFileStream;
+begin
+  fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyNone);
+  try
+    ReadStream(fs);
+  finally
+    fs.Free;
+  end;
+end;
+
+function WriteStream(st: TStream; syms: TStrings): Boolean;
+var
+  dw  : LongWord;
+  ofs : int64;
+  sc  : TSection;
+  ps  : int64;
+  nm  : string;
+begin
+  writeln('read: ');
+  dw := st.ReadDWord;
+  writeln('dw: ' ,dw);
+  Result := dw = WasmId_Int;
+  if not Result then begin
+    writeln('not a wasm file');
+    Exit;
+  end;
+  dw := st.ReadDWord;
+  writeln('version: ', dw);
+  while st.Position<st.Size do begin
+    ofs := st.Position;
+    sc.id := st.ReadByte;
+    sc.Size := ReadU(st);
+    writeln(ofs,': id=', sc.id,'(', SectionIdToStr(sc.id),') sz=', sc.size);
+
+    ps := st.Position+sc.size;
+    if sc.id=0 then begin
+      nm := GetName(st);
+      writeln(nm);
+      if nm = SectionName_Linking then begin
+        writeln('rewriting linking...');
+        ProcessLinkingSection(st, syms);
+        break;
+      end;
+        //DumpLinking(st, sc.size - (st.Position - ofs));
+    end;
+    //if sc.id= 1 then DumpTypes(st);
+
+    if st.Position <> ps then
+    begin
+      //writeln('adjust stream targ=',ps,' actual: ', st.position);
+      st.Position := ps;
+    end;
+  end;
+end;
+
+procedure ProcessWasmFile(const fn, symfn: string);
+var
+  fs :TFileStream;
+  syms:  TStringList;
+begin
+  writeln('proc: ', fn);
+  syms:=TStringList.Create;
+  fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone);
+  try
+    if (symfn<>'') then
+      ReadSymbolsConf(symfn, syms);
+    writeln('size: ', fs.size);
+    WriteStream(fs, syms);
+  finally
+    fs.Free;
+    syms.Free;
+  end;
+end;
+
+procedure RenameExport(var x: TExportSection; syms: TStrings);
+var
+  i : integer;
+  v : string;
+begin
+  for i:=0 to length(x.entries)-1 do begin
+    v := syms.Values[x.entries[i].name];
+    if v <> '' then
+      x.entries[i].name := v;
+  end;
+end;
+
+function ProcessSections(st, dst: TStream; syms: TStrings): Boolean;
+var
+  dw  : LongWord;
+  ofs : int64;
+  sc  : TSection;
+  ps  : int64;
+  x   : TExportSection;
+  i   : integer;
+  mem : TMemoryStream;
+begin
+  dw := st.ReadDWord;
+  Result := dw = WasmId_Int;
+  if not Result then begin
+    Exit;
+  end;
+  dw := st.ReadDWord;
+  while st.Position<st.Size do begin
+    ofs := st.Position;
+    sc.id := st.ReadByte;
+    sc.Size := ReadU(st);
+    writeln(ofs,': id=', sc.id,'(', SectionIdToStr(sc.id),') sz=', sc.size);
+
+    ps := st.Position+sc.size;
+
+    if sc.id = SECT_EXPORT then begin
+      ReadExport(st, x);
+      RenameExport(x, syms);
+
+      st.Position:=0;
+      dst.CopyFrom(st, ofs);
+      st.Position:=ps;
+
+      mem := TMemoryStream.Create;
+      WriteExport(x, mem);
+      mem.Position:=0;
+
+      dst.WriteByte(SECT_EXPORT);
+      WriteU32(dst, mem.Size);
+      dst.CopyFrom(mem, mem.Size);
+
+      writeln('entries = ', length(x.entries));
+      for i:=0 to length(x.entries)-1 do begin
+        writeln(x.entries[i].desc,' ', x.entries[i].name)
+      end;
+
+      dst.CopyFrom(st, st.Size-st.Position);
+      break; // done
+    end;
+    {if sc.id=0 then begin
+      nm := GetName(st);
+      writeln(nm);
+      if nm = SectionName_Linking then begin
+        writeln('rewriting linking...');
+        ProcessLinkingSection(st, syms);
+        break;
+      end;
+        //DumpLinking(st, sc.size - (st.Position - ofs));
+    end;}
+    //if sc.id= 1 then DumpTypes(st);
+
+    if st.Position <> ps then
+    begin
+      //writeln('adjust stream targ=',ps,' actual: ', st.position);
+      st.Position := ps;
+    end;
+  end;
+end;
+
+procedure ProcessWasmSection(const fn, {%H-}symfn: string);
+var
+  fs    : TFileStream;
+  syms  : TStringList;
+  dst   : TMemoryStream;
+begin
+  writeln('proc: ', fn);
+  syms:=TStringList.Create;
+  fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone);
+  dst := TMemoryStream.Create;
+  try
+    if (symfn <> '') and fileExists(symfn) then
+      syms.LoadFromFile(symfn);
+
+    ProcessSections(fs, dst, syms);
+    fs.Position:=0;
+    dst.Position:=0;
+    fs.CopyFrom(dst, dst.Size);
+    fs.Size:=dst.Size;
+
+  finally
+    dst.Free;
+    fs.Free;
+    syms.Free;
+  end;
+end;
+
+end.