diff options
| author | Eli Zaretskii | 2006-03-18 14:51:54 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2006-03-18 14:51:54 +0000 |
| commit | 8daaf78be89633514b94e661945f0814ea3e1f90 (patch) | |
| tree | a0b05ee4473d7f60c22bcacd5078f18fbc77e615 /src | |
| parent | 09b7af0a1c6600f4a2412958ae66b885c79ff5f7 (diff) | |
| download | emacs-8daaf78be89633514b94e661945f0814ea3e1f90.tar.gz emacs-8daaf78be89633514b94e661945f0814ea3e1f90.zip | |
[BROKEN_NOCOMBRELOC]: Include assert.h.
(unexec) [BROKEN_NOCOMBRELOC]: Handle platforms whose nocombreloc option
is broken (e.g., MIPS/NetBSD).
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexelf.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/unexelf.c b/src/unexelf.c index 30a35372544..a236b98eab1 100644 --- a/src/unexelf.c +++ b/src/unexelf.c | |||
| @@ -433,6 +433,9 @@ extern void fatal (const char *msgid, ...); | |||
| 433 | #if __sgi | 433 | #if __sgi |
| 434 | #include <syms.h> /* for HDRR declaration */ | 434 | #include <syms.h> /* for HDRR declaration */ |
| 435 | #endif /* __sgi */ | 435 | #endif /* __sgi */ |
| 436 | #ifdef BROKEN_NOCOMBRELOC | ||
| 437 | #include <assert.h> | ||
| 438 | #endif | ||
| 436 | 439 | ||
| 437 | #ifndef MAP_ANON | 440 | #ifndef MAP_ANON |
| 438 | #ifdef MAP_ANONYMOUS | 441 | #ifdef MAP_ANONYMOUS |
| @@ -687,6 +690,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 687 | int old_mdebug_index; | 690 | int old_mdebug_index; |
| 688 | struct stat stat_buf; | 691 | struct stat stat_buf; |
| 689 | int old_file_size; | 692 | int old_file_size; |
| 693 | #ifdef BROKEN_NOCOMBRELOC | ||
| 694 | int unreloc_sections[10], n_unreloc_sections; | ||
| 695 | #endif | ||
| 690 | 696 | ||
| 691 | /* Open the old file, allocate a buffer of the right size, and read | 697 | /* Open the old file, allocate a buffer of the right size, and read |
| 692 | in the file contents. */ | 698 | in the file contents. */ |
| @@ -1218,6 +1224,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 1218 | 1224 | ||
| 1219 | /* This loop seeks out relocation sections for the data section, so | 1225 | /* This loop seeks out relocation sections for the data section, so |
| 1220 | that it can undo relocations performed by the runtime linker. */ | 1226 | that it can undo relocations performed by the runtime linker. */ |
| 1227 | #ifndef BROKEN_NOCOMBRELOC | ||
| 1221 | for (n = new_file_h->e_shnum - 1; n; n--) | 1228 | for (n = new_file_h->e_shnum - 1; n; n--) |
| 1222 | { | 1229 | { |
| 1223 | ElfW(Shdr) section = NEW_SECTION_H (n); | 1230 | ElfW(Shdr) section = NEW_SECTION_H (n); |
| @@ -1272,6 +1279,81 @@ unexec (new_name, old_name, data_start, bss_start, entry_address) | |||
| 1272 | break; | 1279 | break; |
| 1273 | } | 1280 | } |
| 1274 | } | 1281 | } |
| 1282 | #else /* BROKEN_NOCOMBRELOC */ | ||
| 1283 | for (n = 1, n_unreloc_sections = 0; n < new_file_h->e_shnum; n++) | ||
| 1284 | if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") | ||
| 1285 | || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") | ||
| 1286 | || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".lit4") | ||
| 1287 | || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".lit8") | ||
| 1288 | #ifdef IRIX6_5 /* see above */ | ||
| 1289 | || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got") | ||
| 1290 | #endif | ||
| 1291 | || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata1") | ||
| 1292 | || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1")) | ||
| 1293 | { | ||
| 1294 | assert (n_unreloc_sections | ||
| 1295 | < (sizeof (unreloc_sections) / sizeof (unreloc_sections[0]))); | ||
| 1296 | unreloc_sections[n_unreloc_sections++] = n; | ||
| 1297 | #ifdef DEBUG | ||
| 1298 | fprintf (stderr, "section %d: %s\n", n, | ||
| 1299 | old_section_names + NEW_SECTION_H (n).sh_name); | ||
| 1300 | #endif | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | for (n = new_file_h->e_shnum - 1; n; n--) | ||
| 1304 | { | ||
| 1305 | ElfW(Shdr) section = NEW_SECTION_H (n); | ||
| 1306 | caddr_t reloc, end; | ||
| 1307 | ElfW(Addr) addr, offset; | ||
| 1308 | int target; | ||
| 1309 | |||
| 1310 | switch (section.sh_type) | ||
| 1311 | { | ||
| 1312 | default: | ||
| 1313 | break; | ||
| 1314 | case SHT_REL: | ||
| 1315 | case SHT_RELA: | ||
| 1316 | /* This code handles two different size structs, but there should | ||
| 1317 | be no harm in that provided that r_offset is always the first | ||
| 1318 | member. */ | ||
| 1319 | for (reloc = old_base + section.sh_offset, | ||
| 1320 | end = reloc + section.sh_size; | ||
| 1321 | reloc < end; | ||
| 1322 | reloc += section.sh_entsize) | ||
| 1323 | { | ||
| 1324 | addr = ((ElfW(Rel) *) reloc)->r_offset; | ||
| 1325 | #ifdef __alpha__ | ||
| 1326 | /* The Alpha ELF binutils currently have a bug that | ||
| 1327 | sometimes results in relocs that contain all | ||
| 1328 | zeroes. Work around this for now... */ | ||
| 1329 | if (addr == 0) | ||
| 1330 | continue; | ||
| 1331 | #endif | ||
| 1332 | for (nn = 0; nn < n_unreloc_sections; nn++) | ||
| 1333 | { | ||
| 1334 | target = unreloc_sections[nn]; | ||
| 1335 | if (NEW_SECTION_H (target).sh_addr <= addr | ||
| 1336 | && addr < (NEW_SECTION_H (target).sh_addr + | ||
| 1337 | NEW_SECTION_H (target).sh_size)) | ||
| 1338 | { | ||
| 1339 | offset = (NEW_SECTION_H (target).sh_addr - | ||
| 1340 | NEW_SECTION_H (target).sh_offset); | ||
| 1341 | memcpy (new_base + addr - offset, | ||
| 1342 | old_base + addr - offset, | ||
| 1343 | sizeof (ElfW(Addr))); | ||
| 1344 | #ifdef DEBUG | ||
| 1345 | fprintf (stderr, "unrelocate: [%08lx] <= %08lx\n", | ||
| 1346 | (long) addr, | ||
| 1347 | (long) *((long *) (new_base + addr - offset))); | ||
| 1348 | #endif | ||
| 1349 | break; | ||
| 1350 | } | ||
| 1351 | } | ||
| 1352 | } | ||
| 1353 | break; | ||
| 1354 | } | ||
| 1355 | } | ||
| 1356 | #endif /* BROKEN_NOCOMBRELOC */ | ||
| 1275 | 1357 | ||
| 1276 | /* Write out new_file, and free the buffers. */ | 1358 | /* Write out new_file, and free the buffers. */ |
| 1277 | 1359 | ||