1 /* BFD back-end for Intel 386 COFF files (DJGPP variant).
2    Copyright (C) 1990-2021 Free Software Foundation, Inc.
3    Written by DJ Delorie.
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #define TARGET_SYM		i386_coff_go32_vec
23 #define TARGET_NAME		"coff-go32"
24 #define TARGET_UNDERSCORE	'_'
25 #define COFF_GO32
26 #define COFF_LONG_SECTION_NAMES
27 #define COFF_SUPPORT_GNU_LINKONCE
28 #define COFF_LONG_FILENAMES
29 
30 #define COFF_SECTION_ALIGNMENT_ENTRIES \
31 { COFF_SECTION_NAME_EXACT_MATCH (".data"), \
32   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
33 { COFF_SECTION_NAME_EXACT_MATCH (".text"), \
34   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
35 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.d"), \
36   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
37 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.t"), \
38   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
39 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.r"), \
40   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
41 { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
42   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
43 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
44   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
45 
46 /* Section contains extended relocations. */
47 #define IMAGE_SCN_LNK_NRELOC_OVFL (0x01000000)
48 
49 #include "sysdep.h"
50 #include "bfd.h"
51 
52 /* The following functions are not static, because they are also
53    used for coff-go32-exe (coff-stgo32.c).  */
54 bool _bfd_go32_mkobject (bfd *);
55 void _bfd_go32_swap_scnhdr_in (bfd *, void *, void *);
56 unsigned int _bfd_go32_swap_scnhdr_out (bfd *, void *, void *);
57 
58 #define coff_mkobject _bfd_go32_mkobject
59 #define coff_SWAP_scnhdr_in _bfd_go32_swap_scnhdr_in
60 #define coff_SWAP_scnhdr_out _bfd_go32_swap_scnhdr_out
61 
62 #include "coff-i386.c"
63 
64 bool
_bfd_go32_mkobject(bfd * abfd)65 _bfd_go32_mkobject (bfd * abfd)
66 {
67   const bfd_size_type amt = sizeof (coff_data_type);
68 
69   abfd->tdata.coff_obj_data = bfd_zalloc (abfd, amt);
70   if (abfd->tdata.coff_obj_data == NULL)
71     return false;
72 
73   coff_data (abfd)->go32 = true;
74 
75   return true;
76 }
77 
78 void
_bfd_go32_swap_scnhdr_in(bfd * abfd,void * ext,void * in)79 _bfd_go32_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
80 {
81   SCNHDR *scnhdr_ext = (SCNHDR *) ext;
82   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
83 
84   memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
85 
86   scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
87   scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
88   scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
89 
90   scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
91   scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
92   scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
93   scnhdr_int->s_flags = GET_SCNHDR_FLAGS (abfd, scnhdr_ext->s_flags);
94   scnhdr_int->s_nreloc = GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc);
95   scnhdr_int->s_nlnno = GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
96 
97   /* DJGPP follows the same strategy as PE COFF.
98      Iff the file is an executable then the higher 16 bits
99      of the line number have been stored in the relocation
100      counter field.  */
101   if (abfd->flags & EXEC_P && (strcmp (scnhdr_ext->s_name, ".text") == 0))
102     {
103       scnhdr_int->s_nlnno
104 	= (GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc) << 16)
105 	  + GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
106       scnhdr_int->s_nreloc = 0;
107     }
108 }
109 
110 unsigned int
_bfd_go32_swap_scnhdr_out(bfd * abfd,void * in,void * out)111 _bfd_go32_swap_scnhdr_out (bfd * abfd, void * in, void * out)
112 {
113   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
114   SCNHDR *scnhdr_ext = (SCNHDR *) out;
115   unsigned int ret = bfd_coff_scnhsz (abfd);
116 
117   memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
118 
119   PUT_SCNHDR_VADDR (abfd, scnhdr_int->s_vaddr, scnhdr_ext->s_vaddr);
120   PUT_SCNHDR_PADDR (abfd, scnhdr_int->s_paddr, scnhdr_ext->s_paddr);
121   PUT_SCNHDR_SIZE (abfd, scnhdr_int->s_size, scnhdr_ext->s_size);
122   PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, scnhdr_ext->s_scnptr);
123   PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, scnhdr_ext->s_relptr);
124   PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr, scnhdr_ext->s_lnnoptr);
125   PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
126 
127   if (abfd->flags & EXEC_P && (strcmp (scnhdr_int->s_name, ".text") == 0))
128     {
129       /* DJGPP follows the same strategy as PE COFF.
130 	 By inference from looking at MS output, the 32 bit field
131 	 which is the combination of the number_of_relocs and
132 	 number_of_linenos is used for the line number count in
133 	 executables.  A 16-bit field won't do for cc1.  The MS
134 	 document says that the number of relocs is zero for
135 	 executables, but the 17-th bit has been observed to be there.
136 	 Overflow is not an issue: a 4G-line program will overflow a
137 	 bunch of other fields long before this!  */
138       PUT_SCNHDR_NLNNO (abfd, (scnhdr_int->s_nlnno & 0xffff),
139 			scnhdr_ext->s_nlnno);
140       PUT_SCNHDR_NRELOC (abfd, (scnhdr_int->s_nlnno >> 16),
141 			 scnhdr_ext->s_nreloc);
142     }
143   else
144     {
145       /* DJGPP follows the same strategy as PE COFF.  */
146       if (scnhdr_int->s_nlnno <= MAX_SCNHDR_NLNNO)
147 	PUT_SCNHDR_NLNNO (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno);
148       else
149 	{
150 	  char buf[sizeof (scnhdr_int->s_name) + 1];
151 
152 	  memcpy (buf, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
153 	  buf[sizeof (scnhdr_int->s_name)] = '\0';
154 	  _bfd_error_handler
155 	    /* xgettext:c-format */
156 	    (_("%pB: warning: %s: line number overflow: 0x%lx > 0xffff"),
157 	     abfd, buf, scnhdr_int->s_nlnno);
158 	  bfd_set_error (bfd_error_file_truncated);
159 	  PUT_SCNHDR_NLNNO (abfd, 0xffff, scnhdr_ext->s_nlnno);
160 	  ret = 0;
161 	}
162 
163       /* Although we could encode 0xffff relocs here, we do not, to be
164 	 consistent with other parts of bfd.  Also it lets us warn, as
165 	 we should never see 0xffff here w/o having the overflow flag
166 	 set.  */
167       if (scnhdr_int->s_nreloc < MAX_SCNHDR_NRELOC)
168 	PUT_SCNHDR_NRELOC (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc);
169       else
170 	{
171 	  /* DJGPP can deal with large #s of relocs, but not here.  */
172 	  PUT_SCNHDR_NRELOC (abfd, 0xffff, scnhdr_ext->s_nreloc);
173 	  scnhdr_int->s_flags |= IMAGE_SCN_LNK_NRELOC_OVFL;
174 	  PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
175 	}
176     }
177 
178   return ret;
179 }
180