[comp.unix.internals] finding out where the text/bss sits

brendan@cs.widener.edu (Brendan Kehoe) (01/02/91)

  Hi there .. this is relative to a program I've been hacking on. This
is all on a Sun Sparc-1 under SunOS 4.1. First, I'm trying to find out
the address of where a user's text, data, & bss segments are sitting
(well, more so the bss than anything). I've been digging for hours &
have come up with a few stringy clues, but nothing's come of it yet.

  What I want to be able to do is read in a structure, say
	struct blah {
		char *this;
		struct blah *that;
		struct blah *the_other;
	};
from the bss of another process (it'd have been declared globally).
And I can't assume that a namelist is in the executable. My two
biggest problems are trying to find out where they're sitting and how
to find out the position of the structure if it doesn't have a symbol
table. (Is this impossible to work around?)

 Was that sufficiently obscure? (I'm living on caffeine right now.)

 Back I go...

-- 
     Brendan Kehoe - Widener Sun Network Manager - brendan@cs.widener.edu

 Get ``Red Hot & Blue'', songs by Cole Porter sung by U2, Sinead O'Connor,
The Neville Brothers, Tom Waits, & many more. Proceeds benefit AIDS research.

mike@bria.AIX (Mike Stefanik/78125) (01/03/91)

In article <1991Jan02.041209.9552@cs.widener.edu>, brendan@cs.widener.edu (Brendan Kehoe) writes:
> 
>   Hi there .. this is relative to a program I've been hacking on. This
> is all on a Sun Sparc-1 under SunOS 4.1. First, I'm trying to find out
> the address of where a user's text, data, & bss segments are sitting
> (well, more so the bss than anything). I've been digging for hours &
> have come up with a few stringy clues, but nothing's come of it yet.
> 
>   What I want to be able to do is read in a structure, say
> 	struct blah {
> 		char *this;
> 		struct blah *that;
> 		struct blah *the_other;
> 	};
> from the bss of another process (it'd have been declared globally).
> And I can't assume that a namelist is in the executable. My two
> biggest problems are trying to find out where they're sitting and how
> to find out the position of the structure if it doesn't have a symbol
> table. (Is this impossible to work around?)
> 

[Mounting High Horse]

Unless I am reading this wrong, you are asking about one user process modifying
another user process' bss?  This is extremely bad karma!  For one thing, if
your machine (I know nothing about SPARC machines) even *allows* you to go
writing to arbitrary memory locations without generating exceptions, then I
would throw it in the dumper.

Let's say that process A wants to write to process B's memory: how could you
guarantee that process B's bss is even *in physical memory* at the time?
You can't.  This is what SHARED MEMORY is for.

BTW: The fact that you have globally declared structures *DOES NOT* mean that
they are global for every Tom, Dick, and Harry process on the machine -- it
means that it is global in the context of the current (ie: declaring) process.

To reiterate: USE SHARED MEMORY.  'Nuff said.

[Unmounting High Horse]
-----------------------------------------------------------------------------
Michael Stefanik, Systems Engineer (JOAT), Briareus Corporation
UUCP: ...!uunet!bria!mike
"If it was hard to code, it should be harder to use!"

josef@nixpbe.nixdorf.de (josef Moellers) (01/07/91)

In <304@bria.AIX> mike@bria.AIX (Mike Stefanik/78125) writes:

>In article <1991Jan02.041209.9552@cs.widener.edu>, brendan@cs.widener.edu (Brendan Kehoe) writes:
>> 
>>   Hi there .. this is relative to a program I've been hacking on. This
>> is all on a Sun Sparc-1 under SunOS 4.1. First, I'm trying to find out
>> the address of where a user's text, data, & bss segments are sitting
>> (well, more so the bss than anything). I've been digging for hours &
>> have come up with a few stringy clues, but nothing's come of it yet.
>> 
>>   What I want to be able to do is read in a structure, say
>> 	struct blah {
>> 		char *this;
>> 		struct blah *that;
>> 		struct blah *the_other;
>> 	};
>> from the bss of another process (it'd have been declared globally).
>> And I can't assume that a namelist is in the executable. My two
>> biggest problems are trying to find out where they're sitting and how
>> to find out the position of the structure if it doesn't have a symbol
>> table. (Is this impossible to work around?)
>> 

>[Mounting High Horse]

>Unless I am reading this wrong, you are asking about one user process modifying
>another user process' bss?  This is extremely bad karma!  For one thing, if
>your machine (I know nothing about SPARC machines) even *allows* you to go
>writing to arbitrary memory locations without generating exceptions, then I
>would throw it in the dumper.

>Let's say that process A wants to write to process B's memory: how could you
>guarantee that process B's bss is even *in physical memory* at the time?
>You can't.  This is what SHARED MEMORY is for.

>BTW: The fact that you have globally declared structures *DOES NOT* mean that
>they are global for every Tom, Dick, and Harry process on the machine -- it
>means that it is global in the context of the current (ie: declaring) process.

>To reiterate: USE SHARED MEMORY.  'Nuff said.

>[Unmounting High Horse]

Ever heard of /proc?

To answer the original question:
The header of an executable file contains the sizes of text, data and
bss of a program.

If Your system has a.out object file format, You need to find out
certain things about Your OS:
- where does it place the code? (I'm writing this on a MIPS and they put
  the code at soemthing like 0x400000, give or take a 0)
- what alignment is used? In order to efficiently implement protection
  and code-sharing, there are holes between text and data (and probably
  between data and bss)
From these and from the sizes of the segments, You should be able to
compute the start address of bss.

If You have a system using coff, then this information should be
contained in the section headers:
	struct scnhdr {
		char	s_name[SYMNMLEN];	/* section name */
		long	s_paddr;		/* physical address */
		long	s_vaddr;		/* virtual address */
		:
	};

Then try to find the needle in the haystack B-{)

--
| Josef Moellers		| c/o Siemens Nixdorf Informationssysteme AG |
|  USA: mollers.pad@nixdorf.com	| Abt. STO-XS 113			     |
| !USA: mollers.pad@nixdorf.de	| Heinz-Nixdorf-Ring			     |
| Phone: (+49) 5251 104662	| D-4790 Paderborn			     |

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (01/11/91)

In article <josef.663238265@ugum01>, josef@nixpbe.nixdorf.de (josef Moellers) writes:
|> In <304@bria.AIX> mike@bria.AIX (Mike Stefanik/78125) writes:
|> 
|> >In article <1991Jan02.041209.9552@cs.widener.edu>, brendan@cs.widener.edu (Brendan Kehoe) writes:
|> >> 
|> >>   Hi there .. this is relative to a program I've been hacking on. This
|> >> is all on a Sun Sparc-1 under SunOS 4.1. First, I'm trying to find out
|> 
|> >Unless I am reading this wrong, you are asking about one user process modifying
|> >another user process' bss?  This is extremely bad karma!  For one thing, if
|> 
|> Ever heard of /proc?

No, what is that?  Do you mean /dev/proc?  Whatever it is, SunOS doesn't have it.

|> To answer the original question:
|> The header of an executable file contains the sizes of text, data and
|> bss of a program.
|> 
|> If Your system has a.out object file format, You need to find out
|> certain things about Your OS:
|> - where does it place the code? (I'm writing this on a MIPS and they put
|>   the code at soemthing like 0x400000, give or take a 0)

0x2000.

-- 
Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD
"We could nuke Baghdad into glass, wipe it with Windex, tie fatback on
our feet and go skating." - Air Force Times columnist Fred Reed

guy@auspex.auspex.com (Guy Harris) (01/13/91)

> Was that sufficiently obscure?

Yes, actually.  The really obscure part, as others have noted, is how
you plan to have process A get any access to the BSS space of process B.
UNIX systems generally don't let that happen unless process A is
debugging process B, either by:

	using "ptrace()" - which, on most UNIX systems, only lets a
	parent debug a child, but in SunOS after some 3.x
	release lets a process attach to another one *if* the UIDs of the
	process permit that;

or

	using "/proc" - no, it's not "/dev/proc", at least not on the
	systems I know of; it's a file system type, not a device driver
	- which isn't in current SunOS releases, although it is in some
	AT&T research systems, some S5R3 systems (the 3B4000 one?), S5R4
	(including the release Sun will have, I presume), and some other
	systems.  Files in "/proc" are normally owned by the effective
	user ID of the process they represent, and have mode
	"rw-------", so they impose restrictions similar to those of the
	SunOS PTRACE_ATTACH "ptrace()" request.

If you want the process to share memory, you're probably better off
using shared memory - either S5 shared memory (available since SunOS
3.2, but it's an optional feature that may not be configured into your
kernel) or "mmap()" of a plain file (available since SunOS 4.0, also
available in S5R4 and some other UNIX systems, and should be available
in 4.4BSD and OSF/1).

aegl@unisoft.UUCP (Tony Luck) (01/15/91)

If you don't have "/proc", then this little program will tell you where
things are attached in your address space (its up to you to guess which
things are text, data, bss, stack etc. ... but you get some clues ... like
whether the area is read-only or read-write).

Usage is "checkaddr [ start [ end [ pagesize ] ] ] ... it defaults to
a start address of 0x0, an end address of 4 Gbyte, and a pagesize of 4 Kbyte.
With these parameters it will take a *LONG* time to run as it is a little
program ... so most of the 4Gbyte address space is empty, so it will take,
and catch and longjmp out of about a million bus errors. Some systems may
try to grow the stack to "fix" a bus error that is below the stack but
within the maximum process size limits ... on these systems this program
may take an exceptionally long time ... and a great deal of swapping/paging
may happen.

CAUTION! This program does nothing that's wrong, but bugs in some operating
systems have resulted in unwanted effects (machines have panic'ed or hung).
If you choose to run this, then you are on your own ... don't blame me if
bad things happen. Further disclaimer ... UniSoft Corp. doesn't even know
that I'm posting this ... so don't try to blame them either.


/*
 * Copyright (c) 1991 Tony Luck.
 * Do what you like with this ... except sell it ... and don't blame me
 * for anything that happens.
 *
 * Check accessibility of all pages in address space.
 *
 * Usage: checkaddr [ start [ end [ pagesize ] ] ]
 */
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

#define	INVALID		0
#define	READONLY	1
#define	READWRITE	2

static char	*name[] = {
	"invalid", "readonly", "read/write"
};

static jmp_buf	buf;

/*ARGSUSED*/
static void
trap(signum)
	int	signum;
{
	signal(SIGSEGV, trap);
	longjmp(buf, 1);
}

int
main(argc, argv)
	int	argc;
	char	**argv;
{
	unsigned long	start, addr, oldaddr, limit, pagesize;
	char	tmp;
	int	access_type, lastaccess = -1;

	signal(SIGSEGV, trap);
	if (argc > 1)
		sscanf(argv[1], "%x", &start);
	else
		start = 0;
	if (argc > 2)
		sscanf(argv[2], "%x", &limit);
	else
		limit = 0xffffffff;
	if (argc > 3)
		sscanf(argv[3], "%x", &pagesize);
	else
		pagesize = 0x1000;


	addr = start;
	while (addr < limit) {
		if (setjmp(buf) == 0) {
			tmp = *(char *)addr;
			if (setjmp(buf) == 0) {
				tmp = *(char *)addr;
				*(char *)addr = tmp;
				access_type = READWRITE;
			}
			else {
				access_type = READONLY;
			}
		}
		else {
			access_type = INVALID;
		}
		if (access_type != lastaccess) {
			if (addr > start)
				printf("[0x%.8x -> 0x%.8x]: %s\n", start,
					addr-1, name[lastaccess]);
			start = addr;
			lastaccess = access_type;
		}
		oldaddr = addr;
		addr += pagesize;
		if (addr < oldaddr)
			break; /* address wraparound */
	}
	printf("[0x%.8x -> 0x%.8x]: %s\n", start, addr-1, name[lastaccess]);

	return 0;
}

josef@nixpbe.nixdorf.de (josef Moellers) (01/17/91)

In <3295@unisoft.UUCP> aegl@unisoft.UUCP (Tony Luck) writes:


>If you don't have "/proc", then this little program will tell you where
>things are attached in your address space (its up to you to guess which
>things are text, data, bss, stack etc. ... but you get some clues ... like
>whether the area is read-only or read-write).

[ description of program and program text deleted ]

Rather than bus-error-ing, how about a look at ye olde symboltable?
usually
_start	sits at the very beginning of the program code
etext	sits at the end of the program code
edata	sits at the end of the initialized data
end	sits at the end of the uninitialized data (bss)

--
| Josef Moellers		| c/o Siemens Nixdorf Informationssysteme AG |
|  USA: mollers.pad@nixdorf.com	| Abt. STO-XS 113			     |
| !USA: mollers.pad@nixdorf.de	| Heinz-Nixdorf-Ring			     |
| Phone: (+49) 5251 104662	| D-4790 Paderborn			     |

rlf@dptspd.sat.datapoint.com (Rory Foster) (01/18/91)

Hmm.  What a polemic subject.

Let's see, I don't believe the checkaddr program will do the
trick.  Take the i386 kernel for example, each process has
a 4Gb address space (this is user virtual) and allows real
memory to be shared by each process.  Your user process is
stepping through its own virtual space, but it's a different
virtual space than the other processes on the system.

But let's say that you have a kernel that will let you step
through all real memory, there is a window where you process
could be swapped out by swtch and real memory is reorganized.
When swtch establishes your process again, the data is not
there.  Granted, that could be a small window.

OK, now the COFF issue.  Well, again these are virtual addresses.
You say, s_paddr is physical?  Sorry it's only "a cheap trick".
See Understanding and Using COFF by G. Gircys.  In the middle of
page 38, you'll read that s_vaddr and s_paddr are the same.
The COFF file is "relocatable", so enough said.

Now, if the question where asked, where will my own process
begin loading its sections into virtual memory, then COFF and
ELF should provide some help (depends if you want user virtual
or kernel virtual).  This, however, was not the question.

I believe the original question was to let ProcA read the bss
section of ProcB.  Yes, shared memory is probably what you
want.  Another approach is to write a system call, to locate
the data in real memory and copy it into the address space
of the appropriate process.  But why?  Shared memory is easier.

Regards,

Rory Foster
rlf@dptspd.sat.datapoint.com

aegl@unisoft.UUCP (Tony Luck) (01/29/91)

josef@nixpbe.nixdorf.de (josef Moellers) writes:
>Rather than bus-error-ing, how about a look at ye olde symboltable?
>usually
>_start	sits at the very beginning of the program code
>etext	sits at the end of the program code
>edata	sits at the end of the initialized data
>end	sits at the end of the uninitialized data (bss)

Ah, but do you trust the symbol not to lie to you? And do you trust your kernel
to do all the things that it is supposed to do when mapping a process? Its
surprising how many systems have had odd little bugs that the "checkaddr"
program has shown up  (from forgetting to write protect the processes text to
leaving a read-write copy of the kernel mapped into each processes address
space!!!).

-Tony <aegl@unisoft.com>

allbery@NCoast.ORG (Brandon S. Allbery KB8JRR) (02/01/91)

As quoted from <3324@unisoft.UUCP> by aegl@unisoft.UUCP (Tony Luck):
+---------------
| josef@nixpbe.nixdorf.de (josef Moellers) writes:
| >Rather than bus-error-ing, how about a look at ye olde symboltable?
| >usually
| >_start	sits at the very beginning of the program code
| >etext	sits at the end of the program code
| >edata	sits at the end of the initialized data
| >end	sits at the end of the uninitialized data (bss)
| 
| Ah, but do you trust the symbol not to lie to you? And do you trust your kernel
+---------------

_start, etext, edata, end are magic symbols defined by ld when it creates an
executable.  My experience is that trying to use one of those names for your
own global(s) causes the link to fail....

+---------------
| to do all the things that it is supposed to do when mapping a process? Its
| surprising how many systems have had odd little bugs that the "checkaddr"
| program has shown up  (from forgetting to write protect the processes text to
| leaving a read-write copy of the kernel mapped into each processes address
| space!!!).
+---------------

What and where is "checkaddr"?  (Respond via MAIL, please.  And try to provide
a UUCP-able source for it, since I can't FTP --- failing that, give me an idea
of the size so I can decide if it's worth risking getting someone upset at me
for using them to mail stufffrom  bitftp@pucc....)

++Brandon
-- 
Me: Brandon S. Allbery			    VHF/UHF: KB8JRR on 220, 2m, 440
Internet: allbery@NCoast.ORG		    Packet: KB8JRR @ WA8BXN
America OnLine: KB8JRR			    AMPR: KB8JRR.AmPR.ORG [44.70.4.88]
uunet!usenet.ins.cwru.edu!ncoast!allbery    Delphi: ALLBERY