> This seems to me to be very machine dependent, even compiler
> dependent. I'm sure that the compiler, in any event, would spit all
> kinds of warnings at you. Perhaps a way around it would be to gain
> access somehow to the memory management register, have a function that
> flips a bit just before calling the data code, and cleans up afterwards.
> Perhaps the problem is that C allows you to have identically named
> functions and variables, but you could get around that as well.
>
UNIX System V link editor (ld) allows one to put functions in the .data
section of a COFF file. All you need to do is to create a ld command
file (also called ifile). For example, the following ifile:
SECTIONS {
.data: {
file1.o (.text) /* file1.c, file2.c file3.c contain */
file2.o (.text) /* the functions text that to be */
file3.o (.text) /* placed in the .data section of */
... /* the final a.out */
}
}
and the following command lines:
cc -c file1.c file2.c file3.c
cc -N otherfiles.c ifile
will create an a.out which will have all the functions of file[123].c in
the .data section instead of .text section. One can also use ifile(s) to
do the following:
- place data in .text
- create dummy sections (e.g., store history info)
- create holes within sections
- align sections
- merge sections
- subsystem linking
and many others. It is a very powerful tool, but some of its features
are not well documented!!!
Steve Law
--*-------*-------*-------*-------*-------*-------*--
Name: I. S. Law (Steve)
UUCP: ihnp4!vax135!petsd!law
ARPA: vax135!petsd!law@BERKELEY
US Mail: MS 314B; Concurrent Computer Corp.
106 Apple St; Tinton Falls, NJ 07724
Phone: (201) 758-7280
--*-------*-------*-------*-------*-------*-------*--
In article <7...@petsd.UUCP> petsd!law (Steve Law) writes:
>UNIX System V link editor (ld) allows one to put functions in the .data
>section of a COFF file. All you need to do is to create a ld command
>file (also called ifile). For example ...
The person who started this discussion was already able to create code
in the .data space; whether it's done by the loader or at run-time by
the program is irrelevant. The question is whether it's possible to
_execute_ such a function. On a vax, you can. On a pdp11 with split
I/D, you can't, because .text and .data addresses are each 16 bits,
so an attempt to call a function from .data space will actually call
the function at the same address in .text space. (The workaround is
to use ld -N, so you don't have split I/D.) The remainder of this
discussion focuses on the 3b2, where .text and .data addresses have
separate ranges (.text normally starts at 0x80800000, .data at
0x80880000).
The first thing I tried was "ld -N" as described in ld(1) and a.out(4).
It produced a normal 0410 file, just like a plain "ld" or "ld -n".
Then I tried patching the a.out file to change the magic number from
0410 to 0407; the resulting a.out could not be run (ENOEXEC). So I
looked at the kernel source. In the code for sys exec, there was a
comment which stated that 0407 is unimplemented on the 3b2 because of
a hardware restriction; it's apparently just not possible to have a
segment which is simultaneously executable and writable (or readable).
In article <14...@devwrl.DEC.COM> will...@kirk.DEC (John Williams) writes:
>Perhaps a way around it would be to gain access somehow to the memory
>management register, have a function that flips a bit just before
>calling the data code, and cleans up afterwards.
This would allow a block of impure code to be _alternately_ .text
and .data, which is sufficient for some applications. Certainly this
sort of thing can be done in kernel mode (ptrace() is a good example);
Perhaps sys3b() is the loophole to user mode? The man page says it's
for the 3b20s -- there's a function of the same name on the 3b2, but
it might have a different set of subcommands. Subcommand 7 is to
"Modify the System Status Register". Is this it? In what way should
the register be modified to transmute a block at a given address?
(-: Obviously, you can't execute the data as code - the .data resides on
the 8088, while the .text is on an 8080. No wonder the floating point
was so slow!
--
# Bill Stewart, AT&T Bell Labs 2G-202, Holmdel NJ 1-201-949-0705 ihnp4!ho95c!wcs
Tony Hansen
ihnp4!pegasus!hansen
In article <6...@bentley.UUCP>, k...@bentley.UUCP (KW Heuer) writes:
>I've changed the cross-posting from net.unix to net.unix-wizards, as
>this is no longer a neophyte question.
>...
>The person who started this discussion was already able to create code
>in the .data space; whether it's done by the loader or at run-time by
>the program is irrelevant. The question is whether it's possible to
>_execute_ such a function. On a vax, you can. On a pdp11 with split
>I/D, you can't, because .text and .data addresses are each 16 bits,
>so an attempt to call a function from .data space will actually call
>the function at the same address in .text space. (The workaround is
>to use ld -N, so you don't have split I/D.) The remainder of this
>discussion focuses on the 3b2, where .text and .data addresses have
>separate ranges (.text normally starts at 0x80800000, .data at
>0x80880000).
>[more discussion, speculation]
Well, it IS possible on the 3b2 and very simply. Not only is it
possible to read text space but it is also possible to run data space.
Here's a quickie program which works on the 3b2:
main()
{
char arr[100]; /* needn't be nearly this big but what the heck */
void hello();
charcopy(hello,arr,100);
printf("I've now copied text space to data space.\n");
run(arr);
printf("I've now run data space.\n");
}
void hello()
{
printf("Hello world\n");
}
charcopy(a,b,c)
char *a, *b;
int c;
{
while (c--) *b++ = *a++;
}
run(stuff)
char (*stuff)();
{
(*stuff)();
}
Now maybe some pundit out there can explain WHY this works :-).
--
------------------------------- Disclaimer: The views contained herein are
| dan levy | yvel nad | my own and are not at all those of my em-
| an engihacker @ | ployer or the administrator of any computer
| at&t computer systems division | upon which I may hack.
| skokie, illinois |
-------------------------------- Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa,
vax135}!ttrdc!levy
I must give credit to Ehud Reiter (harvard!reiter) for the idea
on how to do this (he answered my question as to how it was accomplished in
Fortran, and I tried it in both f77 and C, and it worked).
I am sure that I am indeed running the data space rather than just capturing
a pointer to the text space, since in another version of the test program I
did a dump of the buffer, which compared identically to a dis(1) disas-
sembly of the LINKED executable section that I copied.
Maybe it would be a good idea to have a "dummy function" which would be copied
into an array then modified as needed, to avoid the nitty gritty problems of
the final linking? (I noticed that a disassembly of the object [.o] file
was a little different than the linked version, having places where ld(1)
evidently must "fill in the blanks" to have a valid sequence of code when
all external symbols are resolved.)
GOOD, but now the rest of the world wonder where you can read more about it!!??
Lars Hammarstrand.
Mea culpa (partly). This won't run on the 3B2/300, according to
Steve Sommers (ihuxn!sesv). I tested it on the 3B2/400. Reason
given is that the 32000 (3B2/300) chipset creates the data section without
execute permission, while the 32100 chipset (3B2/400) does allow execute
permission in the data section. Sorry if this misled anyone.
Chris Shaw watmath!watrose!cdshaw or cdshaw@watmath
University of Waterloo
Bogus as HELL !!!
> In article <7...@petsd.UUCP> l...@petsd.UUCP writes:
> >>UNIX System V link editor (ld) allows one to put functions in the .data
> etc, etc .....
>
> GOOD, but now the rest of the world wonder where you can read more about it!!??
COFF and COFF-based link editor (ld) are being used in both UNIX and UNIX/RTR
systems. Most of the COFF and ld features (e.g., ifile) can be found in the
COFF section and the LINK EDITOR section of
UNIX System V Release 2.0 Support Tool Guide
This document can be purphased from AT&T. Since UNIX/RTR exercises more
features of COFF and ld than UNIX, additional features them can be found
in one of the UNIX/RTR user's manuals. I don't know the exact volume
number. They used to be in volume 3 of the old user's manuals.
Steve Law
Check out the "Link Editor" section of AT&T's UNIX System V
Support Tools Guide, select number 307-108. The "COFF"
section of the same Guide is also relevant.
See sys3b(2) in the programmers manual for more details.
I haven't tried the same program on a 3b2/400. Perhaps the MMU has
been changed so these machinations are no longer necessary.
The following is a detailed example of how to execute code from data
space. Read no further if you don't want some nitty-gritty stuff.
Although this example shows execution from the stack, the same arguments
apply for execution out of other data space.
The algorithm in the manual page for computing the origin of the
read/write data segment doesn't seem to work properly for either
machine, however. The start of the data segment seems to be
0x80880000, so I have used this as an absolute value.
If you wish an executable that is read into data space to use subroutines
already compiled into the main program, you must link edit the executable
with knowledge of the symbol locations in the main program and you must
know at what address it is going to be loaded. This allows proper symbol
relocation. The file dmm.stb is an example of a loader directive file
used to link edit the test program q.c. Since printf() is the only external
routine that q() must get from main(), it is the only symbol that appears.
The loader directive file can be produced by first getting a namelist of
the main program (with "nm -ex dmmtest> dmm.stb") and then editing the output
with the editor script "ex.script" (use "ex - dmm.stb < ex.script").
The script will produce addresses for all external variables. It can
be manually edited to leave only the necessary ones. It is in the proper
format to be used as a link editor directive file. This script uses the
address of the variable "buf" for the location that q() will be linked at.
This should be changed as appropriate.
To generate a dynamically loadable routine "q.out" you first compile
q.o with "cc -c q.c". Then link edit with "ld -o q.out q.o dmm.stb
The main program must be linked with the "ld" library to get the
object file access routines (use "cc dmmtest.c -lld -o dmmtest"). The
magic number 44 in the program is the size of the output module q.o.
--------------------------
/* dmmtest.c
* Test dual mapped memory feature
* Compile with "cc dmmtest.c -lld -o dmmtest"
* Paul Sherman (poseidon!sherm)
*/
# include <stdio.h>
# include <filehdr.h>
# include <ldfcn.h>
# include <sys/sys3b.h>
# include <sys/param.h>
main()
{
printf("In main before P\n");
P();
printf("In main after P\n");
}
# define QSIZE 44 /* Size of output module */
char buf[QSIZE];
P()
{
LDFILE *f;
int bytes;
extern int etext;
long rw_data, re_data;
long offset;
int (*callq)();
/* compute R/W data origin */
/* fake with known magic number */
rw_data = 0x80880000;
/* attach R/E segment and get origin */
re_data = sys3b(S3BDMM, 1);
/* compute offset */
offset = re_data - rw_data;
/* calculate "virtual" address of executable routine */
callq = (int (*)()) (buf + offset);
printf("In P before Q\n");
/* read routine Q into buf */
f = ldopen("q.out", NULL);
ldnsseek(f, "outsec");
fread(buf, 1, QSIZE, IOPTR(f));
ldclose(f);
/* now jump to data space */
(*callq)();
/* hopefully we returned back here */
printf ("In P after Q\n");
}
-----------------------------
/* File q.c
* Compile separately and read into data space of main routine
* Build q.o with "cc -c q.c"
* Then link edit with "ld -o q.out q.o dmm.stb
* Create dmm.stb from nm output of dmmtest and ex.script
*/
q()
{
printf("I'm in Q now\n");
}
-----------------------------
# Ex script to take namelist output and massage it into a loader
# directive file for dynamic linking.
se ws
1,6d
g/static/d
/\<etext\>/d
/\<edata\>/d
/\<end\>/d
g/|/s// = /
g/|.*$/s//;/
/\<buf\>/
yank a
$
s/;/&\
\
SECTIONS {\
outsec /
put a
s/^.*=//
.-1,.j
s/;/: {q.o}\
}/
wq
-----------------------------
# dmm.stb
#
# Loader directive file for building q.out
#
printf = 0x80800774;
SECTIONS {
outsec 0x80880ae8: {q.o}
}
-----------------------------
Sample output from successful run of dmmtest:
In main before P
In P before Q
I'm in Q now
In P after Q
In main after P
--
Paul Sherman
AT&T Information Systems, Lincroft, NJ
{pegasus!phoenix}!poseidon!sherm
(201) 576-6316
typedef double (*PFD)();
extern PFD make_myexp(/* double base */);
/* make_myexp is implemented with malloc, _init_closure,
* and a `base function' which calls exp. */
PFD Exp, Exp10, Exp2;
/* Each call mallocs a new function object: */
Exp = make_myexp(2.71828183);
Exp10 = make_myexp(10.0);
Exp2 = make_myexp(2.0);
/* Now, pow(x,10.0) == (*Exp10)(x) == Exp10(x) */
--
----------------------------------------------------------
John R. Rose Thinking Machines Corporation
245 First St., Cambridge, MA 02142 (617) 876-1111 X270
ro...@think.arpa ihnp4!think!rose