webber@csd.uwo.ca (Robert E. Webber) (11/21/90)
In article <9011192110.AA15043@decpa.pa.dec.com> cranston@guru.dec.com (Scott Cranston) writes: >strip(1) on MacMinix does not work. The origional flavor before the a.out.h >patch that Joe Pickert posted (part of ps(1) fixes) would not recognize >a file as an executable. After recompiling strip using the new a.out.h >it now runs. However, when I recompile a command and then strip it I get >a SYSTEM BOMB ID=10. > >Any ideas or fixes? A less drastic way of observing the problem is that nm on a normal executable reports the symbol table, on one of the supplied executables, it reports nothing, but on a stripped executable it reports can't read symbol table Insertion of print messages into nm shows the following behavior: cp nm bin/nm nm bin/nm >/dev/null does an lseek to location 6782 and then reads a table of size 1808 ls -l bin/nm reports a file size of 8860 strip bin/nm nm bin/nm >/dev/null does an lseek to location 6782 and then reads a table of size 1808. however, since ls -l bin/nm reports that the file is now 7020 bytes long, the above read only reads 238 bytes and then reports that it can't read the symbol table since the value from read is less than the length to read. the amount of table read is gotten from header.a_syms (header is of type exec which is defined in a.out.h) which is long and so is anded with 0xFFFF and cast to int before being passed to read. the lseek is made to location A_SYMPOS(header) where A_SYMPOS is a macro also defiined in a.out.h. A_SYMPOS(X) expands to: ((long)header.a_hdrlen) + header.a_text + header.a_data + ((header.a_hdrlen > (unsigned char) 32) ? header.a_trsize + header.a_drsize : 0) a_hdrlen is of type unsigned char; all the other quantities are size long. in this case, a_hdrlen is 0 and a_text is 6260 and a_data is 522 (both stripped and unstripped). looking at old stripped executables, the big difference seems to be that a_syms should be set to 0 for a stripped executable. looking at the code to strip.c, we see that a_syms is set to 0L. it is then written out to disk using write_header which writes an image of length a_hdrlen. since a_hdrlen is 0 (as observed above), this is less than totally thrilling. looking back at read_header, we find that it reads a minimum buffer of A_MINHDR and then reads more if a_hdrlen is larger than sizeof (struct exec). A_MINHDR has the value 32. changing write_header to: write_header(fd) int fd; { int WriteLength; WriteLength = A_MINHDR; if (WriteLength < (int) header.a_hdrlen) WriteLength = (int) header.a_hdrlen; lseek(fd, 0L, SEEK_SET); if (write(fd, (char *) & header, WriteLength) != WriteLength) return(1); return(0); } fixed the nm reading problem. however, I still get a system bomb when I try to execute a stripped binary, specifically ID = 28. Looking over the code, the only place in strip.c where the symbol table could be skipped over was the lseek done after the text and data space had been copied. This lseek is conditional on a test of relo_size (which is long) against the integer 0. relo_size at the moment turns out to be 194. Since it is non-zero, an lseek of length symb_size gets done. symb_size is the old value of header.a_syms. relo_size is the difference between st_size coming back from fstating the program and A_MINHDR plus the a_text, a_data, and symb_size. This looks like relo_size is going to be wrong if header is ever bigger than A_MINHDR, but that apparently isn't the case at the moment. The particular lseek that skips over symp_size uses whence set to 1 (which in <unistd.h> is SEEK_CUR relative to current position). This is all messed up because read_header first reads A_MINHDR bytes and then skips back to the beginning of the file and reads a_hdrlen bytes. Since, a_hdrlen is 0, this means that the later reads are 32 bytes off where they should be from. This variable size header stuff doesn't make much sense to me (doubtless it has to do with compatibility with code that I am not seeing (mm/exec.c always reads 32 bytes and then skips over anything else)). So, changed read_header along the lines of write_header above, i.e., introducing a ReadLength variable and then making sure that ReadLength is the max of A_MINHDR and a_hdrlen and doing the read at length ReadLength (thus ensuring we don't do any reads of length 0 for the same reasons we don't want to do writes of length 0). Now stripped programs seem to work just fine and don't bomb my system and nm works too on stripped programs. Since the only changes were to strip.c, don't think any other behavior changed. Seems to me that strip was built assuming that the compiler would put 32 in a_hdrlen, but the compiler/loader actually put 0 there. Not having source to the compiler/loader, I don't know why it is putting 0 there. Am sort of curious how the distributed programs were stripped given that the distributed strip program couldn't possibly work unless the compiler that built the unstripped programs was setting a_hdrlen to 32 or greater (which the distributed compiler on a Mac+ clearly does not). --- BOB (webber@csd.uwo.ca)
archetyp@uxh.cso.uiuc.edu (Joseph R Pickert) (11/28/90)
webber@csd.uwo.ca (Robert E. Webber) writes: >In article <9011192110.AA15043@decpa.pa.dec.com> cranston@guru.dec.com (Scott Cranston) writes: >>strip(1) on MacMinix does not work. The origional flavor before the a.out.h >>patch that Joe Pickert posted (part of ps(1) fixes) would not recognize >>a file as an executable. After recompiling strip using the new a.out.h >>it now runs. However, when I recompile a command and then strip it I get >>a SYSTEM BOMB ID=10. >> >>Any ideas or fixes? >A less drastic way of observing the problem is that nm on a normal executable >reports the symbol table, on one of the supplied executables, it reports >nothing, but on a stripped executable it reports > can't read symbol table >Insertion of print messages into nm shows the following behavior: > cp nm bin/nm > nm bin/nm >/dev/null >does an lseek to location 6782 and then reads a table of size 1808 > ls -l bin/nm >reports a file size of 8860 > strip bin/nm > nm bin/nm >/dev/null >does an lseek to location 6782 and then reads a table of size 1808. >however, since > ls -l bin/nm >reports that the file is now 7020 bytes long, the above read only reads >238 bytes and then reports that it can't read the symbol table since the >value from read is less than the length to read. I am aware of these problems. The ultimate cause is the a.out.h file. I will post a new one soon. Joe Pickert