You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
1
(2) |
2
(2) |
3
|
4
|
|
5
|
6
(3) |
7
(1) |
8
(1) |
9
(4) |
10
(1) |
11
(1) |
|
12
(2) |
13
(7) |
14
(3) |
15
(2) |
16
(7) |
17
(1) |
18
(2) |
|
19
|
20
|
21
|
22
|
23
|
24
|
25
|
|
26
|
27
|
28
|
29
|
30
|
|
|
|
From: Paul F. <pj...@wa...> - 2022-06-13 22:04:37
|
On 6/13/22 19:33, Philippe Waroquiers wrote:
> Re-reading how the test works, the idea is that this test simulates a control-c
> typed in gdb by a user.
> The simulation is done by having the script simulate_control_c sending SIGUSR1
> to vgdb. Vgdb then sends \003 to the valgrind gdbserver.
> This char '003' is then read by valgrind gdbserver, that then stops the guest.
>
> If the guest is blocked in a syscall, vgdb will use ptrace to get the guest
> (and so the valgrind host) out of the syscall.
>
> Maybe the ptrace calls are causing the FreeBSD kernel to consider the
> syscall was interrupted ?
>
> It might be worth starting vgdb with -d -d -d -d
> and see if the EINTR is related to some ptrace calls ?
>
Hi Philippe
That's what I was beginning to think.
In the syscall traces I see
81891 none-amd64-freebsd CALL select(0,0,0,0,0x204e60)
81891 none-amd64-freebsd RET select -1 errno 4 Interrupted system call
81891 none-amd64-freebsd CALL write(0x72c98,0x40268dab8,0x2b)
81891 none-amd64-freebsd GIO fd 470168 wrote 43 bytes
"DEBUG: vgPlain_invoke_gdbserver wait/yield
That's a select that should be blocked being interrupted then my
VG_(printf) debug trace from VG_(invoke_gdbserver) caled via ptrace.
I need to dig more into ptrace. I did start looking at the lldb source
but there's a lot of abstraction with a load of "Plan" classes
corresponding to user commands.
A+
Paul
|
|
From: Mark W. <ma...@so...> - 2022-06-13 20:37:13
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=e95904b99c87606eae1372ee4661e9db03833f08 commit e95904b99c87606eae1372ee4661e9db03833f08 Author: Luboš Luňák <l....@ce...> Date: Tue Apr 26 08:35:16 2022 +0200 treat DW_TAG_skeleton_unit like DW_TAG_compile_unit It's basically the same, except for being split-dwarf. Handling it is required e.g. for reading line info. Diff: --- coregrind/m_debuginfo/readdwarf.c | 6 ++++-- coregrind/m_debuginfo/readdwarf3.c | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index e50d5d46d7..79d6764eaf 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -1136,7 +1136,8 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, tag = step_leb128U( &abbrev_img ); - if ( tag != 0x0011 /*TAG_compile_unit*/ ) + if ( tag != 0x0011 /*TAG_compile_unit*/ + && tag != 0x004a /*TAG_skeleton_unit*/ ) return; /* Not a compile unit (might be partial) or broken DWARF. */ /* DW_CHILDREN_yes or DW_CHILDREN_no */ @@ -1330,7 +1331,8 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, } /* Now store the members we need in the UnitInfo structure */ - if ( tag == 0x0011 /*TAG_compile_unit*/ ) { + if ( tag == 0x0011 /*TAG_compile_unit*/ + || tag == 0x004a /*TAG_skeleton_unit*/ ) { if ( name == 0x03 ) ui->name = sval; /* DW_AT_name */ else if ( name == 0x1b ) ui->compdir = sval; /* DW_AT_compdir */ else if ( name == 0x10 ) ui->stmt_list = cval; /* DW_AT_stmt_list */ diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c index e9aab0dd52..86af340ebc 100644 --- a/coregrind/m_debuginfo/readdwarf3.c +++ b/coregrind/m_debuginfo/readdwarf3.c @@ -2826,7 +2826,8 @@ static void parse_var_DIE ( if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_type_unit - || dtag == DW_TAG_partial_unit) { + || dtag == DW_TAG_partial_unit + || dtag == DW_TAG_skeleton_unit) { Bool have_lo = False; Bool have_hi1 = False; Bool hiIsRelative = False; @@ -3467,7 +3468,8 @@ static Bool parse_inl_DIE ( /* Get info about DW_TAG_compile_unit and DW_TAG_partial_unit which in theory could also contain inlined fn calls, if they cover an address range. */ Bool unit_has_addrs = False; - if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_partial_unit) { + if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_partial_unit + || dtag == DW_TAG_skeleton_unit) { Bool have_lo = False; Addr ip_lo = 0; const HChar *compdir = NULL; @@ -3859,7 +3861,8 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_type_unit - || dtag == DW_TAG_partial_unit) { + || dtag == DW_TAG_partial_unit + || dtag == DW_TAG_skeleton_unit) { if (level == 0) setup_cu_bases(cc, c_die, abbv); /* See if we can find DW_AT_language, since it is important for |
|
From: Mark W. <ma...@so...> - 2022-06-13 20:04:33
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=69767ee522324836e9147154ac0c350662747007 commit 69767ee522324836e9147154ac0c350662747007 Author: Mark Wielaard <ma...@kl...> Date: Mon Jun 13 21:29:01 2022 +0200 Add cachegrind and callgrind post.{diff,out} to .gitignore Diff: --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index c7202fab3a..1bce8a6287 100644 --- a/.gitignore +++ b/.gitignore @@ -92,6 +92,8 @@ # /cachegrind/tests/ /cachegrind/tests/*.dSYM /cachegrind/tests/*.so +/cachegrind/tests/*.post.diff* +/cachegrind/tests/*.post.out /cachegrind/tests/*.stderr.diff* /cachegrind/tests/*.stderr.out /cachegrind/tests/*.stdout.diff* @@ -137,6 +139,8 @@ # /callgrind/tests/ /callgrind/tests/*.dSYM +/callgrind/tests/*.post.diff* +/callgrind/tests/*.post.out /callgrind/tests/*.stderr.diff* /callgrind/tests/*.stderr.out /callgrind/tests/*.stdout.diff* |
|
From: Philippe W. <phi...@sk...> - 2022-06-13 19:49:37
|
On Sun, 2022-06-12 at 11:20 +0200, Paul Floyd wrote: > Hi > > This question is mostly for Philippe, but if anyone else feels fit to > comment please jump in. > > This weekend I have (mostly) finished adding gdb invoker support for > FreeBSD. Previously, like Darwin, the "none" invoker was being used. > > All but one of the gdb invoker regtests are passing, but I'm not sure > how serious the one failure is - gdbserver_tests/nlcontrolc is the one > failing, with a stdoutB diff. > > What is happening is that the first twp phases (burn and sleep) are > working OK. > > But for the final phase (set sleepms to 0 and continue, with the > expectation that all 4 threads be in the 16 minute timeout select calls). > > On FreeBSD I'm seeing the main thread select return and set EINTR. > However I don't see any signals with --trace-signals=yes. Re-reading how the test works, the idea is that this test simulates a control-c typed in gdb by a user. The simulation is done by having the script simulate_control_c sending SIGUSR1 to vgdb. Vgdb then sends \003 to the valgrind gdbserver. This char '003' is then read by valgrind gdbserver, that then stops the guest. If the guest is blocked in a syscall, vgdb will use ptrace to get the guest (and so the valgrind host) out of the syscall. Maybe the ptrace calls are causing the FreeBSD kernel to consider the syscall was interrupted ? It might be worth starting vgdb with -d -d -d -d and see if the EINTR is related to some ptrace calls ? Philippe > > It looks to me that this is an OS thing, with FreeBSD not resuming the > main thread select after the ptrace + signal timeout change. > > This is my only ptrace experience. Any ideas as to what else could be > causing select to be interrupted? > > A+ > Paul > > > _______________________________________________ > Valgrind-developers mailing list > Val...@li... > https://lists.sourceforge.net/lists/listinfo/valgrind-developers |
|
From: Mark W. <ma...@so...> - 2022-06-13 17:07:51
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=d19bbdf1200685ddbb6976cf915fba25f2097162 commit d19bbdf1200685ddbb6976cf915fba25f2097162 Author: Luboš Luňák <l....@ce...> Date: Tue Apr 19 12:20:16 2022 +0200 read dwarf5 DW_FORM_rnglistx and DW_FORM_loclistx The .debug_rnglists/.debug_loclists sections first have a list of offsets and then a list of the actual data that those offsets point to. Diff: --- coregrind/m_debuginfo/readdwarf.c | 6 +++ coregrind/m_debuginfo/readdwarf3.c | 82 +++++++++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index 7d71ff14fa..e50d5d46d7 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -1280,6 +1280,12 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, case 0x20: /* FORM_ref_sig8 */ p = ML_(cur_plus)(p, 8); break; + case 0x22: /* FORM_loclistx */ + (void)step_leb128U(&p); + break; + case 0x23: /* FORM_rnglistx */ + (void)step_leb128U(&p); + break; case 0x25: /* FORM_strx1 */ p = ML_(cur_plus)(p, 1); break; diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c index 85fc976634..e9aab0dd52 100644 --- a/coregrind/m_debuginfo/readdwarf3.c +++ b/coregrind/m_debuginfo/readdwarf3.c @@ -491,6 +491,12 @@ typedef /* DW_AT_str_offsets_base */ Addr cu_str_offsets_base; Bool cu_has_str_offsets_base; + /* DW_AT_rnglists_base */ + Addr cu_rnglists_base; + Bool cu_has_rnglists_base; + /* DW_AT_loclists_base */ + Addr cu_loclists_base; + Bool cu_has_loclists_base; /* --- Needed so we can add stuff to the string table. --- */ struct _DebugInfo* di; /* --- State of the hash table of g_abbv (i.e. parsed abbreviations) @@ -1435,6 +1441,40 @@ void get_Form_contents ( /*OUT*/FormContents* cts, cts->szB = cc->is_dw64 ? 8 : 4; TRACE_D3("%llu", cts->u.val); break; + case DW_FORM_rnglistx: { + if(!cc->cu_has_rnglists_base) { + cc->barf("get_Form_contents: DW_FORM_rnglistsx" + " without DW_AT_rnglists_base"); + } + /* Convert index to offset pointing to the offsets list. */ + ULong index = get_ULEB128(c); + ULong offset_to_offset = cc->cu_rnglists_base + index * sizeof_Dwarfish_UWord( cc->is_dw64 ); + /* And read the offset value from there. */ + Cursor cur; + init_Cursor( &cur, cc->escn_debug_rnglists, offset_to_offset, cc->barf, + "get_Form_contents: index points outside .debug_rnglists" ); + cts->u.val = cc->cu_rnglists_base + get_Dwarfish_UWord(&cur, cc->is_dw64); + cts->szB = 8; + TRACE_D3("%llu", cts->u.val); + break; + } + case DW_FORM_loclistx: { + if(!cc->cu_has_loclists_base) { + cc->barf("get_Form_contents: DW_FORM_loclistsx" + " without DW_AT_loclists_base"); + } + /* Convert index to offset pointing to the offsets list. */ + ULong index = get_ULEB128(c); + ULong offset_to_offset = cc->cu_loclists_base + index * sizeof_Dwarfish_UWord( cc->is_dw64 ); + /* And read the offset value from there. */ + Cursor cur; + init_Cursor( &cur, cc->escn_debug_loclists, offset_to_offset, cc->barf, + "get_Form_contents: index points outside .debug_loclists" ); + cts->u.val = cc->cu_loclists_base + get_Dwarfish_UWord(&cur, cc->is_dw64); + cts->szB = 8; + TRACE_D3("%llu", cts->u.val); + break; + } case DW_FORM_sdata: cts->u.val = (ULong)(Long)get_SLEB128(c); cts->szB = 8; @@ -1807,6 +1847,9 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form ) return 8; else return 4; + case DW_FORM_rnglistx: + case DW_FORM_loclistx: + return VARSZ_FORM; case DW_FORM_sdata: return VARSZ_FORM; case DW_FORM_udata: @@ -2571,27 +2614,32 @@ static void setup_cu_svma(CUConst* cc, Bool have_lo, Addr ip_lo, Bool td3) } } -/* Setup info from DW_AT_addr_base and DW_AT_str_offsets_base. This needs to be - done early, because other DW_AT_* info may depend on it. */ +/* Setup info from DW_AT_addr_base, DW_AT_str_offsets_base, DW_AT_rnglists_base + and DW_AT_loclists_base. This needs to be done early, because other DW_AT_* + info may depend on it. */ static void setup_cu_bases(CUConst* cc, Cursor* c_die, const g_abbv* abbv) { FormContents cts; UInt nf_i; ULong saved_c_pos; - if(cc->cu_has_addr_base && cc->cu_has_str_offsets_base) + if(cc->cu_has_addr_base && cc->cu_has_str_offsets_base + && cc->cu_has_rnglists_base && cc->cu_has_loclists_base) return; saved_c_pos = get_position_of_Cursor(c_die); nf_i = 0; - while (!cc->cu_has_addr_base || !cc->cu_has_str_offsets_base) { + while (!cc->cu_has_addr_base || !cc->cu_has_str_offsets_base + || !cc->cu_has_rnglists_base || !cc->cu_has_loclists_base) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; const name_form *nf = &abbv->nf[nf_i]; if (attr == 0 && form == 0) break; - if (attr != DW_AT_addr_base && attr != DW_AT_str_offsets_base ) { + if (attr != DW_AT_addr_base && attr != DW_AT_str_offsets_base + && attr != DW_AT_rnglists_base && attr != DW_AT_loclists_base) { const UInt form_szB = get_Form_szB (cc, form); if (form_szB == VARSZ_FORM) { - if(form == DW_FORM_addrx || form == DW_FORM_strx) { + if(form == DW_FORM_addrx || form == DW_FORM_strx + || form == DW_FORM_rnglistx || form == DW_FORM_loclistx) { /* Skip without interpreting them, they depend on *_base. */ (void) get_ULEB128(c_die); } else { @@ -2625,6 +2673,24 @@ static void setup_cu_bases(CUConst* cc, Cursor* c_die, const g_abbv* abbv) cc->cu_str_offsets_base = str_offsets_base; } } + if (attr == DW_AT_rnglists_base && cts.szB > 0) { + Addr rnglists_base = cts.u.val; + if (cc->cu_has_rnglists_base) + vg_assert (rnglists_base == cc->cu_rnglists_base); + else { + cc->cu_has_rnglists_base = True; + cc->cu_rnglists_base = rnglists_base; + } + } + if (attr == DW_AT_loclists_base && cts.szB > 0) { + Addr loclists_base = cts.u.val; + if (cc->cu_has_loclists_base) + vg_assert (loclists_base == cc->cu_loclists_base); + else { + cc->cu_has_loclists_base = True; + cc->cu_loclists_base = loclists_base; + } + } nf_i++; } set_position_of_Cursor(c_die, saved_c_pos); @@ -5564,6 +5630,10 @@ void new_dwarf3_reader_wrk ( cc.cu_has_addr_base = False; cc.cu_str_offsets_base = 0; cc.cu_has_str_offsets_base = False; + cc.cu_rnglists_base = 0; + cc.cu_has_rnglists_base = False; + cc.cu_loclists_base = 0; + cc.cu_has_loclists_base = False; cc.di = di; /* The CU's svma can be deduced by looking at the AT_low_pc value in the top level TAG_compile_unit, which is the topmost |
|
From: Mark W. <ma...@so...> - 2022-06-13 16:19:50
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=383f36462fdc25a0e849391cf845e22703a95c08 commit 383f36462fdc25a0e849391cf845e22703a95c08 Author: Luboš Luňák <l....@ce...> Date: Mon Apr 25 22:11:27 2022 +0200 avoid warning about missing DW_AT_*_base in skip_DIE() Similarly to setup_cu_bases(), DW_FORM_addrx etc. may depend on DW_AT_addr_base etc. that have not been read yet. Diff: --- coregrind/m_debuginfo/readdwarf3.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c index 219cb6bbab..85fc976634 100644 --- a/coregrind/m_debuginfo/readdwarf3.c +++ b/coregrind/m_debuginfo/readdwarf3.c @@ -1899,8 +1899,15 @@ void skip_DIE (UWord *sibling, *sibling = cts.u.val; nf_i++; } else if (abbv->nf[nf_i].skip_szB == VARSZ_FORM) { - get_Form_contents( &cts, cc, c_die, False /*td3*/, - &abbv->nf[nf_i] ); + DW_FORM form = abbv->nf[nf_i].at_form; + if(form == DW_FORM_addrx || form == DW_FORM_strx + || form == DW_FORM_rnglistx || form == DW_FORM_loclistx) { + /* Skip without interpreting them, they may depend on e.g. + DW_AT_addr_base that has not been read yet. */ + (void) get_ULEB128(c_die); + } else + get_Form_contents( &cts, cc, c_die, False /*td3*/, + &abbv->nf[nf_i] ); nf_i++; } else { advance_position_of_Cursor (c_die, (ULong)abbv->nf[nf_i].skip_szB); |
|
From: Mark W. <ma...@so...> - 2022-06-13 14:48:16
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=61dfba4232d795c00603c74e6d0573f2d16641e2 commit 61dfba4232d795c00603c74e6d0573f2d16641e2 Author: Luboš Luňák <l....@ce...> Date: Tue Apr 19 11:14:52 2022 +0200 read dwarf5 DW_FORM_addrx* and DW_FORM_strx* as generated by Clang14 DW_FORM_addrx* are offsets into .debug_addr containing addresses. DW_FORM_strx* are offsets into .debug_str_offsets, which contain offsets into .debug_str. Support for these also requires reading DW_AT_addr_base and DW_AT_str_offsets_base before any other field in the abbrev table entry, as those may use this form. Diff: --- coregrind/m_debuginfo/priv_readdwarf3.h | 3 +- coregrind/m_debuginfo/readdwarf.c | 30 ++++ coregrind/m_debuginfo/readdwarf3.c | 261 ++++++++++++++++++++++++++++---- coregrind/m_debuginfo/readelf.c | 21 ++- coregrind/m_debuginfo/readmacho.c | 8 +- 5 files changed, 293 insertions(+), 30 deletions(-) diff --git a/coregrind/m_debuginfo/priv_readdwarf3.h b/coregrind/m_debuginfo/priv_readdwarf3.h index f6d1dd1ee1..25e3cd50dc 100644 --- a/coregrind/m_debuginfo/priv_readdwarf3.h +++ b/coregrind/m_debuginfo/priv_readdwarf3.h @@ -48,7 +48,8 @@ ML_(new_dwarf3_reader) ( DiSlice escn_debug_rnglists, DiSlice escn_debug_loclists, DiSlice escn_debug_loc, DiSlice escn_debug_info_alt, DiSlice escn_debug_abbv_alt, DiSlice escn_debug_line_alt, - DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str + DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str, + DiSlice escn_debug_addr, DiSlice escn_debug_str_offsets ); #endif /* ndef __PRIV_READDWARF3_H */ diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index 56cef9a5f4..7d71ff14fa 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -1271,9 +1271,39 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, break; case 0x19: /* FORM_flag_present */ break; + case 0x1a: /* FORM_strx */ + (void)step_leb128U(&p); + break; + case 0x1b: /* FORM_addrx */ + (void)step_leb128U(&p); + break; case 0x20: /* FORM_ref_sig8 */ p = ML_(cur_plus)(p, 8); break; + case 0x25: /* FORM_strx1 */ + p = ML_(cur_plus)(p, 1); + break; + case 0x26: /* FORM_strx2 */ + p = ML_(cur_plus)(p, 2); + break; + case 0x27: /* FORM_strx3 */ + p = ML_(cur_plus)(p, 3); + break; + case 0x28: /* FORM_strx4 */ + p = ML_(cur_plus)(p, 4); + break; + case 0x29: /* FORM_addrx1 */ + p = ML_(cur_plus)(p, 1); + break; + case 0x2a: /* FORM_addrx2 */ + p = ML_(cur_plus)(p, 2); + break; + case 0x2b: /* FORM_addrx3 */ + p = ML_(cur_plus)(p, 3); + break; + case 0x2c: /* FORM_addrx4 */ + p = ML_(cur_plus)(p, 4); + break; case 0x1f20: /* FORM_GNU_ref_alt */ p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4); break; diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c index 1453ebbdbc..219cb6bbab 100644 --- a/coregrind/m_debuginfo/readdwarf3.c +++ b/coregrind/m_debuginfo/readdwarf3.c @@ -479,10 +479,18 @@ typedef DiSlice escn_debug_info_alt; DiSlice escn_debug_str_alt; DiSlice escn_debug_line_str; + DiSlice escn_debug_addr; + DiSlice escn_debug_str_offsets; /* How much to add to .debug_types resp. alternate .debug_info offsets in cook_die*. */ UWord types_cuOff_bias; UWord alt_cuOff_bias; + /* DW_AT_addr_base */ + Addr cu_addr_base; + Bool cu_has_addr_base; + /* DW_AT_str_offsets_base */ + Addr cu_str_offsets_base; + Bool cu_has_str_offsets_base; /* --- Needed so we can add stuff to the string table. --- */ struct _DebugInfo* di; /* --- State of the hash table of g_abbv (i.e. parsed abbreviations) @@ -1294,6 +1302,87 @@ typedef } FormContents; +// Read data for get_Form_contents() from .debug_addr for the 'index' entry. +static void get_Form_contents_addr( /*OUT*/FormContents* cts, DW_FORM form, + ULong index, const CUConst* cc, Bool td3 ) +{ + if(!cc->cu_has_addr_base) { + VG_(printf)( + "get_Form_contents_addr: %u (%s) without DW_AT_addr_base\n", + form, ML_(pp_DW_FORM)(form)); + cc->barf("get_Form_contents_addr: DW_AT_addr_base not set"); + } + /* We make the same word-size assumption as DW_FORM_addr. */ + UWord addr_pos = cc->cu_addr_base + index * sizeof(UWord); + Cursor cur; + init_Cursor( &cur, cc->escn_debug_addr, addr_pos, cc->barf, + "get_Form_contents_addr: index points outside .debug_addr" ); + if (TD3) { + HChar* tmp = ML_(cur_read_strdup)(get_DiCursor_from_Cursor(&cur), "di.getFC.1"); + TRACE_D3("(indirect address, offset: 0x%lx): %s", addr_pos, tmp); + ML_(dinfo_free)(tmp); + } + cts->u.val = (ULong)(UWord)get_UWord(&cur); + cts->szB = sizeof(UWord); + TRACE_D3("0x%lx", (UWord)cts->u.val); +} + +// Read data for get_Form_contents() from .debug_str for the given offset. +static void get_Form_contents_str( /*OUT*/FormContents* cts, DW_FORM form, + UWord offset, const CUConst* cc, Bool td3 ) +{ + if (!ML_(sli_is_valid)(cc->escn_debug_str) + || offset >= cc->escn_debug_str.szB) { + VG_(printf)( + "get_Form_contents_str: %u (%s) points outside .debug_str\n", + form, ML_(pp_DW_FORM)(form)); + cc->barf("get_Form_contents_str: index points outside .debug_str"); + } + /* FIXME: check the entire string lies inside debug_str, + not just the first byte of it. */ + DiCursor str + = ML_(cur_plus)( ML_(cur_from_sli)(cc->escn_debug_str), offset ); + if (TD3) { + HChar* tmp = ML_(cur_read_strdup)(str, "di.getFC.1"); + TRACE_D3("(indirect string, offset: 0x%lx): %s", offset, tmp); + ML_(dinfo_free)(tmp); + } + cts->u.cur = str; + cts->szB = - (Long)(1 + (ULong)ML_(cur_strlen)(str)); +} + +static inline UInt sizeof_Dwarfish_UWord (Bool is_dw64) +{ + if (is_dw64) + return sizeof(ULong); + else + return sizeof(UInt); +} + +// Read data for get_Form_contents() from .debug_str_offsets for the 'index' entry. +static void get_Form_contents_str_offsets( /*OUT*/FormContents* cts, DW_FORM form, + ULong index, const CUConst* cc, Bool td3 ) +{ + if(!cc->cu_has_str_offsets_base) { + VG_(printf)( + "get_Form_contents_str_offsets: %u (%s) without DW_AT_str_offsets_base\n", + form, ML_(pp_DW_FORM)(form)); + cc->barf("get_Form_contents_str_offsets: DW_AT_str_offsets_base not set"); + } + UWord str_offsets_pos = cc->cu_str_offsets_base + + index * sizeof_Dwarfish_UWord (cc->is_dw64); + Cursor cur; + init_Cursor( &cur, cc->escn_debug_str_offsets, str_offsets_pos, cc->barf, + "get_Form_contents_str_offsets: index " + "points outside .debug_str_offsets" ); + if (TD3) { + HChar* tmp = ML_(cur_read_strdup)(get_DiCursor_from_Cursor(&cur), "di.getFC.1"); + TRACE_D3("(indirect string offset, offset: 0x%lx): %s", str_offsets_pos, tmp); + ML_(dinfo_free)(tmp); + } + get_Form_contents_str( cts, form, get_Dwarfish_UWord(&cur, cc->is_dw64), cc, td3 ); +} + /* From 'c', get the Form data into 'cts'. Either it gets a 1/2/4/8 byte scalar value, or (a reference to) zero or more bytes starting at a DiCursor.*/ @@ -1409,21 +1498,7 @@ void get_Form_contents ( /*OUT*/FormContents* cts, case DW_FORM_strp: { /* this is an offset into .debug_str */ UWord uw = (UWord)get_Dwarfish_UWord( c, cc->is_dw64 ); - if (!ML_(sli_is_valid)(cc->escn_debug_str) - || uw >= cc->escn_debug_str.szB) - cc->barf("get_Form_contents: DW_FORM_strp " - "points outside .debug_str"); - /* FIXME: check the entire string lies inside debug_str, - not just the first byte of it. */ - DiCursor str - = ML_(cur_plus)( ML_(cur_from_sli)(cc->escn_debug_str), uw ); - if (TD3) { - HChar* tmp = ML_(cur_read_strdup)(str, "di.getFC.1"); - TRACE_D3("(indirect string, offset: 0x%lx): %s", uw, tmp); - ML_(dinfo_free)(tmp); - } - cts->u.cur = str; - cts->szB = - (Long)(1 + (ULong)ML_(cur_strlen)(str)); + get_Form_contents_str( cts, form, uw, cc, td3 ); break; } case DW_FORM_line_strp: { @@ -1654,6 +1729,55 @@ void get_Form_contents ( /*OUT*/FormContents* cts, break; } + case DW_FORM_addrx: { + /* this is an offset into .debug_addr */ + ULong index = (ULong)(Long)get_ULEB128(c); + get_Form_contents_addr(cts, form, index, cc, td3); + break; + } + case DW_FORM_addrx1: { + /* this is an offset into .debug_addr */ + ULong index = (ULong)get_UChar(c); + get_Form_contents_addr(cts, form, index, cc, td3); + break; + } + case DW_FORM_addrx2: { + /* this is an offset into .debug_addr */ + ULong index = (ULong)get_UShort(c); + get_Form_contents_addr(cts, form, index, cc, td3); + break; + } + case DW_FORM_addrx4: { + /* this is an offset into .debug_addr */ + ULong index = (ULong)get_UInt(c); + get_Form_contents_addr(cts, form, index, cc, td3); + break; + } + case DW_FORM_strx: { + /* this is an offset into .debug_str_offsets */ + ULong index = (ULong)(Long)get_ULEB128(c); + get_Form_contents_str_offsets(cts, form, index, cc, td3); + break; + } + case DW_FORM_strx1: { + /* this is an offset into .debug_str_offsets */ + ULong index = get_UChar(c); + get_Form_contents_str_offsets(cts, form, index, cc, td3); + break; + } + case DW_FORM_strx2: { + /* this is an offset into .debug_str_offsets */ + ULong index = (ULong)get_UShort(c); + get_Form_contents_str_offsets(cts, form, index, cc, td3); + break; + } + case DW_FORM_strx4: { + /* this is an offset into .debug_str_offsets */ + ULong index = (ULong)get_UInt(c); + get_Form_contents_str_offsets(cts, form, index, cc, td3); + break; + } + default: VG_(printf)( "get_Form_contents: unhandled %u (%s) at <%llx>\n", @@ -1662,14 +1786,6 @@ void get_Form_contents ( /*OUT*/FormContents* cts, } } -static inline UInt sizeof_Dwarfish_UWord (Bool is_dw64) -{ - if (is_dw64) - return sizeof(ULong); - else - return sizeof(UInt); -} - #define VARSZ_FORM 0xffffffff /* If the form is a fixed length form, return the nr of bytes for this form. If the form is a variable length form, return VARSZ_FORM. */ @@ -1740,6 +1856,22 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form ) return sizeof_Dwarfish_UWord(cc->is_dw64); case DW_FORM_implicit_const: return 0; /* Value inside abbrev. */ + case DW_FORM_addrx: + return VARSZ_FORM; + case DW_FORM_strx: + return VARSZ_FORM; + case DW_FORM_addrx1: + case DW_FORM_strx1: + return 1; + case DW_FORM_addrx2: + case DW_FORM_strx2: + return 2; + case DW_FORM_addrx3: + case DW_FORM_strx3: + return 3; + case DW_FORM_addrx4: + case DW_FORM_strx4: + return 4; default: VG_(printf)( "get_Form_szB: unhandled %u (%s)\n", @@ -2432,6 +2564,65 @@ static void setup_cu_svma(CUConst* cc, Bool have_lo, Addr ip_lo, Bool td3) } } +/* Setup info from DW_AT_addr_base and DW_AT_str_offsets_base. This needs to be + done early, because other DW_AT_* info may depend on it. */ +static void setup_cu_bases(CUConst* cc, Cursor* c_die, const g_abbv* abbv) +{ + FormContents cts; + UInt nf_i; + ULong saved_c_pos; + if(cc->cu_has_addr_base && cc->cu_has_str_offsets_base) + return; + saved_c_pos = get_position_of_Cursor(c_die); + nf_i = 0; + while (!cc->cu_has_addr_base || !cc->cu_has_str_offsets_base) { + DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; + DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; + if (attr == 0 && form == 0) + break; + if (attr != DW_AT_addr_base && attr != DW_AT_str_offsets_base ) { + const UInt form_szB = get_Form_szB (cc, form); + if (form_szB == VARSZ_FORM) { + if(form == DW_FORM_addrx || form == DW_FORM_strx) { + /* Skip without interpreting them, they depend on *_base. */ + (void) get_ULEB128(c_die); + } else { + /* Need to read the contents of this one to skip it. */ + get_Form_contents( &cts, cc, c_die, False /*td3*/, + &abbv->nf[nf_i] ); + } + } else { + /* Skip without even reading it, as it may depend on *_base. */ + advance_position_of_Cursor (c_die, form_szB); + } + nf_i++; + continue; + } + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); + if (attr == DW_AT_addr_base && cts.szB > 0) { + Addr addr_base = cts.u.val; + if (cc->cu_has_addr_base) + vg_assert (addr_base == cc->cu_addr_base); + else { + cc->cu_has_addr_base = True; + cc->cu_addr_base = addr_base; + } + } + if (attr == DW_AT_str_offsets_base && cts.szB > 0) { + Addr str_offsets_base = cts.u.val; + if (cc->cu_has_str_offsets_base) + vg_assert (str_offsets_base == cc->cu_str_offsets_base); + else { + cc->cu_has_str_offsets_base = True; + cc->cu_str_offsets_base = str_offsets_base; + } + } + nf_i++; + } + set_position_of_Cursor(c_die, saved_c_pos); +} + static void trace_DIE( DW_TAG dtag, UWord posn, @@ -2571,6 +2762,9 @@ static void parse_var_DIE ( Addr ip_hi1 = 0; Addr rangeoff = 0; const HChar *compdir = NULL; + + if (level == 0) + setup_cu_bases(cc, c_die, abbv); nf_i = 0; while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; @@ -3207,6 +3401,8 @@ static Bool parse_inl_DIE ( Bool has_stmt_list = False; ULong cu_line_offset = 0; + if (level == 0) + setup_cu_bases(cc, c_die, abbv); nf_i = 0; while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; @@ -3566,7 +3762,7 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, Int level, Cursor* c_die, const g_abbv *abbv, - const CUConst* cc, + CUConst* cc, Bool td3 ) { FormContents cts; @@ -3591,6 +3787,8 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, if (dtag == DW_TAG_compile_unit || dtag == DW_TAG_type_unit || dtag == DW_TAG_partial_unit) { + if (level == 0) + setup_cu_bases(cc, c_die, abbv); /* See if we can find DW_AT_language, since it is important for establishing array bounds (see DW_TAG_subrange_type below in this fn) */ @@ -5081,7 +5279,8 @@ void new_dwarf3_reader_wrk ( DiSlice escn_debug_rnglists, DiSlice escn_debug_loclists, DiSlice escn_debug_loc, DiSlice escn_debug_info_alt, DiSlice escn_debug_abbv_alt, DiSlice escn_debug_line_alt, - DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str + DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str, + DiSlice escn_debug_addr, DiSlice escn_debug_str_offsets ) { XArray* /* of TyEnt */ tyents = NULL; @@ -5349,9 +5548,15 @@ void new_dwarf3_reader_wrk ( cc.escn_debug_info_alt = escn_debug_info_alt; cc.escn_debug_str_alt = escn_debug_str_alt; cc.escn_debug_line_str = escn_debug_line_str; + cc.escn_debug_addr = escn_debug_addr; + cc.escn_debug_str_offsets = escn_debug_str_offsets; cc.types_cuOff_bias = escn_debug_info.szB; cc.alt_cuOff_bias = escn_debug_info.szB + escn_debug_types.szB; cc.cu_start_offset = cu_start_offset; + cc.cu_addr_base = 0; + cc.cu_has_addr_base = False; + cc.cu_str_offsets_base = 0; + cc.cu_has_str_offsets_base = False; cc.di = di; /* The CU's svma can be deduced by looking at the AT_low_pc value in the top level TAG_compile_unit, which is the topmost @@ -5795,7 +6000,8 @@ ML_(new_dwarf3_reader) ( DiSlice escn_debug_rnglists, DiSlice escn_debug_loclists, DiSlice escn_debug_loc, DiSlice escn_debug_info_alt, DiSlice escn_debug_abbv_alt, DiSlice escn_debug_line_alt, - DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str + DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str, + DiSlice escn_debug_addr, DiSlice escn_debug_str_offsets ) { volatile Int jumped; @@ -5819,7 +6025,8 @@ ML_(new_dwarf3_reader) ( escn_debug_rnglists, escn_debug_loclists, escn_debug_loc, escn_debug_info_alt, escn_debug_abbv_alt, escn_debug_line_alt, - escn_debug_str_alt, escn_debug_line_str ); + escn_debug_str_alt, escn_debug_line_str, + escn_debug_addr, escn_debug_str_offsets ); d3rd_jmpbuf_valid = False; TRACE_D3("\n------ .debug_info reading was successful ------\n"); } else { diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index b4edb4fe85..25d237b7de 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -2831,6 +2831,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) DiSlice debug_ranges_escn = DiSlice_INVALID; // .debug_ranges (dwarf2) DiSlice debug_rnglists_escn = DiSlice_INVALID; // .debug_rnglists(dwarf5) DiSlice debug_loclists_escn = DiSlice_INVALID; // .debug_loclists(dwarf5) + DiSlice debug_addr_escn = DiSlice_INVALID; // .debug_addr (dwarf5) + DiSlice debug_str_offsets_escn = DiSlice_INVALID; // .debug_str_offsets (dwarf5) DiSlice debug_loc_escn = DiSlice_INVALID; // .debug_loc (dwarf2) DiSlice debug_frame_escn = DiSlice_INVALID; // .debug_frame (dwarf2) DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line (alt) @@ -2960,6 +2962,14 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) if (!ML_(sli_is_valid)(debug_frame_escn)) FIND(".zdebug_frame", debug_frame_escn) + FIND( ".debug_addr", debug_addr_escn) + if (!ML_(sli_is_valid)(debug_addr_escn)) + FIND(".zdebug_addr", debug_addr_escn) + + FIND( ".debug_str_offsets", debug_str_offsets_escn) + if (!ML_(sli_is_valid)(debug_str_offsets_escn)) + FIND(".zdebug_str_offsets", debug_str_offsets_escn) + FIND( ".debug", dwarf1d_escn) FIND( ".line", dwarf1l_escn) @@ -3291,6 +3301,14 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) if (!ML_(sli_is_valid)(debug_frame_escn)) FIND(need_dwarf2, ".zdebug_frame", debug_frame_escn) + FIND( need_dwarf2, ".debug_addr", debug_addr_escn) + if (!ML_(sli_is_valid)(debug_addr_escn)) + FIND(need_dwarf2, ".zdebug_addr", debug_addr_escn) + + FIND( need_dwarf2, ".debug_str_offsets", debug_str_offsets_escn) + if (!ML_(sli_is_valid)(debug_str_offsets_escn)) + FIND(need_dwarf2, ".zdebug_str_offsets", debug_str_offsets_escn) + if (!ML_(sli_is_valid)(debugaltlink_escn)) FIND( need_dwarf2, ".gnu_debugaltlink", debugaltlink_escn) @@ -3532,7 +3550,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) debug_rnglists_escn, debug_loclists_escn, debug_loc_escn, debug_info_alt_escn, debug_abbv_alt_escn, debug_line_alt_escn, - debug_str_alt_escn, debug_line_str_escn + debug_str_alt_escn, debug_line_str_escn, + debug_addr_escn, debug_str_offsets_escn ); } } diff --git a/coregrind/m_debuginfo/readmacho.c b/coregrind/m_debuginfo/readmacho.c index d93e24ecf8..61a3fe9f5a 100644 --- a/coregrind/m_debuginfo/readmacho.c +++ b/coregrind/m_debuginfo/readmacho.c @@ -1113,6 +1113,10 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) = getsectdata(dsli, "__DWARF", "__debug_loclists", NULL); DiSlice debug_loc_mscn = getsectdata(dsli, "__DWARF", "__debug_loc", NULL); + DiSlice debug_addr_mscn + = getsectdata(dsli, "__DWARF", "__debug_addr", NULL); + DiSlice debug_str_offsets_mscn + = getsectdata(dsli, "__DWARF", "__debug_str_offsets", NULL); /* It appears (jrs, 2014-oct-19) that section "__eh_frame" in segment "__TEXT" appears in both the main and dsym files, but @@ -1174,7 +1178,9 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) DiSlice_INVALID, /* ALT .debug_abbv */ DiSlice_INVALID, /* ALT .debug_line */ DiSlice_INVALID, /* ALT .debug_str */ - debug_line_str_mscn /* .debug_line_str */ + debug_line_str_mscn, /* .debug_line_str */ + debug_addr_mscn, + debug_str_offsets_mscn ); } } |