David Gibbs <dagibbs@qnx.com> wrote:
Will Parsons <> wbp@alfa.eng.sun.com> > wrote:
David Gibbs <> dagibbs@qnx.com> > wrote:
Will Parsons <> wbp@alfa.eng.sun.com> > wrote:
We have a requirement to perform checksum calculations on the code
segments of running processes. I have been looking at using
qnx_segment_arm() to give another process read-only access to a segment,
so that the second process could calculate a checksum. The return value
of qnx_segment_get() is a segment selector, apparently - is there any
way of using shm_open()/mmap() to map this segment into local memory?
There is one big problem with qnx_segment_arm – this locks the size
of the segment it is applied to. Hm…you’re only looking at code
segments, so that might be ok – they shouldn’t grow anyway. Locking
the DS would be nasty.
As to shm_open/mmap() – unfortunately there won’t be anyway to do
this to map the other process into memory.
Alternatively, what would have to be done to translate segment info as
returned by qnx_psinfo() to physical memory locations?
No. And, even if you could, there is a strong likelihood that the
memory isn’t actually physically contiguous.
I see two choices – the qnx_segment_arm() and qnx_segment_get() pair,
then use MK_FP to create a 48-bit ptr to the memory you’re going to
checksum – make sure to code your checksum routines as taking far
pointers, so they can do this properly. (Also, note, OS libraries
don’t (as a rule) take far pointers, so you won’t be able to pass
this ptr to any of our library calls.)
OK - considering that I wish to loop thru the code segment, how to I
determine the starting point? Accessing offset 0 in the segment gives
me a segmentation fault. From experimentaion, it looks like the beginning
of valid data is at the offset labelled BEGTEXT in the task map file,
but I don’t see any way of deducing this from the psinfo. Also, the
length of the segment seems be reported differently depending on whether
qns_psinfo() is used to get the segment data or qnx_segment_get(). Which
should I be using?
Actually, I just realized another complication – many/most processes
are actually 32-bit flat-model (equivalent of 16-bit tiny) where they
have only one segment – code & data are all in one large segment.
That is probably why you’re not seeing the code start at 0 – but at
some other offset.
I thought I was using the small model for compiling the programs, but
looking more closely, I think I wasn’t. (Incidentally, the documentation
is a bit confusing on this - the Watcom Utilities manual claims that
flat-model linking is the default, but the Watcom Compiler & Tools manual
claims that the small model is the default.) Is the -ms flag needed by
both the compilation stage and the linking stage or just one?
Which also, unfortunately, leads back to my qnx_segment_arm() locking
the size of the segment issue. It might still be ok, but shouldn’t
be too hard to test – do a qnx_segment_arm() on the CS in a process,
then go out and see if you can malloc() a couple of meg of memory.
But if the monitored processes use the small memory model, this shouldn’t
be necessary, should it?
One other curious thing that I discovered by accident - although the
documentation claims that qnx_segment_arm() must be called to give
another process permission to access its segments, this doesn’t seem
to be necessary at all. It seems I can successfully use qnx_segment_get()
without it.
I know Proc looks at the executable – the different load records
to figure out how to lay the program out in memory – but I don’t
know what it looks at. I know that the (undocumented) -@offset
flag to cc can be used to set the base address for code in the process
after it has been loaded – you might be able to try compiling with
different -@ options to see how that changes things, and from there
figure out where stuff lies in memory. I’m not sure this info is
available from _psinfo – you may have to work from the executable.
Or, what you may find easier to do is, once you’ve determined how
to extract this information, setup a data file that lists things like
executable/code offset/code size/checksum – and use this for verifying
against.
OK - I’ll look into this.
And, just in case you haven’t thought of it, you should also be verifying
any shared libraries that live in /dev/shmem – but that should be far
easier, as you should be able to access them by shm_open() & mmap().
Verifying Slib32 (& Proc32) might be messier, though.
I don’t think I’m using any - what would I look for anyway?
Or, use the undocumented _qnx_debug_xfer() call. This allows you
to read the memory of another process – I expect it will also allow
you to read the code, as this is what the debugger uses. Only problem
is that it isn’t documented, and I don’t really know how to use it
myself.
Any suggestions on how to figure out how use this? I took a look at
the prototype in debug.h, but it wasn’t too informative.
If you have a technical support contact/rep or a sales/fae rep, you might
want to see if someone can give you the source to serserv/parserv/tcpserv,
which are the debug host agents. But, we may not be able to do so because
of licensing/IP issues, as I’m not sure they aren’t owned by Watcom, or
whoever has inherited that IP.
Thanks for the help.