2021-10-11 18:37:13 -03:00

261 lines
7.1 KiB
C

/* @(#)modloadsym.c 1.1 94/10/31 SMI */
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
#ifdef sun386
#include <sys/types.h>
#include <stdio.h>
#include <filehdr.h>
#include <ldfcn.h>
#include <stab.h>
#include <syms.h>
#include <ar.h>
#include <sun/vddrv.h>
#define SYMESZ 18 /* number of bytes in one symbol table entry */
void fatal();
/*
* Read the symbol table (if any) and keep only those symbols which
* are within the module.
*
* This code from taken from nm.c.
*
* Someday we'll have support from the linker to do all this.
*/
LDFILE *fi;
getsymtab(filename, mmapaddr, modstart, modsize)
char *filename;
addr_t mmapaddr;
u_long modstart;
u_int modsize;
{
long symindx; /* symbol table index */
u_int sym_tab_size; /* symbol table size */
SYMENT *symp; /* pointer to symbol table */
SYMENT sym; /* symbol table entry */
AUXENT aux;
char *malloc();
char *symnametmp; /* ptr to symbol name in file*/
int i;
int nsyms; /* number of symbols we'll keep */
struct vdsym *vdsym; /* start of sym tab in mmap'd image */
int vdstroff; /* offset of sym name in mmap'd image */
char *vdstraddr; /* address of name in mmap'd image */
struct filehdr *fhdr; /* pointer to filehdr in mmap'd image */
extern int ncompare();
if ((fi = ldopen(filename, fi)) == NULL)
fatal("modload: %s: cannot open\n", filename);
if (!ISCOFF(HEADER(fi).f_magic))
fatal("modload: %s: bad magic\n", filename);
if (HEADER(fi).f_nsyms == 0)
return (0); /* no symbols */
/*
* seek to the symbol table
*/
if (ldtbseek(fi) != SUCCESS)
fatal("modload: %s: symbols missing from file", filename);
/*
* allocate symbol table memory
* the amount of memory needed is calculated by the
* number of entries multiplied by the size of each entry
*/
sym_tab_size = HEADER(fi).f_nsyms * sizeof (struct syment);
symp = (struct syment *)malloc(sym_tab_size);
if (symp == NULL)
fatal("ran out of memory processing symbol table", filename);
/*
* read the symbol table
*/
nsyms = 0;
for (symindx = 0L; symindx < HEADER(fi).f_nsyms; ++symindx) {
if (FREAD(&sym, SYMESZ, 1, fi) != 1)
fatal("error reading symbol table", filename);
/*
* read in and skip over any aux entries (if there are any)
*/
for (i = 1; i <= sym.n_numaux; ++i) {
if (FREAD(&aux, AUXESZ, 1, fi) != 1)
fatal("error reading symnbol table", filename);
++symindx;
}
if ((u_int)sym.n_value < modstart ||
(u_int)sym.n_value > modstart + modsize)
continue; /* skip symbols out of range */
if (sym.n_name[0] == '.')
continue; /* skip names starting with '.' */
symp[nsyms++] = sym;
}
qsort((char *)symp, nsyms, sizeof(struct syment), ncompare);
/*
* At this point we have the symbols that we're interested in
* sorted by value. Now we will generate our own symbol table
* and place it in our (private) mmap'd copy of the image.
*
* Our symbol table entry has 2 elements. The first is the offset
* from the start of the symbol table to the name of the symbol.
* This offset is converted to a virtual address by the VDLOAD ioctl
* to /dev/vd. The second element is the symbol value.
*/
vdsym = (struct vdsym *)(mmapaddr + (int)(HEADER(fi).f_symptr));
vdstroff = nsyms * sizeof(struct vdsym);
vdstraddr = (char *)&vdsym[nsyms];
for (i = 0 ; i < nsyms; i++) {
vdsym->vdsym_name = vdstroff;
vdsym->vdsym_value = symp[i].n_value;
vdsym++;
symnametmp = (char *)ldgetname(fi, &symp[i]);
strcpy(vdstraddr, symnametmp);
vdstraddr += strlen(symnametmp) + 1;
vdstroff += strlen(symnametmp) + 1;
}
fhdr = (struct filehdr *)mmapaddr;
fhdr->f_nsyms = nsyms;
ldclose(fi);
return (vdstroff); /* return symbol table size */
}
static int ncompare(p1, p2)
register struct syment *p1, *p2;
{
if (p1->n_value > p2->n_value)
return(1);
if (p1->n_value < p2->n_value)
return(-1);
return (0);
}
#else
#include <sys/types.h>
#include <sys/param.h>
#include <a.out.h>
#include <strings.h>
#include <sun/vddrv.h>
void fatal();
/*
* Read the symbol table (if any) and keep only those symbols which
* are within the module.
*
* Some of this code if from _nlist.c.
*/
getsymtab(filename, mmapaddr, modstart, modsize)
char *filename;
addr_t mmapaddr;
u_long modstart;
u_int modsize;
{
struct nlist *ksymp; /* pointer to symbols we're keeping */
struct nlist *symp; /* pointer to sym table in a.out image*/
struct nlist *symaddr; /* ptr to start of sym tab in image */
char *symnametmp; /* ptr to symbol name in file*/
int i;
int n;
int nsyms; /* number of symbols we'll keep */
struct vdsym *vdsym; /* start of sym tab in mmap'd image */
int vdstroff; /* offset of sym name in mmap'd image */
char *vdstraddr; /* address of name in mmap'd image */
struct exec *exec; /* pointer to hdr in mmap'd image */
long straddr; /* start of strings in a.out image */
extern char *malloc();
extern int ncompare();
exec = (struct exec *)mmapaddr; /* pointer to a.out header */
if (exec->a_magic != OMAGIC)
fatal("modload: %s: bad magic %o\n", filename, exec->a_magic);
if (exec->a_syms == 0)
return (0); /* no symbols */
nsyms = 0; /* number of syms we'll keep */
symaddr = (struct nlist *)(mmapaddr + N_SYMOFF(*exec));
symp = symaddr; /* ptr to first sym tab entry */
ksymp = (struct nlist *)malloc((u_int)exec->a_syms);
if (ksymp == NULL)
fatal("ran out of memory processing symbol table", filename);
for (n = exec->a_syms; n > 0; n -= sizeof(struct nlist), symp++) {
if ((u_int)symp->n_value < modstart ||
(u_int)symp->n_value > modstart + modsize)
continue; /* skip symbols out of range */
ksymp[nsyms++] = *symp; /* keep this symtab entry */
}
qsort((char *)ksymp, nsyms, sizeof(struct nlist), ncompare);
/*
* At this point we have the symbols that we're interested in
* sorted by value. Now we will generate our own symbol table
* and place it in our (private) mmap'd copy of the image.
*
* Our symbol table entry has 2 elements. The first is the offset
* from the start of the symbol table to the name of the symbol.
* This offset is converted to a virtual address by the VDLOAD ioctl
* to /dev/vd. The second element is the symbol value.
*/
vdsym = (struct vdsym *)symaddr;
vdstroff = nsyms * sizeof(struct vdsym);
vdstraddr = (char *)&vdsym[nsyms];
straddr = (long)((long)symaddr + exec->a_syms);
for (i = 0; i < nsyms; i++) {
symnametmp = (char *)(straddr + ksymp[i].n_un.n_strx);
vdsym->vdsym_value = ksymp[i].n_value;
vdsym->vdsym_name = vdstroff;
vdsym++;
strcpy(vdstraddr, symnametmp);
vdstraddr += strlen(symnametmp) + 1;
vdstroff += strlen(symnametmp) + 1;
}
exec->a_syms = nsyms;
return (vdstroff); /* return symbol table size */
}
static int ncompare(p1, p2)
register struct nlist *p1, *p2;
{
if (p1->n_value > p2->n_value)
return(1);
if (p1->n_value < p2->n_value)
return(-1);
return (0);
}
#endif