444
+ − 1 /* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1999, 2000
428
+ − 2 Free Software Foundation, Inc.
+ − 3
446
+ − 4 This file is part of XEmacs.
428
+ − 5
446
+ − 6 XEmacs is free software; you can redistribute it and/or modify it
+ − 7 under the terms of the GNU General Public License as published by
+ − 8 the Free Software Foundation; either version 2, or (at your option)
+ − 9 any later version.
428
+ − 10
613
+ − 11 XEmacs is distributed in the hope that it will be useful, but
446
+ − 12 WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ − 14 General Public License for more details.
444
+ − 15
446
+ − 16 You should have received a copy of the GNU General Public License
613
+ − 17 along with XEmacs; see the file COPYING. If not, write to the
446
+ − 18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 19 Boston, MA 02111-1307, USA.
428
+ − 20
446
+ − 21 In other words, you are welcome to use, share and improve this
+ − 22 program. You are forbidden to forbid anyone else to use, share and
+ − 23 improve what you give them. Help stamp out software-hoarding! */
428
+ − 24
+ − 25
+ − 26 /*
+ − 27 * unexec.c - Convert a running program into an a.out file.
+ − 28 *
+ − 29 * Author: Spencer W. Thomas
+ − 30 * Computer Science Dept.
+ − 31 * University of Utah
+ − 32 * Date: Tue Mar 2 1982
+ − 33 * Modified heavily since then.
+ − 34 *
+ − 35 * Synopsis:
446
+ − 36 * void
+ − 37 * unexec (char *new_name,
+ − 38 * char *old_name,
+ − 39 * uintptr_t data_start,
+ − 40 * uintptr_t bss_start,
+ − 41 * uintptr_t entry_address)
428
+ − 42 *
446
+ − 43 * The basic idea is that we start with an ELF file which contains
+ − 44 * .bss (uninitialized global data) section which is normally not in
+ − 45 * the file. As we load lisp the variables, which were first set to 0,
+ − 46 * will change their values. We want to save those changed values into
+ − 47 * another ELF file, which will become a new xemacs image. To do this,
+ − 48 * we need to change several structures in the ELF file.
428
+ − 49 *
446
+ − 50 * First of all, we need to change the programm header which tells
+ − 51 * the linker how to load stuff into memory so that data will come
+ − 52 * from the file and not from the /dev/zero. To do this, we find the
+ − 53 * segment, which is marked as loadable (type PT_LOAD) and which
+ − 54 * covers the old .bss section. We will next change the filesz and
+ − 55 * memsz for that segment to extend over the new data section.
428
+ − 56 *
446
+ − 57 * Next we have to make sure that section header for the stuff which
+ − 58 * used to be uninitialized is changed to be initialized and to come
+ − 59 * from the file. To do this, we change the size and the type of the old
+ − 60 * .bss section (and all other section of the type SHT_NOBITS) to cover the
+ − 61 * new section and to be of type SHT_PROCBITS.
444
+ − 62 *
446
+ − 63 * We also insert a new SHT_NOBITS section to keep some tools, which expect
+ − 64 * .bss happy.
428
+ − 65 *
446
+ − 66 * Finally we need to patch up some references to the section
+ − 67 * indexes since we change the order and undo the relocation info to
+ − 68 * be the same as it was "before" because we actually used the data
+ − 69 * from the memory which were changed by the run-time linker.
428
+ − 70 */
444
+ − 71
+ − 72 #ifndef emacs
+ − 73 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
+ − 74 #include <string.h>
+ − 75 #else
+ − 76 #include <config.h>
+ − 77 extern void fatal (const char *, ...);
+ − 78 #endif
428
+ − 79
+ − 80 #include <sys/types.h>
+ − 81 #include <stdio.h>
+ − 82 #include <sys/stat.h>
+ − 83 #include <memory.h>
+ − 84 #include <errno.h>
+ − 85 #include <unistd.h>
+ − 86 #include <fcntl.h>
446
+ − 87 #ifdef HAVE_ELF_H
428
+ − 88 #include <elf.h>
444
+ − 89 #endif
428
+ − 90 #include <sys/mman.h>
444
+ − 91 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
+ − 92 #include <sys/elf_mips.h>
+ − 93 #include <sym.h>
+ − 94 #endif /* __sony_news && _SYSTYPE_SYSV */
+ − 95 #if __sgi
+ − 96 #include <syms.h> /* for HDRR declaration */
+ − 97 #endif /* __sgi */
428
+ − 98
444
+ − 99 #if __GNU_LIBRARY__ - 0 >= 6
+ − 100 # include <link.h> /* get ElfW etc */
+ − 101 #endif
+ − 102
2286
+ − 103 #include "compiler.h"
+ − 104
444
+ − 105 #ifndef ElfW
+ − 106 # ifdef __STDC__
+ − 107 # define ElfBitsW(bits, type) Elf##bits##_##type
+ − 108 # else
+ − 109 # define ElfBitsW(bits, type) Elf/**/bits/**/_/**/type
+ − 110 # endif
+ − 111 # ifdef _LP64
+ − 112 # define ELFSIZE 64
+ − 113 # else
+ − 114 # define ELFSIZE 32
+ − 115 # endif
+ − 116 /* This macro expands `bits' before invoking ElfBitsW. */
+ − 117 # define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
+ − 118 # define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
+ − 119 #endif
+ − 120
+ − 121 #ifndef ELF_BSS_SECTION_NAME
+ − 122 #define ELF_BSS_SECTION_NAME ".bss"
+ − 123 #endif
428
+ − 124
+ − 125 /* Get the address of a particular section or program header entry,
446
+ − 126 * accounting for the size of the entries. */
428
+ − 127
+ − 128 #define OLD_SECTION_H(n) \
444
+ − 129 (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
428
+ − 130 #define NEW_SECTION_H(n) \
444
+ − 131 (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
428
+ − 132 #define OLD_PROGRAM_H(n) \
444
+ − 133 (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
428
+ − 134 #define NEW_PROGRAM_H(n) \
444
+ − 135 (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
428
+ − 136
+ − 137 #define PATCH_INDEX(n) \
+ − 138 do { \
446
+ − 139 if ((int) (n) >= growme_index) \
428
+ − 140 (n)++; } while (0)
446
+ − 141
428
+ − 142 typedef unsigned char byte;
+ − 143
+ − 144 /* Round X up to a multiple of Y. */
+ − 145
444
+ − 146 static ElfW(Addr)
+ − 147 round_up (ElfW(Addr) x, ElfW(Addr) y)
428
+ − 148 {
+ − 149 int rem = x % y;
+ − 150 if (rem == 0)
+ − 151 return x;
+ − 152 return x - rem + y;
+ − 153 }
+ − 154
+ − 155 /* Return the index of the section named NAME.
+ − 156 SECTION_NAMES, FILE_NAME and FILE_H give information
+ − 157 about the file we are looking in.
+ − 158
+ − 159 If we don't find the section NAME, that is a fatal error
+ − 160 if NOERROR is 0; we return -1 if NOERROR is nonzero. */
+ − 161
+ − 162 static int
+ − 163 find_section (char *name,
446
+ − 164 const char *section_names,
428
+ − 165 char *file_name,
444
+ − 166 ElfW(Ehdr) *old_file_h,
+ − 167 ElfW(Shdr) *old_section_h,
428
+ − 168 int noerror)
+ − 169 {
+ − 170 int idx;
+ − 171
+ − 172 for (idx = 1; idx < old_file_h->e_shnum; idx++)
+ − 173 {
+ − 174 #ifdef DEBUG
+ − 175 fprintf (stderr, "Looking for %s - found %s\n", name,
+ − 176 section_names + OLD_SECTION_H (idx).sh_name);
+ − 177 #endif
+ − 178 if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
+ − 179 name))
446
+ − 180 return idx;
428
+ − 181 }
+ − 182
446
+ − 183 /* If we're here, we found nothing or return did not work */
+ − 184 if ( ! noerror)
+ − 185 fatal ("Can't find %s in %s.\n", name, file_name);
+ − 186
+ − 187 return -1;
428
+ − 188 }
+ − 189
+ − 190 /* ****************************************************************
+ − 191 * unexec
+ − 192 *
+ − 193 * driving logic.
+ − 194 *
+ − 195 * In ELF, this works by replacing the old .bss section with a new
+ − 196 * .data section, and inserting an empty .bss immediately afterwards.
+ − 197 *
+ − 198 */
444
+ − 199 void
428
+ − 200 unexec (char *new_name,
+ − 201 char *old_name,
2286
+ − 202 uintptr_t UNUSED (data_start),
+ − 203 uintptr_t UNUSED (bss_start),
+ − 204 uintptr_t UNUSED (entry_address))
428
+ − 205 {
446
+ − 206 int old_file;
428
+ − 207
446
+ − 208 struct stat stat_buf;
428
+ − 209 caddr_t old_base, new_base;
+ − 210
446
+ − 211 ElfW(Ehdr) *old_file_h, * new_file_h;
+ − 212 ElfW(Phdr) *old_program_h, * new_program_h;
+ − 213 ElfW(Shdr) *old_section_h, * new_section_h;
+ − 214 ElfW(Shdr) * growme = NULL, * grown = NULL;
+ − 215 ElfW(Addr) old_bss_addr = 0, new_data2_addr = 0;
428
+ − 216
446
+ − 217 int growme_index = -1;
444
+ − 218 int n, nn;
446
+ − 219 const char *old_section_names;
+ − 220 int old_mdebug_index, old_data_index;
+ − 221 int new_bss_addr, new_data2_size, new_data2_offset, new_file, new_file_size;
428
+ − 222
446
+ − 223 /* Open the old file */
+ − 224 if ( (old_file = open (old_name, O_RDONLY)) < 0 )
+ − 225 fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
428
+ − 226
+ − 227 if (fstat (old_file, &stat_buf) == -1)
446
+ − 228 fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
428
+ − 229
446
+ − 230 /* map old file into the address space. */
448
+ − 231 old_base = (caddr_t) mmap ((caddr_t) 0, stat_buf.st_size,
+ − 232 PROT_READ, MAP_SHARED, old_file, 0);
+ − 233 if (old_base == (caddr_t) MAP_FAILED)
+ − 234 fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
428
+ − 235
446
+ − 236 old_file_h = (ElfW(Ehdr) *) old_base;
444
+ − 237 old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
+ − 238 old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
446
+ − 239 old_section_names = (const char *) old_base
+ − 240 + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
428
+ − 241
446
+ − 242 /* Find a section which we will grow by looking for the SHT_NOBITS
+ − 243 * section with ALLOCATE flag and with the biggest address. */
+ − 244 for (n = 1; n < old_file_h->e_shnum; n++) {
+ − 245 ElfW(Shdr) * sh = & OLD_SECTION_H(n);
428
+ − 246
446
+ − 247 if ((sh->sh_type == SHT_NOBITS) && (sh->sh_flags & SHF_ALLOC)) {
+ − 248 if ( old_bss_addr < sh->sh_addr ) {
+ − 249 growme = sh;
+ − 250 growme_index = n;
+ − 251 new_data2_addr = old_bss_addr = sh->sh_addr;
+ − 252 }
+ − 253 }
+ − 254 }
428
+ − 255
446
+ − 256 if (growme == NULL )
+ − 257 fatal ("Can't find a section to grow\n", 0, 0);
428
+ − 258
+ − 259 old_data_index = find_section (".data", old_section_names,
+ − 260 old_name, old_file_h, old_section_h, 0);
+ − 261
444
+ − 262 new_bss_addr = (ElfW(Addr)) sbrk (0);
+ − 263 new_data2_size = new_bss_addr - old_bss_addr;
428
+ − 264 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset +
446
+ − 265 (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
428
+ − 266
446
+ − 267 if ( new_bss_addr < old_bss_addr + growme->sh_size )
+ − 268 fatal (".bss shrank when undumping???\n", 0, 0);
428
+ − 269
446
+ − 270 /* Set the output file to the right size and mmap it. */
+ − 271 if ( (new_file = open (new_name, O_RDWR | O_CREAT, 0666)) < 0 )
+ − 272 fatal ("Can't create (%s): errno %d\n", new_name, errno);
428
+ − 273
446
+ − 274 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
428
+ − 275
+ − 276 if (ftruncate (new_file, new_file_size))
446
+ − 277 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
428
+ − 278
444
+ − 279 new_base = (caddr_t) mmap ((caddr_t) 0, new_file_size,
+ − 280 PROT_READ | PROT_WRITE,
446
+ − 281 #ifdef UNEXEC_USE_MAP_PRIVATE
+ − 282 MAP_PRIVATE,
444
+ − 283 #else
446
+ − 284 MAP_SHARED,
444
+ − 285 #endif
446
+ − 286 new_file, 0);
428
+ − 287
+ − 288 if (new_base == (caddr_t) -1)
446
+ − 289 fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
428
+ − 290
444
+ − 291 new_file_h = (ElfW(Ehdr) *) new_base;
+ − 292 new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
446
+ − 293 new_section_h = (ElfW(Shdr) *) ((byte *) new_base + old_file_h->e_shoff +
+ − 294 new_data2_size);
428
+ − 295
+ − 296 /* Make our new file, program and section headers as copies of the
446
+ − 297 * originals. */
428
+ − 298 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
+ − 299 memcpy (new_program_h, old_program_h,
+ − 300 old_file_h->e_phnum * old_file_h->e_phentsize);
+ − 301
+ − 302 /* Modify the e_shstrndx if necessary. */
+ − 303 PATCH_INDEX (new_file_h->e_shstrndx);
+ − 304
+ − 305 /* Fix up file header. We'll add one section. Section header is
446
+ − 306 * further away now. */
444
+ − 307 new_file_h->e_shoff += new_data2_size;
428
+ − 308 new_file_h->e_shnum += 1;
+ − 309
446
+ − 310 /* Fix up a new program header by extending the writable data
+ − 311 * segment so that the bss area is covered too. Find that segment by
+ − 312 * looking for one that starts before and ends after the .bss and is
+ − 313 * PT_LOADable. */
+ − 314 for (n = new_file_h->e_phnum - 1; n >= 0; n--) {
+ − 315 ElfW(Phdr) * ph = & NEW_PROGRAM_H(n);
428
+ − 316 #ifdef DEBUG
446
+ − 317 printf ("%d @ %0x + %0x against %0x + %0x",
+ − 318 n, ph->p_vaddr, ph->p_memsz,growme->sh_addr, growme->sh_size);
428
+ − 319 #endif
446
+ − 320 if ((ph->p_type == PT_LOAD) &&
+ − 321 (ph->p_vaddr <= growme->sh_addr) &&
+ − 322 ((ph->p_vaddr+ph->p_memsz) >= (growme->sh_addr + growme->sh_size))) {
+ − 323 /* Make sure that the size includes any padding before the
+ − 324 * old .bss section. */
+ − 325 ph->p_memsz = ph->p_filesz = new_bss_addr - ph->p_vaddr;
+ − 326 #ifdef DEBUG
+ − 327 puts (" That's the one!");
+ − 328 #endif
+ − 329 break;
+ − 330 }
+ − 331 #ifdef DEBUG
+ − 332 putchar ('\n');
+ − 333 #endif
+ − 334 }
428
+ − 335
446
+ − 336 if (n < 0)
+ − 337 fatal ("Couldn't find segment which covers %s",
+ − 338 old_section_names + growme->sh_name);
428
+ − 339
446
+ − 340 /* Walk through all section headers, insert the new data2 section
+ − 341 * right before the new bss section. */
+ − 342 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) {
+ − 343 ElfW(Shdr) * nsec = & NEW_SECTION_H(nn);
+ − 344 ElfW(Shdr) * osec = & OLD_SECTION_H(n);
428
+ − 345
446
+ − 346 /* If this is the section we want to grow, insert the new data
+ − 347 * section before it. */
+ − 348 if ( osec == growme ) {
+ − 349 /* Steal the data section header for this data2 section but
+ − 350 * use the * 'grow' section's alignment. This * will assure
+ − 351 * that the new section * always be placed in the same spot
+ − 352 * * as the old section by any other * application. */
+ − 353 ElfW(Shdr) * od = &OLD_SECTION_H(old_data_index);
444
+ − 354
446
+ − 355 memcpy (nsec, od, new_file_h->e_shentsize);
428
+ − 356
446
+ − 357 nsec->sh_addr = new_data2_addr;
+ − 358 nsec->sh_offset = new_data2_offset;
+ − 359 nsec->sh_size = new_data2_size;
+ − 360 nsec->sh_addralign = osec->sh_addralign;
+ − 361
+ − 362 /* Copy over what we have in memory now. */
+ − 363 memcpy (nsec->sh_offset + new_base, (caddr_t) osec->sh_addr,
428
+ − 364 new_data2_size);
+ − 365 nn++;
446
+ − 366 grown = nsec++;
+ − 367 }
+ − 368
+ − 369 memcpy (nsec, osec, old_file_h->e_shentsize);
444
+ − 370
446
+ − 371 if ( osec == growme ) {
+ − 372 /* The new bss section's size is zero, and its file offset
+ − 373 * and virtual address should be off by NEW_DATA2_SIZE. */
+ − 374 nsec->sh_offset = grown->sh_offset + new_data2_size;
+ − 375 nsec->sh_addr = grown->sh_addr + new_data2_size;
444
+ − 376
446
+ − 377 /* Let the new bss section address alignment be the same as
+ − 378 * the section address alignment followed the old bss
+ − 379 * section, so this section will be placed in exactly the
+ − 380 * same place. */
+ − 381 nsec->sh_addralign = osec->sh_addralign;
+ − 382 nsec->sh_size = 0;
+ − 383 } else {
+ − 384 /* Any section that was originally placed AFTER the bss
+ − 385 * section should now be off by NEW_DATA2_SIZE. */
+ − 386 if ( round_up (nsec->sh_offset, growme->sh_addralign) >=
+ − 387 new_data2_offset)
+ − 388 nsec->sh_offset += new_data2_size;
+ − 389 }
+ − 390
+ − 391 /* Any section that was originally placed after the section *
+ − 392 * header table should now be off by the size of one section
+ − 393 * header table entry. */
+ − 394 if (nsec->sh_offset > new_file_h->e_shoff)
+ − 395 nsec->sh_offset += new_file_h->e_shentsize;
+ − 396
428
+ − 397
+ − 398 /* If any section hdr refers to the section after the new .data
446
+ − 399 * section, make it refer to next one because we have inserted a
+ − 400 * new section in between. */
+ − 401 PATCH_INDEX (nsec->sh_link);
+ − 402
+ − 403 /* For symbol tables, info is a symbol table index, so don't
+ − 404 * change it. */
+ − 405 if (nsec->sh_type != SHT_SYMTAB && nsec->sh_type != SHT_DYNSYM)
+ − 406 PATCH_INDEX (nsec->sh_info);
+ − 407
+ − 408 /* Any section which used to be NOBITS will now becomes PROGBITS
+ − 409 * if it's ALLOC-atable, unless, of cause, it's not the one we
+ − 410 * decided to grow */
+ − 411 if ( (osec->sh_type == SHT_NOBITS) && (osec->sh_flags & SHF_ALLOC) &&
+ − 412 (osec != growme ) ) {
+ − 413 nsec->sh_type = SHT_PROGBITS;
+ − 414 }
444
+ − 415
446
+ − 416 /* Now, start to copy the content of sections */
+ − 417 if ( nsec->sh_type != SHT_NULL || nsec->sh_type != SHT_NOBITS ) {
428
+ − 418
446
+ − 419 /* Write out the sections. .data and .data1 (and data2,
+ − 420 * called ".data" in the strings table) get copied from the
+ − 421 * current process instead of the old file. */
+ − 422 caddr_t src = old_base + osec->sh_offset;
+ − 423 const char * secname = old_section_names + nsec->sh_name;
+ − 424 const char * names[] = {
+ − 425 ".data",".sdata", ".lit4", ".lit8", ".sdata1", ".data1",
+ − 426 ".sbss", NULL};
+ − 427 int i;
+ − 428
+ − 429 for ( i=0; names[i] != NULL; i++ ) {
+ − 430 if ( ! strcmp (secname, names[i]) ) {
+ − 431 src = (caddr_t) osec->sh_addr;
+ − 432 break;
+ − 433 }
444
+ − 434 }
+ − 435
446
+ − 436 memcpy (nsec->sh_offset + new_base, src, nsec->sh_size);
+ − 437 }
444
+ − 438
446
+ − 439 old_mdebug_index = find_section (".mdebug", old_section_names,
+ − 440 old_name, old_file_h, old_section_h, 1);
444
+ − 441
+ − 442 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
446
+ − 443 if (nsec->sh_type == SHT_MIPS_DEBUG && old_mdebug_index != -1) {
+ − 444 int diff = nsec->sh_offset-OLD_SECTION_H(old_mdebug_index).sh_offset;
+ − 445 HDRR *phdr = (HDRR *)(nsec->sh_offset + new_base);
444
+ − 446
446
+ − 447 if (diff) {
444
+ − 448 phdr->cbLineOffset += diff;
+ − 449 phdr->cbDnOffset += diff;
+ − 450 phdr->cbPdOffset += diff;
+ − 451 phdr->cbSymOffset += diff;
+ − 452 phdr->cbOptOffset += diff;
+ − 453 phdr->cbAuxOffset += diff;
+ − 454 phdr->cbSsOffset += diff;
+ − 455 phdr->cbSsExtOffset += diff;
+ − 456 phdr->cbFdOffset += diff;
+ − 457 phdr->cbRfdOffset += diff;
+ − 458 phdr->cbExtOffset += diff;
446
+ − 459 }
+ − 460 }
444
+ − 461 #endif /* __sony_news && _SYSTYPE_SYSV */
+ − 462
+ − 463 #if __sgi
446
+ − 464 /* Adjust the HDRR offsets in .mdebug and copy the line data if
+ − 465 * it's in its usual 'hole' in the object. Makes the new file
+ − 466 * debuggable with dbx. patches up two problems: the absolute
+ − 467 * file offsets in the HDRR record of .mdebug (see
+ − 468 * /usr/include/syms.h), and the ld bug that gets the line table
+ − 469 * in a hole in the elf file rather than in the .mdebug section
+ − 470 * proper.
+ − 471 *
+ − 472 * David Anderson. davea@sgi.com Jan 16,1994 */
428
+ − 473 #define MDEBUGADJUST(__ct,__fileaddr) \
+ − 474 if (n_phdrr->__ct > 0) \
+ − 475 { \
+ − 476 n_phdrr->__fileaddr += movement; \
+ − 477 }
+ − 478
446
+ − 479 if (n == old_mdebug_index) {
+ − 480 HDRR * o_phdrr = (HDRR *)((byte *)old_base + osec->sh_offset);
+ − 481 HDRR * n_phdrr = (HDRR *)((byte *)new_base + nsec->sh_offset);
444
+ − 482 unsigned movement = new_data2_size;
428
+ − 483
+ − 484 MDEBUGADJUST (idnMax, cbDnOffset);
+ − 485 MDEBUGADJUST (ipdMax, cbPdOffset);
+ − 486 MDEBUGADJUST (isymMax, cbSymOffset);
+ − 487 MDEBUGADJUST (ioptMax, cbOptOffset);
+ − 488 MDEBUGADJUST (iauxMax, cbAuxOffset);
+ − 489 MDEBUGADJUST (issMax, cbSsOffset);
+ − 490 MDEBUGADJUST (issExtMax, cbSsExtOffset);
+ − 491 MDEBUGADJUST (ifdMax, cbFdOffset);
+ − 492 MDEBUGADJUST (crfd, cbRfdOffset);
+ − 493 MDEBUGADJUST (iextMax, cbExtOffset);
446
+ − 494
+ − 495 /* The Line Section, being possible off in a hole of the
+ − 496 * object, requires special handling. */
+ − 497 if (n_phdrr->cbLine > 0) {
+ − 498 if (o_phdrr->cbLineOffset >
+ − 499 osec->sh_offset+ osec->sh_size){
+ − 500 /* line data is in a hole in elf. do special copy
+ − 501 * and adjust for this ld mistake. */
428
+ − 502 n_phdrr->cbLineOffset += movement;
+ − 503
+ − 504 memcpy (n_phdrr->cbLineOffset + new_base,
+ − 505 o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
446
+ − 506 } else {
+ − 507 /* somehow line data is in .mdebug as it is supposed
+ − 508 * to be. */
428
+ − 509 MDEBUGADJUST (cbLine, cbLineOffset);
446
+ − 510 }
+ − 511 }
+ − 512 }
444
+ − 513 #endif /* __sgi */
446
+ − 514 /* If it is the symbol table, its st_shndx field needs to be
+ − 515 * patched. */
+ − 516 if (nsec->sh_type == SHT_SYMTAB || nsec->sh_type == SHT_DYNSYM) {
+ − 517 unsigned int num = nsec->sh_size / nsec->sh_entsize;
+ − 518 ElfW(Sym) * sym = (ElfW(Sym) *)(nsec->sh_offset + new_base);
+ − 519 byte *symnames = ((byte *) new_base +
+ − 520 NEW_SECTION_H (nsec->sh_link).sh_offset);
428
+ − 521
446
+ − 522 for (; num--; sym++) {
+ − 523 const char * symnam = (char *) (symnames + sym->st_name);
+ − 524
+ − 525 /* Update the symbol values of _edata and _end. */
+ − 526 if (strcmp (symnam, "_end") == 0
+ − 527 || strcmp (symnam, "end") == 0
+ − 528 || strcmp (symnam, "_edata") == 0
+ − 529 || strcmp (symnam, "edata") == 0)
+ − 530 memcpy (&sym->st_value, &new_bss_addr,sizeof (new_bss_addr));
+ − 531
+ − 532
+ − 533 if ((sym->st_shndx == SHN_UNDEF) || (sym->st_shndx == SHN_ABS)
+ − 534 || (sym->st_shndx == SHN_COMMON)
+ − 535 || (sym->st_shndx >= SHN_LOPROC &&
+ − 536 sym->st_shndx <= SHN_HIPROC))
+ − 537 continue;
444
+ − 538
428
+ − 539 PATCH_INDEX (sym->st_shndx);
446
+ − 540 }
+ − 541 }
+ − 542 }
444
+ − 543
+ − 544 /* This loop seeks out relocation sections for the data section, so
446
+ − 545 * that it can undo relocations performed by the runtime linker. */
+ − 546 for (n = new_file_h->e_shnum - 1; n; n--) {
444
+ − 547 ElfW(Shdr) section = NEW_SECTION_H (n);
446
+ − 548
+ − 549 if ( section.sh_type == SHT_REL || section.sh_type == SHT_RELA ) {
+ − 550 /* This code handles two different size structs, but there
+ − 551 * should be no harm in that provided that r_offset is
+ − 552 * always the first member. */
+ − 553 ElfW(Shdr) * info = & NEW_SECTION_H(section.sh_info);
+ − 554 const char * nm = old_section_names + info->sh_name;
+ − 555
+ − 556 if (!strcmp (nm, ".data") || !strcmp (nm, ".sdata")
+ − 557 || !strcmp (nm, ".lit4") || !strcmp (nm, ".lit8")
+ − 558 || !strcmp (nm, ".sdata1") || !strcmp (nm, ".data1")) {
+ − 559 ElfW(Addr) offset = info->sh_addr - info->sh_offset;
+ − 560 caddr_t end, reloc = old_base + section.sh_offset;
+ − 561
+ − 562 for (end = reloc + section.sh_size; reloc < end;
+ − 563 reloc += section.sh_entsize) {
+ − 564 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
444
+ − 565 #ifdef __alpha__
446
+ − 566 /* The Alpha ELF binutils currently have a bug that
+ − 567 * sometimes results in relocs that contain all
+ − 568 * zeroes. Work around this for now... */
+ − 569 if (((ElfW(Rel) *) reloc)->r_offset == 0)
+ − 570 continue;
444
+ − 571 #endif
446
+ − 572 memcpy (new_base + addr, old_base + addr,
+ − 573 sizeof(ElfW(Addr)));
444
+ − 574 }
+ − 575 }
+ − 576 }
446
+ − 577 }
444
+ − 578
+ − 579 #ifdef UNEXEC_USE_MAP_PRIVATE
+ − 580 if (lseek (new_file, 0, SEEK_SET) == -1)
446
+ − 581 fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
444
+ − 582
+ − 583 if (write (new_file, new_base, new_file_size) != new_file_size)
446
+ − 584 fatal ("Can't write (%s): errno %d\n", new_name, errno);
444
+ − 585 #endif
+ − 586
428
+ − 587 /* Close the files and make the new file executable. */
+ − 588 if (close (old_file))
446
+ − 589 fatal ("Can't close (%s): errno %d\n", old_name, errno);
428
+ − 590
+ − 591 if (close (new_file))
446
+ − 592 fatal ("Can't close (%s): errno %d\n", new_name, errno);
428
+ − 593
+ − 594 if (stat (new_name, &stat_buf) == -1)
446
+ − 595 fatal ("Can't stat (%s): errno %d\n", new_name, errno);
428
+ − 596
+ − 597 n = umask (777);
+ − 598 umask (n);
+ − 599 stat_buf.st_mode |= 0111 & ~n;
+ − 600 if (chmod (new_name, stat_buf.st_mode) == -1)
446
+ − 601 fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
428
+ − 602 }