From cb43721da5d2e451a068fc3397b89ec1f47ce2bc Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sun, 12 Sep 1999 00:30:27 +0000 Subject: [PATCH] 1999-09-11 Donn Terry * peicode.h (coff_swap_scnhdr_in): If COFF_IMAGE_WITH_PE, the get the overflow of the s_nlnno field from the s_nreloc field. * peigen.c (_bfd_pei_swap_scnhdr_out): If doing a final link, swap the s_nlnno overflow of the .text section into the s_nreloc field. --- bfd/ChangeLog | 6 ++++++ bfd/peicode.h | 16 +++++++++++++-- bfd/peigen.c | 57 ++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 28d57801d6..ff1f942335 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -7,6 +7,12 @@ 1999-09-11 Donn Terry + * peicode.h (coff_swap_scnhdr_in): If COFF_IMAGE_WITH_PE, the + get the overflow of the s_nlnno field from the s_nreloc field. + * peigen.c (_bfd_pei_swap_scnhdr_out): If doing a final link, swap + the s_nlnno overflow of the .text section into the s_nreloc + field. + * peigen.c (add_data_entry): Declare. (pei_swap_aouthdr_out): Get image size right. Set linker version more intuitively. diff --git a/bfd/peicode.h b/bfd/peicode.h index 605b1c0192..0b6bde4e44 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -215,8 +215,20 @@ coff_swap_scnhdr_in (abfd, ext, in) GET_SCNHDR_LNNOPTR (abfd, (bfd_byte *) scnhdr_ext->s_lnnoptr); scnhdr_int->s_flags = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_flags); - scnhdr_int->s_nreloc = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nreloc); - scnhdr_int->s_nlnno = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nlnno); + /* MS handles overflow of line numbers by carrying into the reloc + field (it appears). Since it's supposed to be zero for PE + *IMAGE* format, that's safe. This is still a bit iffy. */ +#ifdef COFF_IMAGE_WITH_PE + scnhdr_int->s_nlnno = + (bfd_h_get_16 (abfd, (bfd_byte *) scnhdr_ext->s_nlnno) + + (bfd_h_get_16 (abfd, (bfd_byte *) scnhdr_ext->s_nreloc) << 16)); + scnhdr_int->s_nreloc = 0; +#else + scnhdr_int->s_nreloc = bfd_h_get_16 (abfd, + (bfd_byte *) scnhdr_ext->s_nreloc); + scnhdr_int->s_nlnno = bfd_h_get_16 (abfd, + (bfd_byte *) scnhdr_ext->s_nlnno); +#endif if (scnhdr_int->s_vaddr != 0) { diff --git a/bfd/peigen.c b/bfd/peigen.c index 24945b409f..a79b85705c 100644 --- a/bfd/peigen.c +++ b/bfd/peigen.c @@ -958,27 +958,50 @@ _bfd_pei_swap_scnhdr_out (abfd, in, out) bfd_h_put_32(abfd, flags, (bfd_byte *) scnhdr_ext->s_flags); } - if (scnhdr_int->s_nlnno <= 0xffff) - bfd_h_put_16(abfd, scnhdr_int->s_nlnno, (bfd_byte *) scnhdr_ext->s_nlnno); - else + if (coff_data (abfd)->link_info + && ! coff_data (abfd)->link_info->relocateable + && ! coff_data (abfd)->link_info->shared + && strcmp (scnhdr_int->s_name, ".text") == 0) { - (*_bfd_error_handler) (_("%s: line number overflow: 0x%lx > 0xffff"), - bfd_get_filename (abfd), - scnhdr_int->s_nlnno); - bfd_set_error (bfd_error_file_truncated); - bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nlnno); - ret = 0; + /* By inference from looking at MS output, the 32 bit field + which is the combintion of the number_of_relocs and + number_of_linenos is used for the line number count in + executables. A 16-bit field won't do for cc1. The MS + document says that the number of relocs is zero for + executables, but the 17-th bit has been observed to be there. + Overflow is not an issue: a 4G-line program will overflow a + bunch of other fields long before this! */ + bfd_h_put_16 (abfd, scnhdr_int->s_nlnno & 0xffff, + (bfd_byte *) scnhdr_ext->s_nlnno); + bfd_h_put_16 (abfd, scnhdr_int->s_nlnno >> 16, + (bfd_byte *) scnhdr_ext->s_nreloc); } - if (scnhdr_int->s_nreloc <= 0xffff) - bfd_h_put_16(abfd, scnhdr_int->s_nreloc, (bfd_byte *) scnhdr_ext->s_nreloc); else { - (*_bfd_error_handler) (_("%s: reloc overflow: 0x%lx > 0xffff"), - bfd_get_filename (abfd), - scnhdr_int->s_nreloc); - bfd_set_error (bfd_error_file_truncated); - bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nreloc); - ret = 0; + if (scnhdr_int->s_nlnno <= 0xffff) + bfd_h_put_16 (abfd, scnhdr_int->s_nlnno, + (bfd_byte *) scnhdr_ext->s_nlnno); + else + { + (*_bfd_error_handler) (_("%s: line number overflow: 0x%lx > 0xffff"), + bfd_get_filename (abfd), + scnhdr_int->s_nlnno); + bfd_set_error (bfd_error_file_truncated); + bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nlnno); + ret = 0; + } + if (scnhdr_int->s_nreloc <= 0xffff) + bfd_h_put_16 (abfd, scnhdr_int->s_nreloc, + (bfd_byte *) scnhdr_ext->s_nreloc); + else + { + (*_bfd_error_handler) (_("%s: reloc overflow: 0x%lx > 0xffff"), + bfd_get_filename (abfd), + scnhdr_int->s_nreloc); + bfd_set_error (bfd_error_file_truncated); + bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nreloc); + ret = 0; + } } return ret; }