mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-25 17:19:15 +02:00

special treatment required to put self as the first parameter in the debug info + added Apple-specific Objective-C related DWARF attributes * properly emit debug information for Objective-C classes and methods * fixed some typos in comments * properly mark "absolute" local variables mapped to parameters as variables in the debug info rather than as parameters (gdb expects one parameter to be passed when calling functions from inside gdb per parameter mentioned in the debug info, even if multiple parameters have the same stack address) git-svn-id: branches/objc@13723 -
572 lines
17 KiB
ObjectPascal
572 lines
17 KiB
ObjectPascal
{
|
|
Copyright (c) 2003-2006 by Peter Vreman and Florian Klaempfl
|
|
|
|
This units contains the base class for debug info generation
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
****************************************************************************
|
|
}
|
|
unit dbgbase;
|
|
|
|
{$i fpcdefs.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
cclasses,
|
|
systems,
|
|
parabase,
|
|
symconst,symbase,symdef,symtype,symsym,symtable,
|
|
fmodule,
|
|
aasmtai,aasmdata;
|
|
|
|
type
|
|
TDebugInfo=class
|
|
protected
|
|
{ definitions }
|
|
procedure appenddef(list:TAsmList;def:tdef);
|
|
procedure beforeappenddef(list:TAsmList;def:tdef);virtual;
|
|
procedure afterappenddef(list:TAsmList;def:tdef);virtual;
|
|
procedure appenddef_ord(list:TAsmList;def:torddef);virtual;
|
|
procedure appenddef_float(list:TAsmList;def:tfloatdef);virtual;
|
|
procedure appenddef_file(list:TAsmList;def:tfiledef);virtual;
|
|
procedure appenddef_enum(list:TAsmList;def:tenumdef);virtual;
|
|
procedure appenddef_array(list:TAsmList;def:tarraydef);virtual;
|
|
procedure appenddef_record(list:TAsmList;def:trecorddef);virtual;
|
|
procedure appenddef_object(list:TAsmList;def:tobjectdef);virtual;
|
|
procedure appenddef_classref(list:TAsmList;def: tclassrefdef);virtual;
|
|
procedure appenddef_pointer(list:TAsmList;def:tpointerdef);virtual;
|
|
procedure appenddef_string(list:TAsmList;def:tstringdef);virtual;
|
|
procedure appenddef_procvar(list:TAsmList;def:tprocvardef);virtual;
|
|
procedure appenddef_variant(list:TAsmList;def:tvariantdef);virtual;
|
|
procedure appenddef_set(list:TAsmList;def:tsetdef);virtual;
|
|
procedure appenddef_formal(list:TAsmList;def:tformaldef);virtual;
|
|
procedure appenddef_undefined(list:TAsmList;def: tundefineddef);virtual;
|
|
procedure appendprocdef(list:TAsmList;def:tprocdef);virtual;
|
|
{ symbols }
|
|
procedure appendsym(list:TAsmList;sym:tsym);
|
|
procedure beforeappendsym(list:TAsmList;sym:tsym);virtual;
|
|
procedure afterappendsym(list:TAsmList;sym:tsym);virtual;
|
|
procedure appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);virtual;
|
|
procedure appendsym_paravar(list:TAsmList;sym:tparavarsym);virtual;
|
|
procedure appendsym_localvar(list:TAsmList;sym:tlocalvarsym);virtual;
|
|
procedure appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);virtual;
|
|
procedure appendsym_unit(list:TAsmList;sym:tunitsym);virtual;
|
|
procedure appendsym_const(list:TAsmList;sym:tconstsym);virtual;
|
|
procedure appendsym_type(list:TAsmList;sym:ttypesym);virtual;
|
|
procedure appendsym_label(list:TAsmList;sym:tlabelsym);virtual;
|
|
procedure appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);virtual;
|
|
procedure appendsym_property(list:TAsmList;sym:tpropertysym);virtual;
|
|
{ symtable }
|
|
procedure write_symtable_parasyms(list:TAsmList;paras: tparalist);
|
|
procedure write_symtable_syms(list:TAsmList;st:TSymtable);
|
|
procedure write_symtable_defs(list:TAsmList;st:TSymtable);
|
|
procedure write_symtable_procdefs(list:TAsmList;st:TSymtable);
|
|
procedure reset_unit_type_info;
|
|
procedure write_used_unit_type_info(list:TAsmList;hp:tmodule);
|
|
public
|
|
constructor Create;virtual;
|
|
procedure inserttypeinfo;virtual;
|
|
procedure insertmoduleinfo;virtual;
|
|
procedure insertlineinfo(list:TAsmList);virtual;
|
|
procedure referencesections(list:TAsmList);virtual;
|
|
end;
|
|
TDebugInfoClass=class of TDebugInfo;
|
|
|
|
var
|
|
CDebugInfo : array[tdbg] of TDebugInfoClass;
|
|
current_debuginfo : tdebuginfo;
|
|
|
|
procedure InitDebugInfo(hp:tmodule);
|
|
procedure DoneDebugInfo(hp:tmodule);
|
|
procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
cutils,
|
|
verbose;
|
|
|
|
|
|
constructor TDebugInfo.Create;
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.insertmoduleinfo;
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.inserttypeinfo;
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.insertlineinfo(list:TAsmList);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.referencesections(list:TAsmList);
|
|
begin
|
|
end;
|
|
|
|
|
|
{**************************************
|
|
Definition
|
|
**************************************}
|
|
|
|
procedure TDebugInfo.appendprocdef(list:TAsmList;def:tprocdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.beforeappenddef(list:TAsmList;def:tdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.afterappenddef(list:TAsmList;def:tdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_ord(list:TAsmList;def:torddef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_float(list:TAsmList;def:tfloatdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_formal(list:TAsmList;def: tformaldef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_undefined(list:TAsmList;def: tundefineddef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_set(list:TAsmList;def: tsetdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_object(list:TAsmList;def: tobjectdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_classref(list:TAsmList;def: tclassrefdef);
|
|
begin
|
|
appenddef_pointer(list,tpointerdef(pvmttype));
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_variant(list:TAsmList;def: tvariantdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_enum(list:TAsmList;def:tenumdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_file(list:TAsmList;def: tfiledef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_array(list:TAsmList;def:tarraydef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_record(list:TAsmList;def:trecorddef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_pointer(list:TAsmList;def:tpointerdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_string(list:TAsmList;def:tstringdef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef_procvar(list:TAsmList;def:tprocvardef);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appenddef(list:TAsmList;def:tdef);
|
|
begin
|
|
if (def.dbg_state in [dbg_state_writing,dbg_state_written]) then
|
|
exit;
|
|
{ never write generic template defs }
|
|
if df_generic in def.defoptions then
|
|
begin
|
|
def.dbg_state:=dbg_state_written;
|
|
exit;
|
|
end;
|
|
{ to avoid infinite loops }
|
|
def.dbg_state := dbg_state_writing;
|
|
beforeappenddef(list,def);
|
|
{ queued defs have to be written later }
|
|
if (def.dbg_state=dbg_state_queued) then
|
|
exit;
|
|
case def.typ of
|
|
stringdef :
|
|
appenddef_string(list,tstringdef(def));
|
|
enumdef :
|
|
appenddef_enum(list,tenumdef(def));
|
|
orddef :
|
|
appenddef_ord(list,torddef(def));
|
|
pointerdef :
|
|
appenddef_pointer(list,tpointerdef(def));
|
|
floatdef :
|
|
appenddef_float(list,tfloatdef(def));
|
|
filedef :
|
|
appenddef_file(list,tfiledef(def));
|
|
recorddef :
|
|
appenddef_record(list,trecorddef(def));
|
|
variantdef :
|
|
appenddef_variant(list,tvariantdef(def));
|
|
classrefdef :
|
|
appenddef_classref(list,tclassrefdef(def));
|
|
setdef :
|
|
appenddef_set(list,tsetdef(def));
|
|
formaldef :
|
|
appenddef_formal(list,tformaldef(def));
|
|
arraydef :
|
|
appenddef_array(list,tarraydef(def));
|
|
procvardef :
|
|
appenddef_procvar(list,tprocvardef(def));
|
|
objectdef :
|
|
appenddef_object(list,tobjectdef(def));
|
|
undefineddef :
|
|
appenddef_undefined(list,tundefineddef(def));
|
|
procdef :
|
|
begin
|
|
{ procdefs are already written in a separate step. procdef
|
|
support in appenddef is only needed for beforeappenddef to
|
|
write all local type defs }
|
|
end;
|
|
else
|
|
internalerror(200601281);
|
|
end;
|
|
afterappenddef(list,def);
|
|
def.dbg_state := dbg_state_written;
|
|
end;
|
|
|
|
|
|
{**************************************
|
|
Symbols
|
|
**************************************}
|
|
|
|
procedure TDebugInfo.beforeappendsym(list:TAsmList;sym:tsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.afterappendsym(list:TAsmList;sym:tsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_paravar(list:TAsmList;sym: tparavarsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_localvar(list:TAsmList;sym: tlocalvarsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_fieldvar(list:TAsmList;sym: tfieldvarsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_const(list:TAsmList;sym:tconstsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_label(list:TAsmList;sym: tlabelsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_property(list:TAsmList;sym: tpropertysym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_type(list:TAsmList;sym: ttypesym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_unit(list:TAsmList;sym: tunitsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.appendsym(list:TAsmList;sym:tsym);
|
|
begin
|
|
if sym.isdbgwritten then
|
|
exit;
|
|
beforeappendsym(list,sym);
|
|
case sym.typ of
|
|
staticvarsym :
|
|
appendsym_staticvar(list,tstaticvarsym(sym));
|
|
unitsym:
|
|
appendsym_unit(list,tunitsym(sym));
|
|
labelsym :
|
|
appendsym_label(list,tlabelsym(sym));
|
|
localvarsym :
|
|
appendsym_localvar(list,tlocalvarsym(sym));
|
|
paravarsym :
|
|
appendsym_paravar(list,tparavarsym(sym));
|
|
constsym :
|
|
appendsym_const(list,tconstsym(sym));
|
|
typesym :
|
|
appendsym_type(list,ttypesym(sym));
|
|
enumsym :
|
|
{ ignore enum syms, they are written by the owner }
|
|
;
|
|
syssym :
|
|
{ ignore sys syms, they are only of internal use }
|
|
;
|
|
procsym :
|
|
{ ignore proc syms, they are written by procdefs }
|
|
;
|
|
absolutevarsym :
|
|
appendsym_absolute(list,tabsolutevarsym(sym));
|
|
propertysym :
|
|
appendsym_property(list,tpropertysym(sym));
|
|
else
|
|
internalerror(200601242);
|
|
end;
|
|
afterappendsym(list,sym);
|
|
sym.isdbgwritten:=true;
|
|
end;
|
|
|
|
|
|
{**************************************
|
|
Symtables
|
|
**************************************}
|
|
|
|
procedure TDebugInfo.write_symtable_defs(list:TAsmList;st:TSymtable);
|
|
var
|
|
def : tdef;
|
|
i : longint;
|
|
begin
|
|
case st.symtabletype of
|
|
staticsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Defs - Begin Staticsymtable')));
|
|
globalsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Defs - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
|
|
end;
|
|
for i:=0 to st.DefList.Count-1 do
|
|
begin
|
|
def:=tdef(st.DefList[i]);
|
|
if (def.dbg_state in [dbg_state_used,dbg_state_queued]) then
|
|
appenddef(list,def);
|
|
end;
|
|
case st.symtabletype of
|
|
staticsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Defs - End Staticsymtable')));
|
|
globalsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Defs - End unit '+st.name^+' has index '+tostr(st.moduleid))));
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.write_symtable_parasyms(list:TAsmList;paras: tparalist);
|
|
var
|
|
i : longint;
|
|
sym : tsym;
|
|
begin
|
|
for i:=0 to paras.Count-1 do
|
|
begin
|
|
sym:=tsym(paras[i]);
|
|
if (sym.visibility<>vis_hidden) and
|
|
(not sym.isdbgwritten) then
|
|
appendsym(list,sym);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.write_symtable_syms(list:TAsmList;st:TSymtable);
|
|
var
|
|
i : longint;
|
|
sym : tsym;
|
|
begin
|
|
case st.symtabletype of
|
|
staticsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Syms - Begin Staticsymtable')));
|
|
globalsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Syms - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
|
|
end;
|
|
for i:=0 to st.SymList.Count-1 do
|
|
begin
|
|
sym:=tsym(st.SymList[i]);
|
|
if (sym.visibility<>vis_hidden) and
|
|
(not sym.isdbgwritten) then
|
|
appendsym(list,sym);
|
|
end;
|
|
case st.symtabletype of
|
|
staticsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Syms - End Staticsymtable')));
|
|
globalsymtable :
|
|
list.concat(tai_comment.Create(strpnew('Syms - End unit '+st.name^+' has index '+tostr(st.moduleid))));
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.write_symtable_procdefs(list:TAsmList;st:TSymtable);
|
|
var
|
|
i : longint;
|
|
def : tdef;
|
|
begin
|
|
for i:=0 to st.DefList.Count-1 do
|
|
begin
|
|
def:=tdef(st.DefList[i]);
|
|
case def.typ of
|
|
procdef :
|
|
begin
|
|
appendprocdef(list,tprocdef(def));
|
|
if assigned(tprocdef(def).localst) then
|
|
write_symtable_procdefs(list,tprocdef(def).localst);
|
|
end;
|
|
objectdef :
|
|
begin
|
|
write_symtable_procdefs(list,tobjectdef(def).symtable);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.reset_unit_type_info;
|
|
var
|
|
hp : tmodule;
|
|
begin
|
|
hp:=tmodule(loaded_units.first);
|
|
while assigned(hp) do
|
|
begin
|
|
hp.is_dbginfo_written:=false;
|
|
hp:=tmodule(hp.next);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TDebugInfo.write_used_unit_type_info(list:TAsmList;hp:tmodule);
|
|
var
|
|
pu : tused_unit;
|
|
begin
|
|
pu:=tused_unit(hp.used_units.first);
|
|
while assigned(pu) do
|
|
begin
|
|
if not pu.u.is_dbginfo_written then
|
|
begin
|
|
{ prevent infinte loop for circular dependencies }
|
|
pu.u.is_dbginfo_written:=true;
|
|
{ write type info from used units, use a depth first
|
|
strategy to reduce the recursion in writing all
|
|
dependent stabs }
|
|
write_used_unit_type_info(list,pu.u);
|
|
if assigned(pu.u.globalsymtable) then
|
|
write_symtable_defs(list,pu.u.globalsymtable);
|
|
end;
|
|
pu:=tused_unit(pu.next);
|
|
end;
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
Init / Done
|
|
****************************************************************************}
|
|
|
|
procedure InitDebugInfo(hp:tmodule);
|
|
begin
|
|
if not assigned(CDebugInfo[target_dbg.id]) then
|
|
begin
|
|
Comment(V_Fatal,'cg_f_debuginfo_output_not_supported');
|
|
exit;
|
|
end;
|
|
hp.DebugInfo:=CDebugInfo[target_dbg.id].Create;
|
|
end;
|
|
|
|
|
|
procedure DoneDebugInfo(hp:tmodule);
|
|
begin
|
|
if assigned(hp.DebugInfo) then
|
|
begin
|
|
hp.DebugInfo.Free;
|
|
hp.DebugInfo:=nil;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
|
|
var
|
|
t : tdbg;
|
|
begin
|
|
t:=r.id;
|
|
if assigned(dbginfos[t]) then
|
|
writeln('Warning: DebugInfo is already registered!')
|
|
else
|
|
Getmem(dbginfos[t],sizeof(tdbginfo));
|
|
dbginfos[t]^:=r;
|
|
CDebugInfo[t]:=c;
|
|
end;
|
|
|
|
|
|
const
|
|
dbg_none_info : tdbginfo =
|
|
(
|
|
id : dbg_none;
|
|
idtxt : 'NONE';
|
|
);
|
|
|
|
initialization
|
|
RegisterDebugInfo(dbg_none_info,TDebugInfo);
|
|
end.
|