Browse Source

[PATCH 021/188] trying to predict the symbol flag based on the symbol
use

From fa50af275ed93955caefc447a31d2dae083f96a2 Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <[email protected]>
Date: Fri, 27 Sep 2019 01:03:39 -0400

git-svn-id: branches/wasm@46017 -

nickysn 5 years ago
parent
commit
b663c9de01

+ 46 - 4
utils/wasmbin/wasmbin.pas

@@ -5,7 +5,7 @@ unit wasmbin;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, lebutils;
+  Classes, SysUtils, lebutils, wasmbincode;
 
 
 const
 const
   valtype_i32   = $7f;
   valtype_i32   = $7f;
@@ -103,6 +103,20 @@ type
     entries : array of TExportEntry;
     entries : array of TExportEntry;
   end;
   end;
 
 
+const
+  ELEMTYPE_FUNC = $70;
+
+type
+  TElementEntry = record
+    table : Uint32;
+    expr  : array of byte;   // instructions
+    funcs : array of UInt32;
+  end;
+
+  TElementSection = record
+    entries : array of TElementEntry;
+  end;
+
 function SectionIdToStr(id: integer): string;
 function SectionIdToStr(id: integer): string;
 function ValTypeToStr(id: integer): string;
 function ValTypeToStr(id: integer): string;
 
 
@@ -124,7 +138,6 @@ procedure ReadCodeSection(src: TStream; var sc: TCodeSection);
 
 
 function isUnreachable(const cd: TCodeEntry): Boolean;
 function isUnreachable(const cd: TCodeEntry): Boolean;
 
 
-
 procedure ReadExportEntry(src: TStream; var ex: TExportEntry);
 procedure ReadExportEntry(src: TStream; var ex: TExportEntry);
 // reads the export entry
 // reads the export entry
 procedure ReadExport(src: TStream; var ex: TExportSection);
 procedure ReadExport(src: TStream; var ex: TExportSection);
@@ -133,8 +146,9 @@ procedure WriteExport(const ex: TExportSection; dst: TStream);
 function isWasmStream(st: TStream): Boolean;
 function isWasmStream(st: TStream): Boolean;
 function isWasmFile(const fn: string): Boolean;
 function isWasmFile(const fn: string): Boolean;
 
 
-const
-  INST_TRAP = $00;
+
+procedure ReadElementEntry(st: TStream; var en: TElementEntry);
+procedure ReadElementSection(st: TStream; var sc: TelementSection);
 
 
 implementation
 implementation
 
 
@@ -300,5 +314,33 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure ReadElementEntry(st: TStream; var en: TElementEntry);
+var
+  ln : integer;
+  i  : integer;
+begin
+  en.table := ReadU(st);
+  ln:=InstLen(st);
+  if ln<0 then Exit;
+  SetLength(en.expr, ln);
+  if ln>0 then st.Read(en.expr[0], ln);
+
+  ln:=ReadU(st);
+  SetLength(en.funcs, ln);
+  for i:=0 to ln-1 do
+    en.funcs[i]:=ReadU(st);
+end;
+
+procedure ReadElementSection(st: TStream; var sc: TelementSection);
+var
+  cnt : integer;
+  i   : integer;
+begin
+  cnt := ReadU(st);
+  SetLength(sc.entries, cnt);
+  for i:=0 to cnt-1 do
+    ReadElementEntry(st, sc.entries[i]);
+end;
+
 end.
 end.
 
 

+ 2 - 2
utils/wasmbin/wasmld.lpi

@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
   <ProjectOptions>
   <ProjectOptions>
-    <Version Value="11"/>
+    <Version Value="12"/>
     <PathDelim Value="\"/>
     <PathDelim Value="\"/>
     <General>
     <General>
       <Flags>
       <Flags>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasCreateFormStatements Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasTitleStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
         <MainUnitHasScaledStatement Value="False"/>
+        <CompatibilityMode Value="True"/>
       </Flags>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
-      <MainUnit Value="0"/>
       <Title Value="wasmld"/>
       <Title Value="wasmld"/>
       <UseAppBundle Value="False"/>
       <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>

+ 24 - 1
utils/wasmbin/wasmld.lpr

@@ -154,6 +154,25 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure ParseTable(st: TStream);
+begin
+end;
+
+procedure ParseElems(st: TStream);
+var
+  s : TElementSection;
+  i : integer;
+  j : integer;
+begin
+  ReadElementSection(st, s);
+  writelN('entries = ', length(s.entries));
+  for i:=0 to length(s.entries)-1 do begin
+    writeln('  ',i,' functions = ', length(s.entries[i].funcs));
+    for j:=0 to length(s.entries[i].funcs) - 1 do
+      writeln('    ',s.entries[i].funcs[j]);
+  end;
+end;
+
 function ProcessSections(st, dst: TStream; syms: TStrings): Boolean;
 function ProcessSections(st, dst: TStream; syms: TStrings): Boolean;
 var
 var
   dw  : LongWord;
   dw  : LongWord;
@@ -178,7 +197,11 @@ begin
 
 
     ps := st.Position+sc.size;
     ps := st.Position+sc.size;
 
 
-    if sc.id=SECT_CODE then begin
+    if sc.id=SECT_ELEMENT then begin
+      ParseElems(st);
+    end else if sc.id=SECT_TABLE then begin
+      ParseTable(st);
+    end else if sc.id=SECT_CODE then begin
       ParseCode(st);
       ParseCode(st);
     (*end else if sc.id = SECT_EXPORT then begin
     (*end else if sc.id = SECT_EXPORT then begin
       ReadExport(st, x);
       ReadExport(st, x);

+ 1 - 1
utils/wasmbin/wasmtool.lpr

@@ -25,7 +25,7 @@ begin
   writeln;
   writeln;
   writeln('options:');
   writeln('options:');
   writeln('  --exportrename @inputfile - renaming export names');
   writeln('  --exportrename @inputfile - renaming export names');
-  writeln('  --symbolflag   @inputfile');
+  writeln('  --symbolflag   @inputfile - update symbol use flags');
   writeln('  --verbose - enabling verbose mode');
   writeln('  --verbose - enabling verbose mode');
 end;
 end;
 
 

+ 82 - 2
utils/wasmbin/wasmtoolutils.pas

@@ -55,6 +55,81 @@ begin
   end;
   end;
 end;
 end;
 
 
+// Assumption is made, there's only 1 table in the file!
+// if a function is a stub function (the only code is "unreachable"), the status given
+//  "weak" (it's a reference function elsewhere)
+// if a function is located in the function table, then the status given is
+//  "hidden" (do not add to the final linked executable)
+// if a function is not located in the function table, the status given is:
+//  "hidden"+"local" (local means the function can be used only in this object file)
+procedure MatchExportNameToSymFlag(
+  x: TExportSection;
+  l: TLinkingSection;
+  e: TElementSection;
+  syms : TStrings)
+begin
+end;
+
+function PredictSymbolsFromLink(const wasmfn: string; syms: TStrings; doVerbose: Boolean = false): Boolean;
+var
+  st : TFileStream;
+  dw : LongWord;
+  foundExport  : Boolean;
+  foundElement : Boolean;
+  foundLink    : Boolean;
+  ofs : Int64;
+  ps  : Int64;
+  sc  : TSection;
+  x   : TExportSection;
+  l   : TLinkingSection;
+  e   : TElementSection;
+  cnt : Integer;
+  nm  : string;
+begin
+  st := TFileStream.Create(wasmfn, fmOpenRead or fmShareDenyNone);
+  try
+    dw := st.ReadDWord;
+    Result := dw = WasmId_Int;
+    if not Result then begin
+      Exit;
+    end;
+    dw := st.ReadDWord;
+
+    foundElement:=false;
+    foundExport:=false;
+    foundLink:=false;
+    while st.Position<st.Size do begin
+      ofs := st.Position;
+      sc.id := st.ReadByte;
+      sc.Size := ReadU(st);
+
+      ps := st.Position+sc.size;
+
+      if sc.id = SECT_EXPORT then begin
+        if doVerbose then writeln(' export section found');
+        ReadExport(st, x);
+        cnt := ExportRenameSym(x, syms);
+        foundExport:=true;
+      end else if sc.id = SECT_CUSTOM then begin
+        nm := ReadName(st);
+        if nm = SectionName_Linking then begin
+          foundLink := true;
+          ReadLinkingSection(st, sc.size, l);
+        end;
+      end;
+
+      if st.Position <> ps then
+        st.Position := ps;
+    end;
+
+    Result := foundLink and foundExport;
+    if Result then
+      MatchExportNameToSymFlag(x, l, syms);
+  finally
+    st.Free;
+  end;
+end;
+
 procedure ChangeSymbolFlag(const fn, symfn: string);
 procedure ChangeSymbolFlag(const fn, symfn: string);
 var
 var
   fs :TFileStream;
   fs :TFileStream;
@@ -63,8 +138,13 @@ begin
   syms:=TStringList.Create;
   syms:=TStringList.Create;
   fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone);
   fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone);
   try
   try
-    if (symfn<>'') then
-      ReadSymbolsConf(symfn, syms);
+    if (symfn<>'') then begin
+      if not isWasmFile(symfn) then
+        ReadSymbolsConf(symfn, syms)
+      else begin
+        PredictSymbolsFromLink(symfn, syms);
+      end;
+    end;
     ChangeSymbolFlagStream(fs, syms);
     ChangeSymbolFlagStream(fs, syms);
   finally
   finally
     fs.Free;
     fs.Free;