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

View File

@ -106,8 +106,9 @@ type
jumplabel : string; // the label is used only for "loop", "block" and "if"
hasRelocIdx : Boolean;
relocIdx : integer;
//relocIdx : integer;
relocType : Byte;
relocObj : TObject; //
vecTableCount : Integer;
vecTable : array of TWasmId;
@ -115,7 +116,7 @@ type
function addInstType: TWasmFuncType;
constructor Create;
destructor Destroy; override;
procedure SetReloc(ARelocType: byte; ARelocIndex: Integer);
procedure SetReloc(ARelocType: byte; ARelocObj: TObject);
property offsetText : TWasmInstrOperand read operand1 write operand1;
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 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
procedure OperandSetType(var op: TWasmInstrOperand; tp: TWasmInstrOperandType); inline;
@ -567,11 +574,11 @@ begin
inherited Destroy;
end;
procedure TWasmInstr.SetReloc(ARelocType: byte; ARelocIndex: Integer);
procedure TWasmInstr.SetReloc(ARelocType: byte; ARelocObj: TObject);
begin
hasRelocIdx := true;
relocType := ARelocType;
relocIdx := ARelocIndex;
relocObj := ARelocObj;
end;
{ TWasmInstrList }
@ -1027,6 +1034,42 @@ begin
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
function FindFuncType(m: TWasmModule; const typeIdx: string): integer;
var

View File

@ -13,25 +13,35 @@ implementation
procedure PopulateRelocData(module: TWasmModule; ci: TWasmInstr);
var
idx : integer;
obj : TObject;
begin
case INST_FLAGS[ci.code].Param of
ipi32OrFunc:
if (ci.operand1.textVal<>'') and (ci.operand1.textVal[1]='$') then begin
//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);
ci.operandNum := idx;
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, idx);
ci.SetReloc(INST_RELOC_FLAGS[ci.code].relocType, obj);
end;
ipLeb:
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;
ipCallType:
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;