diff --git a/utils/wasmbin/wasmbin.pas b/utils/wasmbin/wasmbin.pas index 7648d634aa..3b1a93188a 100644 --- a/utils/wasmbin/wasmbin.pas +++ b/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. diff --git a/utils/wasmbin/wasmlink.pas b/utils/wasmbin/wasmlink.pas index 5021e43773..6bc27f3a46 100644 --- a/utils/wasmbin/wasmlink.pas +++ b/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. diff --git a/utils/wasmbin/wasmlinkchange.pas b/utils/wasmbin/wasmlinkchange.pas index 1edfa9e0da..c35303f9d8 100644 --- a/utils/wasmbin/wasmlinkchange.pas +++ b/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; diff --git a/utils/wasmbin/wasmtoolutils.pas b/utils/wasmbin/wasmtoolutils.pas index 1a1df66767..fffb709358 100644 --- a/utils/wasmbin/wasmtoolutils.pas +++ b/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 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;