From: Mark Geisert <mark@maxrnd.com>
To: Cygwin Patches <cygwin-patches@cygwin.com>
Subject: Re: [PATCH] Cygwin: New tool: cygmon
Date: Wed, 16 Jun 2021 22:59:02 -0700 [thread overview]
Message-ID: <e5827309-3de5-e449-a5cf-0d2c2507891c@maxrnd.com> (raw)
In-Reply-To: <30137899-0301-3616-5f77-298259ca414b@dronecode.org.uk>
Hi Jon,
I appreciate your review. I will fold the suggestions from your short email plus
this longer email into a v2 patch fairly soon.
Jon Turney wrote:
> On 12/06/2021 07:46, Mark Geisert wrote:
>
>> diff --git a/winsup/utils/cygmon.cc b/winsup/utils/cygmon.cc
>> new file mode 100644
>> index 000000000..9156b27d7
>> --- /dev/null
>> +++ b/winsup/utils/cygmon.cc
[...]
>> +#include "../cygwin/include/sys/cygwin.h"
>> +#include "../cygwin/include/cygwin/version.h"
>> +#include "../cygwin/cygtls_padsize.h"
>> +#include "../cygwin/gcc_seh.h"
>
> The latest Makefile.am sets things up so these relative paths aren't needed.
Oh yes, I saw those go by but have not made use of the changes. Will do.
>> +typedef unsigned short ushort;
>> +typedef uint16_t u_int16_t; // to work around ancient gmon.h usage
>
> 'Non-standard sized type needed by ancient gmon.h' might be clearer
Indeed, thanks. Will update.
>> +#include "../cygwin/gmon.h"
[...]
>> +size_t
>> +sample (HANDLE h)
>> +{
>> + static CONTEXT *context = NULL;
>> + size_t status;
>> +
>> + if (!context)
>> + {
>> + context = (CONTEXT *) calloc (1, sizeof (CONTEXT));
>> + context->ContextFlags = CONTEXT_CONTROL;
>> + }
>
> Why isn't this just 'static CONTEXT'?
>
> But it also shouldn't be static, because this function needs to be thread-safe as
> it is called by the profiler thread for every inferior process?
Oof, I must've gotten sidetracked off of coding the change from static to auto by
a squirrel or a shiny disc or something. Yes, the local context buffer needs to
be thread-safe in case of multiple children being profiled. I knew that...
[...]
>> + else
>> +//TODO this approach might not support 32-bit executables on 64-bit
>
> It definitely doesn't. But that's fine.
Will make the comment more definitive.
[...]
>> +void
>> +start_profiler (child *c)
>> +{
>> + DWORD tid;
>> +
>> + if (verbose)
>> + note ("*** start profiler thread on pid %lu\n", c->pid);
>> + c->hquitevt = CreateEvent (NULL, TRUE, FALSE, NULL);
>> + if (!c->hquitevt)
>> + error (0, "unable to create quit event\n");
>> + c->profiling = 1;
>> + c->hprofthr = CreateThread (NULL, 0, profiler, (void *) c, 0, &tid);
>> + if (!c->hprofthr)
>> + error (0, "unable to create profiling thread\n");
>> +
>> +//SetThreadPriority (c->hprofthr, THREAD_PRIORITY_TIME_CRITICAL); Don't do this!
>
> But now I want to see what happens when I do!
You'll be sorry, but yeah the warning here is important because there's a real
temptation here to do something, anything.. I'll make it more descriptive.
[...]
>> + fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY);
[...]
>> + close (fd);
>> + chmod (filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);//XXX ineffective
>
> ???
For the life of me I could not figure out how to make the output file mode 0644
with either open() flags or chmod() afterwards. I keep getting unwanted 'x' bits
set. Perhaps a side-effect of this being a native program rather than a Cygwin
program. I just flagged it until I can resolve it.
[...]
>> +void
>> +info_profile_file (char *filename)
>
> I think this should be a separate tool, since it's not really part of the function
> of this tool.
Yeah, I guess so. I didn't think of that option. I just saw this as too big to
be a Cygwin-specific patch to gprof, where it could plausibly go. I will split
this out to a separate tool called 'gmoninfo' or some such. Suggestions welcome.
[...]
>> +IMAGE_SECTION_HEADER *
>> +find_text_section (LPVOID base, HANDLE h)
>> +{
>> + static IMAGE_SECTION_HEADER asect;
>> + DWORD lfanew;
>> + WORD machine;
>> + WORD nsects;
>> + DWORD ntsig;
>> + char *ptr = (char *) base;
>> +
>> + IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *) ptr;
>> + read_child ((void *) &lfanew, sizeof (lfanew), &idh->e_lfanew, h);
>> + ptr += lfanew;
>> +
>> + /* Code handles 32- or 64-bit headers depending on compilation environment. */
>> + /*TODO It doesn't yet handle 32-bit headers on 64-bit Cygwin or v/v. */
>> + IMAGE_NT_HEADERS *inth = (IMAGE_NT_HEADERS *) ptr;
>> + read_child ((void *) &ntsig, sizeof (ntsig), &inth->Signature, h);
>> + if (ntsig != IMAGE_NT_SIGNATURE)
>> + error (0, "find_text_section: NT signature not found\n");
>> +
>> + read_child ((void *) &machine, sizeof (machine),
>> + &inth->FileHeader.Machine, h);
>> +#ifdef __x86_64__
>> + if (machine != IMAGE_FILE_MACHINE_AMD64)
>> +#else
>> + if (machine != IMAGE_FILE_MACHINE_I386)
>> +#endif
>> + error (0, "target program was built for different machine architecture\n");
>> +
>> + read_child ((void *) &nsects, sizeof (nsects),
>> + &inth->FileHeader.NumberOfSections, h);
>> + ptr += sizeof (*inth);
>> +
>> + IMAGE_SECTION_HEADER *ish = (IMAGE_SECTION_HEADER *) ptr;
>> + for (int i = 0; i < nsects; i++)
>> + {
>> + read_child ((void *) &asect, sizeof (asect), ish, h);
>> + if (0 == memcmp (".text\0\0\0", &asect.Name, 8))
>> + return &asect;
>> + ish++;
>> + }
>
> While this is adequate and correct in 99% of cases, I think what you're perhaps
> looking for here is sections which are executable?
I suppose so, but since the gmon.out files (and gprof) can't deal with disjoint
address spans directly that would mean an additional gmon.out file for each span.
It could work, but I'm vaguely disturbed by the idea.
> (Well, really we want to enumerate executable memory regions in the inferior, to
> profile dynamically generated code as well, but...)
Even more disturbing :), but yes, could be done. At some point the linear search
for which sampling buffer to bump a bucket in might need changing to a hashed
lookup...
[...]
>> +int
>> +load_cygwin ()
>> +{
>
> So: I wonder if this tool should just link with the cygwin DLL.
>
> I think the historical reason for strace to not be a cygwin executable is so that
> it can be used to debug problems with cygwin executables startup.
>
> I don't think that reason applies here?
You're correct that that reason doesn't apply here. Making this a Cygwin program
would also make it much easier to debug! IIRC I started writing this as a Cygwin
program but switched to a native Windows model when I started cribbing code from
strace. But I guess in hindsight it wasn't really necessary to switch. Thanks
for bringing this up for consideration.
Thanks & Regards,
..mark
prev parent reply other threads:[~2021-06-17 7:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-12 6:46 Mark Geisert
2021-06-13 14:40 ` Jon Turney
2021-06-15 8:48 ` Mark Geisert
2021-06-13 14:46 ` Jon Turney
2021-06-17 5:59 ` Mark Geisert [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e5827309-3de5-e449-a5cf-0d2c2507891c@maxrnd.com \
--to=mark@maxrnd.com \
--cc=cygwin-patches@cygwin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).