Referencing NULL pointers
Chris Torek
chris at mimsy.UUCP
Mon Jul 24 17:03:46 AEST 1989
In article <12928 at bloom-beacon.MIT.EDU> jik at athena.mit.edu
(Jonathan I. Kamens) writes:
>"Z0MAGIC" .... I believe that the original code for this came from
>off of the net somewhere,
It did.
>but we've done a lot of work with it to get it to work on both the VAX
>and RT (it was originally only for the VAX), and to fix some other problems.
What other problems? I tried to convince Mike to put it in 4.3BSD,
then in 4.3-tahoe, to no avail, but I have to admit I never put it
in myself.
>No, I don't know where it originally came from. And no, I don't know
>if we're allowed to redistribute it, although I just asked somebody
>and I may get an answer back eventually.
The pack rat hits --More--
>From jdb at mordor.UUCP (John Bruner) Thu Nov 29 13:14:52 1984
Relay-Version: version B 2.10.1 6/24/83; site umcp-cs.UUCP
Posting-Version: version B 2.10.2 9/5/84; site mordor.UUCP
Path: umcp-cs!seismo!ut-sally!mordor!jdb
From: jdb at mordor.UUCP (John Bruner)
Newsgroups: net.unix-wizards
Subject: Z0MAGIC: a.out without a valid page 0
Message-ID: <687 at mordor.UUCP>
Date: Thu, 29-Nov-84 13:14:52 EST
Date-Received: Thu, 29-Nov-84 14:55:12 EST
Distribution: net
Organization: S-1 Project, LLNL
Lines: 637
Several months ago I posted an inquiry about UNIX systems which do
not map virtual address 0 to a valid physical address. I was
interested in the number of library routines which would have to be
"fixed" because they depended upon being able to dereference a NULL
pointer (a zero-valued pointer on a non-tagged machine like the VAX).
The general consensus was that most library routines would work OK
without changes, especially since other implementations of UNIX on
non-DEC machines did not map 0 to a valid address.
I implemented an OPTIONAL new object format on our 4.2BSD 750's last
October. We have been using it for locally-written programs since
then and have had no problems. It has been helpful in finding
errors in some of our programs that were running "correctly" before.
The new object format is referred to as "-Z" format or Z0MAGIC format,
where Z0MAGIC is 0420. A Z0MAGIC executable file differs from a
corresponding ZMAGIC executable file in that the first page of the
text segment is always filled with zeros and the start address
("a_entry" in the a.out header) is 1024 rather than zero. The format
of the file is otherwise identical to a ZMAGIC file. This similarity
has two advantages. First, it is trivial to modify the debuggers and
other user-level programs to understand Z0MAGIC format, and second,
it is possible to produce a ZMAGIC binary from a Z0MAGIC binary by
simply patching the magic number. (This may be useful for transporting
a binary from one machine to another.)
At the user level, the following things were changed:
a.out.h new definitions added.
libc.a nlist.o must be recompiled (no source changes necessary)
ld The flag "-Z" is now recognized. "ld" inserts 1024 bytes of
zeros at the start of the text segment. [Note: the default
object format is still ZMAGIC or "-z" format.]
cc Because the leading 1024 bytes of zeros affect the addresses
assigned to symbols in the text segments, it is necessary for
the "-Z" flag to preceed all input file specifications in the
"ld" argument list. However, "cc" likes to call "ld":
ld -X /lib/crt0.o [ld flags] [files] [libraries] -lc
The "cc" command was changed to recognize "-Z" and call the
loader with "-Z" preceeding "/lib/crt0.o" in the arglist.
file The new magic number was recognized so that an appropriate
identification message could be output.
adb The debugger was informed that Z0MAGIC is a valid a.out
magic number.
dbx The debugger was informed that Z0MAGIC is a valid a.out
magic number. [Caveat: we do not use "dbx" here.]
sdb The debugger was informed that Z0MAGIC is a valid a.out
magic number. [We still use "sdb" locally.]
Also, several programs which use the macros in <a.out.h> should be
recompiled so that they understand Z0MAGIC files. No sources
changes are necessary. Here is a list of (at least most of) the
major ones:
diff gprof make nm prof ranlib size strings strip symorder
At the kernel level, a new flag was added to the x_flag field in the
(shared) text structure: XPZIV (Page Zero InValid). This flag is set
when the magic number is 0420 [why does the kernel source use literal
numeric constants for the magic numbers instead of #define-d names?].
xalloc() calls settprot() to make all pages in the text segment
readonly. A second argument was added to settprot() which specifies
whether page 0 is to be made inaccessible. (This argument is nonzero
if XPZIV is set.) If it is nonzero, the access mode for the first
CLSIZE 512-byte pages of the text segment is set to 0 (no access to
anyone). If the process attempts to reference any location in the
inaccessible area it will receive a SIGBUS signal.
When a traced child process is performing an I-space write on behalf
of its parent, procxmt() temporarily converts the text page to write
access, writes the word, and converts it back to readonly access.
A check was added to forbid writes to non-readable text pages (hence,
forbidding a write to an invalid page zero).
[BTW, I believe that the changes to a PDP-11 kernel would be similar,
although I no longer have access to an 11 to try them on. The new object
format could be based upon NMAGIC with the first 64 bytes of the first
segmentation register left invalid.]
-------------------------------------------------------------------------
++ h/text.h
*** /tmp/,RCSt1002982 Fri Oct 5 17:07:20 1984
--- text.h Thu Sep 20 10:39:07 1984
***************
*** 35,37
#define XLOCK 010 /* Being swapped in or out */
#define XWANT 020 /* Wanted for swapping */
#define XPAGI 040 /* Page in on demand from inode */
--- 35,38 -----
#define XLOCK 010 /* Being swapped in or out */
#define XWANT 020 /* Wanted for swapping */
#define XPAGI 040 /* Page in on demand from inode */
+ #define XPZIV 0100 /* Page 0 is not valid (420-format files) */
-------------------------------------------------------------------------
++ sys/kern_exec.c
*** /tmp/,RCSt1002988 Fri Oct 5 17:07:28 1984
--- kern_exec.c Thu Sep 20 10:51:28 1984
***************
*** 83,88
* 407 = plain executable
* 410 = RO text
* 413 = demand paged RO text
* Also an ASCII line beginning with #! is
* the file name of a ``shell'' and arguments may be prepended
* to the argument list if given here.
--- 83,89 -----
* 407 = plain executable
* 410 = RO text
* 413 = demand paged RO text
+ * 420 = demand paged R0 text, page 0 invalid
* Also an ASCII line beginning with #! is
* the file name of a ``shell'' and arguments may be prepended
* to the argument list if given here.
***************
*** 112,117
u.u_exdata.ux_tsize = 0;
break;
case 0413:
case 0410:
if (u.u_exdata.ux_tsize == 0) {
--- 113,119 -----
u.u_exdata.ux_tsize = 0;
break;
+ case 0420:
case 0413:
case 0410:
if (u.u_exdata.ux_tsize == 0) {
***************
*** 300,306
int nargc, uid, gid;
{
register size_t ts, ds, ss;
! int pagi;
if (u.u_exdata.ux_mag == 0413)
pagi = SPAGI;
--- 302,308 -----
int nargc, uid, gid;
{
register size_t ts, ds, ss;
! int pagi, pziv;
if (u.u_exdata.ux_mag == 0420) {
pagi = SPAGI;
***************
*** 302,308
register size_t ts, ds, ss;
int pagi;
! if (u.u_exdata.ux_mag == 0413)
pagi = SPAGI;
else
pagi = 0;
--- 304,310 -----
register size_t ts, ds, ss;
int pagi, pziv;
! if (u.u_exdata.ux_mag == 0420) {
pagi = SPAGI;
pziv = XPZIV;
} else if (u.u_exdata.ux_mag == 0413) {
***************
*** 304,310
if (u.u_exdata.ux_mag == 0413)
pagi = SPAGI;
! else
pagi = 0;
if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 &&
ip->i_count!=1) {
--- 306,316 -----
if (u.u_exdata.ux_mag == 0420) {
pagi = SPAGI;
! pziv = XPZIV;
! } else if (u.u_exdata.ux_mag == 0413) {
! pagi = SPAGI;
! pziv = 0;
! } else {
pagi = 0;
pziv = 0;
}
***************
*** 306,311
pagi = SPAGI;
else
pagi = 0;
if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 &&
ip->i_count!=1) {
register struct file *fp;
--- 312,319 -----
pziv = 0;
} else {
pagi = 0;
+ pziv = 0;
+ }
if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 &&
ip->i_count!=1) {
register struct file *fp;
***************
*** 369,375
(int)u.u_exdata.ux_dsize,
(int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize),
0, (int *)0);
! xalloc(ip, pagi);
if (pagi && u.u_procp->p_textp)
vinifod((struct fpte *)dptopte(u.u_procp, 0),
PG_FTEXT, u.u_procp->p_textp->x_iptr,
--- 377,383 -----
(int)u.u_exdata.ux_dsize,
(int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize),
0, (int *)0);
! xalloc(ip, pagi, pziv);
if (pagi && u.u_procp->p_textp)
vinifod((struct fpte *)dptopte(u.u_procp, 0),
PG_FTEXT, u.u_procp->p_textp->x_iptr,
-------------------------------------------------------------------------
++ sys/vm_text.c
*** /tmp/,RCSt1002994 Fri Oct 5 17:07:42 1984
--- vm_text.c Fri Sep 21 09:01:32 1984
***************
*** 58,64
* If it is being used, but is not currently in core,
* a swap has to be done to get it back.
*/
! xalloc(ip, pagi)
register struct inode *ip;
{
register struct text *xp;
--- 58,64 -----
* If it is being used, but is not currently in core,
* a swap has to be done to get it back.
*/
! xalloc(ip, pagi, pziv)
register struct inode *ip;
{
register struct text *xp;
***************
*** 94,100
return;
}
xp->x_flag = XLOAD|XLOCK;
! if (pagi)
xp->x_flag |= XPAGI;
ts = clrnd(btoc(u.u_exdata.ux_tsize));
xp->x_size = ts;
--- 94,100 -----
return;
}
xp->x_flag = XLOAD|XLOCK;
! if (pagi) {
xp->x_flag |= XPAGI;
if (pziv)
xp->x_flag |= XPZIV;
***************
*** 96,101
xp->x_flag = XLOAD|XLOCK;
if (pagi)
xp->x_flag |= XPAGI;
ts = clrnd(btoc(u.u_exdata.ux_tsize));
xp->x_size = ts;
if (vsxalloc(xp) == NULL) {
--- 96,104 -----
xp->x_flag = XLOAD|XLOCK;
if (pagi) {
xp->x_flag |= XPAGI;
+ if (pziv)
+ xp->x_flag |= XPZIV;
+ }
ts = clrnd(btoc(u.u_exdata.ux_tsize));
xp->x_size = ts;
if (vsxalloc(xp) == NULL) {
***************
*** 111,117
u.u_procp->p_textp = xp;
xlink(u.u_procp);
if (pagi == 0) {
! settprot(RW);
u.u_procp->p_flag |= SKEEP;
(void) rdwri(UIO_READ, ip,
(caddr_t)ctob(tptov(u.u_procp, 0)),
--- 114,120 -----
u.u_procp->p_textp = xp;
xlink(u.u_procp);
if (pagi == 0) {
! settprot(RW, 0);
u.u_procp->p_flag |= SKEEP;
(void) rdwri(UIO_READ, ip,
(caddr_t)ctob(tptov(u.u_procp, 0)),
***************
*** 119,125
2, (int *)0);
u.u_procp->p_flag &= ~SKEEP;
}
! settprot(RO);
u.u_segflg = 0;
xp->x_flag |= XWRIT;
xp->x_flag &= ~XLOAD;
--- 122,128 -----
2, (int *)0);
u.u_procp->p_flag &= ~SKEEP;
}
! settprot(RO, pziv);
u.u_segflg = 0;
xp->x_flag |= XWRIT;
xp->x_flag &= ~XLOAD;
-------------------------------------------------------------------------
++ sys/sys_process.c
*** /tmp/,RCSt1003000 Fri Oct 5 17:07:51 1984
--- sys_process.c Fri Sep 21 09:22:04 1984
***************
*** 139,144
goto error;
xp->x_iptr->i_flag &= ~ITEXT;
}
i = -1;
if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
if (chgprot((caddr_t)ipc.ip_addr, RW) &&
--- 139,150 -----
goto error;
xp->x_iptr->i_flag &= ~ITEXT;
}
+ /*
+ * Location must be accessible for read (could be invalid
+ * if in page 0 and XPZIV is set.
+ */
+ if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
+ goto error;
i = -1;
if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
if (chgprot((caddr_t)ipc.ip_addr, RW) &&
-------------------------------------------------------------------------
++ vax/vm_machdep.c
*** /tmp/,RCSt1003006 Fri Oct 5 17:07:58 1984
--- vm_machdep.c Fri Sep 21 09:04:55 1984
***************
*** 153,159
return (1);
}
! settprot(tprot)
long tprot;
{
register int *ptaddr, i;
--- 153,159 -----
return (1);
}
! settprot(tprot, pziv)
long tprot;
{
register int *ptaddr, i;
***************
*** 161,167
ptaddr = (int *)mfpr(P0BR);
for (i = 0; i < u.u_tsize; i++) {
ptaddr[i] &= ~PG_PROT;
! ptaddr[i] |= tprot;
}
mtpr(TBIA, 0);
}
--- 161,168 -----
ptaddr = (int *)mfpr(P0BR);
for (i = 0; i < u.u_tsize; i++) {
ptaddr[i] &= ~PG_PROT;
! if (i >= CLSIZE || !pziv)
! ptaddr[i] |= tprot;
}
mtpr(TBIA, 0);
}
-------------------------------------------------------------------------
++ ld.c
*** /tmp/,RCSt1009223 Thu Nov 29 09:51:56 1984
--- /tmp/,RCSt2009223 Thu Nov 29 09:52:15 1984
***************
*** 230,235
int nflag; /* pure procedure */
int dflag; /* define common even with rflag */
int zflag; /* demand paged */
long hsize; /* size of hole at beginning of data to be squashed */
int Aflag; /* doing incremental load */
int Nflag; /* want impure a.out */
--- 230,236 -----
int nflag; /* pure procedure */
int dflag; /* define common even with rflag */
int zflag; /* demand paged */
+ int Zflag; /* demand paged, page 0 not mapped (invalid) */
long hsize; /* size of hole at beginning of data to be squashed */
int Aflag; /* doing incremental load */
int Nflag; /* want impure a.out */
***************
*** 434,440
continue;
case 'n':
nflag++;
! Nflag = zflag = 0;
continue;
case 'N':
Nflag++;
--- 435,441 -----
continue;
case 'n':
nflag++;
! Nflag = zflag = Zflag = 0;
continue;
case 'N':
Nflag++;
***************
*** 438,444
continue;
case 'N':
Nflag++;
! nflag = zflag = 0;
continue;
case 'd':
dflag++;
--- 439,445 -----
continue;
case 'N':
Nflag++;
! nflag = zflag = Zflag = 0;
continue;
case 'd':
dflag++;
***************
*** 461,466
goto next;
case 'z':
zflag++;
Nflag = nflag = 0;
continue;
default:
--- 462,477 -----
goto next;
case 'z':
zflag++;
+ Nflag = nflag = Zflag = 0;
+ continue;
+ case 'Z':
+ if (tsize != 0)
+ error(1, "-Z: too late, some text already loaded (-z assumed)");
+ else {
+ Zflag++;
+ tsize = pagesize;
+ }
+ zflag++; /* -Z implies -z */
Nflag = nflag = 0;
continue;
default:
***************
*** 541,546
filname = 0;
middle();
setupout();
p = argv+1;
for (c=1; c<argc; c++) {
ap = *p++;
--- 552,559 -----
filname = 0;
middle();
setupout();
+ if (Zflag)
+ torigin += pagesize;
p = argv+1;
for (c=1; c<argc; c++) {
ap = *p++;
***************
*** 1019,1025
}
tout = &toutb;
bopen(tout, 0);
! filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);
filhdr.a_text = nflag ? tsize :
round(tsize, zflag ? pagesize : sizeof (long));
filhdr.a_data = zflag ? round(dsize, pagesize) : dsize;
--- 1032,1038 -----
}
tout = &toutb;
bopen(tout, 0);
! filhdr.a_magic = nflag ? NMAGIC : (zflag ? (Zflag ? Z0MAGIC : ZMAGIC) : OMAGIC);
filhdr.a_text = nflag ? tsize :
round(tsize, zflag ? pagesize : sizeof (long));
filhdr.a_data = zflag ? round(dsize, pagesize) : dsize;
***************
*** 1036,1042
else
filhdr.a_entry = entrypt->n_value;
} else
! filhdr.a_entry = 0;
filhdr.a_trsize = (rflag ? trsize:0);
filhdr.a_drsize = (rflag ? drsize:0);
bwrite((char *)&filhdr, sizeof (filhdr), tout);
--- 1049,1055 -----
else
filhdr.a_entry = entrypt->n_value;
} else
! filhdr.a_entry = Zflag ? pagesize : 0;
filhdr.a_trsize = (rflag ? trsize:0);
filhdr.a_drsize = (rflag ? drsize:0);
bwrite((char *)&filhdr, sizeof (filhdr), tout);
***************
*** 1043,1049
if (zflag) {
bflush1(tout);
biobufs = 0;
! bopen(tout, pagesize);
}
wroff = N_TXTOFF(filhdr) + filhdr.a_text;
outb(&dout, filhdr.a_data);
--- 1056,1062 -----
if (zflag) {
bflush1(tout);
biobufs = 0;
! bopen(tout, Zflag ? (2*pagesize) : pagesize);
}
wroff = N_TXTOFF(filhdr) + filhdr.a_text;
outb(&dout, filhdr.a_data);
-------------------------------------------------------------------------
++ cc.c
*** /tmp/,RCSt1009253 Thu Nov 29 09:53:59 1984
--- /tmp/,RCSt2009253 Thu Nov 29 09:54:01 1984
***************
*** 22,28
int idexit();
char **av, **clist, **llist, **plist;
int cflag, eflag, oflag, pflag, sflag, wflag, Rflag, exflag, proflag;
! int gflag, Gflag;
char *dflag;
int exfail;
char *chpass;
--- 22,28 -----
int idexit();
char **av, **clist, **llist, **plist;
int cflag, eflag, oflag, pflag, sflag, wflag, Rflag, exflag, proflag;
! int gflag, Gflag, Zflag;
char *dflag;
int exfail;
char *chpass;
***************
*** 120,125
case 'd':
dflag = argv[i];
continue;
}
t = argv[i];
c = getsuf(t);
--- 120,128 -----
case 'd':
dflag = argv[i];
continue;
+ case 'Z':
+ Zflag++;
+ continue;
}
t = argv[i];
c = getsuf(t);
***************
*** 244,250
nocom:
if (cflag==0 && nl!=0) {
i = 0;
! av[0] = "ld"; av[1] = "-X"; av[2] = crt0; na = 3;
if (outfile) {
av[na++] = "-o";
av[na++] = outfile;
--- 247,256 -----
nocom:
if (cflag==0 && nl!=0) {
i = 0;
! av[0] = "ld"; av[1] = "-X"; na = 2;
! if (Zflag)
! av[na++] = "-Z";
! av[na++] = crt0;
if (outfile) {
av[na++] = "-o";
av[na++] = outfile;
--
John Bruner (S-1 Project, Lawrence Livermore National Laboratory)
MILNET: jdb at mordor.ARPA [jdb at s1-c] (415) 422-0758
UUCP: ...!ucbvax!dual!mordor!jdb ...!decvax!decwrl!mordor!jdb
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: chris at mimsy.umd.edu Path: uunet!mimsy!chris
More information about the Comp.unix.wizards
mailing list