diff options
| author | Alan Modra | 2015-11-08 09:29:00 -0800 |
|---|---|---|
| committer | Paul Eggert | 2015-11-08 10:00:59 -0800 |
| commit | 3ff9fc0e8d738be5004c65c3be314af9aca68148 (patch) | |
| tree | 670d5f6de1d84737c944ba7c0c7f3f4e4395116c | |
| parent | 190b968f189cb7d06223bb39045ec9055df67f68 (diff) | |
| download | emacs-3ff9fc0e8d738be5004c65c3be314af9aca68148.tar.gz emacs-3ff9fc0e8d738be5004c65c3be314af9aca68148.zip | |
ELF unexec: _OBJC_ symbols in bss sections
This code assumed that there was only one bss section. Rather than
checking for a particular index, check the section type. Also, handle
the possibility that the section was SHT_NOBITS originally and is
unchanged, in which case no clearing is needed (and sh_offset isn't
necessarily valid, which can lead to a wild memset).
* unexelf.c (unexec): Properly handle _OBJC_ symbols in bss sections.
| -rw-r--r-- | src/unexelf.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/src/unexelf.c b/src/unexelf.c index 286ba2e99c1..df99f92a466 100644 --- a/src/unexelf.c +++ b/src/unexelf.c | |||
| @@ -1176,20 +1176,25 @@ temacs: | |||
| 1176 | "_OBJC_", sizeof ("_OBJC_") - 1) == 0) | 1176 | "_OBJC_", sizeof ("_OBJC_") - 1) == 0) |
| 1177 | { | 1177 | { |
| 1178 | ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx); | 1178 | ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx); |
| 1179 | ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr; | 1179 | if (new_shdr->sh_type != SHT_NOBITS) |
| 1180 | ptrdiff_t newoff = reladdr + new_shdr->sh_offset; | ||
| 1181 | |||
| 1182 | /* "Unpatch" index. */ | ||
| 1183 | nn = symp->st_shndx; | ||
| 1184 | if (nn > old_bss_index) | ||
| 1185 | nn--; | ||
| 1186 | if (nn == old_bss_index) | ||
| 1187 | memset (new_base + newoff, 0, symp->st_size); | ||
| 1188 | else | ||
| 1189 | { | 1180 | { |
| 1190 | ElfW (Shdr) *old_shdr = &OLD_SECTION_H (nn); | 1181 | ElfW (Shdr) *old_shdr; |
| 1191 | ptrdiff_t oldoff = reladdr + old_shdr->sh_offset; | 1182 | ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr; |
| 1192 | memcpy (new_base + newoff, old_base + oldoff, symp->st_size); | 1183 | ptrdiff_t newoff = reladdr + new_shdr->sh_offset; |
| 1184 | |||
| 1185 | /* "Unpatch" index. */ | ||
| 1186 | nn = symp->st_shndx; | ||
| 1187 | if (nn > old_bss_index) | ||
| 1188 | nn--; | ||
| 1189 | old_shdr = &OLD_SECTION_H (nn); | ||
| 1190 | if (old_shdr->sh_type == SHT_NOBITS) | ||
| 1191 | memset (new_base + newoff, 0, symp->st_size); | ||
| 1192 | else | ||
| 1193 | { | ||
| 1194 | ptrdiff_t oldoff = reladdr + old_shdr->sh_offset; | ||
| 1195 | memcpy (new_base + newoff, old_base + oldoff, | ||
| 1196 | symp->st_size); | ||
| 1197 | } | ||
| 1193 | } | 1198 | } |
| 1194 | } | 1199 | } |
| 1195 | #endif | 1200 | #endif |