makani@marque.mu.edu (Gautam Makani) (02/22/89)
I was'nt too sure whether this was a UNIX or a C problem hence the cross-posting. I have a piece of code to read in line entries from an object file and filter out some information. I get an EMT (core dump) and cannot figure out why. The problem happens when I access a particular part of a struct, *but* i) I can print out the constituent data in that area. ii) Using "sdb" (UNIX debugger), I can access (look at) the variable. iii) Further, what puzzles me is that this happens the *second* time through a loop.I know that seems stupid ... I would appreciate it if someone tells me what's going on. The struct I'm looking at is struct lineno { union { long l_symndx ; long l_paddr ; } l_addr ; unsigned short l_lnno ; } ; #define LINENO struct lineno The problem comes when I access l_symndx as tmplptr->l_addr.l_symndx in any form (in an assignment, printf etc) Further on this machine,(3b15) sizeof(int) = sizeof(long) (if that helps) Code segement follows: ---------------------- for (i = 0, lindex = 0; i <= nlentries ;i++ ) { tmplptr = (LINENO *)lineptr; tmp = (char * ) tmplptr; printf("tmplptr.l_lnno = %lx\n", (long )tmplptr[0].l_lnno); for (ret = 0; ret < 6; ret ++) { printf("%x ", (char )*tmp); tmp++; } printf("\n"); printf("symndx = %lx\n",tmplptr->l_addr.l_symndx ); lineptr = (char *)((long) lineptr + LINESZ); } Program run follows: -------------------- c$ tline tline tmplptr.l_lnno = 0 0 0 0 b7 0 0 symndx = b7 tmplptr.l_lnno = 1 80 80 1 1d 0 1 EMT trap - core dumped Sdb session follows: --------------------- c$ sdb tline 0x8080030b in line:88: printf("symndx = %lx\n",tmplptr->l_addr.l_symndx ); *b line:88 b *R tline tmplptr.l_lnno = 0 0 0 0 b7 0 0 Breakpoint at line:88: printf("symndx = %lx\n",tmplptr->l_addr.l_symndx ); *c symndx = b7 tmplptr.l_lnno = 1 80 80 1 1d 0 1 Breakpoint at line:88: printf("symndx = %lx\n",tmplptr->l_addr.l_symndx ); *tmplptr->l_addr.l_symndx/lx 0x8080011d *s EMT (7) (sig 7) 0x8080030b in line:88: printf("symndx = %lx\n",tmplptr->l_addr.l_symndx ); *q ------------- I realize this is utilizing precious bandwidth. Please reply by e-mail and thanks in advance. ---------------------------------------------------------------------- Makani Gautam Department of MSCS email : makani@marque.mu.edu Marquette University { uwvax!uwmcsd1 | uunet }!marque!makani ----------------------------------------------------------------------
crossgl@ingr.com (Gordon Cross) (02/23/89)
In article <382@marque.mu.edu> makani@marque.UUCP (Gautam Makani) writes: > >I have a piece of code to read in line entries from an object file >and filter out some information. I get an EMT (core dump) and cannot >figure out why. > >The problem happens when I access a particular part of a struct, *but* > i) I can print out the constituent data in that area. > ii) Using "sdb" (UNIX debugger), I can access (look at) the variable. > iii) Further, what puzzles me is that this happens the *second* time through > a loop.I know that seems stupid ... > > I would appreciate it if someone tells me what's going on. This is a common problem on many architectures. In almost all likelyhood you are suffering from an alignment problem (notice this line from your code): > lineptr = (char *)((long) lineptr + LINESZ); It would appear that you have read the entire quantity of line number entries into a buffer. Then you are incrementing a pointer in the (apparantly) logical way to access each line entry in turn. Note that the macro LINESZ is defined to be 6 (check /usr/include/linenum.h)!! But if you try this: printf ("Size of line entry is %d.\n", sizeof (struct lineno)); I will bet that (I am not familiar with the 3b15 in particular) the answer will be 8!! Have you figured it out yet?? If so hit 'n'... The object file is written out without regard to the alignment requirements of the struct lineno. They pack them as tightly as possible to save on file size. The reason why you are failing on the SECOND loop pass is that the field 'l_symndx' will be correctly aligned for every other struct lineno. For example (assumming 4-byte alignment on longs) if your buffer begins at 0x10000 you have: lineno #1 ([0]) at address 0x10000 (correctly aligned) lineno #2 ([1]) at address 0x10006 (incorrectly aligned) lineno #3 ([2]) at address 0x1000c (correctly aligned) . . . You are going to have to do one of several things to correct this problem: 1) copy every other struct lineno into a static location (with proper alignment of course - simply declare a struct lineno variable and you've got it) as you peruse your buffer. 2) read the struct lineno's from the file one at a time into an array using ptr++ instead of ptr = (struct lineno *)((char *)ptr + LINESZ). You can do this yourself or use the 'ld' routines described in section 3X of the AT&T manuals. I like solution (1) because it will usually run faster than solution (2) but solution (2) has the advantage of simplicity... As regards sdb?? It seemingly works because of the nature of ptrace (which sdb uses to copy data from your process for examination). If the symbol table says something is a long, sdb gets the data realigned as a side effect of copying it!! >I realize this is utilizing precious bandwidth. Please reply by e-mail >and thanks in advance. Ooops! Well I guess this is of interest to everyone... -- Gordon Cross UUCP: uunet!ingr!crossgl "all opinions are 111 Westminister Way INTERNET: crossgl@ingr.com mine and not those Madison, AL 35758 MA BELL: (205) 772-7842 of my employer."