mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-18 05:39:26 +02:00
+ implemented reading of T and R records
git-svn-id: trunk@45564 -
This commit is contained in:
parent
f94221d788
commit
788797d078
@ -658,9 +658,230 @@ implementation
|
||||
|
||||
function TRelObjInput.ReadObjData(AReader: TObjectreader; out Data: TObjData): boolean;
|
||||
|
||||
function HandleTR(const T,R: string): boolean;
|
||||
function DecodeRelFlags(n1: Word): TRelRelocationFlags;
|
||||
begin
|
||||
{ todo: implement }
|
||||
result:=[];
|
||||
if (n1 and (1 shl 0))<>0 then
|
||||
include(result,rrfByte);
|
||||
if (n1 and (1 shl 1))<>0 then
|
||||
include(result,rrfSymbol);
|
||||
if (n1 and (1 shl 2))<>0 then
|
||||
include(result,rrfPcRelative);
|
||||
if (n1 and (1 shl 3))<>0 then
|
||||
include(result,rrfTwoByteObjectFormatForByteData);
|
||||
if (n1 and (1 shl 4))<>0 then
|
||||
include(result,rrfUnsignedByteData);
|
||||
if (n1 and (1 shl 5))<>0 then
|
||||
include(result,rrfPage0Reference);
|
||||
if (n1 and (1 shl 6))<>0 then
|
||||
include(result,rrfPageNNNReference);
|
||||
if (n1 and (1 shl 7))<>0 then
|
||||
include(result,rrfMSBWith2ByteMode);
|
||||
if (n1 and (1 shl 8))<>0 then
|
||||
include(result,rrfThreeByteObjectFormatForByteData);
|
||||
if (n1 and (1 shl 9))<>0 then
|
||||
include(result,rrfRealMSBForThreeByteMode);
|
||||
if (n1 and (1 shl 10))<>0 then
|
||||
include(result,rrfReserved10);
|
||||
if (n1 and (1 shl 11))<>0 then
|
||||
include(result,rrfReserved11);
|
||||
end;
|
||||
|
||||
function HandleTR(const T,R: string): boolean;
|
||||
const
|
||||
GenericTErrMsg='Invalid T record';
|
||||
GenericRErrMsg='Invalid R record';
|
||||
UnsupportedRelocationFlags=[rrfPcRelative,rrfUnsignedByteData,
|
||||
rrfPage0Reference,rrfPageNNNReference,rrfThreeByteObjectFormatForByteData,
|
||||
rrfRealMSBForThreeByteMode,rrfReserved10,rrfReserved11];
|
||||
var
|
||||
ArrT, ArrR: array of byte;
|
||||
ArrTIsRelocHiByte: array of boolean;
|
||||
tmpint: Longint;
|
||||
i: Integer;
|
||||
AreaIndex, AreaOffset: Word;
|
||||
LastDataOfsIndex: Integer;
|
||||
LastDataOfsValue: TObjSectionOfs;
|
||||
ObjSec: TObjSection;
|
||||
n1, xx_xx: Word;
|
||||
n1x, n2, RelHiByte: Byte;
|
||||
RelFlags: TRelRelocationFlags;
|
||||
reloc:TRelRelocation;
|
||||
RelocDataOffset: TObjSectionOfs;
|
||||
RelocTyp: TObjRelocationType;
|
||||
begin
|
||||
result:=false;
|
||||
if (length(T)<5) or (((length(T)-2) mod 3)<>0) then
|
||||
begin
|
||||
InputError(GenericTErrMsg);
|
||||
exit;
|
||||
end;
|
||||
if (length(R)<11) or (((length(R)-2) mod 3)<>0) then
|
||||
begin
|
||||
InputError(GenericRErrMsg);
|
||||
exit;
|
||||
end;
|
||||
SetLength(ArrT,((length(T)-2) div 3)+1);
|
||||
for i:=0 to length(ArrT)-1 do
|
||||
begin
|
||||
if (i>0) and (T[i*3]<>' ') then
|
||||
begin
|
||||
InputError(GenericTErrMsg);
|
||||
exit;
|
||||
end;
|
||||
if not TryStrToInt('$'+copy(T,1+i*3,2),tmpint) then
|
||||
begin
|
||||
InputError(GenericTErrMsg);
|
||||
exit;
|
||||
end;
|
||||
if (tmpint<0) or (tmpint>255) then
|
||||
begin
|
||||
InputError(GenericTErrMsg);
|
||||
exit;
|
||||
end;
|
||||
ArrT[i]:=tmpint;
|
||||
end;
|
||||
SetLength(ArrR,((length(R)-2) div 3)+1);
|
||||
for i:=0 to length(ArrR)-1 do
|
||||
begin
|
||||
if (i>0) and (R[i*3]<>' ') then
|
||||
begin
|
||||
InputError(GenericRErrMsg);
|
||||
exit;
|
||||
end;
|
||||
if not TryStrToInt('$'+copy(R,1+i*3,2),tmpint) then
|
||||
begin
|
||||
InputError(GenericRErrMsg);
|
||||
exit;
|
||||
end;
|
||||
if (tmpint<0) or (tmpint>255) then
|
||||
begin
|
||||
InputError(GenericRErrMsg);
|
||||
exit;
|
||||
end;
|
||||
ArrR[i]:=tmpint;
|
||||
end;
|
||||
if (length(ArrT)<2) or (length(ArrR)<4) then
|
||||
internalerror(2020060201);
|
||||
if (ArrR[0]<>0) or (ArrR[1]<>0) then
|
||||
begin
|
||||
InputError(GenericRErrMsg);
|
||||
exit;
|
||||
end;
|
||||
AreaIndex:=(ArrR[3] shl 8) or ArrR[2];
|
||||
AreaOffset:=(ArrT[1] shl 8) or ArrT[0];
|
||||
if AreaIndex>=Data.ObjSectionList.Count then
|
||||
begin
|
||||
InputError('Area index in R record out of bounds');
|
||||
exit;
|
||||
end;
|
||||
ObjSec:=TObjSection(Data.ObjSectionList[AreaIndex]);
|
||||
if AreaOffset>ObjSec.Size then
|
||||
begin
|
||||
InputError('Area offset in T exceeds area size');
|
||||
exit;
|
||||
end;
|
||||
{ parse relocations }
|
||||
SetLength(ArrTIsRelocHiByte,Length(ArrT));
|
||||
LastDataOfsIndex:=2;
|
||||
LastDataOfsValue:=AreaOffset;
|
||||
i:=4;
|
||||
while i<length(ArrR) do
|
||||
begin
|
||||
n1:=ArrR[i];
|
||||
Inc(i);
|
||||
if (n1 and $F0)=$F0 then
|
||||
begin
|
||||
if i>=length(ArrR) then
|
||||
begin
|
||||
InputError(GenericRErrMsg);
|
||||
exit;
|
||||
end;
|
||||
n1x:=ArrR[i];
|
||||
Inc(i);
|
||||
n1:=((n1 and $0F) shl 8) or n1x;
|
||||
end;
|
||||
if (i+2)>=length(ArrR) then
|
||||
begin
|
||||
InputError(GenericRErrMsg);
|
||||
exit;
|
||||
end;
|
||||
n2:=ArrR[i];
|
||||
xx_xx:=ArrR[i+1] or (ArrR[i+2] shl 8);
|
||||
Inc(i,3);
|
||||
RelFlags:=DecodeRelFlags(n1);
|
||||
if ((RelFlags*UnsupportedRelocationFlags)<>[]) or
|
||||
((rrfByte in RelFlags) xor (rrfTwoByteObjectFormatForByteData in RelFlags)) then
|
||||
begin
|
||||
InputError('Unsupported relocation flags ($'+HexStr(n1,3)+')');
|
||||
exit;
|
||||
end;
|
||||
|
||||
if n2<=1 then
|
||||
begin
|
||||
InputError('Invalid relocation data offset');
|
||||
exit;
|
||||
end;
|
||||
if rrfByte in RelFlags then
|
||||
begin
|
||||
if rrfMSBWith2ByteMode in RelFlags then
|
||||
RelocTyp:=RELOC_ABSOLUTE_HI8
|
||||
else
|
||||
RelocTyp:=RELOC_ABSOLUTE_LO8;
|
||||
if (n2+1)>=length(ArrT) then
|
||||
begin
|
||||
InputError('Invalid relocation data offset');
|
||||
exit;
|
||||
end;
|
||||
ArrTIsRelocHiByte[n2+1]:=true;
|
||||
RelHiByte:=ArrT[n2+1];
|
||||
end
|
||||
else
|
||||
begin
|
||||
RelocTyp:=RELOC_ABSOLUTE;
|
||||
if n2>=length(ArrT) then
|
||||
begin
|
||||
InputError('Invalid relocation data offset');
|
||||
exit;
|
||||
end;
|
||||
RelHiByte:=0;
|
||||
end;
|
||||
while LastDataOfsIndex<n2 do
|
||||
begin
|
||||
if not ArrTIsRelocHiByte[LastDataOfsIndex] then
|
||||
Inc(LastDataOfsValue);
|
||||
Inc(LastDataOfsIndex);
|
||||
end;
|
||||
RelocDataOffset:=LastDataOfsValue;
|
||||
|
||||
if rrfSymbol in RelFlags then
|
||||
begin
|
||||
if xx_xx>=Data.ObjSymbolList.Count then
|
||||
begin
|
||||
InputError('Relocation to symbol with invalid index');
|
||||
exit;
|
||||
end;
|
||||
reloc:=TRelRelocation.CreateSymbol(RelocDataOffset,TObjSymbol(Data.ObjSymbolList[xx_xx]),RelocTyp);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if xx_xx>=Data.ObjSectionlist.Count then
|
||||
begin
|
||||
InputError('Relocation to area with invalid index');
|
||||
exit;
|
||||
end;
|
||||
reloc:=TRelRelocation.CreateSection(RelocDataOffset,TObjSection(Data.ObjSectionlist[xx_xx]),RelocTyp);
|
||||
end;
|
||||
reloc.RelFlags:=RelFlags;
|
||||
reloc.HiByte:=RelHiByte;
|
||||
objsec.ObjRelocations.Add(reloc);
|
||||
end;
|
||||
{ read the data }
|
||||
objsec.SecOptions:=objsec.SecOptions+[oso_Data];
|
||||
objsec.Data.seek(AreaOffset);
|
||||
for i:=2 to length(ArrT)-1 do
|
||||
if not ArrTIsRelocHiByte[i] then
|
||||
objsec.Data.write(ArrT[i],1);
|
||||
result:=true;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user