Files
Arquivotheca.AIX-4.1.3/bos/usr/bin/sysdumpdev/tbl.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

864 lines
25 KiB
C

static char sccsid[] = "@(#)99 1.16 src/bos/usr/bin/sysdumpdev/tbl.c, cmddump, bos411, 9428A410j 6/10/91 16:01:42";
/*
* COMPONENT_NAME: CMDDUMP system dump control and formatting
*
* FUNCTIONS: c_tableinit, da_tableinit
*
* ORIGINS: 27
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1988, 1989
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/*
* Fill in the "table of contents" for a dump file.
* There are two such tables.
* 1. component_name/starting cdt offset (C_table)
* 2. data_area_name/starting offset (ZDa_table)
* One per component.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/dump.h>
#include <sys/dasd.h>
#include <sys/hd_config.h>
#include "dmpfmt.h"
#define TBL_INCR 16 /* realloc increment */
extern char *malloc(), *realloc();
extern checkflg; /* exit with error if sync lost */
extern char *Dumpfile; /* name of the dump file */
extern int comp_is_lvm; /* special processing for lvm */
struct cdt0 Cdt0; /* current component dump table */
static struct c_table *C_table; /* table of cdt headers */
static c_tbl_size; /* current size. grows by TBL_INCR */
static c_tbl_idx; /* current index */
struct da_table *ZDa_table; /* table of data areas */
struct da_table *kern_dt; /* kernel da_table */
static da_tbl_size; /* current size. grows by TBL_INCR */
static da_tbl_idx; /* current index */
static BMoffset; /* offset to bitmap */
static struct c_table *get_ct(); /* ensure space in C_table */
static struct da_table *get_da(); /* ensure space in ZDa_table */
static ce_read();
#ifdef _NO_PROTO
void setupvg();
struct pvol *getpvol();
struct lvol* getlvol();
int getwork_Q();
struct buf *getbpool();
static read_da();
int xread();
int readfrompage();
off_t dump_addr();
int ddistance ();
int getbitmap();
void rdpb();
#else
void setupvg( struct da_table *kdt, struct volgrp *vg );
struct pvol *getpvol( struct da_table *kdt, char *addr );
struct lvol *getlvol(struct da_table *kdt, char *addr);
int getwork_Q( struct da_table *kdt, struct buf **lvworkq, struct buf ***workq);
struct buf *getbpool( struct da_table *kdt, struct buf *bp );
static read_da( struct da_table *da, char *addr, char *buf, int len );
int xread( struct da_table *da, char *addr, char *buf, int len);
int readfrompage( int pagen, char *buf, int len );
off_t dump_addr( struct da_table *da, char *addr);
int ddistance ( struct da_table *da, char *from, char *to );
int getbitmap( struct da_table *da );
void rdpb( struct pbuf *ptr, struct pbuf *buf);
#endif
/*
* NAME: c_tableinit
* FUNCTION: make a table of the names of components and their file offsets
* into the dump file
* INPUTS: none
* RETURNS: head of a table of c_table structures, terminated by
* an entry with c_offset = -1
*/
struct c_table *
c_tableinit()
{
struct c_table *ctp;
struct cdt0 h;
int offsetsv;
int offset;
int n;
int i;
if(C_table) { /* free previous table */
free( (char *) C_table);
C_table = 0;
}
offsetsv = jtell(); /* get current offset */
for(;;) {
offset = jtell(); /* start of this component dump table */
if(jread(&h,sizeof(h)) != sizeof(h))
break;
if(offset == 0) {
/* must have a magic number at offset 0 or 512 */
if(h.cdt_magic != DMP_MAGIC) {
offsetsv = offset = 512;
if((jseek(offset) != 0) ||
(jread(&h,sizeof(h)) != sizeof(h)) ||
(h.cdt_magic != DMP_MAGIC)) {
cat_eprint(CAT_DMPMAGIC,
"bad magic: %08x offset 0x%x file %s\n",
h.cdt_magic,offset,Dumpfile);
exit(1);
}
}
}
if(h.cdt_magic == 0)
break;
if(h.cdt_magic != DMP_MAGIC) { /* check for loss of sync */
cat_eprint(CAT_DMPMAGIC,
"bad magic: %08x offset 0x%x file %s\n",
h.cdt_magic,offset,Dumpfile);
exit(1);
}
ctp = get_ct(); /* set a c_table entry */
strncpy(ctp->c_name,h.cdt_name,C_NAMESIZE); /* fill in name */
ctp->c_offset = offset; /* and offset */
n = NUM_ENTRIES(&h); /* number of data areas for this component */
BMoffset = offset + sizeof(h) + n * sizeof(struct cdt_entry);
for(i = 0; i < n; i++) /* skip over each one to get to the */
ce_read(0); /* next component dump table */
jseek(BMoffset);
}
jseek(offsetsv); /* reset file pointer */
ctp = get_ct(); /* "NULL" terminate the c_table list */
ctp->c_name[0] = '\0';
ctp->c_offset = -1; /* "NULL" is -1 */
return(C_table); /* return head of table */
}
/*
* NAME: da_tableinit
* FUNCTION: make a table of the names of data areas and their file offsets
* into the dump file
* INPUTS: none
* RETURNS: head of a table of da_table structures, terminated by
* an entry with da_offset = -1
*/
struct da_table *
da_tableinit()
{
int offsetsv;
int n;
int i;
struct cdt_entry ce;
struct da_table *tp;
static int lvm_init_count;
extern void lvm_da_tableinit();
Debug("da_tableinit: offset %x\n",jtell());
if(ZDa_table && ZDa_table != (struct da_table*)(-1)) { /* free previous table */
free( (char *) ZDa_table);
ZDa_table = 0;
}
offsetsv = jtell(); /* save starting offset */
if(jread(&Cdt0,sizeof(Cdt0)) != sizeof(Cdt0)) /* read cdt header */
goto da_exit;
if(offsetsv == 0) {
/* must have a magic number at offset 0 or 512 */
if(Cdt0.cdt_magic != DMP_MAGIC) {
offsetsv = 512;
if((jseek(offsetsv) != 0) ||
(jread(&Cdt0,sizeof(Cdt0)) != sizeof(Cdt0)))
goto da_exit;
}
}
if(Cdt0.cdt_magic == 0)
goto da_exit;
if(Cdt0.cdt_magic != DMP_MAGIC) {
cat_eprint(CAT_DMPMAGIC,
"bad magic: %08x offset 0x%x file %s\n",
Cdt0.cdt_magic,offsetsv,Dumpfile);
goto da_exit;
}
n = NUM_ENTRIES(&Cdt0);
BMoffset = offsetsv + sizeof(Cdt0) + n * sizeof(ce);
bzero(&ce,sizeof(ce));
for(i = 0; i < n; i++) {
tp = get_da();
tp->da_bmoffset = BMoffset;
tp->da_offset = tp->da_bmoffset + BITMAPSIZE(ce.d_ptr,ce.d_len);
ce_read(&ce); /* sets BMoffset to start of next bitmap */
strncpy(tp->da_name,ce.d_name,DA_NAMESIZE);
tp->da_ptr = (int)ce.d_ptr;
tp->da_len = ce.d_len;
Debug("da_tableinit: tp=%x bmoffset=%x offset=%x name='%s'\n",
tp,tp->da_bmoffset,tp->da_offset,ce.d_name);
}
jseek(offsetsv); /* restore file offset */
tp = get_da();
tp->da_name[0] = '\0';
tp->da_offset = -1; /* "NULL" terminate */
/*
* if this is the LVM component,
* use the tp's to find the vg's and refill in the component entry table.
* Also, switch to the kernel dump to use the kernel segment for finding
* the LVM structures.
*
* Set a kernel_segment_offset for use in displaying the lvm structures
* in the display options. Also, form a table of lbufs and associated
* pbufs.
*/
comp_is_lvm = FALSE; /* lvm_da_tableinit not used */
if (lvm_init_count++ == 0 && !strcmp(Cdt0.cdt_name, "lvm")) {
lvm_da_tableinit();
}
lvm_init_count--;
da_exit:
return(ZDa_table);
}
/*
* NAME: get_ct
* FUNCTION: allocate a c_table structure
* INPUTS: none
* RETURNS: pointer to c_table structure.
*
* This routine internally allocates TBL_INCR structures at a time
* to reduce the number of calls to realloc().
*/
static struct c_table *
get_ct()
{
if(C_table == 0 || c_tbl_size == 0) {
c_tbl_size = 0;
c_tbl_idx = 0;
if((C_table = MALLOC(TBL_INCR,struct c_table)) == 0) {
perror("malloc");
exit(1);
}
c_tbl_size += TBL_INCR;
} else if(c_tbl_idx == c_tbl_size) {
c_tbl_size += TBL_INCR;
if((C_table = REALLOC(C_table,c_tbl_size,struct c_table)) == 0) {
perror("realloc");
exit(1);
}
}
memset(&C_table[c_tbl_idx],0,sizeof(C_table[0]));
return(&C_table[c_tbl_idx++]);
}
/*
* NAME: get_da
* FUNCTION: allocate a da_table structure
* INPUTS: none
* RETURNS: pointer to da_table structure.
*
* This routine internally allocates TBL_INCR structures at a time
* to reduce the number of calls to realloc().
*/
static struct da_table *
get_da()
{
if(ZDa_table == 0 || da_tbl_size == 0) {
da_tbl_size = 0;
da_tbl_idx = 0;
if((ZDa_table = MALLOC(TBL_INCR,struct da_table)) == 0) {
perror("malloc");
exit(1);
}
da_tbl_size += TBL_INCR;
} else if(da_tbl_idx == da_tbl_size) {
da_tbl_size += TBL_INCR;
if((ZDa_table = REALLOC(ZDa_table,da_tbl_size,struct da_table)) == 0) {
perror("realloc");
exit(1);
}
}
memset(&ZDa_table[da_tbl_idx],0,sizeof(ZDa_table[0]));
return(&ZDa_table[da_tbl_idx++]);
}
/*
* NAME: ce_read
* FUNCTION: read the next component dump entry structure
* INPUTS: cep pointer to dump entry structure to fill
* if 0, allocate an internal structure.
* RETURNS: none
*
* The variable BMoffset is set to just after the last byte in the data area.
*/
static bitmap_t bm[DMP_MAXPAGES / sizeof(bitmap_t)];
static
ce_read(cep0)
struct cdt_entry *cep0;
{
int i;
int count;
int tcount;
int addr;
int npages;
int bitmapsize;
int offsetsv;
struct cdt_entry *cep;
struct cdt_entry ce;
cep = cep0 ? cep0 : &ce;
Debug("ce_read: offset=%x\n",jtell());
jread(cep,sizeof(*cep));
offsetsv = jtell();
bitmapsize = BITMAPSIZE(cep->d_ptr,cep->d_len);
npages = NPAGES(cep->d_ptr,cep->d_len);
Debug("ce_read: cep->d_ptr=%x len=%x bmsize=%x npages=%x BMoffset=%x\n",
cep->d_ptr,cep->d_len,bitmapsize,npages,BMoffset);
jseek(BMoffset);
jread(bm,bitmapsize);
addr = (int)cep->d_ptr;
count = cep->d_len;
BMoffset += bitmapsize;
Debug("ce_read: offset=%x PAGESIZE=%x bm[0]=%x\n",jtell(),PAGESIZE,bm[0]);
for(i = 0; i < npages; i++) {
tcount = MIN(count,PAGESIZE-(unsigned)addr % PAGESIZE);
Debug("tcount=%x addr=%x\n",tcount,addr);
if(ISBITMAP(bm,i))
BMoffset += tcount;
else
Debug("PAGE %d not in mem\n",i);
count -= tcount;
addr += tcount;
}
Debug("return: BMoffset=%x\n",BMoffset);
jseek(offsetsv);
}
int lvm_debug;
#define LVM_DEBUG(da) if (lvm_debug) { \
printf("LVM_DA_SET: da=%x bmoffset=%x offset=%x\n", \
da, da->da_bmoffset, da->da_offset); \
printf("\tda_name=%s da_ptr=%x da_len=%x\n", \
da->da_name, da->da_ptr, da->da_len); }
/* set component dump table entries for LVM */
#define LVM_DA_SET(name, ptr, len) da = get_da(); \
strncpy(da->da_name,name,DA_NAMESIZE); \
da->da_bmoffset = kern_dt->da_bmoffset;\
da->da_offset = kern_dt->da_offset; \
da->da_ptr = ptr; \
da->da_len = len; \
LVM_DEBUG(da)
static struct pbuf *hd_pbuf; /* anchor pbuf list for LVM */
/*
* NAME: lvm_da_tableinit
*
* FUNCTION: make a table of the names of data areas and their file offsets
* into the dump file. This routine takes the lvm dump component
* list of addresses of volgrp structures in the kernel segment
* to construct a dump table of addresses into the kernel segment
* for LVM data structures. The lvm component table in the dump
* is used to construct this more useful table for lvm dumps
* unless the kernel component, with the kernel segment, was
* not part of the dump.
* INPUTS: none
*
* RETURNS: none
*/
void
lvm_da_tableinit()
{
int i, n;
struct c_table *c;
struct cdt_entry ce;
struct da_table *da;
struct da_table *ldt; /* LVM data table */
struct vglist { /* vglist as in sysx/lvm/hd_top.c */
struct volgrp *vgp;
long major_num;
} *vglistp;
struct volgrp *vg; /* LVM volume group */
off_t lvmoffsetv; /* offset to LVM component */
int nvgs; /* number of volume groups */
int lvm_comp_set;
lvm_comp_set = FALSE;
lvmoffsetv = jtell(); /* save offset to lvm component */
if ((i = c_lookup("bos")) == -1) /* find "bos" component */
goto lvm_out; /* kernel segment not in the dump */
c = &C_table[i]; /* get bos component dump table */
jseek(c->c_offset); /* seek to bos component dump table*/
/* kerrnel segment is in the dump, form the LVM table */
ldt = ZDa_table; /* save lvm table */
ZDa_table = 0; /* da_tableinit would frees ZDa_table*/
if (kern_dt == NULL) {
kern_dt = da_tableinit(); /* bos component da_table entry */
ZDa_table = 0;
}
if (kern_dt == NULL || strcmp("kernel", kern_dt->da_name))
goto lvm_out;
/* !!! i = Da_lookup("kernel") !!! */
/* !!! kern_dt += i; !!! *//* select "kernel" da_table entry */
ZDa_table = 0; /* so get_da allocates new table */
/* first entry in the LVM component is the address of the pbuf anchor */
hd_pbuf = (struct pbuf *)ldt->da_ptr;
LVM_DA_SET("dmpbuf", (int)hd_pbuf, sizeof(struct pbuf *));
/* get volume group addresses to be looked up in the kernel segment */
vglistp = (struct vglist *) malloc((ldt+1)->da_len);
if (vglistp == NULL)
goto lvm_out;
if (read_da(ldt+1, (char *)(ldt+1)->da_ptr, (char *)vglistp, (ldt+1)->da_len) <= 0)
goto lvm_out;
/* scan array of vg pointers, lookup data in kernel segment */
nvgs = (ldt+1)->da_len / sizeof(struct vglist);
for ( ; nvgs > 0; nvgs--, vglistp++) {
if (vglistp->vgp) {
setupvg(kern_dt, vglistp->vgp);
}
}
da = get_da();
da->da_name[0] = '\0';
da->da_offset = -1; /* "NULL" terminate */
free( (char *) ldt); /* done with init LVM da_table */
ldt = ZDa_table;
ZDa_table = 0;
lvm_comp_set = TRUE;
lvm_out:
/* efficiency is no concern here */
jseek(lvmoffsetv); /* reset offset to start of lvm */
da_tableinit(); /* re-initialize Cdt0 to LVM */
if (lvm_comp_set == TRUE)
comp_is_lvm = TRUE;
ZDa_table = ldt; /* set ZDa_table to lvm */
/* no need to reset Cdt0->cdt_len, it will not be used again */
}
/*
* NAME: setupvg
*
* FUNCTION: make a table of the names of data areas and their file offsets
* into the dump file for a volume gruop.
*
* INPUTS: kdt (pointer to the kernel dump table), vg (volume group pointer)
*
* RETURNS: none
*/
void
setupvg( struct da_table *kdt, struct volgrp *vg )
{
int i, n, numpps, numbytes;
struct da_table *da;
struct volgrp v;
struct buf *b, *pb;
struct buf **workq;
struct lvol *lv;
struct pvol *pv;
if (read_da(kdt, (char *)vg, (char *)&v, sizeof(struct volgrp))
== sizeof(struct volgrp)) {
LVM_DA_SET( "volgrp", (int)vg, sizeof(struct volgrp) );
vg = &v;
/* dump the physical volumes in the volume group */
for (n = 0; n < MAXPVS; ++n) { /* loop thru pvol structs */
if (vg->pvols[n] == NULL)
continue;
pv = getpvol(kdt, (char *)vg->pvols[n]);
if (pv && pv->dev != HD_NODEVICE) {
LVM_DA_SET( "pvol", (int)vg->pvols[n], sizeof(struct pvol) );
if (pv->defect_tbl)
LVM_DA_SET( "dfct_tbl", /* defect table entry */
(int)pv->defect_tbl,
sizeof(struct defect_tbl));
} /* PV dump info set */
} /* end PVs for loop */
/* dump the logical volumes in the volume group */
for (n=0; n < MAXLVS; ++n) { /* loop thru lvol structs */
if (vg->lvols[n]) {
lv = getlvol(kdt, (char *)vg->lvols[n]); /* dump the LV */
if (lv == NULL)
continue;
LVM_DA_SET( "lvol", (int)vg->lvols[n], sizeof(struct lvol) );
/* dump work_Q and buffers */
if (lv->work_Q) {
LVM_DA_SET( "work_Q", (int)lv->work_Q,
(sizeof(struct buf *)) * WORKQ_SIZE);
if (getwork_Q(kdt, lv->work_Q, &workq) > 0)
for (i = 0; i < WORKQ_SIZE; i++) {
if (pb = workq[i]) {
LVM_DA_SET("workqbuf", (int)pb,
sizeof(struct buf));
b = getbpool(kdt, pb);
for (; b && b->av_back;) {
LVM_DA_SET("workqbuf", (int)b->av_back,
sizeof(struct buf));
b = getbpool(kdt, b->av_back);
}
}
}
} /* end the work buf for loop */
/* dump the partitions for the mirrors */
for (i = 0; i < 3; i++) { /* up to 3 PPs per LP */
if (lv->parts[i]) {
numpps = BLK2PART(vg->partshift, lv->nblocks);
numbytes = numpps * sizeof(struct part);
LVM_DA_SET("parts", (int)lv->parts[i], numbytes);
}
}
}
} /* end LVs for loop */
}
}
struct pvol *
getpvol( struct da_table *kdt, char *addr )
{
static struct pvol pv;
int len = sizeof(struct pvol);
return( read_da( kdt, addr, (char *)&pv, len ) == len ? &pv : NULL );
}
struct lvol *
getlvol(struct da_table *kdt, char *addr)
{
static struct lvol lv;
int len = sizeof(struct lvol);
return ( read_da( kdt, addr, (char *)&lv, len) == len ? &lv : NULL );
}
getwork_Q( struct da_table *kdt, struct buf **lvworkq, struct buf ***workq)
{
int n;
n = WORKQ_SIZE * (sizeof(struct buf *));
*workq = (struct buf **)malloc( n );
if (workq == NULL)
return (-1);
if (read_da(kdt, (char *)lvworkq, (char *)*workq, n) != n) {
free(workq);
n = -1;
}
return(n);
}
struct buf *
getbpool( struct da_table *kdt, struct buf *bp )
{
static struct buf b;
int nbytes;
nbytes = read_da( kdt, (char *)bp, (char *)&b, sizeof(struct buf));
return (nbytes == sizeof(struct buf) ? &b : NULL);
}
/*
* NAME: read_da
*
* FUNCTION: used to emulate addressing virtual memory
*
* INPUTS: da - data area table of a component entry
* addr - virtual memory address of dumped component
* buf - data copied to this buffer
* len - length of memory to copy to buf
*
* RETURNS: 0 (success), -1 failure
*
* BITMAPSIZE(ptr,len) is the size in bytes of the bitmap.
* NPAGES(ptr,len) is the number of pages spanned by the virtual address
* range of the data area.
* ISBITMAP(n) is true if relative page 'n' is in the bitmap.
* These macros are also used in the dsp_da and wr_cdt() routine of the
* dmp_do() kernel dump routine, and are defined in sys/dump.h .
*/
static bitmap_t bm[DMP_MAXPAGES / sizeof(bitmap_t)];
static
read_da( struct da_table *da, char *addr, char *buf, int len )
{
off_t data_offset;
getbitmap(da); /* bitmap indicates if page is in dump image */
if ((data_offset = dump_addr(da, addr)) != -1)
if (jseek(data_offset) != -1)
return( xread(da, addr, buf, len) );
return ( -1 );
}
/* round down to block address of block containing address */
#define BALIGN(address) ( (unsigned) address & ~(PAGESIZE - 1) )
/* determine relative block number: how many blocks addr is from saddr */
#define PAGENUM(saddr, addr) ((BALIGN(addr) - BALIGN(saddr)) / PAGESIZE)
/*
* NAME: xread
*
* FUNCTION: read from a dumpfile as though reading from memory
*
* INPUTS: saddr - dumped memory address, (struct da_table)->da_ptr
* addr - read from this virtual memory address
* buf - copy into this buffer
* len - length of read to copy into buffer
*
* RETURNS: number of bytes read
*/
xread( struct da_table *da, /* data table in component */
char *addr, /* virtual memory address to read */
char *buf, /* read copies into buf */
int len /* length of memory to copy */ )
{
int pagen; /* specifies page to read from */
int offset_in_page; /* address position in first page */
int lastpage; /* last page to read from */
int count; /* count of data remaining to be read */
int n;
pagen = PAGENUM(da->da_ptr, addr);
lastpage = pagen + NPAGES(addr, len);
offset_in_page = (unsigned) addr % PAGESIZE;
count = len;
/* read first page */
count -= readfrompage( pagen, buf, MIN(count, PAGESIZE - offset_in_page) );
/* read more pages */
for( pagen++; pagen <= lastpage; pagen++, buf += n, count -= n )
n = readfrompage(pagen, buf, MIN(count, PAGESIZE));
return ( len - count );
}
/*
* NAME: readfrompage
*
* FUNCTION: read from a dumpfile as though reading from a page in memory
*
* INPUTS: pagen - page number from start of dumped pages to be read
* buf - read into buf buffer
* len - length of read to copy into buffer
*
* RETURNS: number of bytes read
*
* ISBITMAP(n) is true if relative page 'n' is in the bitmap.
*/
readfrompage( int pagen, char *buf, int len )
{
int rc;
if (len < 0 || len > PAGESIZE)
rc = -1; /* len must be 0 to PAGESIZE */
else if ( ISBITMAP(bm, pagen) )
rc = jread(buf, len); /* read data */
else {
memset(buf, 0, len); /* memory paged out or never used */
rc = len;
}
return (rc);
}
/*
* NAME: dump_addr
*
* FUNCTION: return offset of addr in dump file.
*
* INPUTS: tp - da_table for a component dump table entry
* addr - address of memory within this dump table entry
*
* RETURNS: offset of addr in the dump file.
*
* ISBITMAP(n) is true if relative page 'n' is in the bitmap.
*/
off_t
dump_addr( struct da_table *da, char *addr)
{
off_t offset; /* offset in dump image */
offset = ddistance ( da, (char *)da->da_ptr, addr );
if (offset != -1)
offset += da->da_bmoffset + BITMAPSIZE(da->da_ptr, da->da_len);
return (offset);
}
/*
* NAME: ddistance
*
* FUNCTION: distance between two addresses in a dumpfile
*
* INPUTS: da - da_table for a component dump table entry
* from - first address
* to - second address
*
* RETURNS: separation of addresses in dump file or -1 on failure
*
* ISBITMAP(n) is true if relative page 'n' is in the bitmap.
*/
ddistance ( struct da_table *da, char *from, char *to )
{
int realdist, dumpdist; /* real distance, distance in dumpfile */
int pagen; /* block dumped */
int offset_in_page; /* offset in a block */
if ((realdist = to - from) == 0)
dumpdist = 0; /* same address */
else if (realdist < 0)
dumpdist = -1; /* first address not before second address */
else if ((int)from < da->da_ptr || (int)to >= (da->da_ptr + da->da_len))
dumpdist = -1; /* address(es) outside of dumped entry */
else {
/* determine distance from beginning of data to first address */
dumpdist = 0;
pagen = PAGENUM(da->da_ptr, from); /* blocks from start of data */
offset_in_page = (unsigned) from % PAGESIZE; /* offset in first page */
getbitmap( da ); /* initialize bit map for this da_table */
/* first page may be a partial block */
if (ISBITMAP(bm, pagen))
dumpdist += MIN(realdist, PAGESIZE - offset_in_page);
realdist -= MIN(realdist, PAGESIZE - offset_in_page);
/* more pages */
for ( ; realdist > 0; pagen++, realdist -= PAGESIZE)
if ( ISBITMAP(bm, pagen) )
dumpdist += MIN(realdist, PAGESIZE);
}
return (dumpdist); /* separation of addresses in dumpfile */
}
/*
* NAME: getbitmap
*
* FUNCTION: get the bitmap for the requested da_table
*
* INPUTS: da - da_table for a component dump table entry
*
* RETURNS: none
*/
getbitmap( struct da_table *da )
{
static struct da_table *da_bm; /* indicates which da's bitmap is set */
if (da_bm != da) {
jseek(da->da_bmoffset); /* seek to bitmap */
jread(bm, BITMAPSIZE(da->da_ptr, da->da_len)); /* read bitmap */
da_bm = da; /* bitmap is set for this da_table */
}
}
/*
* NAME: dsplookuplbuf
*
* FUNCTION: given an lbuf address, display the corresponding pbuf(s)
*
* INPUTS: addr - address of an lbuf
*
* NOTE: hd_pbuf anchors the pbufs. The pbuf field pb_forw links pbufs.
* The list is NULL terminated.
*
* MESSAGE NOTE: This is called from xtr.c which is used in crash. Will
* not be messagified/translated.
* RETURNS: none
*/
void
dsplookuplbuf(int addr)
{
int found=0; /* pbuf found */
struct pbuf pb; /* pbuf pointer */
struct pbuf *paddr; /* pbuf address */
static struct pbuf *saddr; /* start pbuf address */
printf("%x: ", (unsigned int) addr);
if (hd_pbuf && kern_dt) {
if (saddr == NULL) {
if (read_da(kern_dt, (char *)hd_pbuf, (char *) &saddr,
sizeof(struct pbuf *)) != sizeof(struct pubf *))
saddr = NULL;
}
}
if (saddr) {
rdpb(paddr = saddr, &pb);
do {
if ((int)pb.pb_lbuf == addr) {
found = 1;
printf("%x\t", (unsigned int) paddr);
}
/* Don't ever use a NULL pointer */
if( pb.pb_forw == NULL )
break;
rdpb(paddr = pb.pb_forw, &pb);
} while( paddr != saddr );
if ( found )
printf("\n");
else
printf("No pbufs found\n");
}
}
/*
* NAME: rdpb
*
* FUNCTION: read a pbuf from the kernel dump image
*
* INPUTS: ptr - address of a pbuf in the kernel dump image
* buf - copy the pbuf into buf
*/
void
rdpb( struct pbuf *ptr, struct pbuf *buf)
{
int rc;
rc = read_da(kern_dt, (char *)ptr, (char *)buf, sizeof(struct pbuf));
if (rc != sizeof(struct pbuf)) {
buf->pb_lbuf = NULL;
buf->pb_forw = NULL;
}
}