mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 21:48:09 +02:00
[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:
parent
addfbaf889
commit
9d235d92bf
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user