From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 112055 invoked by alias); 6 Feb 2016 21:43:26 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 112041 invoked by uid 89); 6 Feb 2016 21:43:25 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 spammy=atkinson, Atkinson, Giles, magnitude X-HELO: rgout0403.bt.lon5.cpcloud.co.uk Received: from rgout0403.bt.lon5.cpcloud.co.uk (HELO rgout0403.bt.lon5.cpcloud.co.uk) (65.20.0.216) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 06 Feb 2016 21:43:23 +0000 X-OWM-Source-IP: 109.152.145.204 (GB) X-OWM-Env-Sender: gatk@btinternet.com X-CTCH-RefID: str=0001.0A090202.56B668F2.0016,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0 X-Junkmail-Premium-Raw: score=28/50,refid=2.7.2:2016.2.6.200920:17:28.905,ip=109.152.145.204,rules=SUBJ_PHRASE_WATCHES, __BOUNCE_CHALLENGE_SUBJ, __BOUNCE_NDR_SUBJ_EXEMPT, __SUBJ_ALPHA_END, __MIME_VERSION, __MIME_VERSION_APPLEMAIL, __CT, __CT_TEXT_PLAIN, __HAS_FROM, __PHISH_FROM2, __FRAUD_WEBMAIL_FROM, __IN_REP_TO, __CTE, __HAS_MSGID, __SANE_MSGID, __MSGID_APPLEMAIL, __REFERENCES, __TO_MALFORMED_2, __HAS_X_MAILER, __X_MAILER_APPLEMAIL, MIME_LOWER_CASE, __ANY_URI, __HTTPS_URI, URI_ENDS_IN_HTML, __URI_NO_MAILTO, __URI_NO_WWW, __URI_NO_PATH, __FRAUD_MONEY_CURRENCY_DOLLAR, __SUBJ_ALPHA_NEGATE, SUPERLONG_LINE, __URI_IN_BODY, __FORWARDED_MSG, BODY_SIZE_6000_6999, __MIME_TEXT_ONLY, RDNS_GENERIC_POOLED, __URI_NS, SXL_IP_DYNAMIC[204.145.152.109.fur], HTML_00_01, HTML_00_10, __FRAUD_MONEY_CURRENCY, RDNS_SUSP_GENERIC, __USER_AGENT_APPLEMAIL, __PHISH_FROM, __PHISH_SPEAR_STRUCTURE_1, RDNS_SUSP, __FRAUD_WEBMAIL, REFERENCES, BODY_SIZE_7000_LESS, __SINGLE_URI_TEXT, SINGLE_URI_IN_BODY X-CTCH-Spam: Unknown Received: from [192.168.1.64] (109.152.145.204) by rgout04.bt.lon5.cpcloud.co.uk (8.6.122.06) (authenticated as gatk@btinternet.com) id 56B0A64400813E78; Sat, 6 Feb 2016 21:42:21 +0000 Subject: Re: Dynamic watchpoints in dynamic memory Mime-Version: 1.0 (Apple Message framework v1085) Content-Type: text/plain; charset=us-ascii From: Giles Atkinson In-Reply-To: Date: Sat, 06 Feb 2016 21:43:00 -0000 Cc: gdb@sourceware.org Content-Transfer-Encoding: quoted-printable Message-Id: <43990295-BCD6-400F-BEDA-D65C1FE68A74@btinternet.com> References: <1C590CEA-031F-40C0-A814-99829DD80E4D@btinternet.com> To: Simon Marchi X-IsSubscribed: yes X-SW-Source: 2016-02/txt/msg00010.txt.bz2 Simon, Thank you for your comments. Some related comments/answers below: > ... but my first thought would be to try Valgrind Mine too, but that idea had already been discarded before the problem came = to me. > Just to be sure, is it the pointer to the structure that becomes corrupte= d, or a pointer inside the structure, that points to something else?=20 Some times, it can appear to the the later, while it's the former (and you = were just "lucky" that the first dereference did not produce a segfault, because it happened to be in mapped memory). It could be that. It is actually a structure with a pointer to another of = the same type and then a pointer to a different type.=20=20 I parameterised the commands by structure offset to check both possibilitie= s in separate test runs, and it could also look for corruption of the linked list of the primary structures. > Silly question: since you are debugging C, don't you have access to a var= iable that holds the address of the structure?=20 Not silly at all. This is commercial software, with a stripped binary. Th= e idea is to create a script that can be sent to a customer, as the bug is not reproduced elsewhere. So although it is C, I think it makes sense t= o work at assembler level. > ... GDB will have to resort to use software watchpoints, which will slow = down execution of the program by a few orders of magnitude. It can be usef= ul nonetheless. I hope that will be OK. It is very interactive, so with luck the user can = reproduce it slowly. > There might be a super clever way to do this using only base gdb commands= , but for these things I go straight to Python: So would I, if I knew the language, and thought we should persuade a custom= er to install it. I think a variant of your idea can work with base gdb, although it is not c= lever. There are a few bytes in the primary structure where I think I can hide the= related watchpoint number. Very ugly, but worth trying. Many thanks, Giles On 6 Feb 2016, at 03:43, Simon Marchi wrote: > Hi Giles, >=20 > On 2016-02-05 18:21, Giles Atkinson wrote: >> Greetings, >> I have a suspicion that these may be somewhat stupid questions, but I >> feel I have done enough searching of documentation, FAQs etc., >> without result, to be ready to ask. I think this could be a FAQ-level >> query, but found no reference to the topic. >> I have a C program that crashes on a modify access via a >> dynamically-allocated structure member with an illegal address, not >> NULL. >> The core file, circumstances, and code review suggest that an unusual >> event has previously corrupted a pointer >> in the structure, which the failing instruction dereferences. >=20 > You might have done that already, but my first thought would be to try Va= lgrind. It might not help here, since the rogue write spills into allocate= d code, but we never know. That program does some amazing things. >=20 > Just to be sure, is it the pointer to the structure that becomes corrupte= d, or a pointer inside the structure, that points to something else? Some = times, it can appear to the the later, while it's the former (and you were = just "lucky" that the first dereference did not produce a segfault, because= it happened to be in mapped memory). >=20 >> My approach was to set a breakpoint on structure initialisation, with >> a command list to set a watchpoint on the >> pointer member. The watchpoint command list is backtrace and >> continue, output to file. By setting the breakpoint on the >> right instruction, the breakpoint command list can pick the structure >> address from a register, adding an offset. >=20 > Silly question: since you are debugging C, don't you have access to a var= iable that holds the address of the structure? It would be simpler to use = that than to figure out which register to use. >=20 >> That works: so far, so good. >> The target structures are created and destroyed fairly frequently, >> responding to user input. >> To avoid noise in the output, and limit the number of watchpoints, >> there is a breakpoint before deallocation >> that attempts to remove the watchpoint on the structure, again using a >> register value. >> Questions: >> Does this make sense, or have I missed a better way? >=20 > I have done that in the past (using Python though), I think it makes sens= e. It's good to keep in mind that if you track more than a few bytes, GDB = will have to resort to use software watchpoints, which will slow down execu= tion of the program by a few orders of magnitude. It can be useful nonethe= less. >=20 >> How to remove the watchpoint? I can not identify the right syntax. >> The watchpoint is set like this: watch -location *(void **)($esi + $offs= et) >=20 > Again, using C (if possible) would be much easier. Something like >=20 > (gdb) watch -location structure->field >=20 > might do the trick (untested, may require some more & or *). >=20 >> I have tried to remove it with 'clear', but that seems to match watchpoi= nts >> using the 'watch' expression, and what I have is a different >> expression that should yield the same address. >> The register is different on deallocation and the original command is >> not unique. >=20 > There might be a super clever way to do this using only base gdb commands= , but for these things I go straight to Python: >=20 > https://sourceware.org/gdb/onlinedocs/gdb/Breakpoints-In-Python.html >=20 > Create three breakpoint classes: two for the allocation and de-allocation= functions and one of type watchpoint, that will watch the actual structure= s. In the allocation breakpoint's stop handler, you: >=20 > 1. get the address of the structure (e.g.: gdb.parse_and_eval('ptr'), wh= ere ptr is a pointer to the structure) > 2. create an instance of the watchpoint class based on the structure add= ress > 3. put that in a global dict, that maps structure addresses to watchpoin= t object instances >=20 > In the de-allocation's stop handler, you: >=20 > 1. get the address of the structure > 2. find and remove the watchpoint instance from the global dict > 3. call .delete() on the watchpoint. >=20 > This way, you should have watchpoints that follow the lifetime of your ob= jects (which is what I understood you wanted). I hope it makes sense and i= s actually helpful. >=20 >> More puzzlement: my printf commands in (nested) command lists do nothing. >=20 > Hmm I am not sure I understand, could you give a reproducible example? >=20 > Simon