|
@@ -242,6 +242,10 @@ interface
|
|
|
|
|
|
procedure set_def_dwarf_labs(def:tdef);
|
|
procedure set_def_dwarf_labs(def:tdef);
|
|
|
|
|
|
|
|
+ { Convenience version of the method below, so the compiler creates the
|
|
|
|
+ tvarrec for us (must only pass one element in the last parameter). }
|
|
|
|
+ procedure append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const values: array of const);
|
|
|
|
+ procedure append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const value: tvarrec);
|
|
procedure append_entry(tag : tdwarf_tag;has_children : boolean;data : array of const);
|
|
procedure append_entry(tag : tdwarf_tag;has_children : boolean;data : array of const);
|
|
procedure append_block1(attr: tdwarf_attribute; size: aint);
|
|
procedure append_block1(attr: tdwarf_attribute; size: aint);
|
|
procedure append_labelentry(attr : tdwarf_attribute;sym : tasmsymbol);
|
|
procedure append_labelentry(attr : tdwarf_attribute;sym : tasmsymbol);
|
|
@@ -267,7 +271,7 @@ interface
|
|
{ used for global/static variables, local variables, parameters and
|
|
{ used for global/static variables, local variables, parameters and
|
|
absolute variables
|
|
absolute variables
|
|
}
|
|
}
|
|
- procedure appendsym_var_with_name_type_offset(list:TAsmList; sym:tabstractnormalvarsym; const name: string; def: tdef; offset: pint);
|
|
|
|
|
|
+ procedure appendsym_var_with_name_type_offset(list:TAsmList; sym:tabstractnormalvarsym; const name: string; def: tdef; offset: pint; do_self: boolean);
|
|
{ used for fields and properties mapped to fields }
|
|
{ used for fields and properties mapped to fields }
|
|
procedure appendsym_fieldvar_with_name_offset(list:TAsmList;sym: tfieldvarsym;const name: string; def: tdef; offset: pint);
|
|
procedure appendsym_fieldvar_with_name_offset(list:TAsmList;sym: tfieldvarsym;const name: string; def: tdef; offset: pint);
|
|
|
|
|
|
@@ -813,6 +817,129 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ procedure TDebugInfoDwarf.append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const values: array of const);
|
|
|
|
+ begin
|
|
|
|
+ if length(values)<>1 then
|
|
|
|
+ internalerror(2009040402);
|
|
|
|
+ append_attribute(attr,form,values[0]);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ procedure TDebugInfoDwarf.append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const value: tvarrec);
|
|
|
|
+ begin
|
|
|
|
+ { attribute }
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(cardinal(attr)));
|
|
|
|
+
|
|
|
|
+ { form }
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(cardinal(form)));
|
|
|
|
+
|
|
|
|
+ { info itself }
|
|
|
|
+ case form of
|
|
|
|
+ DW_FORM_string:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtChar:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(value.VChar));
|
|
|
|
+ vtString:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(value.VString^));
|
|
|
|
+ vtAnsistring:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(Ansistring(value.VAnsiString)));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200601264);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ DW_FORM_flag:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(byte(value.VBoolean)));
|
|
|
|
+
|
|
|
|
+ DW_FORM_data1:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtInteger:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInteger));
|
|
|
|
+ vtInt64:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInt64^));
|
|
|
|
+ vtQWord:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VQWord^));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200602143);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ DW_FORM_data2:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtInteger:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(value.VInteger));
|
|
|
|
+ vtInt64:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(value.VInt64^));
|
|
|
|
+ vtQWord:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(value.VQWord^));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200602144);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ DW_FORM_data4:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtInteger:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(value.VInteger));
|
|
|
|
+ vtInt64:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(value.VInt64^));
|
|
|
|
+ vtQWord:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(value.VQWord^));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200602145);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ DW_FORM_data8:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtInteger:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(value.VInteger));
|
|
|
|
+ vtInt64:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(value.VInt64^));
|
|
|
|
+ vtQWord:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(value.VQWord^));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200602146);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ DW_FORM_sdata:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtInteger:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(value.VInteger));
|
|
|
|
+ vtInt64:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(value.VInt64^));
|
|
|
|
+ vtQWord:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(value.VQWord^));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200601285);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ DW_FORM_udata:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtInteger:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(value.VInteger));
|
|
|
|
+ vtInt64:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(value.VInt64^));
|
|
|
|
+ vtQWord:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(value.VQWord^));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200601284);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ { block gets only the size, the rest is appended manually by the caller }
|
|
|
|
+ DW_FORM_block1:
|
|
|
|
+ case value.VType of
|
|
|
|
+ vtInteger:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInteger));
|
|
|
|
+ vtInt64:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInt64^));
|
|
|
|
+ vtQWord:
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VQWord^));
|
|
|
|
+ else
|
|
|
|
+ internalerror(200602141);
|
|
|
|
+ end;
|
|
|
|
+ else
|
|
|
|
+ internalerror(200601263);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
{ writing the data through a few simply procedures allows to create easily extra information
|
|
{ writing the data through a few simply procedures allows to create easily extra information
|
|
for debugging of debug info }
|
|
for debugging of debug info }
|
|
procedure TDebugInfoDwarf.append_entry(tag : tdwarf_tag;has_children : boolean;data : array of const);
|
|
procedure TDebugInfoDwarf.append_entry(tag : tdwarf_tag;has_children : boolean;data : array of const);
|
|
@@ -836,130 +963,14 @@ implementation
|
|
i:=0;
|
|
i:=0;
|
|
while i<=high(data) do
|
|
while i<=high(data) do
|
|
begin
|
|
begin
|
|
- { attribute }
|
|
|
|
- if data[i].VType=vtInteger then
|
|
|
|
- begin
|
|
|
|
- current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(data[i].VInteger));
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
|
|
+ if (i+2 > high(data)) then
|
|
|
|
+ internalerror(2009040401);
|
|
|
|
+ if data[i].VType<>vtInteger then
|
|
internalerror(200601261);
|
|
internalerror(200601261);
|
|
- inc(i);
|
|
|
|
-
|
|
|
|
- { form }
|
|
|
|
- if data[i].VType=vtInteger then
|
|
|
|
- begin
|
|
|
|
- current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(data[i].VInteger));
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- internalerror(200601262);
|
|
|
|
- inc(i);
|
|
|
|
-
|
|
|
|
- { info itself }
|
|
|
|
- case tdwarf_form(data[i-1].VInteger) of
|
|
|
|
- DW_FORM_string:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtChar:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(data[i].VChar));
|
|
|
|
- vtString:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(data[i].VString^));
|
|
|
|
- vtAnsistring:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(Ansistring(data[i].VAnsiString)));
|
|
|
|
- else
|
|
|
|
- internalerror(200601264);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- DW_FORM_flag:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(byte(data[i].VBoolean)));
|
|
|
|
-
|
|
|
|
- DW_FORM_data1:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtInteger:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(data[i].VInteger));
|
|
|
|
- vtInt64:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(data[i].VInt64^));
|
|
|
|
- vtQWord:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(data[i].VQWord^));
|
|
|
|
- else
|
|
|
|
- internalerror(200602143);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- DW_FORM_data2:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtInteger:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(data[i].VInteger));
|
|
|
|
- vtInt64:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(data[i].VInt64^));
|
|
|
|
- vtQWord:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(data[i].VQWord^));
|
|
|
|
- else
|
|
|
|
- internalerror(200602144);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- DW_FORM_data4:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtInteger:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(data[i].VInteger));
|
|
|
|
- vtInt64:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(data[i].VInt64^));
|
|
|
|
- vtQWord:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(data[i].VQWord^));
|
|
|
|
- else
|
|
|
|
- internalerror(200602145);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- DW_FORM_data8:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtInteger:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(data[i].VInteger));
|
|
|
|
- vtInt64:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(data[i].VInt64^));
|
|
|
|
- vtQWord:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(data[i].VQWord^));
|
|
|
|
- else
|
|
|
|
- internalerror(200602146);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- DW_FORM_sdata:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtInteger:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(data[i].VInteger));
|
|
|
|
- vtInt64:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(data[i].VInt64^));
|
|
|
|
- vtQWord:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(data[i].VQWord^));
|
|
|
|
- else
|
|
|
|
- internalerror(200601285);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- DW_FORM_udata:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtInteger:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(data[i].VInteger));
|
|
|
|
- vtInt64:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(data[i].VInt64^));
|
|
|
|
- vtQWord:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(data[i].VQWord^));
|
|
|
|
- else
|
|
|
|
- internalerror(200601284);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- { block gets only the size, the rest is appended manually by the caller }
|
|
|
|
- DW_FORM_block1:
|
|
|
|
- case data[i].VType of
|
|
|
|
- vtInteger:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(data[i].VInteger));
|
|
|
|
- vtInt64:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(data[i].VInt64^));
|
|
|
|
- vtQWord:
|
|
|
|
- current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(data[i].VQWord^));
|
|
|
|
- else
|
|
|
|
- internalerror(200602141);
|
|
|
|
- end;
|
|
|
|
- else
|
|
|
|
- internalerror(200601263);
|
|
|
|
- end;
|
|
|
|
- inc(i);
|
|
|
|
|
|
+ if data[i+1].VType<>vtInteger then
|
|
|
|
+ internalerror(200601261);
|
|
|
|
+ append_attribute(tdwarf_attribute(data[i].VInteger),tdwarf_form(data[i+1].VInteger),data[i+2]);
|
|
|
|
+ inc(i,3);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1656,7 +1667,7 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- procedure TDebugInfoDwarf.appendprocdef(list:TAsmList;def:tprocdef);
|
|
|
|
|
|
+ procedure TDebugInfoDwarf.appendprocdef(list:TAsmList; def:tprocdef);
|
|
|
|
|
|
function dwarf_calling_convention(def: tprocdef): Tdwarf_calling_convention;
|
|
function dwarf_calling_convention(def: tprocdef): Tdwarf_calling_convention;
|
|
begin
|
|
begin
|
|
@@ -1675,26 +1686,75 @@ implementation
|
|
|
|
|
|
var
|
|
var
|
|
procendlabel : tasmlabel;
|
|
procendlabel : tasmlabel;
|
|
- funcrettype : tasmsymbol;
|
|
|
|
procentry : string;
|
|
procentry : string;
|
|
- dreg : byte;
|
|
|
|
|
|
+ cc : Tdwarf_calling_convention;
|
|
|
|
+ st : tsymtable;
|
|
|
|
+ i : longint;
|
|
|
|
+ vmtindexnr : pint;
|
|
begin
|
|
begin
|
|
if not assigned(def.procstarttai) then
|
|
if not assigned(def.procstarttai) then
|
|
exit;
|
|
exit;
|
|
|
|
|
|
|
|
+ { Procdefs are not handled by the regular def writing code, so
|
|
|
|
+ dbg_state is not set/checked for them. Do it here. }
|
|
|
|
+ if (def.dbg_state in [dbg_state_writing,dbg_state_written]) then
|
|
|
|
+ exit;
|
|
|
|
+
|
|
|
|
+ { Write methods and only in the scope of their parent objectdefs. }
|
|
|
|
+ if (def.owner.symtabletype=objectsymtable) then
|
|
|
|
+ begin
|
|
|
|
+ { this code can also work for nested procdefs, but is not yet
|
|
|
|
+ activated for those because there is no clear advantage yet to
|
|
|
|
+ limiting the scope of nested procedures to that of their parent,
|
|
|
|
+ and it makes it impossible to set breakpoints in them by
|
|
|
|
+ referring to their name. }
|
|
|
|
+ st:=def.owner;
|
|
|
|
+ while assigned(st.defowner) and
|
|
|
|
+ (tdef(st.defowner).typ = procdef) do
|
|
|
|
+ st:=tprocdef(st.defowner).owner;
|
|
|
|
+ if assigned(st) and
|
|
|
|
+ (tdef(st.defowner).dbg_state<>dbg_state_writing) then
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ def.dbg_state:=dbg_state_writing;
|
|
|
|
+
|
|
current_asmdata.asmlists[al_dwarf_info].concat(tai_comment.Create(strpnew('Procdef '+def.fullprocname(true))));
|
|
current_asmdata.asmlists[al_dwarf_info].concat(tai_comment.Create(strpnew('Procdef '+def.fullprocname(true))));
|
|
append_entry(DW_TAG_subprogram,true,
|
|
append_entry(DW_TAG_subprogram,true,
|
|
- [DW_AT_name,DW_FORM_string,symname(def.procsym)+#0,
|
|
|
|
- DW_AT_calling_convention,DW_FORM_data1,dwarf_calling_convention(def),
|
|
|
|
- DW_AT_external,DW_FORM_flag,po_global in def.procoptions
|
|
|
|
|
|
+ [DW_AT_name,DW_FORM_string,symname(def.procsym)+#0
|
|
{ data continues below }
|
|
{ data continues below }
|
|
{ problem: base reg isn't known here
|
|
{ problem: base reg isn't known here
|
|
DW_AT_frame_base,DW_FORM_block1,1
|
|
DW_AT_frame_base,DW_FORM_block1,1
|
|
}
|
|
}
|
|
]);
|
|
]);
|
|
- { append block data }
|
|
|
|
- { current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(dwarf_reg(def.))); }
|
|
|
|
|
|
|
|
|
|
+ { Append optional flags. }
|
|
|
|
+
|
|
|
|
+ { Calling convention. }
|
|
|
|
+ cc:=dwarf_calling_convention(def);
|
|
|
|
+ if (cc<>DW_CC_normal) then
|
|
|
|
+ append_attribute(DW_AT_calling_convention,DW_FORM_data1,[ord(cc)]);
|
|
|
|
+ { Externally visible. }
|
|
|
|
+ if (po_global in def.procoptions) and
|
|
|
|
+ (def.parast.symtablelevel<=normal_function_level) then
|
|
|
|
+ append_attribute(DW_AT_external,DW_FORM_flag,[true]);
|
|
|
|
+ { Abstract or virtual/overriding method. }
|
|
|
|
+ if (([po_abstractmethod, po_virtualmethod, po_overridingmethod] * def.procoptions) <> []) then
|
|
|
|
+ begin
|
|
|
|
+ if not(po_abstractmethod in def.procoptions) then
|
|
|
|
+ append_attribute(DW_AT_virtuality,DW_FORM_data1,[ord(DW_VIRTUALITY_virtual)])
|
|
|
|
+ else
|
|
|
|
+ append_attribute(DW_AT_virtuality,DW_FORM_data1,[ord(DW_VIRTUALITY_pure_virtual)]);
|
|
|
|
+ { Element number in the vmt (needs to skip stuff coming before the
|
|
|
|
+ actual method addresses in the vmt, so we use vmtmethodoffset()
|
|
|
|
+ and then divide by sizeof(pint)). }
|
|
|
|
+ vmtindexnr:=tobjectdef(def.owner.defowner).vmtmethodoffset(def.extnumber) div sizeof(pint);
|
|
|
|
+ append_attribute(DW_AT_vtable_elem_location,DW_FORM_block1,[1+LengthUleb128(vmtindexnr)]);
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_constu)));
|
|
|
|
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.Create_uleb128bit(vmtindexnr));
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ { Return type. }
|
|
if not(is_void(tprocdef(def).returndef)) then
|
|
if not(is_void(tprocdef(def).returndef)) then
|
|
append_labelentry_ref(DW_AT_type,def_dwarf_lab(tprocdef(def).returndef));
|
|
append_labelentry_ref(DW_AT_type,def_dwarf_lab(tprocdef(def).returndef));
|
|
|
|
|
|
@@ -1716,7 +1776,23 @@ implementation
|
|
finish_entry;
|
|
finish_entry;
|
|
|
|
|
|
if assigned(def.parast) then
|
|
if assigned(def.parast) then
|
|
- write_symtable_syms(current_asmdata.asmlists[al_dwarf_info],def.parast);
|
|
|
|
|
|
+ begin
|
|
|
|
+ { First insert self, because gdb uses the fact whether or not the
|
|
|
|
+ first parameter of a method is artificial to distinguish static
|
|
|
|
+ from regular methods. }
|
|
|
|
+
|
|
|
|
+ { Find the self parameter (it's usually last in the list). }
|
|
|
|
+ for i:=def.parast.symlist.count-1 downto 0 do
|
|
|
|
+ if (tsym(def.parast.symlist[i]).typ = paravarsym) and
|
|
|
|
+ (vo_is_self in tparavarsym(def.parast.symlist[i]).varoptions) then
|
|
|
|
+ { insert it as the first one }
|
|
|
|
+ appendsym_var_with_name_type_offset(list,
|
|
|
|
+ tparavarsym(def.parast.symlist[i]),
|
|
|
|
+ symname(tsym(def.parast.symlist[i])),
|
|
|
|
+ tparavarsym(def.parast.symlist[i]).vardef,0,true);
|
|
|
|
+ { Now insert the rest (this will skip the self parameter). }
|
|
|
|
+ write_symtable_syms(current_asmdata.asmlists[al_dwarf_info],def.parast);
|
|
|
|
+ end;
|
|
{ local type defs and vars should not be written
|
|
{ local type defs and vars should not be written
|
|
inside the main proc }
|
|
inside the main proc }
|
|
if assigned(def.localst) and
|
|
if assigned(def.localst) and
|
|
@@ -1728,7 +1804,13 @@ implementation
|
|
write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],def.parast);
|
|
write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],def.parast);
|
|
if assigned(def.localst) and
|
|
if assigned(def.localst) and
|
|
(def.localst.symtabletype=localsymtable) then
|
|
(def.localst.symtabletype=localsymtable) then
|
|
- write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],def.localst);
|
|
|
|
|
|
+ begin
|
|
|
|
+ write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],def.localst);
|
|
|
|
+ { Write nested procedures -- disabled, see scope check at the
|
|
|
|
+ beginning; currently, these are still written in the global
|
|
|
|
+ scope. }
|
|
|
|
+ // write_symtable_procdefs(current_asmdata.asmlists[al_dwarf_info],def.localst);
|
|
|
|
+ end;
|
|
|
|
|
|
finish_children;
|
|
finish_children;
|
|
end;
|
|
end;
|
|
@@ -1811,11 +1893,11 @@ implementation
|
|
|
|
|
|
procedure TDebugInfoDwarf.appendsym_var(list:TAsmList;sym:tabstractnormalvarsym);
|
|
procedure TDebugInfoDwarf.appendsym_var(list:TAsmList;sym:tabstractnormalvarsym);
|
|
begin
|
|
begin
|
|
- appendsym_var_with_name_type_offset(list,sym,symname(sym),sym.vardef,0);
|
|
|
|
|
|
+ appendsym_var_with_name_type_offset(list,sym,symname(sym),sym.vardef,0,false);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- procedure TDebugInfoDwarf.appendsym_var_with_name_type_offset(list:TAsmList; sym:tabstractnormalvarsym; const name: string; def: tdef; offset: pint);
|
|
|
|
|
|
+ procedure TDebugInfoDwarf.appendsym_var_with_name_type_offset(list:TAsmList; sym:tabstractnormalvarsym; const name: string; def: tdef; offset: pint; do_self: boolean);
|
|
var
|
|
var
|
|
templist : TAsmList;
|
|
templist : TAsmList;
|
|
blocksize : longint;
|
|
blocksize : longint;
|
|
@@ -1830,6 +1912,12 @@ implementation
|
|
if vo_is_external in sym.varoptions then
|
|
if vo_is_external in sym.varoptions then
|
|
exit;
|
|
exit;
|
|
|
|
|
|
|
|
+ { Self must be the first inserted parameter, see
|
|
|
|
+ appendprocdef(). }
|
|
|
|
+ if not(do_self) and
|
|
|
|
+ (vo_is_self in sym.varoptions) then
|
|
|
|
+ exit;
|
|
|
|
+
|
|
{ There is no space allocated for not referenced locals }
|
|
{ There is no space allocated for not referenced locals }
|
|
if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
|
|
if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
|
|
exit;
|
|
exit;
|
|
@@ -1934,6 +2022,13 @@ implementation
|
|
]);
|
|
]);
|
|
{ append block data }
|
|
{ append block data }
|
|
current_asmdata.asmlists[al_dwarf_info].concatlist(templist);
|
|
current_asmdata.asmlists[al_dwarf_info].concatlist(templist);
|
|
|
|
+ { Mark self as artificial for methods, because gdb uses the fact
|
|
|
|
+ whether or not the first parameter of a method is artificial to
|
|
|
|
+ distinguish regular from static methods (since there are no
|
|
|
|
+ no vo_is_self parameters for static methods, we don't have to check
|
|
|
|
+ that). }
|
|
|
|
+ if (vo_is_self in sym.varoptions) then
|
|
|
|
+ append_attribute(DW_AT_artificial,DW_FORM_flag,[true]);
|
|
{$ifndef gdb_supports_DW_AT_variable_parameter}
|
|
{$ifndef gdb_supports_DW_AT_variable_parameter}
|
|
if (sym.typ=paravarsym) and
|
|
if (sym.typ=paravarsym) and
|
|
paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
|
|
paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
|
|
@@ -2147,7 +2242,7 @@ implementation
|
|
begin
|
|
begin
|
|
if (tosym.typ=fieldvarsym) then
|
|
if (tosym.typ=fieldvarsym) then
|
|
internalerror(2009031404);
|
|
internalerror(2009031404);
|
|
- appendsym_var_with_name_type_offset(list,tabstractnormalvarsym(tosym),symname(sym),sym.propdef,offset)
|
|
|
|
|
|
+ appendsym_var_with_name_type_offset(list,tabstractnormalvarsym(tosym),symname(sym),sym.propdef,offset,false)
|
|
end
|
|
end
|
|
else
|
|
else
|
|
appendsym_fieldvar_with_name_offset(list,tfieldvarsym(tosym),symname(sym),sym.propdef,offset)
|
|
appendsym_fieldvar_with_name_offset(list,tfieldvarsym(tosym),symname(sym),sym.propdef,offset)
|
|
@@ -2209,7 +2304,7 @@ implementation
|
|
get_symlist_sym_offset(symlist,tosym,offset);
|
|
get_symlist_sym_offset(symlist,tosym,offset);
|
|
if (tosym.typ=fieldvarsym) then
|
|
if (tosym.typ=fieldvarsym) then
|
|
internalerror(2009031402);
|
|
internalerror(2009031402);
|
|
- appendsym_var_with_name_type_offset(list,tabstractnormalvarsym(tosym),symname(sym),tabstractvarsym(sym).vardef,offset);
|
|
|
|
|
|
+ appendsym_var_with_name_type_offset(list,tabstractnormalvarsym(tosym),symname(sym),tabstractvarsym(sym).vardef,offset,false);
|
|
templist.free;
|
|
templist.free;
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
@@ -2861,6 +2956,8 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
def.symtable.symList.ForEachCall(@enum_membersyms_callback,nil);
|
|
def.symtable.symList.ForEachCall(@enum_membersyms_callback,nil);
|
|
|
|
+ { Write the methods in the scope of the class/object. }
|
|
|
|
+ write_symtable_procdefs(current_asmdata.asmlists[al_dwarf_info],def.symtable);
|
|
finish_children;
|
|
finish_children;
|
|
end;
|
|
end;
|
|
|
|
|