Mercurial > emacs
changeset 7340:1c2342e0edae
(unexec): Handle debugging info properly.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 05 May 1994 19:31:09 +0000 |
parents | b557aa86c53a |
children | 516dd16e2017 |
files | src/=unexsgi.c |
diffstat | 1 files changed, 160 insertions(+), 98 deletions(-) [+] |
line wrap: on
line diff
--- a/src/=unexsgi.c Thu May 05 19:18:57 1994 +0000 +++ b/src/=unexsgi.c Thu May 05 19:31:09 1994 +0000 @@ -418,6 +418,7 @@ #include <unistd.h> #include <fcntl.h> #include <elf.h> +#include <syms.h> /* for HDRR declaration */ #include <sys/mman.h> #ifndef emacs @@ -474,17 +475,16 @@ extern unsigned int bss_end; int new_file, old_file, new_file_size; - /* Pointers to the base of the image of the two files. */ + /* Pointers to the base of the image of the two files. */ caddr_t old_base, new_base; /* Pointers to the file, program and section headers for the old and new - * files. - */ + files. */ Elf32_Ehdr *old_file_h, *new_file_h; Elf32_Phdr *old_program_h, *new_program_h; Elf32_Shdr *old_section_h, *new_section_h; - /* Point to the section name table in the old file */ + /* Point to the section name table in the old file. */ char *old_section_names; Elf32_Addr old_bss_addr, new_bss_addr; @@ -493,9 +493,10 @@ Elf32_Addr new_data2_addr; int n, nn, old_bss_index, old_data_index, new_data2_index; + int old_mdebug_index; struct stat stat_buf; - /* Open the old file & map it into the address space. */ + /* Open the old file & map it into the address space. */ old_file = open (old_name, O_RDONLY); @@ -515,17 +516,30 @@ old_base); #endif - /* Get pointers to headers & section names */ + /* Get pointers to headers & section names. */ old_file_h = (Elf32_Ehdr *) old_base; old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff); old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff); - old_section_names = (char *) old_base - + OLD_SECTION_H(old_file_h->e_shstrndx).sh_offset; + old_section_names + = (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; + + /* Find the mdebug section, if any. */ + for (old_mdebug_index = 1; old_mdebug_index < old_file_h->e_shnum; old_mdebug_index++) + { +#ifdef DEBUG + fprintf (stderr, "Looking for .mdebug - found %s\n", + old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name); +#endif + if (!strcmp (old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name, + ".mdebug")) + break; + } + if (old_mdebug_index == old_file_h->e_shnum) + old_mdebug_index = -1; /* just means no such section was present */ /* Find the old .bss section. Figure out parameters of the new - * data2 and bss sections. - */ + data2 and bss sections. */ for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++) { @@ -540,8 +554,8 @@ if (old_bss_index == old_file_h->e_shnum) fatal ("Can't find .bss in %s.\n", old_name, 0); - old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr; - old_bss_size = OLD_SECTION_H(old_bss_index).sh_size; + old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; + old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; #if defined(emacs) || !defined(DEBUG) bss_end = (unsigned int) sbrk (0); new_bss_addr = (Elf32_Addr) bss_end; @@ -550,7 +564,7 @@ #endif new_data2_addr = old_bss_addr; new_data2_size = new_bss_addr - old_bss_addr; - new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset; + new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; #ifdef DEBUG fprintf (stderr, "old_bss_index %d\n", old_bss_index); @@ -565,34 +579,33 @@ if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size) fatal (".bss shrank when undumping???\n", 0, 0); - /* Set the output file to the right size and mmap(2) it. Set - * pointers to various interesting objects. stat_buf still has - * old_file data. - */ + /* Set the output file to the right size and mmap it. Set + pointers to various interesting objects. stat_buf still has + old_file data. */ new_file = open (new_name, O_RDWR | O_CREAT, 0666); if (new_file < 0) - fatal ("Can't creat(%s): errno %d\n", new_name, errno); + fatal ("Can't creat (%s): errno %d\n", new_name, errno); new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size; if (ftruncate (new_file, new_file_size)) - fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno); + fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, new_file, 0); if (new_base == (caddr_t) -1) - fatal ("Can't mmap(%s): errno %d\n", new_name, errno); + fatal ("Can't mmap (%s): errno %d\n", new_name, errno); new_file_h = (Elf32_Ehdr *) new_base; new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff); - new_section_h = (Elf32_Shdr *) - ((byte *) new_base + old_file_h->e_shoff + new_data2_size); + new_section_h + = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff + + new_data2_size); /* Make our new file, program and section headers as copies of the - * originals. - */ + originals. */ memcpy (new_file_h, old_file_h, old_file_h->e_ehsize); memcpy (new_program_h, old_program_h, @@ -602,8 +615,7 @@ PATCH_INDEX (new_file_h->e_shstrndx); /* Fix up file header. We'll add one section. Section header is - * further away now. - */ + further away now. */ new_file_h->e_shoff += new_data2_size; new_file_h->e_shnum += 1; @@ -616,12 +628,11 @@ #endif /* Fix up a new program header. Extend the writable data segment so - * that the bss area is covered too. Find that segment by looking - * for a segment that ends just before the .bss area. Make sure - * that no segments are above the new .data2. Put a loop at the end - * to adjust the offset and address of any segment that is above - * data2, just in case we decide to allow this later. - */ + that the bss area is covered too. Find that segment by looking + for a segment that ends just before the .bss area. Make sure + that no segments are above the new .data2. Put a loop at the end + to adjust the offset and address of any segment that is above + data2, just in case we decide to allow this later. */ for (n = new_file_h->e_phnum - 1; n >= 0; n--) { @@ -632,11 +643,11 @@ /* Supposedly this condition is okay for the SGI. */ #if 0 - if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr) + if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) fatal ("Program segment above .bss in %s\n", old_name, 0); #endif - if (NEW_PROGRAM_H(n).p_type == PT_LOAD + if (NEW_PROGRAM_H (n).p_type == PT_LOAD && (round_up ((NEW_PROGRAM_H (n)).p_vaddr + (NEW_PROGRAM_H (n)).p_filesz, alignment) @@ -646,143 +657,194 @@ if (n < 0) fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); - NEW_PROGRAM_H(n).p_filesz += new_data2_size; - NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz; + NEW_PROGRAM_H (n).p_filesz += new_data2_size; + NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; -#if 1 /* Maybe allow section after data2 - does this ever happen? */ +#if 1 /* Maybe allow section after data2 - does this ever happen? */ for (n = new_file_h->e_phnum - 1; n >= 0; n--) { - if (NEW_PROGRAM_H(n).p_vaddr - && NEW_PROGRAM_H(n).p_vaddr >= new_data2_addr) - NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size; + if (NEW_PROGRAM_H (n).p_vaddr + && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) + NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size; - if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset) - NEW_PROGRAM_H(n).p_offset += new_data2_size; + if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset) + NEW_PROGRAM_H (n).p_offset += new_data2_size; } #endif /* Fix up section headers based on new .data2 section. Any section - * whose offset or virtual address is after the new .data2 section - * gets its value adjusted. .bss size becomes zero and new address - * is set. data2 section header gets added by copying the existing - * .data header and modifying the offset, address and size. - */ + whose offset or virtual address is after the new .data2 section + gets its value adjusted. .bss size becomes zero and new address + is set. data2 section header gets added by copying the existing + .data header and modifying the offset, address and size. */ for (old_data_index = 1; old_data_index < old_file_h->e_shnum; old_data_index++) - if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name, + if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name, ".data")) break; if (old_data_index == old_file_h->e_shnum) fatal ("Can't find .data in %s.\n", old_name, 0); /* Walk through all section headers, insert the new data2 section right - before the new bss section. */ + before the new bss section. */ for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++) { caddr_t src; - /* If it is bss section, insert the new data2 section before it. */ + /* If it is bss section, insert the new data2 section before it. */ if (n == old_bss_index) { - /* Steal the data section header for this data2 section. */ - memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(old_data_index), + /* Steal the data section header for this data2 section. */ + memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), new_file_h->e_shentsize); - NEW_SECTION_H(nn).sh_addr = new_data2_addr; - NEW_SECTION_H(nn).sh_offset = new_data2_offset; - NEW_SECTION_H(nn).sh_size = new_data2_size; + NEW_SECTION_H (nn).sh_addr = new_data2_addr; + NEW_SECTION_H (nn).sh_offset = new_data2_offset; + NEW_SECTION_H (nn).sh_size = new_data2_size; /* Use the bss section's alignment. This will assure that the new data2 section always be placed in the same spot as the old - bss section by any other application. */ - NEW_SECTION_H(nn).sh_addralign = OLD_SECTION_H(n).sh_addralign; + bss section by any other application. */ + NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign; - /* Now copy over what we have in the memory now. */ - memcpy (NEW_SECTION_H(nn).sh_offset + new_base, - (caddr_t) OLD_SECTION_H(n).sh_addr, + /* Now copy over what we have in the memory now. */ + memcpy (NEW_SECTION_H (nn).sh_offset + new_base, + (caddr_t) OLD_SECTION_H (n).sh_addr, new_data2_size); nn++; } - memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(n), + memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), old_file_h->e_shentsize); /* The new bss section's size is zero, and its file offset and virtual - address should be off by NEW_DATA2_SIZE. */ + address should be off by NEW_DATA2_SIZE. */ if (n == old_bss_index) { /* NN should be `old_bss_index + 1' at this point. */ - NEW_SECTION_H(nn).sh_offset += new_data2_size; - NEW_SECTION_H(nn).sh_addr += new_data2_size; + NEW_SECTION_H (nn).sh_offset += new_data2_size; + NEW_SECTION_H (nn).sh_addr += new_data2_size; /* Let the new bss section address alignment be the same as the section address alignment followed the old bss section, so - this section will be placed in exactly the same place. */ - NEW_SECTION_H(nn).sh_addralign = OLD_SECTION_H(nn).sh_addralign; - NEW_SECTION_H(nn).sh_size = 0; + this section will be placed in exactly the same place. */ + NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign; + NEW_SECTION_H (nn).sh_size = 0; } /* Any section that was original placed AFTER the bss section should now - be off by NEW_DATA2_SIZE. */ - else if (NEW_SECTION_H(nn).sh_offset >= new_data2_offset) - NEW_SECTION_H(nn).sh_offset += new_data2_size; + be off by NEW_DATA2_SIZE. */ + else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) + NEW_SECTION_H (nn).sh_offset += new_data2_size; /* If any section hdr refers to the section after the new .data section, make it refer to next one because we have inserted - a new section in between. */ + a new section in between. */ - PATCH_INDEX(NEW_SECTION_H(nn).sh_link); - PATCH_INDEX(NEW_SECTION_H(nn).sh_info); + PATCH_INDEX (NEW_SECTION_H (nn).sh_link); + PATCH_INDEX (NEW_SECTION_H (nn).sh_info); /* Now, start to copy the content of sections. */ - if (NEW_SECTION_H(nn).sh_type == SHT_NULL - || NEW_SECTION_H(nn).sh_type == SHT_NOBITS) + if (NEW_SECTION_H (nn).sh_type == SHT_NULL + || NEW_SECTION_H (nn).sh_type == SHT_NOBITS) continue; /* Write out the sections. .data and .data1 (and data2, called - * ".data" in the strings table) get copied from the current process - * instead of the old file. - */ - if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data") - || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name), + ".data" in the strings table) get copied from the current process + instead of the old file. */ + if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") + || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), ".data1")) - src = (caddr_t) OLD_SECTION_H(n).sh_addr; + src = (caddr_t) OLD_SECTION_H (n).sh_addr; else - src = old_base + OLD_SECTION_H(n).sh_offset; + src = old_base + OLD_SECTION_H (n).sh_offset; - memcpy (NEW_SECTION_H(nn).sh_offset + new_base, src, - NEW_SECTION_H(nn).sh_size); + memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, + NEW_SECTION_H (nn).sh_size); + + /* Adjust the HDRR offsets in .mdebug and copy the + line data if it's in its usual 'hole' in the object. + Makes the new file debuggable with dbx. + patches up two problems: the absolute file offsets + in the HDRR record of .mdebug (see /usr/include/syms.h), and + the ld bug that gets the line table in a hole in the + elf file rather than in the .mdebug section proper. + David Anderson. davea@sgi.com Jan 16,1994. */ + if (n == old_mdebug_index) + { +#define MDEBUGADJUST(__ct,__fileaddr) \ + if (n_phdrr->__ct > 0) \ + { \ + n_phdrr->__fileaddr += movement; \ + } + + HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset); + HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset); + unsigned movement = new_data2_size; + + MDEBUGADJUST (idnMax, cbDnOffset); + MDEBUGADJUST (ipdMax, cbPdOffset); + MDEBUGADJUST (isymMax, cbSymOffset); + MDEBUGADJUST (ioptMax, cbOptOffset); + MDEBUGADJUST (iauxMax, cbAuxOffset); + MDEBUGADJUST (issMax, cbSsOffset); + MDEBUGADJUST (issExtMax, cbSsExtOffset); + MDEBUGADJUST (ifdMax, cbFdOffset); + MDEBUGADJUST (crfd, cbRfdOffset); + MDEBUGADJUST (iextMax, cbExtOffset); + /* The Line Section, being possible off in a hole of the object, + requires special handling. */ + if (n_phdrr->cbLine > 0) + { + if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset + + OLD_SECTION_H (n).sh_size)) + { + /* line data is in a hole in elf. do special copy and adjust + for this ld mistake. + */ + n_phdrr->cbLineOffset += movement; + + memcpy (n_phdrr->cbLineOffset + new_base, + o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine); + } + else + { + /* somehow line data is in .mdebug as it is supposed to be. */ + MDEBUGADJUST (cbLine, cbLineOffset); + } + } + } /* If it is the symbol table, its st_shndx field needs to be patched. */ - if (NEW_SECTION_H(nn).sh_type == SHT_SYMTAB - || NEW_SECTION_H(nn).sh_type == SHT_DYNSYM) + if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB + || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) { - Elf32_Shdr *spt = &NEW_SECTION_H(nn); + Elf32_Shdr *spt = &NEW_SECTION_H (nn); unsigned int num = spt->sh_size / spt->sh_entsize; - Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H(nn).sh_offset + - new_base); + Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset + + new_base); for (; num--; sym++) { - if ((sym->st_shndx == SHN_UNDEF) - || (sym->st_shndx == SHN_ABS) - || (sym->st_shndx == SHN_COMMON)) + if (sym->st_shndx == SHN_UNDEF + || sym->st_shndx == SHN_ABS + || sym->st_shndx == SHN_COMMON) continue; - PATCH_INDEX(sym->st_shndx); + PATCH_INDEX (sym->st_shndx); } } } - /* Close the files and make the new file executable */ + /* Close the files and make the new file executable. */ if (close (old_file)) - fatal ("Can't close(%s): errno %d\n", old_name, errno); + fatal ("Can't close (%s): errno %d\n", old_name, errno); if (close (new_file)) - fatal ("Can't close(%s): errno %d\n", new_name, errno); + fatal ("Can't close (%s): errno %d\n", new_name, errno); if (stat (new_name, &stat_buf) == -1) - fatal ("Can't stat(%s): errno %d\n", new_name, errno); + fatal ("Can't stat (%s): errno %d\n", new_name, errno); n = umask (777); umask (n); stat_buf.st_mode |= 0111 & ~n; if (chmod (new_name, stat_buf.st_mode) == -1) - fatal ("Can't chmod(%s): errno %d\n", new_name, errno); + fatal ("Can't chmod (%s): errno %d\n", new_name, errno); }