2.11BSD/sys/conf/netbind.c
/*
* netbind
*
* 1/6/95 -- remove 8 character limit on undefined symbol printf. sms.
* 1/8/94 -- revised for new object file format. sms.
*
* Resolve undefined inter-address-space references.
*
* Usage:
* netbind unix.o netnix.o
*
* Produces two files as output:
*
* d.unix.s -- definitions of all symbols referenced by
* unix.o but defined in netnix.o
* d.netnix.s -- definitions of all symbols referenced by
* netnix.o but defined in unix.o
*/
#include <sys/param.h>
#include <sys/file.h>
#include <a.out.h>
#include <stdio.h>
extern char *strdup(), *rindex();
struct xexec refExec, defExec;
#define MAXSYMLEN 32
#define NSYMS 200
struct symbol {
char *s_name;
u_int s_value;
u_int s_type;
} symtab[NSYMS], *symfree;
main(argc, argv)
int argc;
char **argv;
{
if (argc != 3) {
printf("usage: %s unix.bo netnix.bo\n", *argv);
exit(2);
}
resolve(argv[1], argv[2]); /* Produces d.unix.s */
resolve(argv[2], argv[1]); /* Produces d.netnix.s */
exit(0);
}
/*
* resolve --
*
* Resolve references made by ref to symbols defined in def.
*
* Side effects:
* Prints a list of undefined symbols if there are any.
* Produces the .s file corresponding to ref.
* Adds the number of undefined symbols encountered to undef.
*/
resolve(ref, def)
char *ref; /* Name of file referencing symbols */
char *def; /* Name of file defining symbols */
{
FILE *refIN, *defIN, *refSTR, *defSTR, *refOUT, *openobj();
struct nlist syment;
off_t stroff_ref, stroff_def;
int nundef;
char *rp, refout[MAXPATHLEN], name[MAXSYMLEN + 2];
bzero(name, sizeof (name));
if (rp = rindex(ref, '.'))
*rp = '\0';
(void)sprintf(refout, "d.%s.s", ref);
if (rp)
*rp = '.';
if ((refIN = openobj(ref, &refExec, &refSTR)) == NULL)
return;
if ((defIN = openobj(def, &defExec, &defSTR)) == NULL) {
fclose(refIN);
fclose(refSTR);
return;
}
if ((refOUT = fopen(refout, "w")) == NULL) {
perror(refout);
fclose(refIN);
fclose(refSTR);
fclose(defIN);
fclose(defSTR);
return;
}
/*
* Actually generate the .s file needed.
* Assumes that refExec and defExec have been set up to
* hold the a.out headers for the reference and definition
* object files.
*
* Algorithm:
* Build a table of undefined symbols in refIN.
* Define them by reading the symbol table of defIN.
* Generate the .s file to refOUT.
*/
syminit();
nundef = 0;
/* Find the undefined symbols */
stroff_ref = N_STROFF(refExec);
fseek(refIN, N_SYMOFF(refExec), L_SET);
while (fread(&syment, sizeof(syment), 1, refIN) > 0) {
if (syment.n_type == (N_EXT|N_UNDF) && syment.n_value == 0)
{
fseek(refSTR, stroff_ref + syment.n_un.n_strx, L_SET);
fread(name, sizeof (name), 1, refSTR);
if (strcmp(name, "_end") &&
strcmp(name, "_etext") &&
strcmp(name, "_edata"))
{
nundef++;
syment.n_un.n_name = name;
symadd(&syment);
}
}
}
/* Define the undefined symbols */
stroff_def = N_STROFF(defExec);
fseek(defIN, N_SYMOFF(defExec), L_SET);
while (fread(&syment, sizeof(syment), 1, defIN) > 0) {
if ((syment.n_type & N_EXT) == 0)
continue;
fseek(defSTR, stroff_def + syment.n_un.n_strx, L_SET);
fread(name, sizeof (name), 1, defSTR);
syment.n_un.n_name = name;
nundef -= symdef(&syment, &defExec.e);
}
/* Any undefined symbols left? */
if (nundef > 0) {
printf("%s: %d symbols undefined:\n", ref, nundef);
symundef();
}
symprdef(refOUT);
fclose(refSTR);
fclose(defSTR);
fclose(refIN);
fclose(defIN);
fclose(refOUT);
}
/*
* openobj --
*
* Open the indicated file, check to make sure that it is a
* valid object file with a symbol table, and read in the a.out header.
*
* Returns a pointer to an open FILE if successful, NULL if not.
* Prints its own error messages.
*/
FILE *
openobj(filename, exechdr, strfp)
char *filename;
struct xexec *exechdr;
FILE **strfp;
{
register FILE *f;
if (!(f = fopen(filename, "r"))) {
perror(filename);
return((FILE *)NULL);
}
*strfp = fopen(filename, "r"); /* for strings */
if (fread(exechdr, sizeof(*exechdr), 1, f) <= 0) {
printf("%s: no a.out header\n", filename);
goto bad;
}
if (N_BADMAG(exechdr->e)) {
printf("%s: bad magic number\n", filename);
goto bad;
}
if (exechdr->e.a_syms == 0) {
printf("%s: no symbol table\n", filename);
goto bad;
}
return(f);
bad: fclose(f);
fclose(*strfp);
return((FILE *)NULL);
}
/* -------------------- Symbol table management ----------------------- */
/*
* syminit --
*
* Clear and initialize the symbol table.
*/
syminit()
{
symfree = symtab;
}
/*
* symadd --
*
* Add a symbol to the table.
* We store both the symbol name and the symbol number.
*/
symadd(np)
struct nlist *np;
{
if (symfree >= &symtab[NSYMS]) {
printf("Symbol table overflow. Increase NSYMS.\n");
exit (1);
}
symfree->s_name = strdup(np->n_un.n_name);
if (!symfree->s_name)
{
printf("netbind: out of memory for symbol strings\n");
exit(1);
}
symfree->s_type = N_UNDF;
symfree->s_value = 0;
symfree++;
}
/*
* symdef --
*
* Use the supplied symbol to define an undefined entry in
* the symbol table.
*
* Returns 1 if the name of the symbol supplied was found in
* the table, 0 otherwise.
*/
symdef(np, ep)
struct nlist *np;
struct exec *ep;
{
register struct symbol *sp;
for (sp = symtab; sp < symfree; sp++)
if (!strcmp(sp->s_name, np->n_un.n_name)) {
int type = (np->n_type & N_TYPE);
switch (type) {
case N_TEXT:
case N_ABS:
sp->s_type = N_EXT|N_ABS;
sp->s_value = np->n_value;
break;
case N_DATA:
case N_BSS:
sp->s_type = N_EXT|N_ABS;
if (ep->a_flag)
sp->s_value = np->n_value;
else
sp->s_value = np->n_value - ep->a_text;
break;
case N_UNDF:
return(0);
default:
printf("netbind: symbol %s, bad type 0x%x\n",
np->n_un.n_name, np->n_type);
exit(1);
}
return (1);
}
return(0);
}
/*
* symundef --
*
* Print all undefined symbols in the symbol table.
* First sorts the table before printing it.
*/
symundef()
{
register struct symbol *sp;
int scmp();
qsort(symtab, symfree - symtab, sizeof(struct symbol), scmp);
for (sp = symtab; sp < symfree; sp++)
if ((sp->s_type & N_TYPE) == N_UNDF)
printf("%s\n", sp->s_name);
}
scmp(s1, s2)
register struct symbol *s1, *s2;
{
return(strcmp(s1->s_name, s2->s_name));
}
/*
* symprdef --
*
* Output all defined symbols in the symbol table.
* First sorts the table before printing it.
*/
symprdef(refOUT)
FILE *refOUT;
{
register struct symbol *sp;
int scmp();
qsort(symtab, symfree - symtab, sizeof (struct symbol), scmp);
for (sp = symtab; sp < symfree; sp++)
if ((sp->s_type & N_TYPE) != N_UNDF) {
fprintf(refOUT, ".globl %s\n", sp->s_name);
fprintf(refOUT, "%s = %o\n", sp->s_name, sp->s_value);
}
}