Date: Mon, 6 Jan 1997 11:34:18 +0100 (MET) From: Robert Hoehne To: DJGPP workers Subject: Patch for binutils dealing with the stub Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII This is now the patch for 'coff-go32.c' from the bfd library. This patch can be applied to both (from binutils and gdb) but the changes are used only by the binutils. I have changed a little bit the reading of the stub which can be given with the env. variable $(STUB) for more checking of validity and I changed it to get also the stub from an executable file. I have added the aibility to use the old stub from an stubbed file. This is used by objcopy (and strip, because strip is in most parts objcopy). This is done in 'go32_stubbed_coff_bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd))' And at last I have added some comments to understand what I changed. Robert *** coff-go3.c~ Thu Sep 19 22:36:16 1996 --- coff-go3.c Sun Jan 5 11:05:06 1997 *************** You should have received a copy of the G *** 18,31 **** --- 18,55 ---- along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + /* This file handles now also stubbed coff images. The stub is a small + DOS executable program before the coff image to load it in memory + and execute it. This is needed, because DOS cannot run coff files. + + All the functions below are in most parts copied from the normal + coff functions and changed at the points where filepointers are + used in the coff header or symbol headers. + This is needed, because DJGPP uses a very special way to load and run + the coff image. It loads the image in memory and assumes then, that the + image had no stub by using the filepointers as pointers in the coff + image and NOT in the file. + + To be compatible with any existing executables I have fixed this + here and NOT in the DJGPP startup code. + */ + #define TARGET_SYM go32coff_vec #define TARGET_NAME "coff-go32" #define TARGET_UNDERSCORE '_' + #include "bfd.h" + + static boolean + go32_stubbed_coff_bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd)); + + #define coff_bfd_copy_private_bfd_data go32_stubbed_coff_bfd_copy_private_bfd_data + #include "coff-i386.c" extern const bfd_target * coff_object_p(bfd *abfd); + /* This function checks if the bfd is a stubbed coff image */ static const bfd_target * go32_stubbed_coff_object_p(abfd) bfd *abfd; *************** go32_stubbed_coff_object_p(abfd) *** 33,39 **** unsigned short header[3]; char magic[8]; unsigned long coff_start; - bfd_byte *buf; if (bfd_read(&header, 1, sizeof(header), abfd) != sizeof(header)) { --- 57,62 ---- *************** go32_stubbed_coff_object_p(abfd) *** 66,73 **** --- 89,98 ---- if (bfd_seek(abfd, 0, SEEK_SET) != 0) return 0; + /* Setup the correct file header size */ bfd_coff_filhsz(abfd) = coff_start + FILHSZ; + /* Let the normal coff object detecting function do it's work */ return coff_object_p(abfd); } *************** go32_stubbed_coff_swap_filehdr_in (abfd, *** 94,100 **** filehdr_dst->f_timdat = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_timdat); filehdr_dst->f_symptr = GET_FILEHDR_SYMPTR (abfd, (bfd_byte *) filehdr_src->f_symptr); ! if (filehdr_dst->f_symptr != 0) filehdr_dst->f_symptr += STUBSIZE; filehdr_dst->f_nsyms = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_nsyms); filehdr_dst->f_opthdr = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_opthdr); filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags); --- 119,128 ---- filehdr_dst->f_timdat = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_timdat); filehdr_dst->f_symptr = GET_FILEHDR_SYMPTR (abfd, (bfd_byte *) filehdr_src->f_symptr); ! if (filehdr_dst->f_symptr != 0) ! /* this pointer is a nonzero file offset, so it must be ! adjusted */ ! filehdr_dst->f_symptr += STUBSIZE; filehdr_dst->f_nsyms = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_nsyms); filehdr_dst->f_opthdr = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_opthdr); filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags); *************** go32_stubbed_coff_swap_filehdr_out (abfd *** 107,112 **** --- 135,141 ---- PTR in; PTR out; { + /* Copy the stub from 'stub_bytes' to the file header */ struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in; FILHDR *filehdr_out = (FILHDR *) ((unsigned char *)out + STUBSIZE); memcpy(out, _stub_bytes, STUBSIZE); *************** go32_stubbed_coff_swap_filehdr_out (abfd *** 115,120 **** --- 144,151 ---- bfd_h_put_16(abfd, filehdr_in->f_nscns, (bfd_byte *) filehdr_out->f_nscns); bfd_h_put_32(abfd, filehdr_in->f_timdat, (bfd_byte *) filehdr_out->f_timdat); if (filehdr_in->f_symptr != 0) + /* this pointer is a nonzero file offset, so it must be + adjusted */ PUT_FILEHDR_SYMPTR (abfd, (bfd_vma) filehdr_in->f_symptr - STUBSIZE, (bfd_byte *) filehdr_out->f_symptr); else *************** go32_stubbed_coff_swap_scnhdr_in (abfd, *** 146,158 **** scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, (bfd_byte *) scnhdr_ext->s_scnptr); ! if (scnhdr_int->s_scnptr != 0) scnhdr_int->s_scnptr += STUBSIZE; scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, (bfd_byte *) scnhdr_ext->s_relptr); ! if (scnhdr_int->s_relptr != 0) scnhdr_int->s_relptr += STUBSIZE; scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, (bfd_byte *) scnhdr_ext->s_lnnoptr); ! if (scnhdr_int->s_lnnoptr != 0) scnhdr_int->s_lnnoptr += STUBSIZE; scnhdr_int->s_flags = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_flags); #if defined(M88) scnhdr_int->s_nreloc = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_nreloc); --- 177,198 ---- scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, (bfd_byte *) scnhdr_ext->s_scnptr); ! if (scnhdr_int->s_scnptr != 0) ! /* this pointer is a nonzero file offset, so it must be ! adjusted */ ! scnhdr_int->s_scnptr += STUBSIZE; scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, (bfd_byte *) scnhdr_ext->s_relptr); ! if (scnhdr_int->s_relptr != 0) ! /* this pointer is a nonzero file offset, so it must be ! adjusted */ ! scnhdr_int->s_relptr += STUBSIZE; scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, (bfd_byte *) scnhdr_ext->s_lnnoptr); ! if (scnhdr_int->s_lnnoptr != 0) ! /* this pointer is a nonzero file offset, so it must be ! adjusted */ ! scnhdr_int->s_lnnoptr += STUBSIZE; scnhdr_int->s_flags = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_flags); #if defined(M88) scnhdr_int->s_nreloc = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_nreloc); *************** go32_stubbed_coff_swap_scnhdr_out (abfd, *** 188,205 **** --- 228,251 ---- (bfd_byte *) scnhdr_ext->s_size); if (scnhdr_int->s_scnptr != 0) + /* this pointer is a nonzero file offset, so it must be + adjusted */ PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr - STUBSIZE, (bfd_byte *) scnhdr_ext->s_scnptr); else PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, (bfd_byte *) scnhdr_ext->s_scnptr); if (scnhdr_int->s_relptr != 0) + /* this pointer is a nonzero file offset, so it must be + adjusted */ PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr - STUBSIZE, (bfd_byte *) scnhdr_ext->s_relptr); else PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, (bfd_byte *) scnhdr_ext->s_relptr); if (scnhdr_int->s_lnnoptr != 0) + /* this pointer is a nonzero file offset, so it must be + adjusted */ PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr - STUBSIZE, (bfd_byte *) scnhdr_ext->s_lnnoptr); else *************** go32_stubbed_coff_swap_aux_in (abfd, ext *** 328,333 **** --- 374,381 ---- { in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext); if (in->x_sym.x_fcnary.x_fcn.x_lnnoptr != 0) + /* the line pointer is a nonzero file offset, so it must be adjusted to the + correct value */ in->x_sym.x_fcnary.x_fcn.x_lnnoptr += STUBSIZE; in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext); } *************** go32_stubbed_coff_swap_aux_out (abfd, in *** 431,436 **** --- 479,486 ---- if (in->x_sym.x_fcnary.x_fcn.x_lnnoptr == 0) PUT_FCN_LNNOPTR(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext); else + /* the line pointer is a nonzero file offset, so it must be adjusted to the + correct value */ PUT_FCN_LNNOPTR(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr - STUBSIZE, ext); PUT_FCN_ENDNDX(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext); } *************** go32_stubbed_coff_swap_aux_out (abfd, in *** 461,475 **** --- 511,540 ---- return AUXESZ; } + /* + That's the function, which creates the stubbed image. There are + different cases from where the stub is taken. + At first the environment variable $(STUB) is checked. If it exists + and points to a valid stub the stub is taken from that file. + This file can be also a hole executable file, because the stub + is computed from the exe information at the start of that file. + + If there was any error, the standard stub (compiled in this file) + is taken. + */ + static boolean go32_stubbed_coff_mkobject (abfd) bfd * abfd; { + /* Creating a normal coff image failed */ if (coff_mkobject (abfd) == false) return false; + /* Do it only once */ if (!_stub_bytes) { + /* Check at first the environment variable $(STUB) */ char *stub = getenv("STUB"); if (stub) { *************** go32_stubbed_coff_mkobject (abfd) *** 480,506 **** f = open(stub,O_RDONLY|O_BINARY); if (f > 0) { ! _stub_bytes = malloc(st.st_size); ! if (read(f,_stub_bytes,st.st_size) != st.st_size) ! { ! free(_stub_bytes); ! _stub_bytes = NULL; ! } ! else { ! bfd_coff_filhsz(abfd) = st.st_size + FILHSZ; } close(f); } } } } if (!_stub_bytes) { _stub_bytes = malloc(sizeof(stub_bytes)); memcpy(_stub_bytes,stub_bytes,sizeof(stub_bytes)); bfd_coff_filhsz(abfd) = sizeof(stub_bytes) + FILHSZ; } return true; } --- 545,649 ---- f = open(stub,O_RDONLY|O_BINARY); if (f > 0) { ! unsigned short header[3]; ! char magic[8]; ! unsigned long coff_start; ! ! if (read(f, &header, sizeof(header)) >= 0) { ! if (header[0] == 0x5a4d) /* it is an exe file */ ! { ! /* Compute the size of the stub (it is every thing up ! to the beginning of the coff image) */ ! coff_start = (long)header[2]*512L; ! if (header[1]) ! coff_start += (long)header[1] - 512L; ! if (lseek(f, 512L, SEEK_SET) == 512L) ! { ! if (read(f,&magic, 8) == 8) ! { ! if (memcmp(magic,"go32stub",8) == 0) ! { ! /* Now we found a correct stub (hopefully) */ ! _stub_bytes = malloc(coff_start); ! lseek(f, 0L, SEEK_SET); ! if (read(f,_stub_bytes,coff_start) != coff_start) ! { ! free(_stub_bytes); ! _stub_bytes = NULL; ! } ! else ! { ! /* Now set the file header size because it is ! used by all the other bfd functions to compute ! the correct file pointers */ ! bfd_coff_filhsz(abfd) = coff_start + FILHSZ; ! } ! } ! } ! } ! } } close(f); } } } } + + /* There was something wrong above, so use now the standard builtin + stub */ if (!_stub_bytes) { _stub_bytes = malloc(sizeof(stub_bytes)); memcpy(_stub_bytes,stub_bytes,sizeof(stub_bytes)); bfd_coff_filhsz(abfd) = sizeof(stub_bytes) + FILHSZ; } + + return true; + } + + /* If ibfd was a stubbed coff image, copy the stub from that bfd + to the new obfd. This works only, if the size of the stubs are + the same. (obfd is assumed to be a stubbed coff image) + This function returns true always because there should be no + memory problem. + Because this function is part of the coff-go32-exe bfdt-target + I can assume that it is called ONLY for a bfd 'ibfd' for that + target. + */ + + static boolean + go32_stubbed_coff_bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd)) + { + int fd; + + /* obfd is not stubbed */ + if (ibfd->xvec != obfd->xvec) + return true; + + /* only same size stubs are supported, because when calling this + function all filepointers (section pointer, ...) are already + computed and I don't want to recompute them. */ + if (bfd_coff_filhsz(ibfd) != bfd_coff_filhsz(obfd)) + return true; + + fd = open(bfd_get_filename(ibfd),O_BINARY|O_RDONLY); + if (fd <= 0) + return true; + + #if 0 + /* This is not needed, because after the above checks I can assume + that the allocated 'stub_bytes' has the correct size. */ + if (_stub_bytes) + free(_stub_bytes); + _stub_bytes = malloc(bfd_coff_filhsz(ibfd) - FILHSZ); + #endif + + /* Now read in the stub from 'obfd' but without any check + of validity. */ + read(fd, _stub_bytes, bfd_coff_filhsz(ibfd) - FILHSZ); + + close(fd); return true; } Robert ***************************************************************** * Robert Hoehne, Fakultaet fuer Mathematik, TU-Chemnitz-Zwickau * * Post: Am Berg 3, D-09573 Dittmannsdorf * * e-Mail: Robert DOT Hoehne AT Mathematik DOT TU-Chemnitz DOT DE * * WWW: http://www.tu-chemnitz.de/~rho * *****************************************************************