[PATCH 024/188] update symbol flags

From 4e1c01a42dc4ec155efd5ad6ff8bb6a49962948b Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <skalogryz.lists@gmail.com>
Date: Fri, 27 Sep 2019 16:44:35 -0400

git-svn-id: branches/wasm@46020 -
This commit is contained in:
nickysn 2020-08-03 12:59:09 +00:00
parent 1a80e89ccf
commit 52c059f027
2 changed files with 189 additions and 36 deletions

View File

@ -14,6 +14,7 @@ uses
const
ACT_EXPORTRENAME = 'exportrename';
ACT_SYMBOLFLAG = 'symbolflag';
ACT_SYMBOLAUTO = 'symbolauto';
VERSION = '1.0';
@ -25,7 +26,8 @@ begin
writeln;
writeln('options:');
writeln(' --exportrename @inputfile - renaming export names');
writeln(' --symbolflag @inputfile - update symbol use flags');
writeln(' --symbolflag @inputfile - update symbol flags as specified in input');
writeln(' --symbolauto - update symbol by the use');
writeln(' --verbose - enabling verbose mode');
end;
@ -64,6 +66,8 @@ begin
ExportRename(inputFn, ta.paramsFn, doVerbose);
end else if ta.action = ACT_SYMBOLFLAG then begin
ChangeSymbolFlag(inputFn, ta.paramsFn);
end else if ta.action = ACT_SYMBOLAUTO then begin
PredictSymbolsFromLink(inputFn, doVerbose);
end;
end;
end;
@ -95,6 +99,8 @@ begin
ls := Copy(ls, 3, length(ls)-2);
if (ls = 'verbose') then
verbose := true
else if (ls = ACT_SYMBOLAUTO) then
acts.Add( TToolActions.Create(ls, ''))
else begin
if i<=ParamCount then begin
fn:=ParamStr(i);

View File

@ -9,6 +9,7 @@ uses
function ChangeSymbolFlagStream(st: TStream; syms: TStrings): Boolean;
procedure ChangeSymbolFlag(const fn, symfn: string);
function PredictSymbolsFromLink(const wasmfn: string; doVerbose: Boolean = false): Boolean;
procedure MatchExportNameToSymName(const x: TExportSection; const l: TLinkingSection; dst: TStrings);
function ExportRenameSym(var x: TExportSection; syms: TStrings): Integer;
@ -63,41 +64,141 @@ end;
// 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)
const imp: TImportSection;
const c: TCodeSection;
const e: TElementSection;
const x: TExportSection;
var l: TLinkingSection; doVerbose: Boolean);
type
TFuncType = (ftImpl = 0, ftIntf, ftStub, ftExport);
TFuncInfo = record
hasSymbol : Boolean;
fnType : TFuncType;
end;
var
i : integer;
j : integer;
idx : integer;
fn : array of TFuncInfo;
codeofs: integer;
begin
idx := -1;
for i:=0 to length(l.symbols)-1 do
if l.symbols[i].kind = SYMTAB_FUNCTION then begin
writeln(i,' fun idx: ', l.symbols[i].symindex);
if l.symbols[i].symindex>idx then begin
idx:= l.symbols[i].symindex;
end;
end;
SetLength(fn, idx+1);
for i:=0 to length(l.symbols)-1 do
if l.symbols[i].kind = SYMTAB_FUNCTION then begin
idx := l.symbols[i].symindex;
fn[idx].hasSymbol:=true;
end;
for i:=0 to length(e.entries)-1 do
for j:=0 to length(e.entries[i].funcs)-1 do begin
idx := e.entries[i].funcs[j];
fn[idx].fnType:=ftIntf;
end;
codeofs:=0;
for i:=0 to length(imp.entries)-1 do
if imp.entries[i].desc = IMPDESC_FUNC then
inc(codeofs);
for i:=codeofs to length(fn)-1 do begin
if not fn[i].hasSymbol then begin
Continue;
end;
if (fn[i].fnType=ftImpl) and (isUnreachable(c.entries[i-codeofs])) then begin
fn[i].fnType:=ftStub;
end;
end;
for i:=0 to length(x.entries)-1 do begin
if x.entries[i].desc = EXPDESC_FUNC then begin
idx := x.entries[i].index;
if fn[idx].fnType<>ftStub then
fn[idx].fnType:=ftExport;
end;
end;
for i:=0 to length(l.symbols)-1 do begin
if l.symbols[i].kind = SYMTAB_FUNCTION then begin
j := l.symbols[i].symindex;
if j>=codeofs then // not imported
case fn[j].fnType of
ftImpl:
l.symbols[i].flags := l.symbols[i].flags or WASM_SYM_VISIBILITY_HIDDEN or WASM_SYM_BINDING_LOCAL;
ftIntf:
l.symbols[i].flags := l.symbols[i].flags or WASM_SYM_VISIBILITY_HIDDEN;
ftStub:
l.symbols[i].flags := l.symbols[i].flags or WASM_SYM_BINDING_WEAK or WASM_SYM_VISIBILITY_HIDDEN;
ftExport:
//l.symbols[i].flags := l.symbols[i].flags or WASM_SYM_VISIBILITY_HIDDEN or WASM_SYM_BINDING_WEAK;
;
end;
if DoVerbose then begin
write('func ');
if l.symbols[i].hasSymName then
write(l.symbols[i].symname)
else
write('#',j);
write(' ', fn[j].fnType);
writeln;
end;
//if l.symbols[i].symindex>mx then mx := ;
end;
end;
end;
function PredictSymbolsFromLink(const wasmfn: string; syms: TStrings; doVerbose: Boolean = false): Boolean;
function PredictSymbolsFromLink(const wasmfn: string; doVerbose: Boolean = false): Boolean;
var
st : TFileStream;
dw : LongWord;
foundExport : Boolean;
foundCode : Boolean;
foundElement : Boolean;
foundLink : Boolean;
foundExport : Boolean;
foundImport : Boolean;
ofs : Int64;
ps : Int64;
sc : TSection;
x : TExportSection;
c : TCodeSection;
imp : TImportSection;
l : TLinkingSection;
e : TElementSection;
cnt : Integer;
x : TExportSection;
nm : string;
lofs : Int64;
lsize : Int64;
mem : TMemoryStream;
mem2 : TMemoryStream;
begin
st := TFileStream.Create(wasmfn, fmOpenRead or fmShareDenyNone);
st := TFileStream.Create(wasmfn, fmOpenReadWrite or fmShareDenyNone);
try
dw := st.ReadDWord;
Result := dw = WasmId_Int;
if not Result then begin
Exit;
end;
if not Result then Exit;
dw := st.ReadDWord;
foundElement:=false;
foundExport:=false;
foundLink:=false;
foundElement := false;
foundCode := false;
foundLink := false;
foundExport := false;
foundImport := false;
Result := false;
while st.Position<st.Size do begin
ofs := st.Position;
sc.id := st.ReadByte;
@ -105,26 +206,76 @@ begin
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);
case sc.id of
SECT_IMPORT: begin
ReadImportSection(st, imp);
foundImport := true;
end;
SECT_EXPORT: begin
ReadExport(st, x);
foundExport := true;
end;
SECT_ELEMENT: begin
ReadElementSection(st, e);
foundElement := true;
end;
SECT_CODE: begin
ReadCodeSection(st, c);
foundCode := true;
end;
SECT_CUSTOM: begin
nm := ReadName(st);
if nm = SectionName_Linking then begin
lofs:=ofs;
ReadLinkingSection(st, sc.size, l);
foundLink := true;
lsize := ps-lofs;
end;
end;
end;
if st.Position <> ps then
if st.Position <> ps then begin
st.Position := ps;
end;
Result := foundLink and foundCode and foundElement;
if Result then break;
end;
Result := foundLink and foundExport;
if Result then
MatchExportNameToSymFlag(x, l, syms);
if not foundExport then SetLength(x.entries,0);
if not foundImport then SetLength(imp.entries, 0);
if Result then begin
if doVerbose then writeln('detecting symbols');
MatchExportNameToSymFlag(imp, c, e, x, l, doVerbose);
mem:=TMemoryStream.Create;
mem2:=TMemoryStream.Create;
try
st.Position:=lofs+lsize;
mem2.CopyFrom(st, st.Size - st.Position);
st.Position:=lofs;
WriteName(mem, SectionName_Linking);
WriteLinkingSection(mem, l);
st.WriteByte(SECT_CUSTOM);
if doVerbose then writeln('section size: ', mem.Size);
WriteU32(st, mem.Size);
mem.Position:=0;
if doVerbose then writeln('copying from mem');
st.CopyFrom(mem, mem.Size);
mem2.Position:=0;
if doVerbose then writeln('copying from mem2');
st.CopyFrom(mem2, mem2.Size);
st.Size:=st.Position;
finally
mem.Free;
mem2.Free;
end;
if doVerbose then writeln('written: ', st.Position-lofs,' bytes');
end else
writeln('failed. section find status. Likning: ', foundLink,'; Code: ', foundCode,'; Element: ', foundElement);
finally
st.Free;
end;
@ -139,13 +290,9 @@ begin
fs := TFileStream.Create(fn, fmOpenReadWrite or fmShareDenyNone);
try
if (symfn<>'') then begin
if not isWasmFile(symfn) then
ReadSymbolsConf(symfn, syms)
else begin
PredictSymbolsFromLink(symfn, syms);
end;
ReadSymbolsConf(symfn, syms);
ChangeSymbolFlagStream(fs, syms);
end;
ChangeSymbolFlagStream(fs, syms);
finally
fs.Free;
syms.Free;