[PATCH 185/188] changing relocation to use actual wasmmodule objects,

instead of indexes. As the actual symbol index is only known when after
 linking section was written

From 32f96b6a7da19db001b62481e860df5757f0867c Mon Sep 17 00:00:00 2001
From: Dmitry Boyarintsev <skalogryz.lists@gmail.com>
Date: Mon, 13 Apr 2020 09:32:18 -0400

git-svn-id: branches/wasm@46181 -
This commit is contained in:
nickysn 2020-08-03 13:02:16 +00:00
parent addfbaf889
commit 9d235d92bf
3 changed files with 145 additions and 22 deletions

View File

@ -5,7 +5,7 @@ unit wasmbinwriter;
interface interface
uses uses
Classes, SysUtils, Classes, SysUtils, AVL_Tree,
wasmmodule, wasmbin, lebutils, wasmbincode wasmmodule, wasmbin, lebutils, wasmbincode
,wasmlink; ,wasmlink;
@ -18,8 +18,10 @@ type
end; end;
TSymbolObject = class(TObject) TSymbolObject = class(TObject)
idx : Integer;
syminfo : TSymInfo; syminfo : TSymInfo;
next : TSymbolObject; next : TSymbolObject;
wasmObj : TObject;
end; end;
{ TBinWriter } { TBinWriter }
@ -39,9 +41,11 @@ type
symHead : TSymbolObject; symHead : TSymbolObject;
symTail : TSymbolObject; symTail : TSymbolObject;
syms : TAVLTree;
symCount : Integer; symCount : Integer;
function AddSymbolObject: TSymbolObject; function AddSymbolObject(obj: TObject): TSymbolObject;
procedure AddReloc(relocType: byte; ofs: int64; index: UInt32); procedure AddRelocWithIndex(relocType: byte; secOfs: int64; index: UInt32);
procedure AddRelocToObj(relocType: byte; secOfs: int64; wasmObj: TObject);
procedure WriteRelocU32(u: longword); procedure WriteRelocU32(u: longword);
procedure WriteString(const s: string); procedure WriteString(const s: string);
@ -60,13 +64,12 @@ type
procedure WriteCodeSect; procedure WriteCodeSect;
procedure WriteElemSect; procedure WriteElemSect;
procedure PrepareLinkSym(m: TWasmModule);
procedure WriteLinkingSect; procedure WriteLinkingSect;
procedure WriteRelocSect; procedure WriteRelocSect;
procedure pushStream(st: TStream); procedure pushStream(st: TStream);
function popStream: TStream; function popStream: TStream;
procedure PrepareLinkSym(m: TWasmModule);
public public
keepLeb128 : Boolean; // keep leb128 at 4 offset relocatable keepLeb128 : Boolean; // keep leb128 at 4 offset relocatable
writeReloc : Boolean; // writting relocation (linking) information writeReloc : Boolean; // writting relocation (linking) information
@ -93,6 +96,31 @@ procedure WriteLimit(dst: TStream; amin, amax: LongWord);
implementation implementation
function ComparePtrUInt(p1,p2: PtrUInt): Integer; inline;
begin
if p1<p2 then Result:=-1
else if p1=p2 then Result:=0
else Result:=1;
end;
function CompareSymObjs(Item1, Item2: Pointer): Integer;
var
s1, s2: TSymbolObject;
begin
s1:=TSymbolObject(Item1);
s2:=TSymbolObject(Item2);
Result:=ComparePtrUInt(PtrUInt(s1.wasmObj), PtrUInt(s2.wasmObj));
end;
function CompareWasmToSymObj(Item1, Item2: Pointer): Integer;
var
s2: TSymbolObject;
begin
s2:=TSymbolObject(Item2);
Result:=ComparePtrUInt(PtrUInt(Item1), PtrUInt(s2.wasmObj));
end;
procedure WriteLimit(dst: TStream; amin, amax: LongWord); procedure WriteLimit(dst: TStream; amin, amax: LongWord);
begin begin
if not Assigned(dst) then Exit; if not Assigned(dst) then Exit;
@ -161,19 +189,47 @@ end;
{ TBinWriter } { TBinWriter }
function TBinWriter.AddSymbolObject: TSymbolObject; function GetLinkName(const linkInfo: TLinkInfo; const id: string): string;
begin
if linkInfo.Name<>'' then Result:=linkInfo.Name
else Result:=id;
end;
function TBinWriter.AddSymbolObject(obj: TObject): TSymbolObject;
var var
so : TSymbolObject; so : TSymbolObject;
t : TAVLTreeNode;
begin begin
t := syms.FindKey(obj, @CompareWasmToSymObj);
if Assigned(t) then begin
Result:=TSymbolObject(t.Data);
Exit;
end;
so := TSymbolObject.Create; so := TSymbolObject.Create;
if not Assigned(symHead) then symHead:=so; if not Assigned(symHead) then symHead:=so;
if Assigned(symTail) then symTail.Next:=so; if Assigned(symTail) then symTail.Next:=so;
so.idx:=symCount;
so.wasmObj:=obj;
symTail:=so; symTail:=so;
inc(symCount); inc(symCount);
Result:=so; Result:=so;
if (obj is TWasmFunc) then begin
so.syminfo.kind:=SYMTAB_FUNCTION;
so.syminfo.symindex:=TWasmFunc(obj).idNum;
end else if (obj is TWasmGlobal) then begin
so.syminfo.kind:=SYMTAB_GLOBAL;
so.syminfo.symindex:=TWasmGlobal(obj).id.idNum;
so.syminfo.symname:=GetLinkName(TWasmGlobal(obj).LinkInfo, TWasmGlobal(obj).id.id); //todo: use symbolic name
end else if (obj is TWasmTable) then begin
so.syminfo.kind:=SYMTAB_TABLE;
so.syminfo.symindex:=TWasmTable(obj).id.idNum;
end;
syms.Add(so);
end; end;
procedure TBinWriter.AddReloc(relocType: byte; ofs: int64; index: UInt32); procedure TBinWriter.AddRelocWithIndex(relocType: byte; secOfs: int64; index: UInt32);
var var
i : integer; i : integer;
f : TWasmFunc; f : TWasmFunc;
@ -186,7 +242,7 @@ begin
i:=relocCount; i:=relocCount;
reloc[i].sec:=writeSec; reloc[i].sec:=writeSec;
reloc[i].reltype:=relocType; reloc[i].reltype:=relocType;
reloc[i].offset:=ofs; reloc[i].offset:=secOfs;
reloc[i].index:=index; reloc[i].index:=index;
inc(relocCount); inc(relocCount);
@ -202,6 +258,16 @@ begin
end; end;
end; end;
procedure TBinWriter.AddRelocToObj(relocType: byte; secOfs: int64; wasmObj: TObject);
var
idx : integer;
begin
if not Assigned(wasmObj) then Exit;
idx:=AddSymbolObject(wasmObj).idx;
AddRelocWithIndex(relocType, secOfs, idx);
end;
procedure TBinWriter.WriteRelocU32(u: longword); procedure TBinWriter.WriteRelocU32(u: longword);
begin begin
WriteU(dst, u, sizeof(u)*8, keepLeb128); WriteU(dst, u, sizeof(u)*8, keepLeb128);
@ -520,7 +586,8 @@ begin
if writeReloc then begin if writeReloc then begin
for j:=0 to el.funcCount-1 do begin for j:=0 to el.funcCount-1 do begin
AddReloc(R_WASM_FUNCTION_INDEX_LEB, dst.Position - sc.datapos, el.funcs[j].idNum); AddRelocToObj(R_WASM_FUNCTION_INDEX_LEB, dst.Position - sc.datapos,
GetFuncByNum(module, el.funcs[j].idNum));
WriteRelocU32(el.funcs[j].idNum); WriteRelocU32(el.funcs[j].idNum);
end; end;
end else end else
@ -620,9 +687,8 @@ begin
dst.WriteByte(ci.code); dst.WriteByte(ci.code);
if ci.hasRelocIdx then begin if ci.hasRelocIdx then begin
idx := ci.relocIdx;
rt := ci.relocType; rt := ci.relocType;
AddReloc(rt, dst.Position+ofsAddition, LongWord(idx)); AddRelocToObj(rt, dst.Position+ofsAddition, ci.relocObj);
end; end;
case INST_FLAGS[ci.code].Param of case INST_FLAGS[ci.code].Param of
@ -745,10 +811,12 @@ constructor TBinWriter.Create;
begin begin
inherited Create; inherited Create;
strm:=TList.Create; strm:=TList.Create;
syms:=TAVLTree.Create(@CompareSymObjs);
end; end;
destructor TBinWriter.Destroy; destructor TBinWriter.Destroy;
begin begin
syms.Free;
strm.Free; strm.Free;
inherited Destroy; inherited Destroy;
end; end;
@ -761,7 +829,7 @@ begin
or l.NoStrip; or l.NoStrip;
end; end;
procedure LinkInfoToBin(const src: TLinkInfo; var dst: TSymInfo; ASymTab: byte; aofs: longword); procedure LinkInfoToBin(const src: TLinkInfo; var dst: TSymInfo; ASymTab: byte; objFnIdx: longword);
begin begin
dst.kind := ASymTab; dst.kind := ASymTab;
dst.flags := 0; dst.flags := 0;
@ -773,7 +841,7 @@ begin
if src.isHidden then dst.flags := dst.flags or WASM_SYM_VISIBILITY_HIDDEN; if src.isHidden then dst.flags := dst.flags or WASM_SYM_VISIBILITY_HIDDEN;
if src.isUndefined then dst.flags := dst.flags or WASM_SYM_UNDEFINED; if src.isUndefined then dst.flags := dst.flags or WASM_SYM_UNDEFINED;
if src.NoStrip then dst.flags := dst.flags or WASM_SYM_NO_STRIP; if src.NoStrip then dst.flags := dst.flags or WASM_SYM_NO_STRIP;
dst.symindex := aofs; dst.symindex := objFnIdx;
dst.hasSymIndex := ASymTab<>SYMTAB_DATA; dst.hasSymIndex := ASymTab<>SYMTAB_DATA;
dst.hasSymName := src.Name<>''; dst.hasSymName := src.Name<>'';
if (dst.hasSymName) then begin if (dst.hasSymName) then begin
@ -788,14 +856,16 @@ var
f : TWasmFunc; f : TWasmFunc;
so : TSymbolObject; so : TSymbolObject;
begin begin
writeln('preparing symlinks');
for i:=0 to m.FuncCount-1 do begin for i:=0 to m.FuncCount-1 do begin
f := m.GetFunc(i); f := m.GetFunc(i);
if isFuncLinkSym(f.LinkInfo) or (f.codeRefCount>0) then begin if isFuncLinkSym(f.LinkInfo) or (f.codeRefCount>0) then begin
if f.LinkInfo.Name ='' then f.LinkInfo.Name := f.id; if f.LinkInfo.Name ='' then f.LinkInfo.Name := f.id;
so:=AddSymbolObject; so:=AddSymbolObject(f);
LinkInfoToBin(f.linkInfo, so.syminfo, SYMTAB_FUNCTION, f.idNum); LinkInfoToBin(f.linkInfo, so.syminfo, SYMTAB_FUNCTION, f.idNum);
end; end;
end; end;
writeln('done');
end; end;
end. end.

View File

@ -106,8 +106,9 @@ type
jumplabel : string; // the label is used only for "loop", "block" and "if" jumplabel : string; // the label is used only for "loop", "block" and "if"
hasRelocIdx : Boolean; hasRelocIdx : Boolean;
relocIdx : integer; //relocIdx : integer;
relocType : Byte; relocType : Byte;
relocObj : TObject; //
vecTableCount : Integer; vecTableCount : Integer;
vecTable : array of TWasmId; vecTable : array of TWasmId;
@ -115,7 +116,7 @@ type
function addInstType: TWasmFuncType; function addInstType: TWasmFuncType;
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
procedure SetReloc(ARelocType: byte; ARelocIndex: Integer); procedure SetReloc(ARelocType: byte; ARelocObj: TObject);
property offsetText : TWasmInstrOperand read operand1 write operand1; property offsetText : TWasmInstrOperand read operand1 write operand1;
property alignText : TWasmInstrOperand read operand2 write operand2; property alignText : TWasmInstrOperand read operand2 write operand2;
@ -326,6 +327,12 @@ procedure OperandSetType(var op: TWasmInstrOperand; tp: TWasmInstrOperandType);
procedure OperandSetInt32(var op: TWasmInstrOperand; i32: Int32); inline; procedure OperandSetInt32(var op: TWasmInstrOperand; i32: Int32); inline;
procedure OperandSetText(var op: TWasmInstrOperand; const txt: string); inline; procedure OperandSetText(var op: TWasmInstrOperand; const txt: string); inline;
// should be used after normalization
// todo: what about imported functions?
function GetFuncByNum(m: TWasmModule; const idNum: Integer): TWasmFunc;
function GetGlobalByNum(m: TWasmModule; const idNum: Integer): TWasmGlobal;
function GetMemByNum(m: TWasmModule; const idNum: Integer): TWasmMemory;
implementation implementation
procedure OperandSetType(var op: TWasmInstrOperand; tp: TWasmInstrOperandType); inline; procedure OperandSetType(var op: TWasmInstrOperand; tp: TWasmInstrOperandType); inline;
@ -567,11 +574,11 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TWasmInstr.SetReloc(ARelocType: byte; ARelocIndex: Integer); procedure TWasmInstr.SetReloc(ARelocType: byte; ARelocObj: TObject);
begin begin
hasRelocIdx := true; hasRelocIdx := true;
relocType := ARelocType; relocType := ARelocType;
relocIdx := ARelocIndex; relocObj := ARelocObj;
end; end;
{ TWasmInstrList } { TWasmInstrList }
@ -1027,6 +1034,42 @@ begin
end; end;
end; end;
function GetFuncByNum(m: TWasmMOdule; const idNum: Integer): TWasmFunc;
var
i : integer;
begin
for i:=0 to m.FuncCount-1 do begin
Result := m.GetFunc(i);
if Assigned(Result) and (Result.idNum = idNum) then
Exit;
end;
Result:=nil;
end;
function GetGlobalByNum(m: TWasmModule; const idNum: Integer): TWasmGlobal;
var
i : integer;
begin
for i:=0 to m.GlobalCount-1 do begin
Result := m.GetGlobal(i);
if Assigned(Result) and (Result.id.idNum = idNum) then
Exit;
end;
Result:=nil;
end;
function GetMemByNum(m: TWasmModule; const idNum: Integer): TWasmMemory;
var
i : integer;
begin
for i:=0 to m.MemoryCount-1 do begin
Result := m.GetMemory(i);
if Assigned(Result) and (Result.id.idNum = idNum) then
Exit;
end;
Result:=nil;
end;
// only looking up for the by the type index name // only looking up for the by the type index name
function FindFuncType(m: TWasmModule; const typeIdx: string): integer; function FindFuncType(m: TWasmModule; const typeIdx: string): integer;
var var

View File

@ -13,25 +13,35 @@ implementation
procedure PopulateRelocData(module: TWasmModule; ci: TWasmInstr); procedure PopulateRelocData(module: TWasmModule; ci: TWasmInstr);
var var
idx : integer; idx : integer;
obj : TObject;
begin begin
case INST_FLAGS[ci.code].Param of case INST_FLAGS[ci.code].Param of
ipi32OrFunc: ipi32OrFunc:
if (ci.operand1.textVal<>'') and (ci.operand1.textVal[1]='$') then begin if (ci.operand1.textVal<>'') and (ci.operand1.textVal[1]='$') then begin
//if not ci.hasRelocIdx then //if not ci.hasRelocIdx then
idx := RegisterfuncInElem(module, ci.operand1.textVal); idx := RegisterFuncInElem(module, ci.operand1.textVal);
obj := GetFuncByNum(module, idx);
//AddReloc(rt, dst.Position+ofsAddition, idx); //AddReloc(rt, dst.Position+ofsAddition, idx);
ci.operandNum := idx; ci.operandNum := idx;
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, idx); ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, obj);
end; end;
ipLeb: ipLeb:
if (INST_RELOC_FLAGS[ci.code].doReloc) then begin if (INST_RELOC_FLAGS[ci.code].doReloc) then begin
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, ci.operandNum); case INST_RELOC_FLAGS[ci.code].relocType of
R_WASM_GLOBAL_INDEX_LEB:
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, GetGlobalByNum(module, ci.operandNum));
R_WASM_MEMORY_ADDR_LEB :
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, GetMemByNum(module, ci.operandNum));
end;
end; end;
ipCallType: ipCallType:
if Assigned(ci.insttype) then if Assigned(ci.insttype) then
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, ci.insttype.typeNum); begin
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, ci.insttype);
end;
end; end;
end; end;