diff --git a/compiler/dbgdwarf.pas b/compiler/dbgdwarf.pas index 46997119f9..6edfc58687 100644 --- a/compiler/dbgdwarf.pas +++ b/compiler/dbgdwarf.pas @@ -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; + {**************************************************************************** ****************************************************************************}