[PATCH 010/188] starting wasmtool

From 8bc85f8323cf0fc24a838a0dcc8cde90b91dabee Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <skalogryz.lists@gmail.com>
Date: Thu, 26 Sep 2019 09:24:27 -0400

git-svn-id: branches/wasm@46006 -
This commit is contained in:
nickysn 2020-08-03 12:58:54 +00:00
parent 18910afe47
commit d4f8da8112
4 changed files with 353 additions and 0 deletions

3
.gitattributes vendored
View File

@ -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

View File

@ -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>

View File

@ -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.

View File

@ -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.