Merge branch 'mfr-dwarf-tag-string' into 'main'

Draft: Introduce DW_TAG_string_type for dwarf-4

See merge request freepascal.org/fpc/source!683
This commit is contained in:
Martin 2025-04-04 22:54:51 +02:00
commit 451a647b6b

View File

@ -259,9 +259,12 @@ interface
end;
{ TDebugInfoDwarf4 }
TDebugInfoDwarf4 = class(TDebugInfoDwarf3)
public
function dwarf_version: Word; override;
procedure appenddef_string(list:TAsmList;def:tstringdef);override;
end;
@ -4486,6 +4489,145 @@ implementation
Result:=4;
end;
procedure TDebugInfoDwarf4.appenddef_string(list: TAsmList; def: tstringdef);
procedure addstringdef(const name: shortstring; chardef: tdef; deref: boolean; lensize: aint);
var
upperopcodes: longint;
begin
{ deref=true -> ansi/unicde/widestring; deref = false -> short/longstring }
if assigned(def.typesym) then
append_entry(DW_TAG_string_type,false,[
DW_AT_name,DW_FORM_string,name+#0,
DW_AT_data_location,DW_FORM_block1,2+ord(not(deref))
])
else
append_entry(DW_TAG_string_type,false,[
DW_AT_data_location,DW_FORM_block1,2+ord(not(deref))
]);
{ in all cases we start with the address of the string }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
if deref then
begin
{ ansi/unicode/widestring -> dereference the address of the string, and then
we point to address of the string
}
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
end
else
begin
{ shortstring characters begin at string[1], so add one to the string's address }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit0)+lensize));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus)))
end;
{ reference to the element type of the string }
append_labelentry_ref(DW_AT_type,def_dwarf_lab(chardef));
if deref then
begin
if not (is_widestring(def) and (tf_winlikewidestring in target_info.flags)) then
upperopcodes:=14
else
upperopcodes:=17;
// DWARF-4: DW_AT_byte_size
// DWARF-5: DW_AT_string_length_byte_size
append_attribute(DW_AT_byte_size, DW_FORM_data1, [4]); // size of the length field
append_block1(DW_AT_string_length, upperopcodes);
{ high(string) is stored sizeof(sizeint) bytes before the string data }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_dup)));
{ pointer = nil? }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_bra)));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit_unaligned(4));
{ yes -> length = 0 }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit0)));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_skip)));
if upperopcodes=17 then
{ skip the extra deref_size argument and the division by two of the length }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit_unaligned(6))
else
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit_unaligned(3));
{ no -> load length }
if upperopcodes=17 then
{ for Windows WideString the size is always a DWORD }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit4)))
else
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit0)+sizesinttype.size));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_minus)));
if upperopcodes=17 then
begin
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref_size)));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(4));
end
else
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
{ for widestrings, the length is specified in bytes, so divide by two }
if (upperopcodes=17) then
begin
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit1)));
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_shr)));
end;
{ skip to past end is not allowed, thus use a nop here }
{ Replace NOP by DW_OP_stack_value / only needed if done OP_shr, but ok in other cases}
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_stack_value)));
end
else
begin
// DWARF-4: DW_AT_byte_size
// DWARF-5: DW_AT_string_length_byte_size
append_attribute(DW_AT_byte_size, DW_FORM_data1, [lensize]); // size of the length field
append_block1(DW_AT_string_length, 1);
{ for shortstrings, the length is the first byte of the string }
current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
end;
finish_entry;
end;
begin
if (ds_dwarf_cpp in current_settings.debugswitches) then
begin
// At least LLDB 6.0.0 does not like this implementation of string types.
// Call the inherited DWARF 2 implementation, which works fine.
inherited;
exit;
end;
case def.stringtype of
st_shortstring:
begin
addstringdef('ShortString',cansichartype,false,1);
end;
st_longstring:
begin
{$ifdef cpu64bitaddr}
addstringdef('LongString',cansichartype,false,8);
{$else cpu64bitaddr}
addstringdef('LongString',cansichartype,false,4);
{$endif cpu64bitaddr}
end;
st_ansistring:
begin
addstringdef('AnsiString',cansichartype,true,-1);
end;
st_unicodestring:
begin
addstringdef('UnicodeString',cwidechartype,true,-1);
end;
st_widestring:
begin
addstringdef('WideString',cwidechartype,true,-1)
end;
end;
end;
{****************************************************************************
****************************************************************************}