diff options
| author | Richard M. Stallman | 1996-08-21 20:18:00 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-08-21 20:18:00 +0000 |
| commit | d7b43eaa00c71f48a19134bf89751820f1ccf17b (patch) | |
| tree | 900c40c728c9d75078025f924f0ffb196b978174 /src | |
| parent | 18aa68c389251d4a2b9cafa5b49a4cfe41fae480 (diff) | |
| download | emacs-d7b43eaa00c71f48a19134bf89751820f1ccf17b.tar.gz emacs-d7b43eaa00c71f48a19134bf89751820f1ccf17b.zip | |
Conditionalize the changes below on not __linux__.
Include reloc.h and elf_abi.h.
(rel_dyn_section, dynstr_section, dynsym_section): New variables.
(old_data_scnhdr): New variable.
(CHECK_SCNHDR): Compare just 8 chars of section name.
(unexec): Check for rel_dyn_section, dynsym_section, dynstr_section.
Do call update_dynamic_symbols.
(update_dynamic_symbols): Finish it up and take away #if 0.
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexalpha.c | 151 |
1 files changed, 91 insertions, 60 deletions
diff --git a/src/unexalpha.c b/src/unexalpha.c index 48b4059fcaf..2adfd1fa57e 100644 --- a/src/unexalpha.c +++ b/src/unexalpha.c | |||
| @@ -31,6 +31,10 @@ Boston, MA 02111-1307, USA. */ | |||
| 31 | #include <aouthdr.h> | 31 | #include <aouthdr.h> |
| 32 | #include <scnhdr.h> | 32 | #include <scnhdr.h> |
| 33 | #include <syms.h> | 33 | #include <syms.h> |
| 34 | #ifndef __linux__ | ||
| 35 | # include <reloc.h> | ||
| 36 | # include <elf_abi.h> | ||
| 37 | #endif | ||
| 34 | 38 | ||
| 35 | static void fatal_unexec (); | 39 | static void fatal_unexec (); |
| 36 | static void mark_x (); | 40 | static void mark_x (); |
| @@ -52,11 +56,14 @@ static void mark_x (); | |||
| 52 | extern int errno; | 56 | extern int errno; |
| 53 | extern char *strerror (); | 57 | extern char *strerror (); |
| 54 | 58 | ||
| 55 | void *sbrk(); | 59 | void *sbrk (); |
| 56 | 60 | ||
| 57 | #define EEOF -1 | 61 | #define EEOF -1 |
| 58 | 62 | ||
| 59 | static struct scnhdr *text_section; | 63 | static struct scnhdr *text_section; |
| 64 | static struct scnhdr *rel_dyn_section; | ||
| 65 | static struct scnhdr *dynstr_section; | ||
| 66 | static struct scnhdr *dynsym_section; | ||
| 60 | static struct scnhdr *init_section; | 67 | static struct scnhdr *init_section; |
| 61 | static struct scnhdr *finit_section; | 68 | static struct scnhdr *finit_section; |
| 62 | static struct scnhdr *rdata_section; | 69 | static struct scnhdr *rdata_section; |
| @@ -71,6 +78,8 @@ static struct scnhdr *sdata_section; | |||
| 71 | static struct scnhdr *sbss_section; | 78 | static struct scnhdr *sbss_section; |
| 72 | static struct scnhdr *bss_section; | 79 | static struct scnhdr *bss_section; |
| 73 | 80 | ||
| 81 | static struct scnhdr old_data_scnhdr; | ||
| 82 | |||
| 74 | static unsigned long Brk; | 83 | static unsigned long Brk; |
| 75 | 84 | ||
| 76 | struct headers { | 85 | struct headers { |
| @@ -157,7 +166,7 @@ unexec (new_name, a_name, data_start, bss_start, entry_address) | |||
| 157 | #define CHECK_SCNHDR(ptr, name, flags) \ | 166 | #define CHECK_SCNHDR(ptr, name, flags) \ |
| 158 | ptr = NULL; \ | 167 | ptr = NULL; \ |
| 159 | for (i = 0; i < nhdr.fhdr.f_nscns && !ptr; i++) \ | 168 | for (i = 0; i < nhdr.fhdr.f_nscns && !ptr; i++) \ |
| 160 | if (strcmp (nhdr.section[i].s_name, name) == 0) \ | 169 | if (strncmp (nhdr.section[i].s_name, name, 8) == 0) \ |
| 161 | { \ | 170 | { \ |
| 162 | if (nhdr.section[i].s_flags != flags) \ | 171 | if (nhdr.section[i].s_flags != flags) \ |
| 163 | fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \ | 172 | fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \ |
| @@ -167,6 +176,15 @@ unexec (new_name, a_name, data_start, bss_start, entry_address) | |||
| 167 | 176 | ||
| 168 | CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT); | 177 | CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT); |
| 169 | CHECK_SCNHDR (init_section, _INIT, STYP_INIT); | 178 | CHECK_SCNHDR (init_section, _INIT, STYP_INIT); |
| 179 | #ifdef _REL_DYN | ||
| 180 | CHECK_SCNHDR (rel_dyn_section, _REL_DYN, STYP_REL_DYN); | ||
| 181 | #endif /* _REL_DYN */ | ||
| 182 | #ifdef _DYNSYM | ||
| 183 | CHECK_SCNHDR (dynsym_section, _DYNSYM, STYP_DYNSYM); | ||
| 184 | #endif /* _REL_DYN */ | ||
| 185 | #ifdef _DYNSTR | ||
| 186 | CHECK_SCNHDR (dynstr_section, _DYNSTR, STYP_DYNSTR); | ||
| 187 | #endif /* _REL_DYN */ | ||
| 170 | #ifdef _FINI | 188 | #ifdef _FINI |
| 171 | CHECK_SCNHDR (finit_section, _FINI, STYP_FINI); | 189 | CHECK_SCNHDR (finit_section, _FINI, STYP_FINI); |
| 172 | #endif /* _FINI */ | 190 | #endif /* _FINI */ |
| @@ -200,6 +218,8 @@ unexec (new_name, a_name, data_start, bss_start, entry_address) | |||
| 200 | 218 | ||
| 201 | Brk = brk; | 219 | Brk = brk; |
| 202 | 220 | ||
| 221 | bcopy (data_section, &old_data_scnhdr, sizeof (old_data_scnhdr)); | ||
| 222 | |||
| 203 | nhdr.aout.dsize = brk - DATA_START; | 223 | nhdr.aout.dsize = brk - DATA_START; |
| 204 | nhdr.aout.bsize = 0; | 224 | nhdr.aout.bsize = 0; |
| 205 | if (entry_address == 0) | 225 | if (entry_address == 0) |
| @@ -341,15 +361,8 @@ unexec (new_name, a_name, data_start, bss_start, entry_address) | |||
| 341 | stat.st_size - ohdr.fhdr.f_symptr - cbHDRR, | 361 | stat.st_size - ohdr.fhdr.f_symptr - cbHDRR, |
| 342 | "writing symbol table of %s", new_name); | 362 | "writing symbol table of %s", new_name); |
| 343 | 363 | ||
| 344 | #if 0 | 364 | #ifndef __linux__ |
| 345 | 365 | update_dynamic_symbols (oldptr, new_name, new, nhdr.aout); | |
| 346 | /* Not needed for now */ | ||
| 347 | |||
| 348 | update_dynamic_symbols (oldptr, new_name, new, newsyms, | ||
| 349 | ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->issExtMax, | ||
| 350 | ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->cbExtOffset, | ||
| 351 | ((pHDRR) (oldptr + ohdr.fhdr.f_symptr))->cbSsExtOffset); | ||
| 352 | |||
| 353 | #endif | 366 | #endif |
| 354 | 367 | ||
| 355 | #undef symhdr | 368 | #undef symhdr |
| @@ -364,69 +377,87 @@ unexec (new_name, a_name, data_start, bss_start, entry_address) | |||
| 364 | } | 377 | } |
| 365 | 378 | ||
| 366 | 379 | ||
| 367 | #if 0 | ||
| 368 | |||
| 369 | /* Not needed for now */ | ||
| 370 | |||
| 371 | /* The following function updates the values of some symbols | ||
| 372 | that are used by the dynamic loader: | ||
| 373 | |||
| 374 | _edata | ||
| 375 | _end | ||
| 376 | 380 | ||
| 377 | */ | ||
| 378 | 381 | ||
| 382 | #ifndef __linux__ | ||
| 379 | 383 | ||
| 380 | update_dynamic_symbols (old, new_name, new, newsyms, nsyms, symoff, stroff) | 384 | update_dynamic_symbols (old, new_name, new, aout) |
| 381 | char *old; /* Pointer to old executable */ | 385 | char *old; /* Pointer to old executable */ |
| 382 | char *new_name; /* Name of new executable */ | 386 | char *new_name; /* Name of new executable */ |
| 383 | int new; /* File descriptor for new executable */ | 387 | int new; /* File descriptor for new executable */ |
| 384 | long newsyms; /* Offset of Symbol table in new executable */ | 388 | struct aouthdr aout; /* a.out info from the file header */ |
| 385 | int nsyms; /* Number of symbol table entries */ | ||
| 386 | long symoff; /* Offset of External Symbols in old file */ | ||
| 387 | long stroff; /* Offset of string table in old file */ | ||
| 388 | { | 389 | { |
| 389 | long i; | 390 | typedef struct dynrel_info { |
| 390 | int found = 0; | 391 | char * addr; |
| 391 | EXTR n_end, n_edata; | 392 | unsigned type:8; |
| 393 | unsigned index:24; | ||
| 394 | unsigned info:8; | ||
| 395 | unsigned pad:8; | ||
| 396 | } dr_info; | ||
| 397 | |||
| 398 | int nsyms = rel_dyn_section->s_size / sizeof (struct dynrel_info); | ||
| 399 | int i; | ||
| 400 | dr_info * rd_base = (dr_info *) (old + rel_dyn_section->s_scnptr); | ||
| 401 | Elf32_Sym * ds_base = (Elf32_Sym *) (old + dynsym_section->s_scnptr); | ||
| 392 | 402 | ||
| 393 | /* We go through the symbol table entries until we have found the two | 403 | for (i = 0; i < nsyms; i++) { |
| 394 | symbols. */ | 404 | register Elf32_Sym x; |
| 395 | 405 | ||
| 396 | /* cbEXTR is the size of an external symbol table entry */ | 406 | if (rd_base[i].index == 0) |
| 407 | continue; | ||
| 397 | 408 | ||
| 398 | for (i = 0; i < nsyms && found < 2; i += cbEXTR) | 409 | x = ds_base[rd_base[i].index]; |
| 399 | { | 410 | |
| 400 | register pEXTR x = (pEXTR) (old + symoff + i); | 411 | #if 0 |
| 401 | char *s; | 412 | fprintf (stderr, "Object inspected: %s, addr = %lx, shndx = %x", |
| 402 | 413 | old + dynstr_section->s_scnptr + x.st_name, rd_base[i].addr, x.st_shndx); | |
| 403 | s = old + stroff + x->asym.iss; /* name of the symbol */ | 414 | #endif |
| 404 | 415 | ||
| 405 | if (!strcmp(s,"_edata")) | 416 | |
| 406 | { | 417 | if ((ELF32_ST_BIND (x.st_info) == STB_GLOBAL) |
| 407 | found++; | 418 | && (x.st_shndx == 0) |
| 408 | bcopy (x, &n_edata, cbEXTR); | 419 | /* && (x.st_value == NULL) */ |
| 409 | n_edata.asym.value = Brk; | 420 | ) { |
| 410 | SEEK (new, newsyms + cbHDRR + i, | 421 | /* OK, this is probably a reference to an object in a shared |
| 411 | "seeking to symbol _edata in %s", new_name); | 422 | library, so copy the old value. This is done in several steps: |
| 412 | WRITE (new, &n_edata, cbEXTR, | 423 | 1. reladdr is the address of the location in question relative to |
| 413 | "writing symbol table entry for _edata into %s", new_name); | 424 | the start of the data section, |
| 414 | } | 425 | 2. oldref is the addr is the mapped in temacs executable, |
| 415 | else if (!strcmp(s,"_end")) | 426 | 3. newref is the address of the location in question in the |
| 416 | { | 427 | undumped executable, |
| 417 | found++; | 428 | 4. len is the size of the object reference in bytes -- |
| 418 | bcopy (x, &n_end, cbEXTR); | 429 | currently only 4 (long) and 8 (quad) are supported. |
| 419 | n_end.asym.value = Brk; | 430 | */ |
| 420 | SEEK (new, newsyms + cbHDRR + i, | 431 | register unsigned long reladdr = rd_base[i].addr - old_data_scnhdr.s_vaddr; |
| 421 | "seeking to symbol _end in %s", new_name); | 432 | char * oldref = old + old_data_scnhdr.s_scnptr + reladdr; |
| 422 | WRITE (new, &n_end, cbEXTR, | 433 | unsigned long newref = aout.tsize + reladdr; |
| 423 | "writing symbol table entry for _end into %s", new_name); | 434 | int len; |
| 424 | } | 435 | |
| 436 | #if 0 | ||
| 437 | fprintf (stderr, "...relocated\n"); | ||
| 438 | #endif | ||
| 439 | |||
| 440 | if (rd_base[i].type == R_REFLONG) | ||
| 441 | len = 4; | ||
| 442 | else if (rd_base[i].type == R_REFQUAD) | ||
| 443 | len = 8; | ||
| 444 | else | ||
| 445 | fatal_unexec ("unrecognized relocation type in .dyn.rel section (symbol #%d)", i); | ||
| 446 | |||
| 447 | SEEK (new, newref, "seeking to dynamic symbol in %s", new_name); | ||
| 448 | WRITE (new, oldref, len, "writing old dynrel info in %s", new_name); | ||
| 425 | } | 449 | } |
| 426 | 450 | ||
| 451 | #if 0 | ||
| 452 | else | ||
| 453 | fprintf (stderr, "...not relocated\n"); | ||
| 454 | #endif | ||
| 455 | |||
| 456 | } | ||
| 457 | |||
| 427 | } | 458 | } |
| 428 | 459 | ||
| 429 | #endif | 460 | #endif /* !__linux__ */ |
| 430 | 461 | ||
| 431 | 462 | ||
| 432 | /* | 463 | /* |