- {
- /* First, we're just finding the earliest PT_LOAD.
- By the normal rules, this will be the lowest-addressed one.
- We only have anything interesting to do if it's executable. */
- last_load = m;
- if (first_load == NULL)
- {
- if (!segment_executable (*m))
- return TRUE;
- first_load = m;
- }
- /* Now that we've noted the first PT_LOAD, we're looking for
- the first non-executable PT_LOAD with a nonempty p_filesz. */
- else if (!moved_headers
- && segment_eligible_for_headers (seg, maxpagesize,
- sizeof_headers))
- {
- /* This is the one we were looking for!
-
- First, clear the flags on previous segments that
- say they include the file header and phdrs. */
- struct elf_segment_map *prevseg;
- for (prevseg = *first_load;
- prevseg != seg;
- prevseg = prevseg->next)
- if (prevseg->p_type == PT_LOAD)
- {
- prevseg->includes_filehdr = 0;
- prevseg->includes_phdrs = 0;
- }
-
- /* This segment will include those headers instead. */
- seg->includes_filehdr = 1;
- seg->includes_phdrs = 1;
-
- moved_headers = TRUE;
- }
- }
-
+ {
+ bfd_boolean executable = segment_executable (seg);
+
+ if (executable
+ && seg->count > 0
+ && seg->sections[0]->vma % bed->minpagesize == 0)
+ {
+ asection *lastsec = seg->sections[seg->count - 1];
+ bfd_vma end = lastsec->vma + lastsec->size;
+ if (end % bed->minpagesize != 0)
+ {
+ /* This is an executable segment that starts on a page
+ boundary but does not end on a page boundary. Fill
+ it out to a whole page with code fill (the tail of
+ the segment will not be within any section). Thus
+ the entire code segment can be mapped from the file
+ as whole pages and that mapping will contain only
+ valid instructions.
+
+ To accomplish this, we must fake out the code in
+ assign_file_positions_for_load_sections (elf.c) so
+ that it advances past the rest of the final page,
+ rather than trying to put the next (unaligned, or
+ unallocated) section. We do this by appending a
+ dummy section record to this element in the segment
+ map. No such output section ever actually exists,
+ but this gets the layout logic to advance the file
+ positions past this partial page. Since we are
+ lying to BFD like this, nothing will ever know to
+ write the section contents. So we do that by hand
+ after the fact, in nacl_final_write_processing, below. */
+
+ struct elf_segment_map *newseg;
+ asection *sec;
+ struct bfd_elf_section_data *secdata;
+
+ BFD_ASSERT (!seg->p_size_valid);
+
+ secdata = bfd_zalloc (abfd, sizeof *secdata);
+ if (secdata == NULL)
+ return FALSE;
+
+ sec = bfd_zalloc (abfd, sizeof *sec);
+ if (sec == NULL)
+ return FALSE;
+
+ /* Fill in only the fields that actually affect the logic
+ in assign_file_positions_for_load_sections. */
+ sec->vma = end;
+ sec->lma = lastsec->lma + lastsec->size;
+ sec->size = bed->minpagesize - (end % bed->minpagesize);
+ sec->flags = (SEC_ALLOC | SEC_LOAD
+ | SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED);
+ sec->used_by_bfd = secdata;
+
+ secdata->this_hdr.sh_type = SHT_PROGBITS;
+ secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+ secdata->this_hdr.sh_addr = sec->vma;
+ secdata->this_hdr.sh_size = sec->size;
+
+ newseg = bfd_alloc (abfd,
+ sizeof *newseg + ((seg->count + 1)
+ * sizeof (asection *)));
+ if (newseg == NULL)
+ return FALSE;
+ memcpy (newseg, seg,
+ sizeof *newseg + (seg->count * sizeof (asection *)));
+ newseg->sections[newseg->count++] = sec;
+ *m = seg = newseg;
+ }
+ }
+
+ /* First, we're just finding the earliest PT_LOAD.
+ By the normal rules, this will be the lowest-addressed one. */
+ if (first_load == NULL)
+ first_load = m;
+
+ /* Now that we've noted the first PT_LOAD, we're looking for
+ the first non-executable PT_LOAD with a nonempty p_filesz. */
+ else if (headers == NULL
+ && segment_eligible_for_headers (seg, bed->minpagesize,
+ sizeof_headers))
+ headers = m;
+ }