* Add -Xg to help pages

* -Xg now produces a .dbg file with debuginfo
    that can be used by gdb. The main executable gets
    a debuglink section that references the .dbg file.

git-svn-id: trunk@9778 -
This commit is contained in:
peter 2008-01-17 01:20:37 +00:00
parent bd70396a93
commit 793fd8fc09
10 changed files with 351 additions and 278 deletions

View File

@ -25,9 +25,7 @@ Unit fpccrc;
Interface Interface
Function Crc32(Const HStr:String):cardinal;
Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:integer):cardinal; Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:integer):cardinal;
Function UpdCrc32(InitCrc:cardinal;b:byte):cardinal;
Implementation Implementation
@ -57,21 +55,6 @@ begin
end; end;
Function Crc32(Const HStr:String):cardinal;
var
i : integer;
InitCrc : cardinal;
begin
if Crc32Tbl[1]=0 then
MakeCrc32Tbl;
InitCrc:=cardinal($ffffffff);
for i:=1 to Length(Hstr) do
InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(Hstr[i])] xor (InitCrc shr 8);
Crc32:=InitCrc;
end;
Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:Integer):cardinal; Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:Integer):cardinal;
var var
i : integer; i : integer;
@ -80,21 +63,14 @@ begin
if Crc32Tbl[1]=0 then if Crc32Tbl[1]=0 then
MakeCrc32Tbl; MakeCrc32Tbl;
p:=@InBuf; p:=@InBuf;
result:=not InitCrc;
for i:=1 to InLen do for i:=1 to InLen do
begin begin
InitCrc:=Crc32Tbl[byte(InitCrc) xor byte(p^)] xor (InitCrc shr 8); result:=Crc32Tbl[byte(result) xor byte(p^)] xor (result shr 8);
inc(p); inc(p);
end; end;
UpdateCrc32:=InitCrc; result:=not result;
end; end;
Function UpdCrc32(InitCrc:cardinal;b:byte):cardinal;
begin
if Crc32Tbl[1]=0 then
MakeCrc32Tbl;
UpdCrc32:=Crc32Tbl[byte(InitCrc) xor b] xor (InitCrc shr 8);
end;
end. end.

View File

@ -94,7 +94,8 @@ interface
procedure Load_ReadStaticLibrary(const para:TCmdStr); procedure Load_ReadStaticLibrary(const para:TCmdStr);
procedure ParseScript_Load; procedure ParseScript_Load;
procedure ParseScript_Order; procedure ParseScript_Order;
procedure ParseScript_CalcPos; procedure ParseScript_MemPos;
procedure ParseScript_DataPos;
procedure PrintLinkerScript; procedure PrintLinkerScript;
function RunLinkScript(const outputname:TCmdStr):boolean; function RunLinkScript(const outputname:TCmdStr):boolean;
protected protected
@ -127,8 +128,8 @@ interface
Implementation Implementation
uses uses
cutils,cfileutl, cutils,cfileutl,cstreams,
script,globals,verbose,comphook,ppu, script,globals,verbose,comphook,ppu,fpccrc,
aasmbase,aasmtai,aasmdata,aasmcpu, aasmbase,aasmtai,aasmdata,aasmcpu,
owbase,owar,ogmap; owbase,owar,ogmap;
@ -139,6 +140,32 @@ Implementation
Helpers Helpers
*****************************************************************************} *****************************************************************************}
function GetFileCRC(const fn:string):cardinal;
var
fs : TCStream;
bufcount,
bufsize : Integer;
buf : pbyte;
begin
result:=0;
bufsize:=64*1024;
fs:=TCFileStream.Create(fn,fmOpenRead or fmShareDenyNone);
if CStreamError<>0 then
begin
fs.Free;
Comment(V_Error,'Can''t open file: '+fn);
exit;
end;
getmem(buf,bufsize);
repeat
bufcount:=fs.Read(buf^,bufsize);
result:=UpdateCrc32(result,buf^,bufcount);
until bufcount<bufsize;
freemem(buf);
fs.Free;
end;
{ searches an object file } { searches an object file }
function FindObjectFile(s:TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr; function FindObjectFile(s:TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr;
var var
@ -913,14 +940,14 @@ Implementation
end; end;
procedure TInternalLinker.ParseScript_CalcPos; procedure TInternalLinker.ParseScript_MemPos;
var var
s, s,
para, para,
keyword : String; keyword : String;
hp : TCmdStrListItem; hp : TCmdStrListItem;
begin begin
exeoutput.CalcPos_Start; exeoutput.MemPos_Start;
hp:=TCmdStrListItem(linkscript.first); hp:=TCmdStrListItem(linkscript.first);
while assigned(hp) do while assigned(hp) do
begin begin
@ -930,13 +957,40 @@ Implementation
keyword:=Upper(GetToken(s,' ')); keyword:=Upper(GetToken(s,' '));
para:=GetToken(s,' '); para:=GetToken(s,' ');
if keyword='EXESECTION' then if keyword='EXESECTION' then
ExeOutput.CalcPos_ExeSection(para) ExeOutput.MemPos_ExeSection(para)
else if keyword='ENDEXESECTION' then else if keyword='ENDEXESECTION' then
ExeOutput.CalcPos_EndExeSection ExeOutput.MemPos_EndExeSection
else if keyword='HEADER' then else if keyword='HEADER' then
ExeOutput.CalcPos_Header ExeOutput.MemPos_Header;
hp:=TCmdStrListItem(hp.next);
end;
end;
procedure TInternalLinker.ParseScript_DataPos;
var
s,
para,
keyword : String;
hp : TCmdStrListItem;
begin
exeoutput.DataPos_Start;
hp:=TCmdStrListItem(linkscript.first);
while assigned(hp) do
begin
s:=hp.str;
if (s='') or (s[1]='#') then
continue;
keyword:=Upper(GetToken(s,' '));
para:=GetToken(s,' ');
if keyword='EXESECTION' then
ExeOutput.DataPos_ExeSection(para)
else if keyword='ENDEXESECTION' then
ExeOutput.DataPos_EndExeSection
else if keyword='HEADER' then
ExeOutput.DataPos_Header
else if keyword='SYMBOLS' then else if keyword='SYMBOLS' then
ExeOutput.CalcPos_Symbols; ExeOutput.DataPos_Symbols;
hp:=TCmdStrListItem(hp.next); hp:=TCmdStrListItem(hp.next);
end; end;
end; end;
@ -965,6 +1019,7 @@ Implementation
var var
bsssize : aint; bsssize : aint;
bsssec : TExeSection; bsssec : TExeSection;
dbgname : TCmdStr;
begin begin
result:=false; result:=false;
@ -999,16 +1054,34 @@ Implementation
if ErrorCount>0 then if ErrorCount>0 then
goto myexit; goto myexit;
{ Calc positions in mem and file } { Calc positions in mem }
ParseScript_CalcPos; ParseScript_MemPos;
exeoutput.FixupRelocations; exeoutput.FixupRelocations;
exeoutput.PrintMemoryMap; exeoutput.PrintMemoryMap;
if ErrorCount>0 then if ErrorCount>0 then
goto myexit; goto myexit;
exeoutput.WriteExeFile(outputname);
if cs_link_separate_dbg_file in current_settings.globalswitches then if cs_link_separate_dbg_file in current_settings.globalswitches then
exeoutput.WriteDbgFile(ChangeFileExt(outputname,'.dbg')); begin
{ create debuginfo, which is an executable without data on disk }
dbgname:=ChangeFileExt(outputname,'.dbg');
exeoutput.ExeWriteMode:=ewm_dbgonly;
ParseScript_DataPos;
exeoutput.WriteExeFile(dbgname);
{ create executable with link to just created debuginfo file }
exeoutput.ExeWriteMode:=ewm_exeonly;
exeoutput.RemoveDebugInfo;
exeoutput.GenerateDebugLink(dbgname,GetFileCRC(dbgname));
ParseScript_MemPos;
ParseScript_DataPos;
exeoutput.WriteExeFile(outputname);
end
else
begin
exeoutput.ExeWriteMode:=ewm_exefull;
ParseScript_DataPos;
exeoutput.WriteExeFile(outputname);
end;
{$warning TODO fixed section names} {$warning TODO fixed section names}
status.codesize:=exeoutput.findexesection('.text').size; status.codesize:=exeoutput.findexesection('.text').size;

View File

@ -2686,6 +2686,7 @@ P*2WT_Specify MPW tool type application (Classic Mac OS)
**2Xc_Pass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, Linux) **2Xc_Pass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, Linux)
**2Xd_Do not use standard library search path (needed for cross compile) **2Xd_Do not use standard library search path (needed for cross compile)
**2Xe_Use external linker **2Xe_Use external linker
**2Xg_Create debuginfo in a separate file and add a debuglink section to executable
**2XD_Try to link units dynamically (defines FPC_LINK_DYNAMIC) **2XD_Try to link units dynamically (defines FPC_LINK_DYNAMIC)
**2Xi_Use internal linker **2Xi_Use internal linker
**2Xm_Generate link map **2Xm_Generate link map

View File

@ -734,7 +734,7 @@ const
option_info=11024; option_info=11024;
option_help_pages=11025; option_help_pages=11025;
MsgTxtSize = 45492; MsgTxtSize = 45576;
MsgIdxMax : array[1..20] of longint=( MsgIdxMax : array[1..20] of longint=(
24,86,238,84,63,50,108,22,135,60, 24,86,238,84,63,50,108,22,135,60,

View File

@ -1071,19 +1071,22 @@ const msgtxt : array[0..000189,1..240] of char=(
'**2Xd_Do not use standard library search path (needed for cross compil'+ '**2Xd_Do not use standard library search path (needed for cross compil'+
'e)'#010+ 'e)'#010+
'**2Xe_Use external linker'#010+ '**2Xe_Use external linker'#010+
'**2XD_Try to link units dynamically (defines FPC_LINK_DYNAMIC)'#010+ '**2Xg_Create debuginfo in a separate file and add a debuglink section '+
'to executable'#010+
'**2XD_Try to link units dynam','ically (defines FPC_LINK_DYNAMIC)'#010+
'**2Xi_Use internal linker'#010+ '**2Xi_Use internal linker'#010+
'**2Xm_Generate link',' map'#010+ '**2Xm_Generate link map'#010+
'**2XM<x>_Set the name of the '#039'main'#039' program routine (default i'+ '**2XM<x>_Set the name of the '#039'main'#039' program routine (default i'+
's '#039'main'#039')'#010+ 's '#039'main'#039')'#010+
'**2XP<x>_Prepend the binutils names with the prefix <x>'#010+ '**2XP<x>_Prepend the binutils names with the prefix <x>'#010+
'**2Xr<x>_Set library search path to <x> (needed for cross compile) (Be'+ '**2Xr<x>_Set library se','arch path to <x> (needed for cross compile) ('+
'OS, Linux)'#010+ 'BeOS, Linux)'#010+
'**2XR<x>_Prepend <x> to al','l linker search paths (BeOS, Darwin, FreeB'+ '**2XR<x>_Prepend <x> to all linker search paths (BeOS, Darwin, FreeBSD'+
'SD, Linux, Mac OS, Solaris)'#010+ ', Linux, Mac OS, Solaris)'#010+
'**2Xs_Strip all symbols from executable'#010+ '**2Xs_Strip all symbols from executable'#010+
'**2XS_Try to link units statically (default, defines FPC_LINK_STATIC)'#010+ '**2XS_Try to link units statically (default, d','efines FPC_LINK_STATIC'+
'**2Xt_Link with static libraries (-static is passed to linke','r)'#010+ ')'#010+
'**2Xt_Link with static libraries (-static is passed to linker)'#010+
'**2XX_Try to smartlink units (defines FPC_LINK_SMART)'#010+ '**2XX_Try to smartlink units (defines FPC_LINK_SMART)'#010+
'**1*_'#010+ '**1*_'#010+
'**1?_Show this help'#010+ '**1?_Show this help'#010+

View File

@ -102,6 +102,9 @@ interface
N_EXCL = $C2; N_EXCL = $C2;
N_RBRAC = $E0; N_RBRAC = $E0;
{ GNU extensions }
debuglinkname='.gnu_debuglink';
type type
TObjSectionOption = ( TObjSectionOption = (
{ Has Data available in the file } { Has Data available in the file }
@ -388,6 +391,8 @@ interface
property IsVar: boolean read FIsVar; property IsVar: boolean read FIsVar;
end; end;
TExeWriteMode = (ewm_exefull,ewm_dbgonly,ewm_exeonly);
TExeOutput = class TExeOutput = class
private private
{ ExeSectionList } { ExeSectionList }
@ -395,7 +400,6 @@ interface
FCExeSection : TExeSectionClass; FCExeSection : TExeSectionClass;
FCurrExeSec : TExeSection; FCurrExeSec : TExeSection;
FExeSectionList : TFPHashObjectList; FExeSectionList : TFPHashObjectList;
FDebugSectionList : TFPHashObjectList;
Fzeronr : longint; Fzeronr : longint;
{ Symbols } { Symbols }
FExeSymbolList : TFPHashObjectList; FExeSymbolList : TFPHashObjectList;
@ -410,6 +414,7 @@ interface
FImageBase : aint; FImageBase : aint;
protected protected
{ writer } { writer }
FExeWriteMode : TExeWriteMode;
FWriter : TObjectwriter; FWriter : TObjectwriter;
commonObjSection : TObjSection; commonObjSection : TObjSection;
internalObjData : TObjData; internalObjData : TObjData;
@ -441,11 +446,15 @@ interface
procedure Order_Symbol(const aname:string);virtual; procedure Order_Symbol(const aname:string);virtual;
procedure Order_EndExeSection;virtual; procedure Order_EndExeSection;virtual;
procedure Order_ObjSection(const aname:string);virtual; procedure Order_ObjSection(const aname:string);virtual;
procedure CalcPos_ExeSection(const aname:string);virtual; procedure MemPos_Start;virtual;
procedure CalcPos_EndExeSection;virtual; procedure MemPos_Header;virtual;
procedure CalcPos_Header;virtual; procedure MemPos_ExeSection(const aname:string);virtual;
procedure CalcPos_Start;virtual; procedure MemPos_EndExeSection;virtual;
procedure CalcPos_Symbols;virtual; procedure DataPos_Start;virtual;
procedure DataPos_Header;virtual;
procedure DataPos_ExeSection(const aname:string);virtual;
procedure DataPos_EndExeSection;virtual;
procedure DataPos_Symbols;virtual;
procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList); procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
procedure PackUnresolvedExeSymbols(const s:string); procedure PackUnresolvedExeSymbols(const s:string);
procedure ResolveSymbols(StaticLibraryList:TFPHashObjectList); procedure ResolveSymbols(StaticLibraryList:TFPHashObjectList);
@ -455,12 +464,12 @@ interface
procedure MergeStabs; procedure MergeStabs;
procedure RemoveUnreferencedSections; procedure RemoveUnreferencedSections;
procedure RemoveEmptySections; procedure RemoveEmptySections;
procedure RemoveDebugInfo;
procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);virtual; procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);virtual;
function writedbgfile(const fn:string):boolean; procedure GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
function writeexefile(const fn:string):boolean; function WriteExeFile(const fn:string):boolean;
property Writer:TObjectWriter read FWriter; property Writer:TObjectWriter read FWriter;
property ExeSectionList:TFPHashObjectList read FExeSectionList; property ExeSectionList:TFPHashObjectList read FExeSectionList;
property DebugSectionList:TFPHashObjectList read FDebugSectionList;
property ObjDataList:TFPObjectList read FObjDataList; property ObjDataList:TFPObjectList read FObjDataList;
property ExeSymbolList:TFPHashObjectList read FExeSymbolList; property ExeSymbolList:TFPHashObjectList read FExeSymbolList;
property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols; property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols;
@ -470,6 +479,7 @@ interface
property EntryName:string read FEntryName write FEntryName; property EntryName:string read FEntryName write FEntryName;
property ImageBase:aint read FImageBase write FImageBase; property ImageBase:aint read FImageBase write FImageBase;
property CurrExeSec:TExeSection read FCurrExeSec; property CurrExeSec:TExeSection read FCurrExeSec;
property ExeWriteMode:TExeWriteMode read FExeWriteMode write FExeWriteMode;
end; end;
TExeOutputClass=class of TExeOutput; TExeOutputClass=class of TExeOutput;
@ -1384,6 +1394,7 @@ implementation
begin begin
{ init writer } { init writer }
FWriter:=TObjectwriter.create; FWriter:=TObjectwriter.create;
FExeWriteMode:=ewm_exefull;
{ object files } { object files }
FObjDataList:=TFPObjectList.Create(true); FObjDataList:=TFPObjectList.Create(true);
{ symbols } { symbols }
@ -1395,7 +1406,6 @@ implementation
FEntryName:='start'; FEntryName:='start';
{ sections } { sections }
FExeSectionList:=TFPHashObjectList.Create(true); FExeSectionList:=TFPHashObjectList.Create(true);
FDebugSectionList:=TFPHashObjectList.Create(true);
FImageBase:=0; FImageBase:=0;
SectionMemAlign:=$1000; SectionMemAlign:=$1000;
SectionDataAlign:=$200; SectionDataAlign:=$200;
@ -1412,102 +1422,20 @@ implementation
CommonObjSymbols.free; CommonObjSymbols.free;
ExeVTableList.free; ExeVTableList.free;
FExeSectionList.free; FExeSectionList.free;
FDebugSectionList.free;
ObjDatalist.free; ObjDatalist.free;
FWriter.free; FWriter.free;
inherited destroy; inherited destroy;
end; end;
function TExeOutput.writedbgfile(const fn:string):boolean; function TExeOutput.WriteExeFile(const fn:string):boolean;
var
ObjWriter : TObjectwriter;
exesec : TExeSection;
objsec : TObjSection;
header : string[6];
s : string;
i,j,
seccnt,
secstart : longint;
begin begin
result:=false; result:=false;
{
File layout:
<header> 6 bytes
<section count> 4 bytes
(
<section offset> 4 bytes
<section name> asciiz
...
)
(
<section data>
...
)
}
header:='FPCDBG';
{ Calculate file offsets }
secstart:=length(header)+sizeof(seccnt);
for i:=0 to DebugSectionList.Count-1 do
begin
exesec:=TExeSection(DebugSectionList[i]);
inc(secstart,sizeof(secstart)+length(exesec.Name)+1);
end;
for i:=0 to DebugSectionList.Count-1 do
begin
exesec:=TExeSection(DebugSectionList[i]);
exesec.DataPos:=secstart;
for j:=0 to exesec.ObjSectionList.Count-1 do
begin
objsec:=TObjSection(exesec.ObjSectionList[j]);
inc(secstart,objsec.size);
end;
end;
{ Create file }
ObjWriter:=TObjectwriter.Create;
if not ObjWriter.createfile(fn) then
begin
ObjWriter.Free;
exit;
end;
{ Header }
ObjWriter.Write(header[1], Length(header));
seccnt:=DebugSectionList.Count;
ObjWriter.Write(seccnt,sizeof(seccnt));
for i:=0 to DebugSectionList.Count-1 do
begin
exesec:=TExeSection(DebugSectionList[i]);
ObjWriter.Write(exesec.DataPos,sizeof(secstart));
s:=exesec.Name;
ObjWriter.Write(s[1],length(s));
ObjWriter.writezeros(1);
end;
{ Write section data }
for i:=0 to DebugSectionList.Count-1 do
begin
exesec:=TExeSection(DebugSectionList[i]);
if exesec.DataPos<>ObjWriter.ObjSize then
internalerror(200702241);
for j:=0 to exesec.ObjSectionList.Count-1 do
begin
objsec:=TObjSection(exesec.ObjSectionList[j]);
ObjWriter.writearray(objsec.data);
end;
end;
ObjWriter.Free;
result:=true;
end;
function TExeOutput.writeexefile(const fn:string):boolean;
begin
result:=false;
if FWriter.createfile(fn) then if FWriter.createfile(fn) then
begin begin
{ Only write the .o if there are no errors } { Only write the .o if there are no errors }
if errorcount=0 then if errorcount=0 then
result:=writeData result:=writedata
else else
result:=true; result:=true;
{ close the writer } { close the writer }
@ -1703,7 +1631,18 @@ implementation
end; end;
procedure TExeOutput.CalcPos_ExeSection(const aname:string); procedure TExeOutput.MemPos_Start;
begin
CurrMemPos:=0;
end;
procedure TExeOutput.MemPos_Header;
begin
end;
procedure TExeOutput.MemPos_ExeSection(const aname:string);
var var
i : longint; i : longint;
objsec : TObjSection; objsec : TObjSection;
@ -1717,6 +1656,51 @@ implementation
CurrMemPos:=align(CurrMemPos,SectionMemAlign); CurrMemPos:=align(CurrMemPos,SectionMemAlign);
CurrExeSec.MemPos:=CurrMemPos; CurrExeSec.MemPos:=CurrMemPos;
{ set position of object ObjSections }
for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
begin
objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
objsec.setmempos(CurrMemPos);
end;
{ calculate size of the section }
CurrExeSec.Size:=CurrMemPos-CurrExeSec.MemPos;
end;
procedure TExeOutput.MemPos_EndExeSection;
begin
if not assigned(CurrExeSec) then
exit;
FCurrExeSec:=nil;
end;
procedure TExeOutput.DataPos_Start;
begin
end;
procedure TExeOutput.DataPos_Header;
begin
end;
procedure TExeOutput.DataPos_ExeSection(const aname:string);
var
i : longint;
objsec : TObjSection;
begin
{ Section can be removed }
FCurrExeSec:=FindExeSection(aname);
if not assigned(CurrExeSec) then
exit;
{ don't write normal section if writing only debug info }
if (ExeWriteMode=ewm_dbgonly) and
not(oso_debug in CurrExeSec.SecOptions) then
exit;
if (oso_Data in currexesec.SecOptions) then if (oso_Data in currexesec.SecOptions) then
begin begin
CurrDataPos:=align(CurrDataPos,SectionDataAlign); CurrDataPos:=align(CurrDataPos,SectionDataAlign);
@ -1727,26 +1711,19 @@ implementation
for i:=0 to CurrExeSec.ObjSectionList.Count-1 do for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
begin begin
objsec:=TObjSection(CurrExeSec.ObjSectionList[i]); objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
{ Position in memory }
objsec.setmempos(CurrMemPos);
{ Position in File }
if (oso_Data in objsec.SecOptions) then if (oso_Data in objsec.SecOptions) then
begin begin
if not (oso_Data in currexesec.SecOptions) then if not(oso_Data in currexesec.SecOptions) then
internalerror(200603043); internalerror(200603043);
if not assigned(objsec.Data) then if not assigned(objsec.Data) then
internalerror(200603044); internalerror(200603044);
objsec.setDatapos(CurrDataPos); objsec.setDatapos(CurrDataPos);
end; end;
end; end;
{ calculate size of the section }
CurrExeSec.Size:=CurrMemPos-CurrExeSec.MemPos;
end; end;
procedure TExeOutput.CalcPos_EndExeSection; procedure TExeOutput.DataPos_EndExeSection;
begin begin
if not assigned(CurrExeSec) then if not assigned(CurrExeSec) then
exit; exit;
@ -1754,19 +1731,7 @@ implementation
end; end;
procedure TExeOutput.CalcPos_Start; procedure TExeOutput.DataPos_Symbols;
begin
CurrMemPos:=0;
CurrDataPos:=0;
end;
procedure TExeOutput.CalcPos_Header;
begin
end;
procedure TExeOutput.CalcPos_Symbols;
var var
i : longint; i : longint;
sym : TExeSymbol; sym : TExeSymbol;
@ -2067,6 +2032,41 @@ implementation
end; end;
procedure TExeOutput.GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
var
debuglink : array[0..1023] of byte;
len : longint;
objsec : TObjSection;
exesec : TExeSection;
begin
{ From the gdb manual chapter 15. GDB Files:
* A filename, with any leading directory components removed, followed by a zero byte,
* zero to three bytes of padding, as needed to reach the next four-byte boundary within the section, and
* a four-byte CRC checksum, stored in the same endianness used for the executable file itself. The checksum is computed
on the debugging information file's full contents by the function given below, passing zero as the crc argument.
}
fillchar(debuglink,sizeof(debuglink),0);
len:=0;
move(dbgname[1],debuglink[len],length(dbgname));
inc(len,length(dbgname)+1);
len:=align(len,4);
if source_info.endian<>target_info.endian then
SwapEndian(dbgcrc);
move(dbgcrc,debuglink[len],sizeof(cardinal));
inc(len,4);
{ Add section }
exesec:=FindExeSection(debuglinkname);
if not assigned(exesec) then
exesec:=CExeSection.create(ExeSectionList,debuglinkname);
exesec.SecOptions:=[oso_data,oso_keep];
exesec.SecAlign:=4;
objsec:=internalObjData.createsection(exesec.name,0,exesec.SecOptions);
internalObjData.writebytes(debuglink,len);
exesec.AddObjSection(objsec);
end;
procedure TExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList); procedure TExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
begin begin
end; end;
@ -2184,7 +2184,7 @@ implementation
(stabexesec.ObjSectionlist.count=0) then (stabexesec.ObjSectionlist.count=0) then
exit; exit;
{ Create new stabsection } { Create new stabsection }
stabRelocofs:=pointer(@hstab.nvalue)-@hstab; stabRelocofs:=pbyte(@hstab.nvalue)-pbyte(@hstab);
mergedstabsec:=internalObjData.CreateSection(sec_stab,''); mergedstabsec:=internalObjData.CreateSection(sec_stab,'');
mergedstabstrsec:=internalObjData.CreateSection(sec_stabstr,''); mergedstabstrsec:=internalObjData.CreateSection(sec_stabstr,'');
@ -2338,22 +2338,12 @@ implementation
begin begin
exesec:=TExeSection(ExeSectionList[i]); exesec:=TExeSection(ExeSectionList[i]);
if (cs_link_separate_dbg_file in current_settings.globalswitches) and
(oso_debug in exesec.SecOptions) then
begin
Comment(V_Debug,'Adding debug section '+exesec.name+' to debugfile');
ExeSectionList.OwnsObjects:=false;
ExeSectionList[i]:=nil;
ExeSectionList.OwnsObjects:=true;
DebugSectionList.Add(exesec.Name,exesec);
end
else
begin
doremove:=not(oso_keep in exesec.SecOptions) and doremove:=not(oso_keep in exesec.SecOptions) and
( (
(exesec.ObjSectionlist.count=0) or (exesec.ObjSectionlist.count=0) or
( (
(cs_link_strip in current_settings.globalswitches) and (cs_link_strip in current_settings.globalswitches) and
not(cs_link_separate_dbg_file in current_settings.globalswitches) and
(oso_debug in exesec.SecOptions) (oso_debug in exesec.SecOptions)
) )
); );
@ -2374,6 +2364,20 @@ implementation
ExeSectionList[i]:=nil; ExeSectionList[i]:=nil;
end; end;
end; end;
ExeSectionList.Pack;
end;
procedure TExeOutput.RemoveDebugInfo;
var
i : longint;
exesec : TExeSection;
begin
for i:=0 to ExeSectionList.Count-1 do
begin
exesec:=TExeSection(ExeSectionList[i]);
if (oso_debug in exesec.SecOptions) then
ExeSectionList[i]:=nil;
end; end;
ExeSectionList.Pack; ExeSectionList.Pack;
end; end;
@ -2551,16 +2555,14 @@ implementation
procedure TExeOutput.FixupRelocations; procedure TExeOutput.FixupRelocations;
procedure FixupSectionList(List:TFPHashObjectList);
var var
i,j : longint; i,j : longint;
exesec : TExeSection; exesec : TExeSection;
objsec : TObjSection; objsec : TObjSection;
begin begin
for i:=0 to List.Count-1 do for i:=0 to ExeSectionList.Count-1 do
begin begin
exesec:=TExeSection(List[i]); exesec:=TExeSection(ExeSectionList[i]);
if not assigned(exesec) then if not assigned(exesec) then
continue; continue;
for j:=0 to exesec.ObjSectionlist.count-1 do for j:=0 to exesec.ObjSectionlist.count-1 do
@ -2573,11 +2575,6 @@ implementation
end; end;
end; end;
begin
FixupSectionList(ExeSectionList);
FixupSectionList(DebugSectionList);
end;
{**************************************************************************** {****************************************************************************
TObjInput TObjInput

View File

@ -227,14 +227,16 @@ interface
nsects : smallint; nsects : smallint;
nsyms, nsyms,
sympos : aint; sympos : aint;
function totalheadersize:longint;
procedure ExeSectionList_pass2_header(p:TObject;arg:pointer); procedure ExeSectionList_pass2_header(p:TObject;arg:pointer);
procedure write_symbol(const name:string;value:aint;section:smallint;typ,aux:byte); procedure write_symbol(const name:string;value:aint;section:smallint;typ,aux:byte);
procedure globalsyms_write_symbol(p:TObject;arg:pointer); procedure globalsyms_write_symbol(p:TObject;arg:pointer);
procedure ExeSectionList_write_header(p:TObject;arg:pointer); procedure ExeSectionList_write_header(p:TObject;arg:pointer);
procedure ExeSectionList_write_data(p:TObject;arg:pointer); procedure ExeSectionList_write_data(p:TObject;arg:pointer);
protected protected
procedure CalcPos_Header;override; procedure MemPos_Header;override;
procedure CalcPos_Symbols;override; procedure DataPos_Header;override;
procedure DataPos_Symbols;override;
function writedata:boolean;override; function writedata:boolean;override;
procedure Order_ObjSectionList(ObjSectionList : TFPObjectList);override; procedure Order_ObjSectionList(ObjSectionList : TFPObjectList);override;
public public
@ -253,7 +255,7 @@ interface
constructor create;override; constructor create;override;
procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override; procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
procedure Order_End;override; procedure Order_End;override;
procedure CalcPos_ExeSection(const aname:string);override; procedure MemPos_ExeSection(const aname:string);override;
end; end;
TObjSymbolrec = record TObjSymbolrec = record
@ -1988,17 +1990,13 @@ const pemagic : array[0..3] of byte = (
sechdr.vsize:=Size sechdr.vsize:=Size
else else
sechdr.vsize:=mempos; sechdr.vsize:=mempos;
{ sechdr.dataSize is size of initilized data. For .bss section it must be zero } { sechdr.dataSize is size of initilized data. For .bss section it must be zero }
if Name <> '.bss' then if (Name <> '.bss') then
begin
if oso_data in SecOptions then
begin
sechdr.dataSize:=Size; sechdr.dataSize:=Size;
if (sechdr.dataSize>0) and
(oso_data in SecOptions) then
sechdr.datapos:=datapos; sechdr.datapos:=datapos;
end
else
sechdr.dataSize:=Size;
end;
sechdr.nrelocs:=0; sechdr.nrelocs:=0;
sechdr.relocpos:=0; sechdr.relocpos:=0;
if win32 then if win32 then
@ -2014,6 +2012,10 @@ const pemagic : array[0..3] of byte = (
begin begin
with TExeSection(p) do with TExeSection(p) do
begin begin
{ The debuginfo sections should already be stripped }
{ if (ExeWriteMode=ewm_exeonly) and
(oso_debug in SecOptions) then
internalerror(200801161); }
inc(plongint(arg)^); inc(plongint(arg)^);
secsymidx:=plongint(arg)^; secsymidx:=plongint(arg)^;
end; end;
@ -2024,9 +2026,15 @@ const pemagic : array[0..3] of byte = (
var var
objsec : TObjSection; objsec : TObjSection;
i : longint; i : longint;
b : boolean;
begin begin
with texesection(p) do with texesection(p) do
begin begin
{ don't write normal section if writing only debug info }
if (ExeWriteMode=ewm_dbgonly) and
not(oso_debug in SecOptions) then
exit;
if oso_data in secoptions then if oso_data in secoptions then
begin begin
FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size); FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
@ -2048,7 +2056,7 @@ const pemagic : array[0..3] of byte = (
end; end;
procedure tcoffexeoutput.CalcPos_Header; function tcoffexeoutput.totalheadersize:longint;
var var
stubsize, stubsize,
optheadersize : longint; optheadersize : longint;
@ -2063,20 +2071,30 @@ const pemagic : array[0..3] of byte = (
stubsize:=sizeof(go32v2stub); stubsize:=sizeof(go32v2stub);
optheadersize:=sizeof(coffdjoptheader); optheadersize:=sizeof(coffdjoptheader);
end; end;
{ retrieve amount of ObjSections } result:=stubsize+sizeof(tcoffheader)+optheadersize;
nsects:=0;
ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@nsects);
{ calculate start positions after the headers }
currdatapos:=stubsize+optheadersize+sizeof(tcoffsechdr)*nsects;
currmempos:=stubsize+optheadersize+sizeof(tcoffsechdr)*nsects;
end; end;
procedure tcoffexeoutput.CalcPos_Symbols; procedure tcoffexeoutput.MemPos_Header;
begin begin
inherited CalcPos_Symbols; { calculate start positions after the headers }
nsyms:=0; currmempos:=totalheadersize+sizeof(tcoffsechdr)*(ExeSectionList.Count-2);
sympos:=0; end;
procedure tcoffexeoutput.DataPos_Header;
begin
{ retrieve amount of sections }
nsects:=0;
ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@nsects);
{ calculate start positions after the headers }
currdatapos:=totalheadersize+sizeof(tcoffsechdr)*nsects;
end;
procedure tcoffexeoutput.DataPos_Symbols;
begin
inherited DataPos_Symbols;
{ Calculating symbols position and size } { Calculating symbols position and size }
nsyms:=ExeSymbolList.Count; nsyms:=ExeSymbolList.Count;
sympos:=CurrDataPos; sympos:=CurrDataPos;
@ -2093,6 +2111,7 @@ const pemagic : array[0..3] of byte = (
textExeSec, textExeSec,
dataExeSec, dataExeSec,
bssExeSec : TExeSection; bssExeSec : TExeSection;
hassymbols : boolean;
procedure UpdateDataDir(const secname:string;idx:longint); procedure UpdateDataDir(const secname:string;idx:longint);
var var
@ -2116,6 +2135,12 @@ const pemagic : array[0..3] of byte = (
if not assigned(TextExeSec) or if not assigned(TextExeSec) or
not assigned(DataExeSec) then not assigned(DataExeSec) then
internalerror(200602231); internalerror(200602231);
{ do we need to write symbols? }
hassymbols:=(ExeWriteMode=ewm_dbgonly) or
(
(ExeWriteMode=ewm_exefull) and
not(cs_link_strip in current_settings.globalswitches)
);
{ Stub } { Stub }
if win32 then if win32 then
begin begin
@ -2124,11 +2149,12 @@ const pemagic : array[0..3] of byte = (
end end
else else
FWriter.write(go32v2stub,sizeof(go32v2stub)); FWriter.write(go32v2stub,sizeof(go32v2stub));
{ COFF header } { Initial header, will be updated later }
fillchar(header,sizeof(header),0); fillchar(header,sizeof(header),0);
header.mach:=COFF_MAGIC; header.mach:=COFF_MAGIC;
header.nsects:=nsects; header.nsects:=nsects;
header.sympos:=sympos; header.sympos:=sympos;
if hassymbols then
header.syms:=nsyms; header.syms:=nsyms;
if win32 then if win32 then
header.opthdr:=sizeof(tcoffpeoptheader) header.opthdr:=sizeof(tcoffpeoptheader)
@ -2137,21 +2163,21 @@ const pemagic : array[0..3] of byte = (
if win32 then if win32 then
begin begin
header.flag:=PE_FILE_EXECUTABLE_IMAGE or PE_FILE_LINE_NUMS_STRIPPED; header.flag:=PE_FILE_EXECUTABLE_IMAGE or PE_FILE_LINE_NUMS_STRIPPED;
if target_info.system in [system_i386_win32,system_arm_wince,system_i386_wince] then
header.flag:=header.flag or PE_FILE_32BIT_MACHINE;
if IsSharedLibrary then if IsSharedLibrary then
header.flag:=header.flag or PE_FILE_DLL; header.flag:=header.flag or PE_FILE_DLL;
if FindExeSection('.reloc')=nil then if FindExeSection('.reloc')=nil then
header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED; header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
if FindExeSection('.stab')=nil then if (FindExeSection('.stab')=nil) and
(FindExeSection('.debug_info')=nil) and
(FindExeSection('.gnu_debuglink')=nil) then
header.flag:=header.flag or PE_FILE_DEBUG_STRIPPED; header.flag:=header.flag or PE_FILE_DEBUG_STRIPPED;
if (cs_link_strip in current_settings.globalswitches) then if not hassymbols then
header.flag:=header.flag or PE_FILE_LOCAL_SYMS_STRIPPED; header.flag:=header.flag or PE_FILE_LOCAL_SYMS_STRIPPED;
end end
else else
header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES; header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
if target_info.system in [system_i386_win32,system_arm_wince,system_i386_wince] then
header.flag:=header.flag or PE_FILE_32BIT_MACHINE;
FWriter.write(header,sizeof(header)); FWriter.write(header,sizeof(header));
{ Optional COFF Header } { Optional COFF Header }
if win32 then if win32 then
@ -2224,17 +2250,14 @@ const pemagic : array[0..3] of byte = (
{ Section data } { Section data }
ExeSectionList.ForEachCall(@ExeSectionList_write_data,nil); ExeSectionList.ForEachCall(@ExeSectionList_write_data,nil);
{ Optional Symbols } { Optional Symbols }
if not(cs_link_strip in current_settings.globalswitches) then
begin
if SymPos<>FWriter.Size then if SymPos<>FWriter.Size then
internalerror(200602252); internalerror(200602252);
{ ObjSymbols } if hassymbols then
ExeSymbolList.ForEachCall(@globalsyms_write_symbol,nil); ExeSymbolList.ForEachCall(@globalsyms_write_symbol,nil);
{ Strings } { Strings }
i:=FCoffStrs.size+4; i:=FCoffStrs.size+4;
FWriter.write(i,4); FWriter.write(i,4);
FWriter.writearray(FCoffStrs); FWriter.writearray(FCoffStrs);
end;
{ Release } { Release }
FCoffStrs.Free; FCoffStrs.Free;
FCoffSyms.Free; FCoffSyms.Free;
@ -2583,7 +2606,7 @@ const pemagic : array[0..3] of byte = (
end; end;
procedure TPECoffexeoutput.CalcPos_ExeSection(const aname:string); procedure TPECoffexeoutput.MemPos_ExeSection(const aname:string);
begin begin
if aname='.reloc' then if aname='.reloc' then
GenerateRelocs; GenerateRelocs;

View File

@ -786,8 +786,8 @@ begin
bufstart:=sizeof(tppuheader); bufstart:=sizeof(tppuheader);
bufidx:=0; bufidx:=0;
{reset} {reset}
crc:=cardinal($ffffffff); crc:=0;
interface_crc:=cardinal($ffffffff); interface_crc:=0;
do_interface_crc:=true; do_interface_crc:=true;
Error:=false; Error:=false;
do_crc:=true; do_crc:=true;

View File

@ -774,7 +774,7 @@ implementation
if (newlen-oldlen>12) and if (newlen-oldlen>12) and
((newlen+length(prefix)>128) or (newlen-oldlen>32)) then ((newlen+length(prefix)>128) or (newlen-oldlen>32)) then
begin begin
crc:=$ffffffff; crc:=0;
for i:=0 to tprocdef(st.defowner).paras.count-1 do for i:=0 to tprocdef(st.defowner).paras.count-1 do
begin begin
hp:=tparavarsym(tprocdef(st.defowner).paras[i]); hp:=tparavarsym(tprocdef(st.defowner).paras[i]);
@ -3336,7 +3336,7 @@ implementation
if (newlen-oldlen>12) and if (newlen-oldlen>12) and
((newlen>128) or (newlen-oldlen>64)) then ((newlen>128) or (newlen-oldlen>64)) then
begin begin
crc:=$ffffffff; crc:=0;
for i:=0 to paras.count-1 do for i:=0 to paras.count-1 do
begin begin
hp:=tparavarsym(paras[i]); hp:=tparavarsym(paras[i]);

View File

@ -1050,7 +1050,7 @@ implementation
Concat(' OBJSECTION .idata$6*'); Concat(' OBJSECTION .idata$6*');
Concat(' OBJSECTION .idata$7*'); Concat(' OBJSECTION .idata$7*');
Concat('ENDEXESECTION'); Concat('ENDEXESECTION');
secnames:='.edata,.rsrc,.reloc,'+ secnames:='.edata,.rsrc,.reloc,.gnu_debuglink,'+
'.debug_aranges,.debug_pubnames,.debug_info,.debug_abbrev,.debug_line,.debug_frame,.debug_str,.debug_loc,'+ '.debug_aranges,.debug_pubnames,.debug_info,.debug_abbrev,.debug_line,.debug_frame,.debug_str,.debug_loc,'+
'.debug_macinfo,.debug_weaknames,.debug_funcnames,.debug_typenames,.debug_varnames,.debug_ranges'; '.debug_macinfo,.debug_weaknames,.debug_funcnames,.debug_typenames,.debug_varnames,.debug_ranges';
repeat repeat