public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
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

      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).