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
|
3
|
4
(2) |
|
5
|
6
|
7
|
8
(7) |
9
|
10
|
11
(1) |
|
12
(4) |
13
|
14
|
15
|
16
|
17
(12) |
18
|
|
19
|
20
|
21
|
22
|
23
(3) |
24
(1) |
25
|
|
26
(1) |
27
(17) |
28
(1) |
29
|
30
(2) |
|
|
|
From: Petar J. <pe...@so...> - 2020-04-17 18:39:13
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=6f84421546eaf0eae3c303a62ae133387fe1a706 commit 6f84421546eaf0eae3c303a62ae133387fe1a706 Author: Aleksandar Rikalo <ale...@rt...> Date: Fri Apr 17 18:38:11 2020 +0000 mips: fix helgrind/tests/annotate_hbefore for nanoMIPS Implement do_acasW() function for nanoMIPS. Diff: --- helgrind/tests/annotate_hbefore.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/helgrind/tests/annotate_hbefore.c b/helgrind/tests/annotate_hbefore.c index e53423b425..259d3b64c8 100644 --- a/helgrind/tests/annotate_hbefore.c +++ b/helgrind/tests/annotate_hbefore.c @@ -252,6 +252,35 @@ UWord do_acasW ( UWord* addr, UWord expected, UWord nyu ) return success; } +#elif defined(VGA_nanomips) + +/* return 1 if success, 0 if failure */ +UWord do_acasW ( UWord* addr, UWord expected, UWord nyu ) +{ + UWord success; + UWord block[3] = { (UWord)addr, nyu, expected}; + + __asm__ __volatile__( + "lw $t0, 0(%1)" "\n\t" + "lw $t2, 8(%1)" "\n\t" + "lw $t3, 4(%1)" "\n\t" + "ll $t1, 0($t0)" "\n\t" + "bnec $t1, $t2, 1f" "\n\t" + "sc $t3, 0($t0)" "\n\t" + "move %0, $t3" "\n\t" + "bc 2f" "\n\t" + "1:" "\n\t" + "move %0, $zero" "\n\t" + "2:" "\n\t" + : /*out*/ "=r"(success) + : /*in*/ "r"(&block[0]) + : /*trash*/ "t0", "t1", "t2", "t3", "memory" + ); + + assert(success == 0 || success == 1); + return success; +} + #elif defined(VGA_mips64) && !defined(VGABI_N32) // mips64 |
|
From: Petar J. <pe...@so...> - 2020-04-17 18:39:04
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=8035dbe16b1349d66b53a363a8b0dccac9076c55 commit 8035dbe16b1349d66b53a363a8b0dccac9076c55 Author: Aleksandar Rikalo <ale...@rt...> Date: Fri Apr 17 18:31:42 2020 +0000 mips: support Ico_U1 in extractConst() for nanoMIPS Add missing case in extractConst(). It fixes Memcheck chrashing on nanoMIPS. Diff: --- VEX/priv/host_nanomips_isel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/VEX/priv/host_nanomips_isel.c b/VEX/priv/host_nanomips_isel.c index d348f21930..16932dd65f 100644 --- a/VEX/priv/host_nanomips_isel.c +++ b/VEX/priv/host_nanomips_isel.c @@ -194,6 +194,9 @@ static inline Int extractConst(IRConst *c) case Ico_U8: return (Int)(Char)c->Ico.U8; + case Ico_U1: + return !!c->Ico.U1; + default: vpanic("NANOMIPSisel_extractConst() fails"); } |
|
From: Petar J. <pe...@so...> - 2020-04-17 18:25:32
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=93bb2da218a691532cd709b195b687e02ac0f1d2 commit 93bb2da218a691532cd709b195b687e02ac0f1d2 Author: Aleksandar Rikalo <ale...@rt...> Date: Fri Apr 17 18:22:38 2020 +0000 Fix memcheck/vbit-test for BE platforms We do not need u1 member of bits union as long as we use u32 for the same purpose. Overlapping uint8_t with uint32_t causes a problem on BE platforms, since LSB of u32 is not overlap with u1. Diff: --- NEWS | 1 + memcheck/tests/vbit-test/binary.c | 8 ++++---- memcheck/tests/vbit-test/vbits.c | 4 ++-- memcheck/tests/vbit-test/vbits.h | 2 -- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index e33d1b14d8..6f082d6ac7 100644 --- a/NEWS +++ b/NEWS @@ -122,6 +122,7 @@ where XXXXXX is the bug number as listed below. 416667 gcc10 ppc64le impossible constraint in 'asm' in test_isa. 416753 new 32bit time syscalls for 2038+ 417187 [MIPS] Conditional branch problem since 'grail' changes +417238 Test memcheck/tests/vbit-test fails on mips64 BE 417281 s390x: /bin/true segfaults with "grail" enabled 417427 commit to fix vki_siginfo_t definition created numerous regression errors on ppc64 diff --git a/memcheck/tests/vbit-test/binary.c b/memcheck/tests/vbit-test/binary.c index 045221b05d..b93ab15858 100644 --- a/memcheck/tests/vbit-test/binary.c +++ b/memcheck/tests/vbit-test/binary.c @@ -38,7 +38,7 @@ and_combine(vbits_t v1, vbits_t v2, value_t val2, int invert_val2) if (invert_val2) { switch (v2.num_bits) { - case 1: val2.u1 = ~val2.u1 & 1; break; + case 1: val2.u32 = ~val2.u32 & 1; break; case 8: val2.u8 = ~val2.u8 & 0xff; break; case 16: val2.u16 = ~val2.u16 & 0xffff; break; case 32: val2.u32 = ~val2.u32; break; @@ -50,7 +50,7 @@ and_combine(vbits_t v1, vbits_t v2, value_t val2, int invert_val2) switch (v2.num_bits) { case 1: - new.bits.u1 = (v1.bits.u1 & ~v2.bits.u1 & val2.u1) & 1; + new.bits.u32 = (v1.bits.u32 & ~v2.bits.u32 & val2.u32) & 1; break; case 8: new.bits.u8 = (v1.bits.u8 & ~v2.bits.u8 & val2.u8) & 0xff; @@ -427,9 +427,9 @@ all_bits_zero_value(unsigned num_bits) value_t val; switch (num_bits) { - case 1: val.u1 = 0; break; case 8: val.u8 = 0; break; case 16: val.u16 = 0; break; + case 1: case 32: val.u32 = 0; break; case 64: val.u64 = 0; break; default: @@ -445,7 +445,7 @@ all_bits_one_value(unsigned num_bits) value_t val; switch (num_bits) { - case 1: val.u1 = 1; break; + case 1: val.u32 = 1; break; case 8: val.u8 = 0xff; break; case 16: val.u16 = 0xffff; break; case 32: val.u32 = ~0u; break; diff --git a/memcheck/tests/vbit-test/vbits.c b/memcheck/tests/vbit-test/vbits.c index 9307efb359..2e925eda05 100644 --- a/memcheck/tests/vbit-test/vbits.c +++ b/memcheck/tests/vbit-test/vbits.c @@ -656,7 +656,7 @@ or_vbits(vbits_t v1, vbits_t v2) vbits_t new = { .num_bits = v1.num_bits }; switch (v1.num_bits) { - case 1: new.bits.u1 = (v1.bits.u1 | v2.bits.u1) & 1; break; + case 1: new.bits.u32 = (v1.bits.u32 | v2.bits.u32) & 1; break; case 8: new.bits.u8 = v1.bits.u8 | v2.bits.u8; break; case 16: new.bits.u16 = v1.bits.u16 | v2.bits.u16; break; case 32: new.bits.u32 = v1.bits.u32 | v2.bits.u32; break; @@ -685,7 +685,7 @@ and_vbits(vbits_t v1, vbits_t v2) vbits_t new = { .num_bits = v1.num_bits }; switch (v1.num_bits) { - case 1: new.bits.u1 = (v1.bits.u1 & v2.bits.u1) & 1; break; + case 1: new.bits.u32 = (v1.bits.u32 & v2.bits.u32) & 1; break; case 8: new.bits.u8 = v1.bits.u8 & v2.bits.u8; break; case 16: new.bits.u16 = v1.bits.u16 & v2.bits.u16; break; case 32: new.bits.u32 = v1.bits.u32 & v2.bits.u32; break; diff --git a/memcheck/tests/vbit-test/vbits.h b/memcheck/tests/vbit-test/vbits.h index ebeb33ad90..0a50fab61d 100644 --- a/memcheck/tests/vbit-test/vbits.h +++ b/memcheck/tests/vbit-test/vbits.h @@ -36,7 +36,6 @@ typedef uint64_t uint256_t[4]; typedef struct { unsigned num_bits; union { - uint8_t u1; uint8_t u8; uint16_t u16; uint32_t u32; @@ -51,7 +50,6 @@ typedef struct { we do not expect to test with specific floating point values. So we don't need to represent them. */ typedef union { - uint8_t u1; uint8_t u8; uint16_t u16; uint32_t u32; |
|
From: Petar J. <pe...@so...> - 2020-04-17 18:14:49
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=feccc40da7a5d9ec29d23d819dbdf17ad793ac3d commit feccc40da7a5d9ec29d23d819dbdf17ad793ac3d Author: Petar Jovanovic <mip...@gm...> Date: Fri Apr 17 18:11:16 2020 +0000 update NEWS with fix for #417187 The KDE issue #417187 has been fixed in commit 8bd259eb14d884009e2e51e6ad5834c06d193e17 mips: update VEX to support speculative conditional branching commit ddc311558e11c47a06ba996a7d075b336726fc0b mips: treat delay slot as part of the previous instruction Diff: --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index e48a4cc98f..e33d1b14d8 100644 --- a/NEWS +++ b/NEWS @@ -121,6 +121,7 @@ where XXXXXX is the bug number as listed below. 416464 Fix false reports for uninitialized memory for PR_CAPBSET_READ/DROP 416667 gcc10 ppc64le impossible constraint in 'asm' in test_isa. 416753 new 32bit time syscalls for 2038+ +417187 [MIPS] Conditional branch problem since 'grail' changes 417281 s390x: /bin/true segfaults with "grail" enabled 417427 commit to fix vki_siginfo_t definition created numerous regression errors on ppc64 |
|
From: Petar J. <pe...@so...> - 2020-04-17 18:14:41
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=fd97444eb2a82e13923a48b0b6951e3530d02c74 commit fd97444eb2a82e13923a48b0b6951e3530d02c74 Author: Stefan Maksimovic <ste...@rt...> Date: Fri Apr 17 18:05:20 2020 +0000 mips: add a special case for beq r0, r0, imm This results in unconditional PUTs to PC in generated IR code. This fixes: memcheck/tests/cdebug_zlib memcheck/tests/cdebug_zlib_gnu memcheck/tests/origin2-not-quite memcheck/tests/origin5-bz2 none/tests/mips64/branch_and_jump_instructions Diff: --- VEX/priv/guest_mips_toIR.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/VEX/priv/guest_mips_toIR.c b/VEX/priv/guest_mips_toIR.c index d915487af0..489d91afb7 100644 --- a/VEX/priv/guest_mips_toIR.c +++ b/VEX/priv/guest_mips_toIR.c @@ -20034,16 +20034,31 @@ static UInt disInstr_MIPS_WRK_00(UInt cins, const VexArchInfo* archinfo, *lastn = mkexpr(t0); break; - case 0x04: /* BEQ */ - DIP("beq r%u, r%u, %u", rs, rt, imm); + case 0x04: /* BEQ, B */ + if (rs == 0 && rt == 0) { + ULong branch_offset; + t0 = newTemp(ty); + DIP("b %u", imm); - if (mode64) - dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)), - imm, bstmt); - else - dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), - imm, bstmt); + if (mode64) { + branch_offset = extend_s_18to64(imm << 2); + assign(t0, mkU64(guest_PC_curr_instr + 4 + branch_offset)); + } else { + branch_offset = extend_s_18to32(imm << 2); + assign(t0, mkU32(guest_PC_curr_instr + 4 + branch_offset)); + } + *lastn = mkexpr(t0); + } else { + DIP("beq r%u, r%u, %u", rs, rt, imm); + + if (mode64) + dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)), + imm, bstmt); + else + dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), + imm, bstmt); + } break; case 0x05: /* BNE */ |
|
From: Petar J. <pe...@so...> - 2020-04-17 18:14:34
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=8bd259eb14d884009e2e51e6ad5834c06d193e17 commit 8bd259eb14d884009e2e51e6ad5834c06d193e17 Author: Petar Jovanovic <mip...@gm...> Date: Fri Apr 17 18:02:39 2020 +0000 mips: update VEX to support speculative conditional branching This partially fixes KDE #417187. Diff: --- VEX/priv/guest_generic_bb_to_IR.c | 5 +---- VEX/priv/host_mips_isel.c | 12 ++---------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/VEX/priv/guest_generic_bb_to_IR.c b/VEX/priv/guest_generic_bb_to_IR.c index 5932eb8043..2f204c5b0a 100644 --- a/VEX/priv/guest_generic_bb_to_IR.c +++ b/VEX/priv/guest_generic_bb_to_IR.c @@ -1448,10 +1448,7 @@ IRSB* bb_to_IR ( // Try for an extend based on a conditional branch, specifically in the // hope of identifying and recovering, an "A && B" condition spread across // two basic blocks. - if (irsb_be.tag == Be_Cond - /* sewardj 2019Dec14: It also causes crashing on MIPS, even for - --tool=none. */ - && arch_guest != VexArchMIPS64 && arch_guest != VexArchMIPS32) + if (irsb_be.tag == Be_Cond) { if (debug_print) { vex_printf("\n-+-+ (ext# %d) Considering cbranch to" diff --git a/VEX/priv/host_mips_isel.c b/VEX/priv/host_mips_isel.c index 51ac757731..899c7868e0 100644 --- a/VEX/priv/host_mips_isel.c +++ b/VEX/priv/host_mips_isel.c @@ -2366,13 +2366,9 @@ static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e) case Ico_U8: l = (Long) (Int) (Char) con->Ico.U8; break; -#if 0 - // Not needed until chasing cond branches in bb_to_IR is enabled on - // MIPS. See comment on And1/Or1 below. case Ico_U1: l = con->Ico.U1 ? 1 : 0; break; -#endif default: vpanic("iselIntExpr_R.const(mips)"); } @@ -2773,11 +2769,7 @@ static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e) r_dst, mode64)); return MIPScc_NE; } -#if 0 - // sewardj 2019Dec14: this is my best attempt at And1/Or1, but I am not - // sure if it is correct. In any case it is not needed until chasing cond - // branches is enabled on MIPS. Currently it is disabled, in function bb_to_IR - // (see comments there). + if (e->tag == Iex_Binop && (e->Iex.Binop.op == Iop_And1 || e->Iex.Binop.op == Iop_Or1)) { HReg r_argL = iselWordExpr_R(env, e->Iex.Binop.arg1); @@ -2798,7 +2790,7 @@ static MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e) r_dst, mode64)); return MIPScc_EQ; } -#endif + if (e->tag == Iex_RdTmp) { HReg r_dst = iselWordExpr_R_wrk(env, e); /* Store result to guest_COND */ |
|
From: Petar J. <pe...@so...> - 2020-04-17 18:14:27
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=ddc311558e11c47a06ba996a7d075b336726fc0b commit ddc311558e11c47a06ba996a7d075b336726fc0b Author: Stefan Maksimovic <ste...@rt...> Date: Fri Apr 17 17:54:58 2020 +0000 mips: treat delay slot as part of the previous instruction Do so by recursively calling disInstr_MIPS_WRK() if the instruction currently being disassembled is a branch/jump, effectively combining them into one IR instruction. A notable change is that the branch/jump + delay slot combination now forms an eight-byte instruction. This is related to KDE #417187. This fixes drd/tests/annotate_hbefore on mips. Diff: --- VEX/priv/guest_mips_toIR.c | 62 +++++++++++++++++++++++++++++----------------- include/pub_tool_machine.h | 4 +-- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/VEX/priv/guest_mips_toIR.c b/VEX/priv/guest_mips_toIR.c index 87f53e3347..d915487af0 100644 --- a/VEX/priv/guest_mips_toIR.c +++ b/VEX/priv/guest_mips_toIR.c @@ -24799,23 +24799,33 @@ static DisResult disInstr_MIPS_WRK ( Long delta64, DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins); if (delta != 0) { - if (branch_or_jump(guest_code + delta - 4)) { - if (lastn == NULL && bstmt == NULL) { - vassert(0); - } else { - dres.whatNext = Dis_StopHere; - - if (lastn != NULL) { - delay_slot_jump = True; - } else if (bstmt != NULL) { - delay_slot_branch = True; - } - } + if (branch_or_jump(guest_code + delta - 4) + && (lastn != NULL || bstmt != NULL)) { + dres.whatNext = Dis_StopHere; + delay_slot_jump = (lastn != NULL); + delay_slot_branch = (bstmt != NULL); } - if (branch_or_link_likely(guest_code + delta - 4)) { - likely_delay_slot = True; - } + likely_delay_slot = (lastn != NULL) + && branch_or_link_likely(guest_code + delta - 4); + } + + // Emit an Illegal instruction in case a branch/jump + // instruction is encountered in the delay slot + // of an another branch/jump + if ((delay_slot_branch || likely_delay_slot || delay_slot_jump) && + (branch_or_jump(guest_code + delta) || + branch_or_link_likely(guest_code + delta))) { + if (mode64) + putPC(mkU64(guest_PC_curr_instr + 4)); + else + putPC(mkU32(guest_PC_curr_instr + 4)); + + dres.jk_StopHere = Ijk_SigILL; + dres.whatNext = Dis_StopHere; + lastn = NULL; + bstmt = NULL; + return dres; } /* Spot "Special" instructions (see comment at top of file). */ @@ -25028,14 +25038,23 @@ decode_failure: decode_success: + dres.len = 4; + DIP("\n"); + /* All decode successes end up here. */ switch (dres.whatNext) { case Dis_Continue: - if (mode64) - putPC(mkU64(guest_PC_curr_instr + 4)); - else - putPC(mkU32(guest_PC_curr_instr + 4)); - + if (branch_or_jump(guest_code + delta) || + branch_or_link_likely(guest_code + delta)) { + guest_PC_curr_instr += 4; + dres = disInstr_MIPS_WRK(delta64 + 4, archinfo, abiinfo, sigill_diag); + dres.len = 8; + } else { + if (mode64) + putPC(mkU64(guest_PC_curr_instr + 4)); + else + putPC(mkU32(guest_PC_curr_instr + 4)); + } break; case Dis_StopHere: @@ -25058,9 +25077,6 @@ decode_success: else putPC(mkU32(guest_PC_curr_instr + 4)); } - dres.len = 4; - - DIP("\n"); return dres; diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h index 4779eea015..25e125653b 100644 --- a/include/pub_tool_machine.h +++ b/include/pub_tool_machine.h @@ -92,13 +92,13 @@ #elif defined(VGP_mips32_linux) # define VG_MIN_INSTR_SZB 4 -# define VG_MAX_INSTR_SZB 4 +# define VG_MAX_INSTR_SZB 8 # define VG_CLREQ_SZB 20 # define VG_STACK_REDZONE_SZB 0 #elif defined(VGP_mips64_linux) # define VG_MIN_INSTR_SZB 4 -# define VG_MAX_INSTR_SZB 4 +# define VG_MAX_INSTR_SZB 8 # define VG_CLREQ_SZB 20 # define VG_STACK_REDZONE_SZB 0 |
|
From: Julian S. <se...@so...> - 2020-04-17 17:26:03
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=40187fcd61ee877f78701c46a74ac1dadbe65b3d commit 40187fcd61ee877f78701c46a74ac1dadbe65b3d Author: Julian Seward <js...@ac...> Date: Fri Apr 17 19:23:26 2020 +0200 Remove the exp-sgcheck tool. It only ever worked on x86 and amd64, and even on those it had a high false positive rate and was slow. Everything it does, ASan can do faster, better, and on more architectures. So there's no reason to keep this tool any more. Diff: --- Makefile.am | 2 - configure.ac | 5 - docs/xml/FAQ.xml | 4 - docs/xml/manual-core.xml | 4 +- docs/xml/manual.xml | 2 - docs/xml/valgrind-manpage.xml | 9 - exp-sgcheck.supp | 20 - exp-sgcheck/Makefile.am | 109 - exp-sgcheck/docs/sg-manual.xml | 327 - exp-sgcheck/h_intercepts.c | 440 -- exp-sgcheck/h_main.c | 722 --- exp-sgcheck/h_main.h | 80 - exp-sgcheck/pc_common.c | 814 --- exp-sgcheck/pc_common.h | 76 - exp-sgcheck/pc_main.c | 158 - exp-sgcheck/sg_main.c | 2569 -------- exp-sgcheck/sg_main.h | 76 - exp-sgcheck/tests/Makefile.am | 69 - exp-sgcheck/tests/bad_percentify.c | 647 -- .../tests/bad_percentify.stderr.exp-glibc28-amd64 | 30 - exp-sgcheck/tests/bad_percentify.stdout.exp | 3 - exp-sgcheck/tests/bad_percentify.vgtest | 2 - exp-sgcheck/tests/filter_add | 8 - exp-sgcheck/tests/filter_stderr | 38 - exp-sgcheck/tests/filter_suppgen | 11 - exp-sgcheck/tests/globalerr.c | 15 - .../tests/globalerr.stderr.exp-gcc491-amd64 | 17 - .../tests/globalerr.stderr.exp-glibc28-amd64 | 17 - exp-sgcheck/tests/globalerr.stdout.exp | 0 exp-sgcheck/tests/globalerr.vgtest | 2 - exp-sgcheck/tests/hackedbz2.c | 6537 -------------------- .../tests/hackedbz2.stderr.exp-glibc28-amd64 | 17 - exp-sgcheck/tests/hackedbz2.stdout.exp | 70 - exp-sgcheck/tests/hackedbz2.vgtest | 2 - exp-sgcheck/tests/hsg.c | 48 - exp-sgcheck/tests/hsg.stderr.exp | 116 - exp-sgcheck/tests/hsg.stdout.exp | 1 - exp-sgcheck/tests/hsg.vgtest | 4 - exp-sgcheck/tests/is_arch_supported | 15 - exp-sgcheck/tests/preen_invars.c | 52 - .../tests/preen_invars.stderr.exp-glibc28-amd64 | 9 - exp-sgcheck/tests/preen_invars.stdout.exp | 1 - exp-sgcheck/tests/preen_invars.vgtest | 2 - exp-sgcheck/tests/preen_invars_so.c | 12 - exp-sgcheck/tests/stackerr.c | 53 - exp-sgcheck/tests/stackerr.stderr.exp-glibc27-x86 | 28 - .../tests/stackerr.stderr.exp-glibc28-amd64 | 28 - exp-sgcheck/tests/stackerr.stdout.exp | 0 exp-sgcheck/tests/stackerr.vgtest | 3 - helgrind/tests/annotate_hbefore.c | 3 +- solaris/valgrind.p5m | 4 - tests/check_headers_and_includes | 1 - 52 files changed, 3 insertions(+), 13279 deletions(-) diff --git a/Makefile.am b/Makefile.am index 242b38a142..08db834019 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,6 @@ TOOLS = \ none EXP_TOOLS = \ - exp-sgcheck \ exp-bbv # Put docs last because building the HTML is slow and we want to get @@ -45,7 +44,6 @@ SUPP_FILES = \ glibc-2.34567-NPTL-helgrind.supp \ glibc-2.2-LinuxThreads-helgrind.supp \ glibc-2.X-drd.supp \ - exp-sgcheck.supp \ darwin9.supp darwin9-drd.supp \ darwin10.supp darwin10-drd.supp \ darwin11.supp darwin12.supp darwin13.supp darwin14.supp darwin15.supp \ diff --git a/configure.ac b/configure.ac index 3336329e9c..9e6ed71387 100755 --- a/configure.ac +++ b/configure.ac @@ -1166,9 +1166,6 @@ if test "$VGCONF_OS" != "solaris"; then # add the suppressions antidisirregardless. DEFAULT_SUPP="xfree-4.supp ${DEFAULT_SUPP}" DEFAULT_SUPP="xfree-3.supp ${DEFAULT_SUPP}" - - # Add glibc and X11 suppressions for exp-sgcheck - DEFAULT_SUPP="exp-sgcheck.supp ${DEFAULT_SUPP}" fi @@ -4853,8 +4850,6 @@ AC_CONFIG_FILES([ none/tests/x86-darwin/Makefile none/tests/amd64-solaris/Makefile none/tests/x86-solaris/Makefile - exp-sgcheck/Makefile - exp-sgcheck/tests/Makefile exp-bbv/Makefile exp-bbv/tests/Makefile exp-bbv/tests/x86/Makefile diff --git a/docs/xml/FAQ.xml b/docs/xml/FAQ.xml index d0d917edce..b124606282 100644 --- a/docs/xml/FAQ.xml +++ b/docs/xml/FAQ.xml @@ -483,10 +483,6 @@ int main(void) <para>Unfortunately, Memcheck doesn't do bounds checking on global or stack arrays. We'd like to, but it's just not possible to do in a reasonable way that fits with how Memcheck works. Sorry.</para> - - <para>However, the experimental tool SGcheck can detect errors like - this. Run Valgrind with the <option>--tool=exp-sgcheck</option> option - to try it, but be aware that it is not as robust as Memcheck.</para> </answer> </qandaentry> diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml index 8d24616a0e..72730ec7bb 100644 --- a/docs/xml/manual-core.xml +++ b/docs/xml/manual-core.xml @@ -613,7 +613,7 @@ in most cases. We group the available options by rough categories.</para> <listitem> <para>Run the Valgrind tool called <varname>toolname</varname>, e.g. memcheck, cachegrind, callgrind, helgrind, drd, massif, - dhat, lackey, none, exp-sgcheck, exp-bbv, etc.</para> + dhat, lackey, none, exp-bbv, etc.</para> </listitem> </varlistentry> @@ -2562,7 +2562,7 @@ need to use them.</para> malloc related functions, using the synonym <varname>somalloc</varname>. This synonym is usable for all tools doing standard replacement of malloc related functions - (e.g. memcheck, helgrind, drd, massif, dhat, exp-sgcheck). + (e.g. memcheck, helgrind, drd, massif, dhat). </para> <itemizedlist> diff --git a/docs/xml/manual.xml b/docs/xml/manual.xml index b90514935a..da37102d00 100644 --- a/docs/xml/manual.xml +++ b/docs/xml/manual.xml @@ -42,8 +42,6 @@ xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="../../none/docs/nl-manual.xml" parse="xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> - <xi:include href="../../exp-sgcheck/docs/sg-manual.xml" parse="xml" - xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="../../exp-bbv/docs/bbv-manual.xml" parse="xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> diff --git a/docs/xml/valgrind-manpage.xml b/docs/xml/valgrind-manpage.xml index 7498c614c4..332ca4884c 100644 --- a/docs/xml/valgrind-manpage.xml +++ b/docs/xml/valgrind-manpage.xml @@ -202,15 +202,6 @@ system: <filename>&vg-docs-path;</filename>, or online: -<refsect1 id="sgcheck-options"> -<title>SGcheck Options</title> - -<xi:include href="../../exp-sgcheck/docs/sg-manual.xml" - xpointer="sg.opts.list" - xmlns:xi="http://www.w3.org/2001/XInclude" /> - -</refsect1> - <refsect1 id="bbv-options"> <title>BBV Options</title> diff --git a/exp-sgcheck.supp b/exp-sgcheck.supp deleted file mode 100644 index b2d4aebfd9..0000000000 --- a/exp-sgcheck.supp +++ /dev/null @@ -1,20 +0,0 @@ -{ - ld-2.X possibly applying relocations - exp-sgcheck:SorG - obj:*/*lib*/ld-2.*so* - obj:*/*lib*/ld-2.*so* -} - -# I'm pretty sure this is a false positive caused by the sg_ stuff -{ - glibc realpath false positive - exp-sgcheck:SorG - fun:realpath - fun:* -} - -{ - I think this is glibc's ultra optimised getenv doing 2 byte reads - exp-sgcheck:SorG - fun:getenv -} diff --git a/exp-sgcheck/Makefile.am b/exp-sgcheck/Makefile.am deleted file mode 100644 index 8927ff630b..0000000000 --- a/exp-sgcheck/Makefile.am +++ /dev/null @@ -1,109 +0,0 @@ -include $(top_srcdir)/Makefile.tool.am - -EXTRA_DIST = docs/sg-manual.xml - -#---------------------------------------------------------------------------- -# Headers, etc -#---------------------------------------------------------------------------- - -noinst_HEADERS = \ - h_main.h \ - pc_common.h \ - sg_main.h - -#---------------------------------------------------------------------------- -# exp-sgcheck-<platform> -#---------------------------------------------------------------------------- - -noinst_PROGRAMS = exp-sgcheck-@VGCONF_ARCH_PRI@-@VGCONF_OS@ -if VGCONF_HAVE_PLATFORM_SEC -noinst_PROGRAMS += exp-sgcheck-@VGCONF_ARCH_SEC@-@VGCONF_OS@ -endif - -EXP_PTRCHECK_SOURCES_COMMON = \ - h_main.c \ - pc_common.c \ - pc_main.c \ - sg_main.c - -exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES = \ - $(EXP_PTRCHECK_SOURCES_COMMON) -exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS = \ - $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) -exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS = $(LTO_CFLAGS) \ - $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) -exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_DEPENDENCIES = \ - $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_PRI_CAPS@) -exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDADD = \ - $(TOOL_LDADD_@VGCONF_PLATFORM_PRI_CAPS@) -exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS = \ - $(TOOL_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) -exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LINK = \ - $(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \ - @VALT_LOAD_ADDRESS_PRI@ \ - $(LINK) \ - $(exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS) \ - $(exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS) - -if VGCONF_HAVE_PLATFORM_SEC -exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_SOURCES = \ - $(EXP_PTRCHECK_SOURCES_COMMON) -exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CPPFLAGS = \ - $(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) -exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS = $(LTO_CFLAGS) \ - $(AM_CFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) -exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_DEPENDENCIES = \ - $(TOOL_DEPENDENCIES_@VGCONF_PLATFORM_SEC_CAPS@) -exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDADD = \ - $(TOOL_LDADD_@VGCONF_PLATFORM_SEC_CAPS@) -exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS = \ - $(TOOL_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) -exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LINK = \ - $(top_builddir)/coregrind/link_tool_exe_@VGCONF_OS@ \ - @VALT_LOAD_ADDRESS_SEC@ \ - $(LINK) \ - $(exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_CFLAGS) \ - $(exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_LDFLAGS) -endif - -#---------------------------------------------------------------------------- -# vgpreload_exp-sgcheck-<platform>.so -#---------------------------------------------------------------------------- - -noinst_PROGRAMS += vgpreload_exp-sgcheck-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so -if VGCONF_HAVE_PLATFORM_SEC -noinst_PROGRAMS += vgpreload_exp-sgcheck-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so -endif - -if VGCONF_OS_IS_DARWIN -noinst_DSYMS = $(noinst_PROGRAMS) -endif - -VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON = h_intercepts.c - -vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_SOURCES = \ - $(VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON) -vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CPPFLAGS = \ - $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) -vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_CFLAGS = \ - $(AM_CFLAGS_PSO_@VGCONF_PLATFORM_PRI_CAPS@) -O2 -vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_DEPENDENCIES = \ - $(LIBREPLACEMALLOC_@VGCONF_PLATFORM_PRI_CAPS@) -vgpreload_exp_sgcheck_@VGCONF_ARCH_PRI@_@VGCONF_OS@_so_LDFLAGS = \ - $(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) \ - $(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) - -if VGCONF_HAVE_PLATFORM_SEC -vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_SOURCES = \ - $(VGPRELOAD_EXP_PTRCHECK_SOURCES_COMMON) -vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CPPFLAGS = \ - $(AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) -vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_CFLAGS = \ - $(AM_CFLAGS_PSO_@VGCONF_PLATFORM_SEC_CAPS@) -O2 -vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_DEPENDENCIES = \ - $(LIBREPLACEMALLOC_@VGCONF_PLATFORM_SEC_CAPS@) -vgpreload_exp_sgcheck_@VGCONF_ARCH_SEC@_@VGCONF_OS@_so_LDFLAGS = \ - $(PRELOAD_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) \ - $(LIBREPLACEMALLOC_LDFLAGS_@VGCONF_PLATFORM_SEC_CAPS@) -endif - diff --git a/exp-sgcheck/docs/sg-manual.xml b/exp-sgcheck/docs/sg-manual.xml deleted file mode 100644 index c03e77811d..0000000000 --- a/exp-sgcheck/docs/sg-manual.xml +++ /dev/null @@ -1,327 +0,0 @@ -<?xml version="1.0"?> <!-- -*- sgml -*- --> -<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" -[ <!ENTITY % vg-entities SYSTEM "../../docs/xml/vg-entities.xml"> %vg-entities; ]> - - -<chapter id="sg-manual" - xreflabel="SGCheck: an experimental stack and global array overrun detector"> - <title>SGCheck: an experimental stack and global array overrun detector</title> - -<para>To use this tool, you must specify -<option>--tool=exp-sgcheck</option> on the Valgrind -command line.</para> - - - - -<sect1 id="sg-manual.overview" xreflabel="Overview"> -<title>Overview</title> - -<para>SGCheck is a tool for finding overruns of stack and global -arrays. It works by using a heuristic approach derived from an -observation about the likely forms of stack and global array accesses. -</para> - -</sect1> - - - - -<sect1 id="sg-manual.options" xreflabel="SGCheck Command-line Options"> -<title>SGCheck Command-line Options</title> - -<para id="sg.opts.list">There are no SGCheck-specific command-line options at present.</para> -<!-- -<para>SGCheck-specific command-line options are:</para> - - -<variablelist id="sg.opts.list"> -</variablelist> ---> - -</sect1> - - - -<sect1 id="sg-manual.how-works.sg-checks" - xreflabel="How SGCheck Works"> -<title>How SGCheck Works</title> - -<para>When a source file is compiled -with <option>-g</option>, the compiler attaches DWARF3 -debugging information which describes the location of all stack and -global arrays in the file.</para> - -<para>Checking of accesses to such arrays would then be relatively -simple, if the compiler could also tell us which array (if any) each -memory referencing instruction was supposed to access. Unfortunately -the DWARF3 debugging format does not provide a way to represent such -information, so we have to resort to a heuristic technique to -approximate it. The key observation is that - <emphasis> - if a memory referencing instruction accesses inside a stack or - global array once, then it is highly likely to always access that - same array</emphasis>.</para> - -<para>To see how this might be useful, consider the following buggy -fragment:</para> -<programlisting><![CDATA[ - { int i, a[10]; // both are auto vars - for (i = 0; i <= 10; i++) - a[i] = 42; - } -]]></programlisting> - -<para>At run time we will know the precise address -of <computeroutput>a[]</computeroutput> on the stack, and so we can -observe that the first store resulting from <computeroutput>a[i] = -42</computeroutput> writes <computeroutput>a[]</computeroutput>, and -we will (correctly) assume that that instruction is intended always to -access <computeroutput>a[]</computeroutput>. Then, on the 11th -iteration, it accesses somewhere else, possibly a different local, -possibly an un-accounted for area of the stack (eg, spill slot), so -SGCheck reports an error.</para> - -<para>There is an important caveat.</para> - -<para>Imagine a function such as <function>memcpy</function>, which is used -to read and write many different areas of memory over the lifetime of the -program. If we insist that the read and write instructions in its memory -copying loop only ever access one particular stack or global variable, we -will be flooded with errors resulting from calls to -<function>memcpy</function>.</para> - -<para>To avoid this problem, SGCheck instantiates fresh likely-target -records for each entry to a function, and discards them on exit. This -allows detection of cases where (e.g.) <function>memcpy</function> -overflows its source or destination buffers for any specific call, but -does not carry any restriction from one call to the next. Indeed, -multiple threads may make multiple simultaneous calls to -(e.g.) <function>memcpy</function> without mutual interference.</para> - -<para>It is important to note that the association is done between - a <emphasis>binary instruction</emphasis> and an array, the - <emphasis>first time</emphasis> this binary instruction accesses an - array during a function call. When the same instruction is executed - again during the same function call, then SGCheck might report a - problem, if these further executions are not accessing the same - array. This technique causes several limitations in SGCheck, see - <xref linkend="sg-manual.limitations"/>. -</para> -</sect1> - - - -<sect1 id="sg-manual.cmp-w-memcheck" - xreflabel="Comparison with Memcheck"> -<title>Comparison with Memcheck</title> - -<para>SGCheck and Memcheck are complementary: their capabilities do -not overlap. Memcheck performs bounds checks and use-after-free -checks for heap arrays. It also finds uses of uninitialised values -created by heap or stack allocations. But it does not perform bounds -checking for stack or global arrays.</para> - -<para>SGCheck, on the other hand, does do bounds checking for stack or -global arrays, but it doesn't do anything else.</para> - -</sect1> - - - - - -<sect1 id="sg-manual.limitations" - xreflabel="Limitations"> -<title>Limitations</title> - -<para>This is an experimental tool, which relies rather too heavily on some -not-as-robust-as-I-would-like assumptions on the behaviour of correct -programs. There are a number of limitations which you should be aware -of.</para> - -<itemizedlist> - - <listitem> - <para>False negatives (missed errors): it follows from the - description above (<xref linkend="sg-manual.how-works.sg-checks"/>) - that the first access by a memory referencing instruction to a - stack or global array creates an association between that - instruction and the array, which is checked on subsequent accesses - by that instruction, until the containing function exits. Hence, - the first access by an instruction to an array (in any given - function instantiation) is not checked for overrun, since SGCheck - uses that as the "example" of how subsequent accesses should - behave.</para> - <para>It also means that errors will not be found in an instruction - executed only once (e.g. because this instruction is not in a loop, - or the loop is executed only once).</para> - </listitem> - - <listitem> - <para>False positives (false errors): similarly, and more serious, - it is clearly possible to write legitimate pieces of code which - break the basic assumption upon which the checking algorithm - depends. For example:</para> - -<programlisting><![CDATA[ - { int a[10], b[10], *p, i; - for (i = 0; i < 10; i++) { - p = /* arbitrary condition */ ? &a[i] : &b[i]; - *p = 42; - } - } -]]></programlisting> - - <para>In this case the store sometimes - accesses <computeroutput>a[]</computeroutput> and - sometimes <computeroutput>b[]</computeroutput>, but in no cases is - the addressed array overrun. Nevertheless the change in target - will cause an error to be reported.</para> - - <para>It is hard to see how to get around this problem. The only - mitigating factor is that such constructions appear very rare, at - least judging from the results using the tool so far. Such a - construction appears only once in the Valgrind sources (running - Valgrind on Valgrind) and perhaps two or three times for a start - and exit of Firefox. The best that can be done is to suppress the - errors.</para> - </listitem> - - <listitem> - <para>Performance: SGCheck has to read all of - the DWARF3 type and variable information on the executable and its - shared objects. This is computationally expensive and makes - startup quite slow. You can expect debuginfo reading time to be in - the region of a minute for an OpenOffice sized application, on a - 2.4 GHz Core 2 machine. Reading this information also requires a - lot of memory. To make it viable, SGCheck goes to considerable - trouble to compress the in-memory representation of the DWARF3 - data, which is why the process of reading it appears slow.</para> - </listitem> - - <listitem> - <para>Performance: SGCheck runs slower than Memcheck. This is - partly due to a lack of tuning, but partly due to algorithmic - difficulties. The - stack and global checks can sometimes require a number of range - checks per memory access, and these are difficult to short-circuit, - despite considerable efforts having been made. A - redesign and reimplementation could potentially make it much faster. - </para> - </listitem> - - <listitem> - <para>Coverage: Stack and global checking is fragile. If a shared - object does not have debug information attached, then SGCheck will - not be able to determine the bounds of any stack or global arrays - defined within that shared object, and so will not be able to check - accesses to them. This is true even when those arrays are accessed - from some other shared object which was compiled with debug - info.</para> - - <para>At the moment SGCheck accepts objects lacking debuginfo - without comment. This is dangerous as it causes SGCheck to - silently skip stack and global checking for such objects. It would - be better to print a warning in such circumstances.</para> - </listitem> - - <listitem> - <para>Coverage: SGCheck does not check whether the areas read - or written by system calls do overrun stack or global arrays. This - would be easy to add.</para> - </listitem> - - <listitem> - <para>Platforms: the stack/global checks won't work properly on - PowerPC, ARM or S390X platforms, only on X86 and AMD64 targets. - That's because the stack and global checking requires tracking - function calls and exits reliably, and there's no obvious way to do - it on ABIs that use a link register for function returns. - </para> - </listitem> - - <listitem> - <para>Robustness: related to the previous point. Function - call/exit tracking for X86 and AMD64 is believed to work properly - even in the presence of longjmps within the same stack (although - this has not been tested). However, code which switches stacks is - likely to cause breakage/chaos.</para> - </listitem> -</itemizedlist> - -</sect1> - - - - - -<sect1 id="sg-manual.todo-user-visible" - xreflabel="Still To Do: User-visible Functionality"> -<title>Still To Do: User-visible Functionality</title> - -<itemizedlist> - - <listitem> - <para>Extend system call checking to work on stack and global arrays.</para> - </listitem> - - <listitem> - <para>Print a warning if a shared object does not have debug info - attached, or if, for whatever reason, debug info could not be - found, or read.</para> - </listitem> - - <listitem> - <para>Add some heuristic filtering that removes obvious false - positives. This would be easy to do. For example, an access - transition from a heap to a stack object almost certainly isn't a - bug and so should not be reported to the user.</para> - </listitem> - -</itemizedlist> - -</sect1> - - - - -<sect1 id="sg-manual.todo-implementation" - xreflabel="Still To Do: Implementation Tidying"> -<title>Still To Do: Implementation Tidying</title> - -<para>Items marked CRITICAL are considered important for correctness: -non-fixage of them is liable to lead to crashes or assertion failures -in real use.</para> - -<itemizedlist> - - <listitem> - <para> sg_main.c: Redesign and reimplement the basic checking - algorithm. It could be done much faster than it is -- the current - implementation isn't very good. - </para> - </listitem> - - <listitem> - <para> sg_main.c: Improve the performance of the stack / global - checks by doing some up-front filtering to ignore references in - areas which "obviously" can't be stack or globals. This will - require using information that m_aspacemgr knows about the address - space layout.</para> - </listitem> - - <listitem> - <para>sg_main.c: fix compute_II_hash to make it a bit more sensible - for ppc32/64 targets (except that sg_ doesn't work on ppc32/64 - targets, so this is a bit academic at the moment).</para> - </listitem> - -</itemizedlist> - -</sect1> - - - -</chapter> diff --git a/exp-sgcheck/h_intercepts.c b/exp-sgcheck/h_intercepts.c deleted file mode 100644 index 6fe8680317..0000000000 --- a/exp-sgcheck/h_intercepts.c +++ /dev/null @@ -1,440 +0,0 @@ - -/*--------------------------------------------------------------------*/ -/*--- Ptrcheck: a pointer-use checker. pc_intercepts.c ---*/ -/*--------------------------------------------------------------------*/ - -/* - This file is part of Ptrcheck, a Valgrind tool for checking pointer - use in programs. - - Copyright (C) 2003-2017 Nicholas Nethercote - nj...@va... - - 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 the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - The GNU General Public License is contained in the file COPYING. -*/ - -/* Nothing actually in here. However it appears this file is needed - to make malloc intercepting work. (jrs, 2 july 08 -- not sure about - that). -*/ - -#include "pub_tool_basics.h" -#include "pub_tool_hashtable.h" -#include "pub_tool_redir.h" -#include "pub_tool_tooliface.h" -#include "pub_tool_clreq.h" - - -/* The following intercepts are copied verbatim from - memcheck/mc_replace_strmem.c. If you copy more in, please keep - them in the same order as in mc_replace_strmem.c. */ - - -#define STRRCHR(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* s, int c ) \ - { \ - HChar ch = (HChar)c; \ - const HChar* p = s; \ - const HChar* last = NULL; \ - while (True) { \ - if (*p == ch) last = p; \ - if (*p == 0) return CONST_CAST(HChar *,last); \ - p++; \ - } \ - } - -// Apparently rindex() is the same thing as strrchr() -STRRCHR(VG_Z_LIBC_SONAME, strrchr) -STRRCHR(VG_Z_LIBC_SONAME, rindex) -#if defined(VGO_linux) -STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr) -STRRCHR(VG_Z_LD_LINUX_SO_2, rindex) -#elif defined(VGO_darwin) -STRRCHR(VG_Z_DYLD, strrchr) -STRRCHR(VG_Z_DYLD, rindex) -#elif defined(VGO_solaris) -STRRCHR(VG_Z_LD_SO_1, strrchr) -#endif - - -#define STRCHR(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \ - { \ - HChar ch = (HChar)c ; \ - const HChar* p = s; \ - while (True) { \ - if (*p == ch) return CONST_CAST(HChar *,p); \ - if (*p == 0) return NULL; \ - p++; \ - } \ - } - -// Apparently index() is the same thing as strchr() -STRCHR(VG_Z_LIBC_SONAME, strchr) -STRCHR(VG_Z_LIBC_SONAME, index) -#if defined(VGO_linux) -STRCHR(VG_Z_LIBC_SONAME, __GI_strchr) -STRCHR(VG_Z_LD_LINUX_SO_2, strchr) -STRCHR(VG_Z_LD_LINUX_SO_2, index) -STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr) -STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index) -#elif defined(VGO_darwin) -STRCHR(VG_Z_DYLD, strchr) -STRCHR(VG_Z_DYLD, index) -#elif defined(VGO_solaris) -STRCHR(VG_Z_LD_SO_1, strchr) -#endif - - -#define STRNLEN(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT n ) \ - { \ - SizeT i = 0; \ - while (i < n && str[i] != 0) i++; \ - return i; \ - } - -STRNLEN(VG_Z_LIBC_SONAME, strnlen) - - -// Note that this replacement often doesn't get used because gcc inlines -// calls to strlen() with its own built-in version. This can be very -// confusing if you aren't expecting it. Other small functions in this file -// may also be inline by gcc. -#define STRLEN(soname, fnname) \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \ - SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \ - { \ - SizeT i = 0; \ - while (str[i] != 0) i++; \ - return i; \ - } - -STRLEN(VG_Z_LIBC_SONAME, strlen) -#if defined(VGO_linux) -STRLEN(VG_Z_LIBC_SONAME, __GI_strlen) -STRLEN(VG_Z_LD_LINUX_SO_2, strlen) -STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen) -STRLEN(VG_Z_LD_SO_1, strlen) -#elif defined(VGO_solaris) -STRLEN(VG_Z_LD_SO_1, strlen) -#endif - - -#define STRCPY(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \ - char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \ - { \ - HChar* dst_orig = dst; \ - \ - while (*src) *dst++ = *src++; \ - *dst = 0; \ - \ - return dst_orig; \ - } - -STRCPY(VG_Z_LIBC_SONAME, strcpy) -#if defined(VGO_linux) -STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy) -#elif defined(VGO_darwin) -STRCPY(VG_Z_DYLD, strcpy) -#elif defined(VGO_solaris) -STRCPY(VG_Z_LD_SO_1, strcpy) -#endif - - -#define STRNCMP(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - ( const char* s1, const char* s2, SizeT nmax ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - ( const char* s1, const char* s2, SizeT nmax ) \ - { \ - SizeT n = 0; \ - while (True) { \ - if (n >= nmax) return 0; \ - if (*s1 == 0 && *s2 == 0) return 0; \ - if (*s1 == 0) return -1; \ - if (*s2 == 0) return 1; \ - \ - if (*(const unsigned char*)s1 < *(const unsigned char*)s2) return -1; \ - if (*(const unsigned char*)s1 > *(const unsigned char*)s2) return 1; \ - \ - s1++; s2++; n++; \ - } \ - } - -STRNCMP(VG_Z_LIBC_SONAME, strncmp) -#if defined(VGO_linux) -STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp) -#elif defined(VGO_darwin) -STRNCMP(VG_Z_DYLD, strncmp) -#endif - - -#define STRCMP(soname, fnname) \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - ( const char* s1, const char* s2 ); \ - int VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - ( const char* s1, const char* s2 ) \ - { \ - register UChar c1; \ - register UChar c2; \ - while (True) { \ - c1 = *(const UChar *)s1; \ - c2 = *(const UChar *)s2; \ - if (c1 != c2) break; \ - if (c1 == 0) break; \ - s1++; s2++; \ - } \ - if ((UChar)c1 < (UChar)c2) return -1; \ - if ((UChar)c1 > (UChar)c2) return 1; \ - return 0; \ - } - -STRCMP(VG_Z_LIBC_SONAME, strcmp) -#if defined(VGO_linux) -STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp) -STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp) -STRCMP(VG_Z_LD64_SO_1, strcmp) -#elif defined(VGO_solaris) -STRCMP(VG_Z_LD_SO_1, strcmp) -#endif - - -#define MEMCHR(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \ - { \ - SizeT i; \ - UChar c0 = (UChar)c; \ - const UChar* p = s; \ - for (i = 0; i < n; i++) \ - if (p[i] == c0) return CONST_CAST(void *,&p[i]); \ - return NULL; \ - } - -MEMCHR(VG_Z_LIBC_SONAME, memchr) -#if defined(VGO_darwin) -MEMCHR(VG_Z_DYLD, memchr) -#endif - - -#define MEMCPY(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - ( void *dst, const void *src, SizeT len ); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - ( void *dst, const void *src, SizeT len ) \ - { \ - const Addr WS = sizeof(UWord); /* 8 or 4 */ \ - const Addr WM = WS - 1; /* 7 or 3 */ \ - \ - if (len > 0) { \ - if (dst < src) { \ - \ - /* Copying backwards. */ \ - SizeT n = len; \ - Addr d = (Addr)dst; \ - Addr s = (Addr)src; \ - \ - if (((s^d) & WM) == 0) { \ - /* s and d have same UWord alignment. */ \ - /* Pull up to a UWord boundary. */ \ - while ((s & WM) != 0 && n >= 1) \ - { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ - /* Copy UWords. */ \ - while (n >= WS) \ - { *(UWord*)d = *(UWord*)s; s += WS; d += WS; n -= WS; } \ - if (n == 0) \ - return dst; \ - } \ - if (((s|d) & 1) == 0) { \ - /* Both are 16-aligned; copy what we can thusly. */ \ - while (n >= 2) \ - { *(UShort*)d = *(UShort*)s; s += 2; d += 2; n -= 2; } \ - } \ - /* Copy leftovers, or everything if misaligned. */ \ - while (n >= 1) \ - { *(UChar*)d = *(UChar*)s; s += 1; d += 1; n -= 1; } \ - \ - } else if (dst > src) { \ - \ - SizeT n = len; \ - Addr d = ((Addr)dst) + n; \ - Addr s = ((Addr)src) + n; \ - \ - /* Copying forwards. */ \ - if (((s^d) & WM) == 0) { \ - /* s and d have same UWord alignment. */ \ - /* Back down to a UWord boundary. */ \ - while ((s & WM) != 0 && n >= 1) \ - { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ - /* Copy UWords. */ \ - while (n >= WS) \ - { s -= WS; d -= WS; *(UWord*)d = *(UWord*)s; n -= WS; } \ - if (n == 0) \ - return dst; \ - } \ - if (((s|d) & 1) == 0) { \ - /* Both are 16-aligned; copy what we can thusly. */ \ - while (n >= 2) \ - { s -= 2; d -= 2; *(UShort*)d = *(UShort*)s; n -= 2; } \ - } \ - /* Copy leftovers, or everything if misaligned. */ \ - while (n >= 1) \ - { s -= 1; d -= 1; *(UChar*)d = *(UChar*)s; n -= 1; } \ - \ - } \ - } \ - \ - return dst; \ - } - -MEMCPY(VG_Z_LIBC_SONAME, memcpy) -#if defined(VGO_linux) -MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */ -MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */ -#elif defined(VGO_solaris) -MEMCPY(VG_Z_LD_SO_1, memcpy) -#endif - - -/* Copy SRC to DEST, returning the address of the terminating '\0' in - DEST. (minor variant of strcpy) */ -#define STPCPY(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( char* dst, const char* src ) \ - { \ - while (*src) *dst++ = *src++; \ - *dst = 0; \ - \ - return dst; \ - } - -STPCPY(VG_Z_LIBC_SONAME, stpcpy) -#if defined(VGO_linux) -STPCPY(VG_Z_LD_LINUX_SO_2, stpcpy) -STPCPY(VG_Z_LD_LINUX_X86_64_SO_2, stpcpy) -#endif - - -/* Find the first occurrence of C in S. */ -#define GLIBC232_RAWMEMCHR(soname, fnname) \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in); \ - void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void* s, int c_in) \ - { \ - UChar c = (UChar)c_in; \ - const UChar* char_ptr = s; \ - while (1) { \ - if (*char_ptr == c) return CONST_CAST(void *,char_ptr); \ - char_ptr++; \ - } \ - } - -GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, rawmemchr) -#if defined (VGO_linux) -GLIBC232_RAWMEMCHR(VG_Z_LIBC_SONAME, __GI___rawmemchr) -#endif - - -#define STRSTR(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (const char* haystack, const char* needle); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (const char* haystack, const char* needle) \ - { \ - const HChar* h = haystack; \ - const HChar* n = needle; \ - \ - /* find the length of n, not including terminating zero */ \ - UWord nlen = 0; \ - while (n[nlen]) nlen++; \ - \ - /* if n is the empty string, match immediately. */ \ - if (nlen == 0) return CONST_CAST(HChar *,h); \ - \ - /* assert(nlen >= 1); */ \ - HChar n0 = n[0]; \ - \ - while (1) { \ - const HChar hh = *h; \ - if (hh == 0) return NULL; \ - if (hh != n0) { h++; continue; } \ - \ - UWord i; \ - for (i = 0; i < nlen; i++) { \ - if (n[i] != h[i]) \ - break; \ - } \ - /* assert(i >= 0 && i <= nlen); */ \ - if (i == nlen) \ - return CONST_CAST(HChar *,h); \ - \ - h++; \ - } \ - } - -#if defined(VGO_linux) -STRSTR(VG_Z_LIBC_SONAME, strstr) -#elif defined(VGO_solaris) -STRSTR(VG_Z_LIBC_SONAME, strstr) -#endif - - -#define STRPBRK(soname, fnname) \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (const char* sV, const char* acceptV); \ - char* VG_REPLACE_FUNCTION_ZU(soname,fnname) \ - (const char* sV, const char* acceptV) \ - { \ - const HChar* s = sV; \ - const HChar* accept = acceptV; \ - \ - /* find the length of 'accept', not including terminating zero */ \ - UWord nacc = 0; \ - while (accept[nacc]) nacc++; \ - \ - /* if n is the empty string, fail immediately. */ \ - if (nacc == 0) return NULL; \ - \ - /* assert(nacc >= 1); */ \ - while (1) { \ - UWord i; \ - HChar sc = *s; \ - if (sc == 0) \ - break; \ - for (i = 0; i < nacc; i++) { \ - if (sc == accept[i]) \ - return CONST_CAST(HChar *,s); \ - } \ - s++; \ - } \ - \ - return NULL; \ - } - -#if defined(VGO_linux) -STRPBRK(VG_Z_LIBC_SONAME, strpbrk) -#elif defined(VGO_solaris) -STRPBRK(VG_Z_LIBC_SONAME, strpbrk) -#endif - - -/*--------------------------------------------------------------------*/ -/*--- end pc_intercepts.c ---*/ -/*--------------------------------------------------------------------*/ diff --git a/exp-sgcheck/h_main.c b/exp-sgcheck/h_main.c deleted file mode 100644 index 64cac3a323..0000000000 --- a/exp-sgcheck/h_main.c +++ /dev/null @@ -1,722 +0,0 @@ - -/*--------------------------------------------------------------------*/ -/*--- Ptrcheck: a pointer-use checker. ---*/ -/*--- This file checks heap accesses. ---*/ -/*--- h_main.c ---*/ -/*--------------------------------------------------------------------*/ - -/* - This file is part of Ptrcheck, a Valgrind tool for checking pointer - use in programs. - - Initial version (Annelid): - - Copyright (C) 2003-2017 Nicholas Nethercote - nj...@va... - - Valgrind-3.X port: - - Copyright (C) 2008-2017 OpenWorks Ltd - in...@op... - - 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 the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - The GNU General Public License is contained in the file COPYING. -*/ - -#include "pub_tool_basics.h" -#include "pub_tool_libcbase.h" -#include "pub_tool_libcprint.h" -#include "pub_tool_libcassert.h" -#include "pub_tool_mallocfree.h" -#include "pub_tool_execontext.h" -#include "pub_tool_hashtable.h" -#include "pub_tool_tooliface.h" -#include "pub_tool_replacemalloc.h" -#include "pub_tool_options.h" -#include "pub_tool_execontext.h" -#include "pub_tool_aspacemgr.h" // VG_(am_shadow_malloc) -#include "pub_tool_vki.h" // VKI_MAX_PAGE_SIZE -#include "pub_tool_machine.h" // VG_({get,set}_shadow_regs_area) et al -#include "pub_tool_debuginfo.h" // VG_(get_fnname) -#include "pub_tool_threadstate.h" // VG_(get_running_tid) -#include "pub_tool_oset.h" -#include "pub_tool_vkiscnums.h" -#include "pub_tool_machine.h" -#include "pub_tool_wordfm.h" -#include "pub_tool_xarray.h" - -#include "pc_common.h" - -//#include "h_list.h" -#include "h_main.h" - -#include "sg_main.h" // sg_instrument_*, and struct _SGEnv - - - -/*------------------------------------------------------------*/ -/*--- Debug/trace options ---*/ -/*------------------------------------------------------------*/ - -static ULong stats__client_mallocs = 0; -static ULong stats__client_frees = 0; -static ULong stats__segs_allocd = 0; -static ULong stats__segs_recycled = 0; - - -////////////////////////////////////////////////////////////// -// // -// Segments low level storage // -// // -////////////////////////////////////////////////////////////// - -// NONPTR, UNKNOWN, BOTTOM defined in h_main.h since -// pc_common.c needs to see them, for error processing - -// we only start recycling segs when this many exist -#define N_FREED_SEGS (1 * 1000 * 1000) - -struct _Seg { - Addr addr; - SizeT szB; /* may be zero */ - ExeContext* ec; /* where malloc'd or freed */ - /* When 1, indicates block is in use. Otherwise, used to form a - linked list of freed blocks, running from oldest freed block to - the most recently freed block. */ - struct _Seg* nextfree; -}; - -// Determines if 'a' is before, within, or after seg's range. Sets 'cmp' to -// -1/0/1 accordingly. Sets 'n' to the number of bytes before/within/after. -void Seg__cmp(Seg* seg, Addr a, Int* cmp, UWord* n) -{ - if (a < seg->addr) { - *cmp = -1; - *n = seg->addr - a; - } else if (a < seg->addr + seg->szB && seg->szB > 0) { - *cmp = 0; - *n = a - seg->addr; - } else { - *cmp = 1; - *n = a - (seg->addr + seg->szB); - } -} - -/*inline*/ Bool Seg__is_freed(Seg* seg) -{ - if (!is_known_segment(seg)) - return False; - else - return seg->nextfree != (Seg*)1; -} - -ExeContext* Seg__where(Seg* seg) -{ - tl_assert(is_known_segment(seg)); - return seg->ec; -} - -SizeT Seg__size(Seg* seg) -{ - tl_assert(is_known_segment(seg)); - return seg->szB; -} - -Addr Seg__addr(Seg* seg) -{ - tl_assert(is_known_segment(seg)); - return seg->addr; -} - - -#define N_SEGS_PER_GROUP 10000 - -typedef - struct _SegGroup { - struct _SegGroup* admin; - UWord nextfree; /* 0 .. N_SEGS_PER_GROUP */ - Seg segs[N_SEGS_PER_GROUP]; - } - SegGroup; - -static SegGroup* group_list = NULL; -static UWord nFreeSegs = 0; -static Seg* freesegs_youngest = NULL; -static Seg* freesegs_oldest = NULL; - - -static SegGroup* new_SegGroup ( void ) { - SegGroup* g = VG_(malloc)("pc.h_main.nTG.1", sizeof(SegGroup)); - VG_(memset)(g, 0, sizeof(*g)); - return g; -} - -/* Get a completely new Seg */ -static Seg* new_Seg ( void ) -{ - Seg* teg; - SegGroup* g; - if (group_list == NULL) { - g = new_SegGroup(); - g->admin = NULL; - group_list = g; - } - tl_assert(group_list->nextfree <= N_SEGS_PER_GROUP); - if (group_list->nextfree == N_SEGS_PER_GROUP) { - g = new_SegGroup(); - g->admin = group_list; - group_list = g; - } - tl_assert(group_list->nextfree < N_SEGS_PER_GROUP); - teg = &group_list->segs[ group_list->nextfree ]; - group_list->nextfree++; - stats__segs_allocd++; - return teg; -} - -static Seg* get_Seg_for_malloc ( void ) -{ - Seg* seg; - if (nFreeSegs < N_FREED_SEGS) { - seg = new_Seg(); - seg->nextfree = (Seg*)1; - return seg; - } - /* else recycle the oldest Seg in the free list */ - tl_assert(freesegs_youngest); - tl_assert(freesegs_oldest); - tl_assert(freesegs_youngest != freesegs_oldest); - seg = freesegs_oldest; - freesegs_oldest = seg->nextfree; - nFreeSegs--; - seg->nextfree = (Seg*)1; - stats__segs_recycled++; - return seg; -} - -static void set_Seg_freed ( Seg* seg ) -{ - tl_assert(seg); - tl_assert(!Seg__is_freed(seg)); - if (nFreeSegs == 0) { - tl_assert(freesegs_oldest == NULL); - tl_assert(freesegs_youngest == NULL); - seg->nextfree = NULL; - freesegs_youngest = seg; - freesegs_oldest = seg; - nFreeSegs++; - } else { - tl_assert(freesegs_youngest); - tl_assert(freesegs_oldest); - if (nFreeSegs == 1) { - tl_assert(freesegs_youngest == freesegs_oldest); - } else { - tl_assert(freesegs_youngest != freesegs_oldest); - } - tl_assert(freesegs_youngest->nextfree == NULL); - tl_assert(seg != freesegs_youngest && seg != freesegs_oldest); - seg->nextfree = NULL; - freesegs_youngest->nextfree = seg; - freesegs_youngest = seg; - nFreeSegs++; - } -} - -static WordFM* addr_to_seg_map = NULL; /* GuestAddr -> Seg* */ - -static void addr_to_seg_map_ENSURE_INIT ( void ) -{ - if (UNLIKELY(addr_to_seg_map == NULL)) { - addr_to_seg_map = VG_(newFM)( VG_(malloc), "pc.h_main.attmEI.1", - VG_(free), NULL/*unboxedcmp*/ ); - } -} - -static Seg* find_Seg_by_addr ( Addr ga ) -{ - UWord keyW, valW; - addr_to_seg_map_ENSURE_INIT(); - if (VG_(lookupFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga )) { - tl_assert(keyW == ga); - return (Seg*)valW; - } else { - return NULL; - } -} - -static void bind_addr_to_Seg ( Addr ga, Seg* seg ) -{ - Bool b; - addr_to_seg_map_ENSURE_INIT(); - b = VG_(addToFM)( addr_to_seg_map, (UWord)ga, (UWord)seg ); - tl_assert(!b); /* else ga is already bound */ -} - -static void unbind_addr_from_Seg ( Addr ga ) -{ - Bool b; - UWord keyW, valW; - addr_to_seg_map_ENSURE_INIT(); - b = VG_(delFromFM)( addr_to_seg_map, &keyW, &valW, (UWord)ga ); - tl_assert(b); /* else ga was not already bound */ - tl_assert(keyW == ga); - tl_assert(valW != 0); -} - - -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// - -// Returns the added heap segment -static Seg* add_new_segment ( ThreadId tid, Addr p, SizeT size ) -{ - Seg* seg = get_Seg_for_malloc(); - tl_assert(seg != (Seg*)1); /* since we're using 1 as a special value */ - seg->addr = p; - seg->szB = size; - seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ ); - tl_assert(!Seg__is_freed(seg)); - - bind_addr_to_Seg(p, seg); - - return seg; -} - - - -static -void* alloc_and_new_mem_heap ( ThreadId tid, - SizeT size, SizeT alignment, Bool is_zeroed ) -{ - Addr p; - - if ( ((SSizeT)size) < 0) return NULL; - - p = (Addr)VG_(cli_malloc)(alignment, size); - if (is_zeroed) VG_(memset)((void*)p, 0, size); - - add_new_segment( tid, p, size ); - - stats__client_mallocs++; - return (void*)p; -} - -static void die_and_free_mem_heap ( ThreadId tid, Seg* seg ) -{ - // Empty and free the actual block - tl_assert(!Seg__is_freed(seg)); - - VG_(cli_free)( (void*)seg->addr ); - - // Remember where freed - seg->ec = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ ); - - set_Seg_freed(seg); - unbind_addr_from_Seg( seg->addr ); - - stats__client_frees++; -} - -static void handle_free_heap( ThreadId tid, void* p ) -{ - Seg* seg = find_Seg_by_addr( (Addr)p ); - if (!seg) { - /* freeing a block that wasn't malloc'd. Ignore. */ - return; - } - die_and_free_mem_heap( tid, seg ); -} - - -/*------------------------------------------------------------*/ -/*--- malloc() et al replacements ---*/ -/*------------------------------------------------------------*/ - -void* h_replace_malloc ( ThreadId tid, SizeT n ) -{ - return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment), - /*is_zeroed*/False ); -} - -void* h_replace___builtin_new ( ThreadId tid, SizeT n ) -{ - return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment), - /*is_zeroed*/False ); -} - -void* h_replace___builtin_vec_new ( ThreadId tid, SizeT n ) -{ - return alloc_and_new_mem_heap ( tid, n, VG_(clo_alignment), - /*is_zeroed*/False ); -} - -void* h_replace_memalign ( ThreadId tid, SizeT align, SizeT n ) -{ - return alloc_and_new_mem_heap ( tid, n, align, - /*is_zeroed*/False ); -} - -void* h_replace_calloc ( ThreadId tid, SizeT nmemb, SizeT size1 ) -{ - return alloc_and_new_mem_heap ( tid, nmemb*size1, VG_(clo_alignment), - /*is_zeroed*/True ); -} - -void h_replace_free ( ThreadId tid, void* p ) -{ - // Should arguably check here if p.vseg matches the segID of the - // pointed-to block... unfortunately, by this stage, we don't know what - // p.vseg is, because we don't know the address of p (the p here is a - // copy, and we've lost the address of its source). To do so would - // require passing &p in, which would require rewriting part of - // vg_replace_malloc.c... argh. - // - // However, Memcheck does free checking, and will catch almost all - // violations this checking would have caught. (Would only miss if we - // unluckily passed an unrelated pointer to the very start of a heap - // block that was unrelated to that block. This is very unlikely!) So - // we haven't lost much. - - handle_free_heap(tid, p); -} - -void h_replace___builtin_delete ( ThreadId tid, void* p ) -{ - handle_free_heap(tid, p); -} - -void h_replace___builtin_vec_delete ( ThreadId tid, void* p ) -{ - handle_free_heap(tid, p); -} - -void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size ) -{ - Seg* seg; - - /* First try and find the block. */ - seg = find_Seg_by_addr( (Addr)p_old ); - if (!seg) - return NULL; - - tl_assert(seg->addr == (Addr)p_old); - - if (new_size <= seg->szB) { - /* new size is smaller: allocate, copy from old to new */ - Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size); - VG_(memcpy)((void*)p_new, p_old, new_size); - - /* Free old memory */ - die_and_free_mem_heap( tid, seg ); - - /* This has to be after die_and_free_mem_heap, otherwise the - former succeeds in shorting out the new block, not the - old, in the case when both are on the same list. */ - add_new_segment ( tid, p_new, new_size ); - - return (void*)p_new; - } else { - /* new size is bigger: allocate, copy from old to new */ - Addr p_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_size); - VG_(memcpy)((void*)p_new, p_old, seg->szB); - - /* Free old memory */ - die_and_free_mem_heap( tid, seg ); - - /* This has to be after die_and_free_mem_heap, otherwise the - former succeeds in shorting out the new block, not the old, - in the case when both are on the same list. NB jrs - 2008-Sept-11: not sure if this comment is valid/correct any - more -- I suspect not. */ - add_new_segment ( tid, p_new, new_size ); - - return (void*)p_new; - } -} - -SizeT h_replace_malloc_usable_size ( ThreadId tid, void* p ) -{ - Seg* seg = find_Seg_by_addr( (Addr)p ); - - // There may be slop, but pretend there isn't because only the asked-for - // area will have been shadowed properly. - return ( seg ? seg->szB : 0 ); -} - - -/*--------------------------------------------------------------------*/ -/*--- Instrumentation ---*/ -/*--------------------------------------------------------------------*/ - -/* The h_ instrumenter that follows is complex, since it deals with - shadow value computation. - - It also needs to generate instrumentation for the sg_ side of - things. That's relatively straightforward. However, rather than - confuse the code herein any further, we simply delegate the problem - to sg_main.c, by using the four functions - sg_instrument_{init,fini,IRStmt,final_jump}. These four completely - abstractify the sg_ instrumentation. See comments in sg_main.c's - instrumentation section for further details. */ - - -/* Carries info about a particular tmp. The tmp's number is not - recorded, as this is implied by (equal to) its index in the tmpMap - in PCEnv. The tmp's type is also not recorded, as this is present - in PCEnv.sb->tyenv. - - When .kind is NonShad, .shadow may give the identity of the temp - currently holding the associated shadow value, or it may be - IRTemp_INVALID if code to compute the shadow has not yet been - emitted. - - When .kind is Shad tmp holds a shadow value, and so .shadow must be - IRTemp_INVALID, since it is illogical for a shadow tmp itself to be - shadowed. -*/ -typedef - enum { NonShad=1, Shad=2 } - TempKind; - -typedef - struct { - TempKind kind; - IRTemp shadow; - } - TempMapEnt; - - - -/* Carries around state during Ptrcheck instrumentation. */ -typedef - struct { - /* MODIFIED: the superblock being constructed. IRStmts are - added. */ - IRSB* sb; - Bool trace; - - /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the - current kind and possibly shadow temps for each temp in the - IRSB being constructed. Note that it does not contain the - type of each tmp. If you want to know the type, look at the - relevant entry in sb->tyenv. It follows that at all times - during the instrumentation process, the valid indices for - tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is - total number of NonShad and Shad temps allocated so far. - - The reason for this strange split (types in one place, all - other info in another) is that we need the types to be - attached to sb so as to make it possible to do - "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the - instrumentation process. - - Note that only integer temps of the guest word size are - shadowed, since it is impossible (or meaningless) to hold a - pointer in any other type of temp. */ - XArray* /* of TempMapEnt */ qmpMap; - - /* READONLY: the host word type. Needed for constructing - arguments of type 'HWord' to be passed to helper functions. - Ity_I32 or Ity_I64 only. */ - IRType hWordTy; - - /* READONLY: the guest word type, Ity_I32 or Ity_I64 only. */ - IRType gWordTy; - - /* READONLY: the guest state size, so we can generate shadow - offsets correctly. */ - Int guest_state_sizeB; - } - PCEnv; - -/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on - demand), as they are encountered. This is for two reasons. - - (1) (less important reason): Many original tmps are unused due to - initial IR optimisation, and we do not want to spaces in tables - tracking them. - - Shadow IRTemps are therefore allocated on demand. pce.tmpMap is a - table indexed [0 .. n_types-1], which gives the current shadow for - each original tmp, or INVALID_IRTEMP if none is so far assigned. - It is necessary to support making multiple assignments to a shadow - -- specifically, after testing a shadow for definedness, it needs - to be made defined. But IR's SSA property disallows this. - - (2) (more important reason): Therefore, when a shadow needs to get - a new value, a new temporary is created, the value is assigned to - that, and the tmpMap is updated to reflect the new binding. - - A corollary is that if the tmpMap maps a given tmp to - IRTemp_INVALID and we are hoping to read that shadow tmp, it means - there's a read-before-write error in the original tmps. The IR - sanity checker should catch all such anomalies, however. -*/ - -/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to - both the table in pce->sb and to our auxiliary mapping. Note that - newTemp may cause pce->tmpMap to resize, hence previous results - from VG_(indexXA)(pce->tmpMap) are invalidated. */ -static IRTemp newTemp ( PCEnv* pce, IRType ty, TempKind kind ) -{ - Word newIx; - TempMapEnt ent; - IRTemp tmp = newIRTemp(pce->sb->tyenv, ty); - ent.kind = kind; - ent.shadow = IRTemp_INVALID; - newIx = VG_(addToXA)( pce->qmpMap, &ent ); - tl_assert(newIx == (Word)tmp); - return tmp; -} - -/*------------------------------------------------------------*/ -/*--- Constructing IR fragments ---*/ -/*------------------------------------------------------------*/ - -/* add stmt to a bb */ -static /*inline*/ void stmt ( HChar cat, PCEnv* pce, IRStmt* st ) { - if (pce->trace) { - VG_(printf)(" %c: ", cat); - ppIRStmt(st); - VG_(printf)("\n"); - } - addStmtToIRSB(pce->sb, st); -} - -static IRTemp for_sg__newIRTemp_cb ( IRType ty, void* opaque ) -{ - PCEnv* pce = (PCEnv*)opaque; - return newTemp( pce, ty, NonShad ); -} - - -IRSB* h_instrument ( VgCallbackClosure* closure, - IRSB* sbIn, - const VexGuestLayout* layout, - const VexGuestExtents* vge, - const VexArchInfo* archinfo_host, - IRType gWordTy, IRType hWordTy ) -{ - Bool verboze = 0||False; - Int i /*, j*/; - PCEnv pce; - struct _SGEnv* sgenv; - - if (gWordTy != hWordTy) { - /* We don't currently support this case. */ - VG_(tool_panic)("host/guest word size mismatch"); - } - - /* Check we're not completely nuts */ - tl_assert(sizeof(UWord) == sizeof(void*)); - tl_assert(sizeof(Word) == sizeof(void*)); - tl_assert(sizeof(Addr) == sizeof(void*)); - tl_assert(sizeof(ULong) == 8); - tl_assert(sizeof(Long) == 8); - tl_assert(sizeof(Addr) == sizeof(void*)); - tl_assert(sizeof(UInt) == 4); - tl_assert(sizeof(Int) == 4); - - /* Set up the running environment. Both .sb and .tmpMap are - modified as we go along. Note that tmps are added to both - .sb->tyenv and .tmpMap together, so the valid index-set for - those two arrays should always be identical. */ - VG_(memset)(&pce, 0, sizeof(pce)); - pce.sb = deepCopyIRSBExceptStmts(sbIn); - pce.trace = verboze; - pce.hWordTy = hWordTy; - pce.gWordTy = gWordTy; - pce.guest_state_sizeB = layout->total_sizeB; - - pce.qmpMap = VG_(... [truncated message content] |
|
From: Mark W. <ma...@so...> - 2020-04-17 14:30:38
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=ad0ca50fc9fa5c65dca9f0aa14e3955644b876bd commit ad0ca50fc9fa5c65dca9f0aa14e3955644b876bd Author: Mark Wielaard <ma...@kl...> Date: Fri Apr 17 16:29:11 2020 +0200 Add avx_tests.h to noinst_HEADERS to make sure it appears in dist. Diff: --- none/tests/amd64/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/none/tests/amd64/Makefile.am b/none/tests/amd64/Makefile.am index 3196d00cea..88dc9b4da9 100644 --- a/none/tests/amd64/Makefile.am +++ b/none/tests/amd64/Makefile.am @@ -3,6 +3,9 @@ include $(top_srcdir)/Makefile.tool-tests.am dist_noinst_SCRIPTS = filter_cpuid filter_inf_nan filter_stderr gen_insn_test.pl +# Used by avx-1.c and avx_estimate_insn.c +noinst_HEADERS = avx_tests.h + CLEANFILES = $(addsuffix .c,$(INSN_TESTS)) INSN_TESTS = insn_basic insn_mmx insn_sse insn_sse2 insn_fpu |
|
From: Julian S. <se...@so...> - 2020-04-17 14:23:33
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=afe1d87762a4c1500ceb6d38075d2c6db1cd4482 commit afe1d87762a4c1500ceb6d38075d2c6db1cd4482 Author: Julian Seward <js...@ac...> Date: Fri Apr 17 16:17:49 2020 +0200 Update bug status. Diff: --- NEWS | 4 ++++ docs/internals/3_15_BUGSTATUS.txt | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 5d8792b5c4..e48a4cc98f 100644 --- a/NEWS +++ b/NEWS @@ -121,6 +121,7 @@ where XXXXXX is the bug number as listed below. 416464 Fix false reports for uninitialized memory for PR_CAPBSET_READ/DROP 416667 gcc10 ppc64le impossible constraint in 'asm' in test_isa. 416753 new 32bit time syscalls for 2038+ +417281 s390x: /bin/true segfaults with "grail" enabled 417427 commit to fix vki_siginfo_t definition created numerous regression errors on ppc64 417452 s390_insn_store_emit: dst->tag for HRcVec128 @@ -135,7 +136,10 @@ n-i-bz Add support for the Linux io_uring system calls n-i-bz sys_statx: don't complain if both |filename| and |buf| are NULL. n-i-bz Fix non-glibc build of test suite with s390x_features 418004 Grail code additions break ppc64. +418435 s390x: spurious "Conditional jump or move depends on uninitialised [..]" 418997 s390x: Support Iex_ITE for float and vector types +419503 s390x: Avoid modifying registers returned from isel functions + Release 3.15.0 (12 April 2019) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/internals/3_15_BUGSTATUS.txt b/docs/internals/3_15_BUGSTATUS.txt index 9509426a04..88d5466f6b 100644 --- a/docs/internals/3_15_BUGSTATUS.txt +++ b/docs/internals/3_15_BUGSTATUS.txt @@ -170,8 +170,6 @@ of 3.15.0. It doesn't carry over bugs from earlier versions. === zz_other/x86 ======================================================= --- Wed 4 Mar 10:48:31 CET 2020 - .416682 [MIPS-Linux] mmap failed under valgrind .416753 new 32bit time syscalls for 2038+ @@ -218,6 +216,23 @@ Needs investigation .418004 Grail code additions break ppc64 +.418106 configure error: Valgrind not working with Darwin version 18.14.2 + +.418756 MAP_FIXED_NOREPLACE mmap flag unsupported + +.418840 SIG_IGN doesn't clear pending signal if SIG_IGN is already the handler + +.418961 Character encoding issue on website + +.419054 Unhandled syscall getcpu on arm32 + +.419562 PR_SET_PTRACER error with Ubuntu on WSL + +.419864 arm32 fe: valgrind: Unrecognised instruction at address 0x5bf24a3 + +-- as of Fri 17 Apr 16:15:11 CEST 2020 + +Bug 416760 - ppc64le Assertion 'VG_IS_16_ALIGNED(sizeof(struct rt_sigframe))' failed (edit) - ================== Extras |
|
From: Mark W. <ma...@so...> - 2020-04-17 14:13:27
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=bc7eb9046f93558903fc388a00dbb60c89a9cf73 commit bc7eb9046f93558903fc388a00dbb60c89a9cf73 Author: Mark Wielaard <ma...@kl...> Date: Fri Apr 17 16:12:06 2020 +0200 Add missing vki header files to nobase_pkginclude_HEADERS. Otherwise they don't show up in the dist tarball. Diff: --- include/Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/Makefile.am b/include/Makefile.am index 9bf02c224c..05cec97898 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -82,6 +82,8 @@ nobase_pkginclude_HEADERS = \ vki/vki-scnums-nanomips-linux.h \ vki/vki-scnums-darwin.h \ vki/vki-scnums-solaris.h \ + vki/vki-scnums-shared-linux.h \ + vki/vki-scnums-32bit-linux.h \ vki/vki-xen.h \ vki/vki-xen-domctl.h \ vki/vki-xen-evtchn.h \ @@ -96,4 +98,5 @@ nobase_pkginclude_HEADERS = \ vki/vki-xen-version.h \ vki/vki-xen-xsm.h \ vki/vki-xen-x86.h \ - vki/vki-linux-drm.h + vki/vki-linux-drm.h \ + vki/vki-linux-io_uring.h |
|
From: Julian S. <se...@so...> - 2020-04-17 12:56:04
|
https://sourceware.org/git/gitweb.cgi?p=valgrind.git;h=ecf5636a1442c024a9b30debcbec8c2013ec5af7 commit ecf5636a1442c024a9b30debcbec8c2013ec5af7 Author: Julian Seward <js...@ac...> Date: Fri Apr 17 14:55:37 2020 +0200 Add a missing \n in debug output printing. Diff: --- VEX/priv/guest_arm64_toIR.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VEX/priv/guest_arm64_toIR.c b/VEX/priv/guest_arm64_toIR.c index fe80e593c4..ab68da13dd 100644 --- a/VEX/priv/guest_arm64_toIR.c +++ b/VEX/priv/guest_arm64_toIR.c @@ -5387,7 +5387,7 @@ Bool dis_ARM64_load_store(/*MB_OUT*/DisResult* dres, UInt insn, else { vassert(0); } - DIP("ldurs%c %s, [%s, #%lld]", + DIP("ldurs%c %s, [%s, #%lld]\n", ch, nameIRegOrZR(is64, tt), nameIReg64orSP(nn), (Long)simm9); return True; } |