+ dwarf for procedures and local symbols

git-svn-id: trunk@2360 -
This commit is contained in:
florian 2006-01-28 21:26:37 +00:00
parent cbdda429c5
commit 64acd83ab4
3 changed files with 162 additions and 126 deletions

View File

@ -255,6 +255,9 @@ interface
procedure UsedAsmSymbolListCheckUndefined;
end;
function LengthUleb128(a: aword) : byte;
function LengthSleb128(a: aint) : byte;
const
{ alt_jump,alt_addr,alt_data,alt_dbgline,alt_dbgfile }
asmlabeltypeprefix : array[tasmlabeltype] of char = ('j','a','d','l','f','t','c');
@ -274,6 +277,51 @@ implementation
symbolsgrow = 100;
function LengthUleb128(a: aword) : byte;
var
b: byte;
begin
result:=0;
repeat
b := a and $7f;
a := a shr 7;
if (a <> 0) then
b := b or $80;
inc(result);
if a=0 then
break;
until false;
end;
function LengthSleb128(a: aint) : byte;
var
b, size: byte;
neg, more: boolean;
begin
more := true;
neg := a < 0;
size := sizeof(a)*8;
result:=0;
repeat
b := a and $7f;
a := a shr 7;
if (neg) then
a := a or -(1 shl (size - 7));
if (((a = 0) and
(a and $40 = 0)) or
((a = -1) and
(a and $40 <> 0))) then
more := false
else
b := b or $80;
inc(result);
if not(more) then
break;
until false;
end;
{*****************************************************************************
TAsmSymbol
*****************************************************************************}

View File

@ -1,7 +1,8 @@
{
Copyright (c) 1998-2006 by the Free Pascal team
This unit implements generic GNU assembler (v2.8 or later)
This unit implements the generic part of the GNU assembler
(v2.8 or later) writer
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
@ -63,7 +64,6 @@ interface
function NextSetLabel: string;
end;
implementation
uses

View File

@ -221,8 +221,10 @@ implementation
verbose,
systems,
cpubase,
cgbase,
finput,
fmodule,
defutil,
symconst,symsym
;
@ -573,7 +575,7 @@ implementation
procedure TDebugInfoDwarf.finish_children;
begin
asmlist[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
asmlist[al_dwarf_info].concat(tai_const.create_8bit(0));
end;
@ -889,32 +891,35 @@ implementation
procedure TDebugInfoDwarf.append_procdef(list:taasmoutput;pd:tprocdef);
{
var
templist : taasmoutput;
stabsendlabel : tasmlabel;
procendlabel : tasmlabel;
mangled_length : longint;
p : pchar;
hs : string;
}
begin
{
if assigned(pd.procstarttai) then
begin
templist:=taasmoutput.create;
{ para types }
write_def_stabstr(templist,pd);
if assigned(pd.parast) then
write_symtable_syms(templist,pd.parast);
{ local type defs and vars should not be written
inside the main proc stab }
if assigned(pd.localst) and
(pd.localst.symtabletype=localsymtable) then
write_symtable_syms(templist,pd.localst);
asmlist[al_procedures].insertlistbefore(pd.procstarttai,templist);
{ end of procedure }
objectlibrary.getlabel(stabsendlabel,alt_dbgtype);
templist.concat(tai_label.create(stabsendlabel));
append_entry(DW_TAG_subprogram,true,
[DW_AT_name,DW_FORM_string,pd.procsym.name+#0
{ data continues below }
{ problem: base reg isn't known here
DW_AT_frame_base,DW_FORM_block1,1
}
]);
{ append block data }
{ asmlist[al_dwarf_info].concat(tai_const.create_8bit(dwarf_reg(pd.))); }
if not(is_void(tprocdef(pd).rettype.def)) then
append_labelentry_ref(DW_AT_type,def_dwarf_lab(tprocdef(pd).rettype.def));
{ mark end of procedure }
objectlibrary.getlabel(procendlabel,alt_dbgtype);
asmlist[al_procedures].insertbefore(tai_label.create(procendlabel),pd.procendtai);
append_labelentry(DW_AT_low_pc,objectlibrary.newasmsymbol(pd.mangledname,AB_LOCAL,AT_DATA));
append_labelentry(DW_AT_high_pc,procendlabel);
{
if assigned(pd.funcretsym) and
(tabstractnormalvarsym(pd.funcretsym).refs>0) then
begin
@ -934,31 +939,25 @@ implementation
tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(pd.funcretsym).localloc.reference.offset))));
end;
end;
mangled_length:=length(pd.mangledname);
getmem(p,2*mangled_length+50);
strpcopy(p,'192,0,0,');
{$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
strpcopy(strend(p),pd.mangledname);
if (tf_use_function_relative_addresses in target_info.flags) then
begin
strpcopy(strend(p),'-');
{$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
strpcopy(strend(p),pd.mangledname);
end;
templist.concat(Tai_stab.Create(stab_stabn,strnew(p)));
strpcopy(p,'224,0,0,'+stabsendlabel.name);
if (tf_use_function_relative_addresses in target_info.flags) then
begin
strpcopy(strend(p),'-');
{$IFDEF POWERPC64}strpcopy(strend(p), '.');{$ENDIF POWERPC64}
strpcopy(strend(p),pd.mangledname);
end;
templist.concat(Tai_stab.Create(stab_stabn,strnew(p)));
freemem(p,2*mangled_length+50);
asmlist[al_procedures].insertlistbefore(pd.procendtai,templist);
templist.free;
end;
}
finish_entry;
{
{ para types }
write_def_stabstr(templist,pd);
}
if assigned(pd.parast) then
write_symtable_syms(list,pd.parast);
{ local type defs and vars should not be written
inside the main proc stab }
if assigned(pd.localst) and
(pd.localst.symtabletype=localsymtable) then
write_symtable_syms(list,pd.localst);
finish_children;
end;
end;
@ -976,7 +975,11 @@ implementation
end;
procedure append_globalvarsym(sym:tglobalvarsym);
procedure append_varsym(sym:tabstractnormalvarsym);
var
templist : taasmoutput;
blocksize : longint;
regidx : longint;
begin
{ external symbols can't be resolved at link time, so we
can't generate stabs for them
@ -986,6 +989,56 @@ implementation
if vo_is_external in sym.varoptions then
exit;
{ There is no space allocated for not referenced locals }
if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
exit;
templist:=taasmoutput.create;
case sym.localloc.loc of
LOC_REGISTER,
LOC_CREGISTER,
LOC_MMREGISTER,
LOC_CMMREGISTER,
LOC_FPUREGISTER,
LOC_CFPUREGISTER :
begin
{
regidx:=findreg_by_number(sym.localloc.register);
{ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
{ this is the register order for GDB}
if regidx<>0 then
result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
}
end;
else
begin
case sym.typ of
globalvarsym:
begin
if (vo_is_thread_var in sym.varoptions) then
begin
{$warning !!! FIXME: dwarf for thread vars !!!}
end
else
begin
templist.concat(tai_const.create_8bit(3));
templist.concat(tai_const.createname(sym.mangledname,AT_DATA,0));
blocksize:=1+sizeof(aword);
end;
end;
localvarsym:
begin
regidx:=findreg_by_number(sym.localloc.reference.base);
templist.concat(tai_const.create_8bit(ord(DW_OP_breg0)+regdwarf_table[regidx]));
templist.concat(tai_const.create_sleb128bit(sym.localloc.reference.offset));
blocksize:=Lengthsleb128(sym.localloc.reference.offset)+1;
end
else
internalerror(200601288);
end;
end;
end;
append_entry(DW_TAG_variable,false,[
DW_AT_name,DW_FORM_string,sym.name+#0,
{
@ -994,85 +1047,18 @@ implementation
}
DW_AT_external,DW_FORM_flag,true,
{ data continues below }
DW_AT_location,DW_FORM_block1,1+sizeof(aword)
DW_AT_location,DW_FORM_block1,blocksize
]);
{ append block data }
asmlist[al_dwarf_info].concat(tai_const.create_8bit(3));
asmlist[al_dwarf_info].concat(tai_const.createname(sym.mangledname,AT_DATA,0));
asmlist[al_dwarf_info].concatlist(templist);
append_labelentry_ref(DW_AT_type,def_dwarf_lab(sym.vartype.def));
// ,,
{
case sym.localloc.loc of
LOC_REGISTER,
LOC_CREGISTER,
LOC_MMREGISTER,
LOC_CMMREGISTER,
LOC_FPUREGISTER,
LOC_CFPUREGISTER :
begin
regidx:=findreg_by_number(sym.localloc.register);
{ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
{ this is the register order for GDB}
if regidx<>0 then
result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
end;
else
begin
if (vo_is_thread_var in sym.varoptions) then
threadvaroffset:='+'+tostr(sizeof(aint))
else
threadvaroffset:='';
{ Here we used S instead of
because with G GDB doesn't look at the address field
but searches the same name or with a leading underscore
but these names don't exist in pascal !}
st:='S'+st;
result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_LCSYM},0,${line},${mangledname}$2',[st,threadvaroffset]);
end;
end;
}
templist.free;
finish_entry;
end;
function localvarsym_stabstr(sym:tlocalvarsym):Pchar;
var
st : string;
regidx : Tregisterindex;
begin
{
result:=nil;
{ There is no space allocated for not referenced locals }
if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
exit;
st:=def_stab_number(sym.vartype.def);
case sym.localloc.loc of
LOC_REGISTER,
LOC_CREGISTER,
LOC_MMREGISTER,
LOC_CMMREGISTER,
LOC_FPUREGISTER,
LOC_CFPUREGISTER :
begin
regidx:=findreg_by_number(sym.localloc.register);
{ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
{ this is the register order for GDB}
if regidx<>0 then
result:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
end;
LOC_REFERENCE :
{ offset to ebp => will not work if the framepointer is esp
so some optimizing will make things harder to debug }
result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
else
internalerror(2003091814);
end;
}
end;
function paravarsym_stabstr(sym:tparavarsym):Pchar;
var
st : string;
@ -1216,7 +1202,7 @@ implementation
begin
case sym.typ of
globalvarsym :
append_globalvarsym(tglobalvarsym(sym));
append_varsym(tglobalvarsym(sym));
unitsym:
{ for now, we ignore unit symbols }
;
@ -1227,8 +1213,10 @@ implementation
stabstr:=sym_stabstr_evaluate(sym,'"${name}",${N_LSYM},0,${line},0',[]);
fieldvarsym :
stabstr:=fieldvarsym_stabstr(tfieldvarsym(sym));
}
localvarsym :
stabstr:=localvarsym_stabstr(tlocalvarsym(sym));
append_varsym(tlocalvarsym(sym));
{
paravarsym :
stabstr:=paravarsym_stabstr(tparavarsym(sym));
typedconstsym :