| OLD | NEW |
| 1 /* Native Client support for ELF | 1 /* Native Client support for ELF |
| 2 Copyright 2012, 2013 Free Software Foundation, Inc. | 2 Copyright 2012, 2013 Free Software Foundation, Inc. |
| 3 | 3 |
| 4 This file is part of BFD, the Binary File Descriptor library. | 4 This file is part of BFD, the Binary File Descriptor library. |
| 5 | 5 |
| 6 This program is free software; you can redistribute it and/or modify | 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 | 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 | 8 the Free Software Foundation; either version 3 of the License, or |
| 9 (at your option) any later version. | 9 (at your option) any later version. |
| 10 | 10 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 so we have to look through the sections. */ | 37 so we have to look through the sections. */ |
| 38 unsigned int i; | 38 unsigned int i; |
| 39 for (i = 0; i < seg->count; ++i) | 39 for (i = 0; i < seg->count; ++i) |
| 40 if (seg->sections[i]->flags & SEC_CODE) | 40 if (seg->sections[i]->flags & SEC_CODE) |
| 41 return TRUE; | 41 return TRUE; |
| 42 } | 42 } |
| 43 return FALSE; | 43 return FALSE; |
| 44 } | 44 } |
| 45 | 45 |
| 46 /* Determine if this segment is eligible to receive the file and program | 46 /* Determine if this segment is eligible to receive the file and program |
| 47 headers. It must be read-only, non-executable, and have contents. | 47 headers. It must be read-only and non-executable. |
| 48 Its first section must start far enough past the page boundary to | 48 Its first section must start far enough past the page boundary to |
| 49 allow space for the headers. */ | 49 allow space for the headers. */ |
| 50 static bfd_boolean | 50 static bfd_boolean |
| 51 segment_eligible_for_headers (struct elf_segment_map *seg, | 51 segment_eligible_for_headers (struct elf_segment_map *seg, |
| 52 bfd_vma minpagesize, bfd_vma sizeof_headers) | 52 bfd_vma minpagesize, bfd_vma sizeof_headers) |
| 53 { | 53 { |
| 54 bfd_boolean any_contents = FALSE; | |
| 55 unsigned int i; | 54 unsigned int i; |
| 56 if (seg->count == 0 || seg->sections[0]->lma % minpagesize < sizeof_headers) | 55 if (seg->count == 0 || seg->sections[0]->lma % minpagesize < sizeof_headers) |
| 57 return FALSE; | 56 return FALSE; |
| 58 for (i = 0; i < seg->count; ++i) | 57 for (i = 0; i < seg->count; ++i) |
| 59 { | 58 { |
| 60 if ((seg->sections[i]->flags & (SEC_CODE|SEC_READONLY)) != SEC_READONLY) | 59 if ((seg->sections[i]->flags & (SEC_CODE|SEC_READONLY)) != SEC_READONLY) |
| 61 return FALSE; | 60 return FALSE; |
| 62 if (seg->sections[i]->flags & SEC_HAS_CONTENTS) | |
| 63 any_contents = TRUE; | |
| 64 } | 61 } |
| 65 return any_contents; | 62 return TRUE; |
| 66 } | 63 } |
| 67 | 64 |
| 68 | 65 |
| 69 /* We permute the segment_map to get BFD to do the file layout we want: | 66 /* We permute the segment_map to get BFD to do the file layout we want: |
| 70 The first non-executable PT_LOAD segment appears first in the file | 67 The first non-executable PT_LOAD segment appears first in the file |
| 71 and contains the ELF file header and phdrs. */ | 68 and contains the ELF file header and phdrs. */ |
| 72 bfd_boolean | 69 bfd_boolean |
| 73 nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) | 70 nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) |
| 74 { | 71 { |
| 72 const struct elf_backend_data *const bed = get_elf_backend_data (abfd); |
| 75 struct elf_segment_map **m = &elf_tdata (abfd)->segment_map; | 73 struct elf_segment_map **m = &elf_tdata (abfd)->segment_map; |
| 76 struct elf_segment_map **first_load = NULL; | 74 struct elf_segment_map **first_load = NULL; |
| 77 struct elf_segment_map **last_load = NULL; | 75 struct elf_segment_map **last_load = NULL; |
| 78 bfd_boolean moved_headers = FALSE; | 76 bfd_boolean moved_headers = FALSE; |
| 79 int sizeof_headers = info == NULL ? 0 : bfd_sizeof_headers (abfd, info); | 77 int sizeof_headers; |
| 80 bfd_vma minpagesize = get_elf_backend_data (abfd)->minpagesize; | |
| 81 | 78 |
| 82 if (info != NULL && info->user_phdrs) | 79 if (info != NULL && info->user_phdrs) |
| 83 /* The linker script used PHDRS explicitly, so don't change what the | 80 /* The linker script used PHDRS explicitly, so don't change what the |
| 84 user asked for. */ | 81 user asked for. */ |
| 85 return TRUE; | 82 return TRUE; |
| 86 | 83 |
| 84 if (info != NULL) |
| 85 /* We're doing linking, so evalute SIZEOF_HEADERS as in a linker script. */ |
| 86 sizeof_headers = bfd_sizeof_headers (abfd, info); |
| 87 else |
| 88 { |
| 89 /* We're not doing linking, so this is objcopy or suchlike. |
| 90 We just need to collect the size of the existing headers. */ |
| 91 struct elf_segment_map *seg; |
| 92 sizeof_headers = bed->s->sizeof_ehdr; |
| 93 for (seg = *m; seg != NULL; seg = seg->next) |
| 94 sizeof_headers += bed->s->sizeof_phdr; |
| 95 } |
| 96 |
| 87 while (*m != NULL) | 97 while (*m != NULL) |
| 88 { | 98 { |
| 89 struct elf_segment_map *seg = *m; | 99 struct elf_segment_map *seg = *m; |
| 90 | 100 |
| 91 if (seg->p_type == PT_LOAD) | 101 if (seg->p_type == PT_LOAD) |
| 92 { | 102 { |
| 93 bfd_boolean executable = segment_executable (seg); | 103 bfd_boolean executable = segment_executable (seg); |
| 94 | 104 |
| 95 if (executable | 105 if (executable |
| 96 && seg->count > 0 | 106 && seg->count > 0 |
| 97 » && seg->sections[0]->vma % minpagesize == 0) | 107 » && seg->sections[0]->vma % bed->minpagesize == 0) |
| 98 { | 108 { |
| 99 asection *lastsec = seg->sections[seg->count - 1]; | 109 asection *lastsec = seg->sections[seg->count - 1]; |
| 100 bfd_vma end = lastsec->vma + lastsec->size; | 110 bfd_vma end = lastsec->vma + lastsec->size; |
| 101 » if (end % minpagesize != 0) | 111 » if (end % bed->minpagesize != 0) |
| 102 { | 112 { |
| 103 /* This is an executable segment that starts on a page | 113 /* This is an executable segment that starts on a page |
| 104 boundary but does not end on a page boundary. Fill | 114 boundary but does not end on a page boundary. Fill |
| 105 it out to a whole page with code fill (the tail of | 115 it out to a whole page with code fill (the tail of |
| 106 the segment will not be within any section). Thus | 116 the segment will not be within any section). Thus |
| 107 the entire code segment can be mapped from the file | 117 the entire code segment can be mapped from the file |
| 108 as whole pages and that mapping will contain only | 118 as whole pages and that mapping will contain only |
| 109 valid instructions. | 119 valid instructions. |
| 110 | 120 |
| 111 To accomplish this, we must fake out the code in | 121 To accomplish this, we must fake out the code in |
| (...skipping 20 matching lines...) Expand all Loading... |
| 132 return FALSE; | 142 return FALSE; |
| 133 | 143 |
| 134 sec = bfd_zalloc (abfd, sizeof *sec); | 144 sec = bfd_zalloc (abfd, sizeof *sec); |
| 135 if (sec == NULL) | 145 if (sec == NULL) |
| 136 return FALSE; | 146 return FALSE; |
| 137 | 147 |
| 138 /* Fill in only the fields that actually affect the logic | 148 /* Fill in only the fields that actually affect the logic |
| 139 in assign_file_positions_for_load_sections. */ | 149 in assign_file_positions_for_load_sections. */ |
| 140 sec->vma = end; | 150 sec->vma = end; |
| 141 sec->lma = lastsec->lma + lastsec->size; | 151 sec->lma = lastsec->lma + lastsec->size; |
| 142 » » sec->size = minpagesize - (end % minpagesize); | 152 » » sec->size = bed->minpagesize - (end % bed->minpagesize); |
| 143 sec->flags = (SEC_ALLOC | SEC_LOAD | 153 sec->flags = (SEC_ALLOC | SEC_LOAD |
| 144 | SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED); | 154 | SEC_READONLY | SEC_CODE | SEC_LINKER_CREATED); |
| 145 sec->used_by_bfd = secdata; | 155 sec->used_by_bfd = secdata; |
| 146 | 156 |
| 147 secdata->this_hdr.sh_type = SHT_PROGBITS; | 157 secdata->this_hdr.sh_type = SHT_PROGBITS; |
| 148 secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; | 158 secdata->this_hdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; |
| 149 secdata->this_hdr.sh_addr = sec->vma; | 159 secdata->this_hdr.sh_addr = sec->vma; |
| 150 secdata->this_hdr.sh_size = sec->size; | 160 secdata->this_hdr.sh_size = sec->size; |
| 151 | 161 |
| 152 newseg = bfd_alloc (abfd, | 162 newseg = bfd_alloc (abfd, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 167 last_load = m; | 177 last_load = m; |
| 168 if (first_load == NULL) | 178 if (first_load == NULL) |
| 169 { | 179 { |
| 170 if (!executable) | 180 if (!executable) |
| 171 goto next; | 181 goto next; |
| 172 first_load = m; | 182 first_load = m; |
| 173 } | 183 } |
| 174 /* Now that we've noted the first PT_LOAD, we're looking for | 184 /* Now that we've noted the first PT_LOAD, we're looking for |
| 175 the first non-executable PT_LOAD with a nonempty p_filesz. */ | 185 the first non-executable PT_LOAD with a nonempty p_filesz. */ |
| 176 else if (!moved_headers | 186 else if (!moved_headers |
| 177 » » && segment_eligible_for_headers (seg, minpagesize, | 187 » » && segment_eligible_for_headers (seg, bed->minpagesize, |
| 178 sizeof_headers)) | 188 sizeof_headers)) |
| 179 { | 189 { |
| 180 /* This is the one we were looking for! | 190 /* This is the one we were looking for! |
| 181 | 191 |
| 182 First, clear the flags on previous segments that | 192 First, clear the flags on previous segments that |
| 183 say they include the file header and phdrs. */ | 193 say they include the file header and phdrs. */ |
| 184 struct elf_segment_map *prevseg; | 194 struct elf_segment_map *prevseg; |
| 185 for (prevseg = *first_load; | 195 for (prevseg = *first_load; |
| 186 prevseg != seg; | 196 prevseg != seg; |
| 187 prevseg = prevseg->next) | 197 prevseg = prevseg->next) |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 { | 346 { |
| 337 /* We don't have a proper way to report an error here. So | 347 /* We don't have a proper way to report an error here. So |
| 338 instead fudge things so that elf_write_shdrs_and_ehdr will | 348 instead fudge things so that elf_write_shdrs_and_ehdr will |
| 339 fail. */ | 349 fail. */ |
| 340 elf_elfheader (abfd)->e_shoff = (file_ptr) -1; | 350 elf_elfheader (abfd)->e_shoff = (file_ptr) -1; |
| 341 } | 351 } |
| 342 | 352 |
| 343 free (fill); | 353 free (fill); |
| 344 } | 354 } |
| 345 } | 355 } |
| OLD | NEW |