1 /* Native Client support for ELF
2    Copyright (C) 2012-2016 Free Software Foundation, Inc.
3 
4    This file is part of BFD, the Binary File Descriptor library.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 #include "sysdep.h"
20 #include "bfd.h"
21 #include "libbfd.h"
22 #include "elf-bfd.h"
23 #include "elf-nacl.h"
24 #include "elf/common.h"
25 #include "elf/internal.h"
26 
27 static bfd_boolean
28 segment_executable (struct elf_segment_map *seg)
29 {
30   if (seg->p_flags_valid)
31     return (seg->p_flags & PF_X) != 0;
32   else
33     {
34       /* The p_flags value has not been computed yet,
35 	 so we have to look through the sections.  */
36       unsigned int i;
37       for (i = 0; i < seg->count; ++i)
38 	if (seg->sections[i]->flags & SEC_CODE)
39 	  return TRUE;
40     }
41   return FALSE;
42 }
43 
44 /* Determine if this segment is eligible to receive the file and program
45    headers.  It must be read-only and non-executable.
46    Its first section must start far enough past the page boundary to
47    allow space for the headers.  */
48 static bfd_boolean
49 segment_eligible_for_headers (struct elf_segment_map *seg,
50 			      bfd_vma minpagesize, bfd_vma sizeof_headers)
51 {
52   unsigned int i;
53   if (seg->count == 0 || seg->sections[0]->lma % minpagesize < sizeof_headers)
54     return FALSE;
55   for (i = 0; i < seg->count; ++i)
56     {
57       if ((seg->sections[i]->flags & (SEC_CODE|SEC_READONLY)) != SEC_READONLY)
58 	return FALSE;
59     }
60   return TRUE;
61 }
62 
63 
64 /* We permute the segment_map to get BFD to do the file layout we want:
65    The first non-executable PT_LOAD segment appears first in the file
66    and contains the ELF file header and phdrs.  */
67 bfd_boolean
68 nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
69 {
70   const struct elf_backend_data *const bed = get_elf_backend_data (abfd);
71   struct elf_segment_map **m = &elf_seg_map (abfd);
72   struct elf_segment_map **first_load = NULL;
73   struct elf_segment_map **last_load = NULL;
74   bfd_boolean moved_headers = FALSE;
75   int sizeof_headers;
76 
77   if (info != NULL && info->user_phdrs)
78     /* The linker script used PHDRS explicitly, so don't change what the
79        user asked for.  */
80     return TRUE;
81 
82   if (info != NULL)
83     /* We're doing linking, so evalute SIZEOF_HEADERS as in a linker script.  */
84     sizeof_headers = bfd_sizeof_headers (abfd, info);
85   else
86     {
87       /* We're not doing linking, so this is objcopy or suchlike.
88 	 We just need to collect the size of the existing headers.  */
89       struct elf_segment_map *seg;
90       sizeof_headers = bed->s->sizeof_ehdr;
91       for (seg = *m; seg != NULL; seg = seg->next)
92 	sizeof_headers += bed->s->sizeof_phdr;
93     }
94 
95   while (*m != NULL)
96     {
97       struct elf_segment_map *seg = *m;
98 
99       if (seg->p_type == PT_LOAD)
100 	{
101 	  bfd_boolean executable = segment_executable (seg);
102 
103 	  if (executable
104 	      && seg->count > 0
105 	      && seg->sections[0]->vma % bed->minpagesize == 0)
106 	    {
107 	      asection *lastsec = seg->sections[seg->count - 1];
108 	      bfd_vma end = lastsec->vma + lastsec->size;
109 	      if (end % bed->minpagesize != 0)
110 		{
111 		  /* This is an executable segment that starts on a page
112 		     boundary but does not end on a page boundary.  Fill
113 		     it out to a whole page with code fill (the tail of
114 		     the segment will not be within any section).  Thus
115 		     the entire code segment can be mapped from the file
116 		     as whole pages and that mapping will contain only
117 		     valid instructions.
118 
119 		     To accomplish this, we must fake out the code in
120 		     assign_file_positions_for_load_sections (elf.c) so
121 		     that it advances past the rest of the final page,
122 		     rather than trying to put the next (unaligned, or
123 		     unallocated) section.  We do this by appending a
124 		     dummy section record to this element in the segment
125 		     map.  No such output section ever actually exists,
126 		     but this gets the layout logic to advance the file
127 		     positions past this partial page.  Since we are
128 		     lying to BFD like this, nothing will ever know to
129 		     write the section contents.  So we do that by hand
130 		     after the fact, in nacl_final_write_processing, below.  */
131 
132 		  struct elf_segment_map *newseg;
133 		  asection *sec;
134 		  struct bfd_elf_section_data *secdata;
135 
136 		  BFD_ASSERT (!seg->p_size_valid);
137 
138 		  secdata = bfd_zalloc (abfd, sizeof *secdata);
139 		  if (secdata == NULL)
140 		    return FALSE;
141 
142 		  sec = bfd_zalloc (abfd, sizeof *sec);
143 		  if (sec == NULL)
144 		    return FALSE;
145 
146 		  /* Fill in only the fields that actually affect the logic
147 		     in assign_file_positions_for_load_sections.  */
148 		  sec->vma = end;
149 		  sec->lma = lastsec->lma + lastsec->size;
150 		  sec->size = bed->minpagesize - (end % bed->minpagesize);
151 		  sec->flags = (SEC_ALLOC | SEC_LOAD
152 				| SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED);
153 		  sec->used_by_bfd = secdata;
154 
155 		  secdata->this_hdr.sh_type = SHT_PROGBITS;
156 		  secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
157 		  secdata->this_hdr.sh_addr = sec->vma;
158 		  secdata->this_hdr.sh_size = sec->size;
159 
160 		  newseg = bfd_alloc (abfd,
161 				      sizeof *newseg + ((seg->count + 1)
162 							* sizeof (asection *)));
163 		  if (newseg == NULL)
164 		    return FALSE;
165 		  memcpy (newseg, seg,
166 			  sizeof *newseg + (seg->count * sizeof (asection *)));
167 		  newseg->sections[newseg->count++] = sec;
168 		  *m = seg = newseg;
169 		}
170 	    }
171 
172 	  /* First, we're just finding the earliest PT_LOAD.
173 	     By the normal rules, this will be the lowest-addressed one.
174 	     We only have anything interesting to do if it's executable.  */
175 	  last_load = m;
176 	  if (first_load == NULL)
177 	    {
178 	      if (!executable)
179 		goto next;
180 	      first_load = m;
181 	    }
182 	  /* Now that we've noted the first PT_LOAD, we're looking for
183 	     the first non-executable PT_LOAD with a nonempty p_filesz.  */
184 	  else if (!moved_headers
185 		   && segment_eligible_for_headers (seg, bed->minpagesize,
186 						    sizeof_headers))
187 	    {
188 	      /* This is the one we were looking for!
189 
190 		 First, clear the flags on previous segments that
191 		 say they include the file header and phdrs.  */
192 	      struct elf_segment_map *prevseg;
193 	      for (prevseg = *first_load;
194 		   prevseg != seg;
195 		   prevseg = prevseg->next)
196 		if (prevseg->p_type == PT_LOAD)
197 		  {
198 		    prevseg->includes_filehdr = 0;
199 		    prevseg->includes_phdrs = 0;
200 		  }
201 
202 	      /* This segment will include those headers instead.  */
203 	      seg->includes_filehdr = 1;
204 	      seg->includes_phdrs = 1;
205 
206 	      moved_headers = TRUE;
207 	    }
208 	}
209 
210     next:
211       m = &seg->next;
212     }
213 
214   if (first_load != last_load && moved_headers)
215     {
216       /* Now swap the first and last PT_LOAD segments'
217 	 positions in segment_map.  */
218       struct elf_segment_map *first = *first_load;
219       struct elf_segment_map *last = *last_load;
220       *first_load = first->next;
221       first->next = last->next;
222       last->next = first;
223     }
224 
225   return TRUE;
226 }
227 
228 /* After nacl_modify_segment_map has done its work, the file layout has
229    been done as we wanted.  But the PT_LOAD phdrs are no longer in the
230    proper order for the ELF rule that they must appear in ascending address
231    order.  So find the two segments we swapped before, and swap them back.  */
232 bfd_boolean
233 nacl_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
234 {
235   struct elf_segment_map **m = &elf_seg_map (abfd);
236   Elf_Internal_Phdr *phdr = elf_tdata (abfd)->phdr;
237   Elf_Internal_Phdr *p = phdr;
238 
239   if (info != NULL && info->user_phdrs)
240     /* The linker script used PHDRS explicitly, so don't change what the
241        user asked for.  */
242     return TRUE;
243 
244   /* Find the PT_LOAD that contains the headers (should be the first).  */
245   while (*m != NULL)
246     {
247       if ((*m)->p_type == PT_LOAD && (*m)->includes_filehdr)
248 	break;
249 
250       m = &(*m)->next;
251       ++p;
252     }
253 
254   if (*m != NULL)
255     {
256       struct elf_segment_map **first_load_seg = m;
257       Elf_Internal_Phdr *first_load_phdr = p;
258       struct elf_segment_map **next_load_seg = NULL;
259       Elf_Internal_Phdr *next_load_phdr = NULL;
260 
261       /* Now move past that first one and find the PT_LOAD that should be
262 	 before it by address order.  */
263 
264       m = &(*m)->next;
265       ++p;
266 
267       while (*m != NULL)
268 	{
269 	  if (p->p_type == PT_LOAD && p->p_vaddr < first_load_phdr->p_vaddr)
270 	    {
271 	      next_load_seg = m;
272 	      next_load_phdr = p;
273 	      break;
274 	    }
275 
276 	  m = &(*m)->next;
277 	  ++p;
278 	}
279 
280       /* Swap their positions in the segment_map back to how they used to be.
281 	 The phdrs have already been set up by now, so we have to slide up
282 	 the earlier ones to insert the one that should be first.  */
283       if (next_load_seg != NULL)
284 	{
285 	  Elf_Internal_Phdr move_phdr;
286 	  struct elf_segment_map *first_seg = *first_load_seg;
287 	  struct elf_segment_map *next_seg = *next_load_seg;
288 	  struct elf_segment_map *first_next = first_seg->next;
289 	  struct elf_segment_map *next_next = next_seg->next;
290 
291 	  if (next_load_seg == &first_seg->next)
292 	    {
293 	      *first_load_seg = next_seg;
294 	      next_seg->next = first_seg;
295 	      first_seg->next = next_next;
296 	    }
297 	  else
298 	    {
299 	      *first_load_seg = first_next;
300 	      *next_load_seg = next_next;
301 
302 	      first_seg->next = *next_load_seg;
303 	      *next_load_seg = first_seg;
304 
305 	      next_seg->next = *first_load_seg;
306 	      *first_load_seg = next_seg;
307 	    }
308 
309 	  move_phdr = *next_load_phdr;
310 	  memmove (first_load_phdr + 1, first_load_phdr,
311 		   (next_load_phdr - first_load_phdr) * sizeof move_phdr);
312 	  *first_load_phdr = move_phdr;
313 	}
314     }
315 
316   return TRUE;
317 }
318 
319 void
320 nacl_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
321 {
322   struct elf_segment_map *seg;
323   for (seg = elf_seg_map (abfd); seg != NULL; seg = seg->next)
324     if (seg->p_type == PT_LOAD
325 	&& seg->count > 1
326 	&& seg->sections[seg->count - 1]->owner == NULL)
327       {
328 	/* This is a fake section added in nacl_modify_segment_map, above.
329 	   It's not a real BFD section, so nothing wrote its contents.
330 	   Now write out its contents.  */
331 
332 	asection *sec = seg->sections[seg->count - 1];
333 	char *fill;
334 
335 	BFD_ASSERT (sec->flags & SEC_LINKER_CREATED);
336 	BFD_ASSERT (sec->flags & SEC_CODE);
337 	BFD_ASSERT (sec->size > 0);
338 
339 	fill = abfd->arch_info->fill (sec->size, bfd_big_endian (abfd), TRUE);
340 
341 	if (fill == NULL
342 	    || bfd_seek (abfd, sec->filepos, SEEK_SET) != 0
343 	    || bfd_bwrite (fill, sec->size, abfd) != sec->size)
344 	  {
345 	    /* We don't have a proper way to report an error here.  So
346 	       instead fudge things so that elf_write_shdrs_and_ehdr will
347 	       fail.  */
348 	    elf_elfheader (abfd)->e_shoff = (file_ptr) -1;
349 	  }
350 
351 	free (fill);
352       }
353 }
354