[alt.sources] [comp.unix.programmer] ld -A EXAMPLE !

devil@techunix.BITNET (Gil Tene) (09/11/90)

Archive-name: dyn/11-Sep-90
Original-posting-by: devil@techunix.BITNET (Gil Tene)
Original-subject: ld -A EXAMPLE !
Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)

[Reposted from comp.unix.programmer.
Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti).]

Hello Unix programmers,

I have replied last week to a question about dynamic loading, and
mentioned that I have some example code for using ld -A.

Since then I have been SWAMPED with requests for this example code,
so I put a little program together. This program (dyn.c) accepts
the name of an object file (compiled with cc -c), loads it while
running, and runs it.

I have not put too much sweat into commenting this, and it is mainly
whipped up from some old code I used, and some stuff I got from other
people. So no flames or grudges about bad looking code, please. Just
use this as an example.

The FIRST function in the object file that is loaded is the
one that is run.

I have tested this on a Sun 3 running SunOs 4.0.3 and on a VAX
running BSD. This program DOES NOT work on a sun-4, I have no
idea why, but everyone out there is welcome to fix it up and
let me know what the fix was... There is also some strange
printf behaviour on the Sun-3.

Notice that the program expects the name of the object file
(h.o) without the .o extension, i.e. "h" for "h.o".

VAX (BSD) :
        cc -o dyn dyn.c

SUN :
        cc -o dyn -Bstatic dyn.c
        (the program doesn't work with dynamic libs. ).

Well, read, use, and enjoy.

Gil.

------------------------------------------------------------------
dyn.c :
Cut here :
-------------------------------------------------------------------

/*dyn.c an example "incremental" load (ld -A) program : */

#include <a.out.h>
#include <stdio.h>

char *sbrk();

/* static global variables: */
static char *base;              /* base for for algorithm load. */
static char myname[50];         /* main's executable file name */
static char (*load())(); /* the load function's body comes later on.. */

runc(name)
char *name;
{
        char (*c_func)();       /* the algorithm's function */
        c_func = load(name);
        if (c_func != 0)
                (*(int(*)())c_func)();
}


#define round(x,s) ((((x)-1) & ~((s)-1)) + (s))

char ld[] = "/bin/ld";  /* used in load below */

static char (*load(name))()
char *name;
/* This function loads an algorithm from a given file */
{
        struct exec exec;
        char n1[30];
        char n2[30];
        char basec[20];
        char libc_path[50];
        int fd;
        int nread,nalloc,nread_text,nread_data,database;
        char *oldbase;

        oldbase = base;
        /* align base to page size : */
        base = (char *) round((int)base,getpagesize());
        sbrk(base - oldbase);
        base = sbrk(0);
        strcpy(n1,name);
        strcat(n1,".o");
        strcpy(n2,name);
        strcat(n2,".out");
        sprintf(basec,"%x",(int)base);
        execx(ld,"/bin/ld",
                "-N",
                "-x",
                "-A",myname,"-T",basec,
                n1,"-o",n2,
                "-lc",
                0);
        fd = open(n2,0);
        if (fd > 0)
        {
                read(fd,(char *)&exec,sizeof exec);
                nread_text = round(exec.a_text,4);
                nread_data = round(exec.a_data,4);
                nalloc = nread_text + nread_data + exec.a_bss;

                nalloc = round(nalloc,1024);
                oldbase = sbrk(nalloc);

                (int)database = (int)oldbase + nread_text;
                base += nalloc;
                read(fd,oldbase,nread_text);
                read(fd,database,nread_data);
                close(fd);
                return( (char (*)()) oldbase);
        }
        else
        {
                printf("error while loading algorithm... !");
                close(fd);
                return(0);
        }
}

execx(name,arg1)
char *name;
char *arg1;
/* called by load above... */
{
char **a,**arg;
int rc;
        a = arg = &arg1;
        if(vfork() == 0) {
                execv(name,arg);
        }
        wait(&rc);
}

main(argc,argv)
int argc;
char **argv;
{
        char name[50];
        printf("main image name : %s\n",argv[0]);
        strcpy(myname,argv[0]); /* get the running image name into myname */
        printf("enter file name to load and run (no .o) :");
        gets(name);
        printf("loading and running : \n");
        runc(name);
        printf("main done...\n");
}

------------------------------------------------------------------
h.c :
Cut here :
-------------------------------------------------------------------

/* h.c : an example program to be incrementally loaded : */

my_first_func()
{
        char s[80];
        printf("hello world.\n");
        printf(" Enter a string : ");
        gets(s);
        printf(" I got : %s\n",s);
        printf(" bye bye.\n");
}

--------------------------------------------------------

--
--------------------------------------------------------------------
| Gil Tene                      "Some days it just doesn't pay     |
| devil@techunix.technion.ac.il   to go to sleep in the morning."  |
--------------------------------------------------------------------