accessing other process's text segment

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?

Alternatively, what would have to be done to translate segment info as
returned by qnx_psinfo() to physical memory locations?

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

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.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

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?

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.

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.

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.

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.

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.

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.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

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.

Will Parsons <wbp@alfa.eng.sun.com> wrote:

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?

The default for QNX4 is to COMPILE -ms (small model) and to LINK -mf
(or flat model). Any object compiled small can be linked flat, but
an object compiled flat can not be linked small.

If you link small model, I don’t think you can use any of the
shared libraries. (Shared libraries are used by: X, Photon,
QNX Windows, TCP/IP to my knowledge.)

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?

I don’t THINK so. But, with this you are well into territory that is NOT
a high-runner case for use of the OS. All the qnx_segment_*() functions
were primarily written for 16-bit applications and in some use in
4.1x (and 4.0x) versions of the OS before 32-bit applications were
supported, and before the shm_open() and mmap() APIs were available.
To my knowledge they have not been heavily used with 32-bit applications.
I know about the qnx_segment_arm() locking the DS side-effect from
dealings with Dev drivers that share a segment with Dev, and even then
last dealt with it probably about 5 years ago.

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.

See above comment. :slight_smile: It may be a couple of things – it may be that
you just want read access, so no bits need to be set. It may be that
your reader process is running as root, and as superuser this gets you
the perms you need.

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?

You ARE use Slib32. Everyone does.

As for others – as noted above, any application that uses Photon, X,
QNX Windows, or TCP/IP probably is using a shared library. Do an
“ls /dev/shmem” and see if any libraries exist.

Another couple of things that might be interesting to look at:

“sin mem” and “sin fo inP”.

Thanks for the help.

You’re welcome.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.