Browse Source

[PATCH 017/188] update name gathering from linking section

From cc238c5c8b3b91c2811b0fe49de827d7e6be7981 Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <[email protected]>
Date: Thu, 26 Sep 2019 12:37:23 -0400

git-svn-id: branches/wasm@46013 -
nickysn 5 years ago
parent
commit
a6eab10ee5

+ 41 - 0
utils/wasmbin/wasmbin.pas

@@ -87,7 +87,13 @@ type
     entries : array of TCodeEntry;
   end;
 
+const
+  EXPDESC_FUNC   = $00;
+  EXPDESC_TABLE  = $01;
+  EXPDESC_MEM    = $02;
+  EXPDESC_GLOBAL = $03;
 
+type
   TExportEntry = record
     name    : string;
     desc    : byte;
@@ -123,6 +129,9 @@ procedure ReadExportEntry(src: TStream; var ex: TExportEntry);
 procedure ReadExport(src: TStream; var ex: TExportSection);
 procedure WriteExport(const ex: TExportSection; dst: TStream);
 
+function isWasmStream(st: TStream): Boolean;
+function isWasmFile(const fn: string): Boolean;
+
 implementation
 
 function ValTypeToStr(id: integer): string;
@@ -246,5 +255,37 @@ begin
   end;
 end;
 
+function isWasmStream(st: TStream): Boolean;
+var
+  pos : Int64;
+begin
+  try
+    pos:=st.Position;
+    try
+      Result := st.ReadDWord = WasmId_Int;
+    finally
+      st.Position:=pos;
+    end;
+  except
+    Result:=false;
+  end;
+end;
+
+function isWasmFile(const fn: string): Boolean;
+var
+  fs: TFileStream;
+begin
+  try
+    fs:=TFileStream.Create(fn, fmOpenRead or fmShareDenyNone);
+    try
+      Result:=isWasmStream(fs);
+    finally
+      fs.Free;
+    end;
+  except
+    Result := false;
+  end;
+end;
+
 end.
 

+ 39 - 4
utils/wasmbin/wasmlink.pas

@@ -47,7 +47,7 @@ type
     version : UInt32; // the version of linking metadata contained in this section. Currently: 2
   end;
 
-  TLinkinSubSection = record
+  TLinkingSubSection = record
     sectype : UInt8;   // code identifying type of subsection
     length  : UInt32;  // size of this subsection in bytes
   end;
@@ -131,7 +131,7 @@ const
   WASM_SYM_NO_STRIP          = $80;
 
 function ReadMetaData(st: TStream; out m:TLinkingMetadata): Boolean;
-function ReadLinkSubSect(st: TStream; out m: TLinkinSubSection): Boolean;
+function ReadLinkSubSect(st: TStream; out m: TLinkingSubSection): Boolean;
 function ReadSymInfo(st: TStream; out m: TSymInfo): Boolean;
 
 procedure WriteSymInfo(st: TStream; const m: TSymInfo);
@@ -143,6 +143,16 @@ procedure DumpLinking(st: TStream; secsize: integer);
 function SubSecTypeToStr(b: Byte): string;
 function SymKindToStr(b: Byte): string;
 
+type
+  TLinkingSection = record
+    metadata: TLinkingMetadata;
+    symbols : array of TSymInfo;
+  end;
+
+// the stream should be set at the beggining of the section
+// after name and size values
+procedure ReadLinkingSection(st: TStream; size: integer; var sc: TLinkingSection);
+
 implementation
 
 function ReadMetaData(st: TStream; out m:TLinkingMetadata): Boolean;
@@ -152,7 +162,7 @@ begin
   Result:=true;
 end;
 
-function ReadLinkSubSect(st: TStream; out m: TLinkinSubSection): Boolean;
+function ReadLinkSubSect(st: TStream; out m: TLinkingSubSection): Boolean;
 begin
   FillChar(m, sizeof(m), 0);
   m.sectype := ReadU(st);
@@ -213,7 +223,7 @@ procedure DumpLinking(st: TStream; secsize: integer);
 var
   mt  : TLinkingMetadata;
   en  : Int64;
-  sub : TLinkinSubSection;
+  sub : TLinkingSubSection;
   cnt : LongWord;
   nx  : Int64;
   i   : integer;
@@ -268,5 +278,30 @@ begin
   end;
 end;
 
+procedure ReadLinkingSection(st: TStream; size: integer; var sc: TLinkingSection);
+var
+  eofs : int64;
+  sub  : TLinkingSubSection;
+  cnt  : integer;
+  i    : integer;
+  nx   : int64;
+begin
+  eofs := st.Position+size;
+  ReadMetadata(st, sc.metadata);
+  while st.Position < eofs do begin
+    ReadLinkSubSect(st, sub);
+    nx := st.Position+sub.length;
+    case sub.sectype of
+      //todo: others!
+      WASM_SYMBOL_TABLE: begin
+        cnt := ReadU(st);
+        SetLength(sc.symbols, cnt);
+        for i:=0 to cnt-1 do
+          ReadSymInfo(st, sc.symbols[i]);
+      end;
+    end;
+    st.Position:=nx;
+  end;
+end;
 
 end.

+ 1 - 1
utils/wasmbin/wasmlinkchange.pas

@@ -56,7 +56,7 @@ procedure ProcessLinkingSection(st: TStream; syms: TStrings);
 var
   mt  : TLinkingMetadata;
   //en  : Int64;
-  sub : TLinkinSubSection;
+  sub : TLinkingSubSection;
   cnt : LongWord;
   nx  : Int64;
   i   : integer;

+ 85 - 1
utils/wasmbin/wasmtoolutils.pas

@@ -12,6 +12,7 @@ procedure ChangeSymbolFlag(const fn, symfn: string);
 
 function ExportRenameSym(var x: TExportSection; syms: TStrings): Integer;
 function ExportRenameProcess(st, dst: TStream; syms: TStrings; doVerbose: Boolean): Boolean;
+function ExportNameGather(const wasmfile: string; syms: TStrings; doVerbose: Boolean = false): Boolean;
 procedure ExportRename(const fn, symfn: string; doVerbose: Boolean);
 
 implementation
@@ -135,6 +136,85 @@ begin
   end;
 end;
 
+// match between exported function names and symbol names
+procedure MatchExportNameToSymName(const x: TExportSection; const l: TLinkingSection;  dst: TStrings);
+var
+  expname : string;
+  i,j     : integer;
+begin
+  for i:=0 to length(x.entries)-1 do begin
+    // gathering only function names for now
+    if x.entries[i].desc <> EXPDESC_FUNC then continue;
+    expname := x.entries[i].name;
+    for j:=0 to length(l.symbols)-1 do begin
+      if (l.symbols[j].kind = SYMTAB_FUNCTION)
+        and (l.symbols[j].symindex = x.entries[i].index)
+        and (l.symbols[j].hasSymName)
+      then
+        dst.Values[ l.symbols[j].symname ] := expname;
+    end;
+  end;
+
+end;
+
+function ExportNameGather(const wasmfile: string; syms: TStrings; doVerbose: Boolean = false): Boolean;
+var
+  dw  : LongWord;
+  ofs : int64;
+  sc  : TSection;
+  ps  : int64;
+  mem : TMemoryStream;
+  cnt : integer;
+  st  : TFileStream;
+  nm  : string;
+  x   : TExportSection;
+  foundExport: Boolean;
+  l   : TLinkingSection;
+  foundLink: Boolean;
+begin
+  st := TFileStream.Create(wasmfile, fmOpenRead or fmShareDenyNone);
+  try
+    dw := st.ReadDWord;
+    Result := dw = WasmId_Int;
+    if not Result then begin
+      Exit;
+    end;
+    dw := st.ReadDWord;
+
+    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
+      MatchExportNameToSymName(x, l, syms);
+  finally
+    st.Free;
+  end;
+end;
+
 procedure ExportRename(const fn, symfn: string; doVerbose: Boolean);
 var
   fs    : TFileStream;
@@ -149,7 +229,11 @@ begin
     if (symfn <> '') and fileExists(symfn) then
     begin
       if doVerbose then writeln('reading symbols: ', symfn);
-      syms.LoadFromFile(symfn);
+
+      if isWasmFile(symfn) then
+        ExportNameGather(symfn, syms, doVerbose)
+      else
+        syms.LoadFromFile(symfn);
       if doVerbose then write(syms.Text);
     end;