summaryrefslogtreecommitdiff
path: root/src/unexelf.c
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2009-05-06 02:27:51 +0000
committerYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2009-05-06 02:27:51 +0000
commitbcda200f6a983541782e326144778db4096ba805 (patch)
tree07af4d5e11f67ac7fbc46265da35c3b218af16f5 /src/unexelf.c
parentd01179d9077f640e41958cfec8b1691a28db3f50 (diff)
(unexec): Consider a section to precede the .bss section
if its addresses overlap that of .bss. (unexec) [NS_IMPL_GNUSTEP]: Copy ObjC-related data from old file instead of dumping process.
Diffstat (limited to 'src/unexelf.c')
-rw-r--r--src/unexelf.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/src/unexelf.c b/src/unexelf.c
index 83e5700375..45de52dffd 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -985,9 +985,29 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
placed after the .bss section. Overlap can occur if the
section just before .bss has less-strict alignment; this
was observed between .symtab and .bss on Solaris 2.5.1
- (sparc) with GCC snapshot 960602. */
+ (sparc) with GCC snapshot 960602.
- if (NEW_SECTION_H (nn).sh_offset >= old_bss_offset)
+> dump -h temacs
+
+temacs:
+
+ **** SECTION HEADER TABLE ****
+[No] Type Flags Addr Offset Size Name
+ Link Info Adralgn Entsize
+
+[22] 1 3 0x335150 0x315150 0x4 .data.rel.local
+ 0 0 0x4 0
+
+[23] 8 3 0x335158 0x315158 0x42720 .bss
+ 0 0 0x8 0
+
+[24] 2 0 0 0x315154 0x1c9d0 .symtab
+ 25 1709 0x4 0x10
+ */
+
+ if (NEW_SECTION_H (nn).sh_offset >= old_bss_offset
+ || (NEW_SECTION_H (nn).sh_offset + NEW_SECTION_H (nn).sh_size
+ > new_data2_offset))
NEW_SECTION_H (nn).sh_offset += new_data2_incr;
/* Any section that was originally placed after the section
@@ -1206,11 +1226,41 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
for (; symp < symendp; symp ++)
- if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
- || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
- memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
+ {
+ if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
+ || strcmp ((char *) (symnames + symp->st_name), "end") == 0
+ || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
+ || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
+ memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
+
+ /* Strictly speaking, #ifdef below is not necessary. But we
+ keep it to indicate that this kind of change may also be
+ necessary for other unexecs to support GNUstep. */
+#ifdef NS_IMPL_GNUSTEP
+ /* ObjC runtime modifies the values of some data structures
+ such as classes and selectors in the .data section after
+ loading. As the dump process copies the .data section
+ from the current process, that causes problems when the
+ modified classes are reinitialized in the dumped
+ executable. We copy such data from the old file, not
+ from the current process. */
+ if (strncmp ((char *) (symnames + symp->st_name),
+ "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
+ {
+ caddr_t old, new;
+
+ new = ((symp->st_value - NEW_SECTION_H (symp->st_shndx).sh_addr)
+ + NEW_SECTION_H (symp->st_shndx).sh_offset + new_base);
+ /* "Unpatch" index. */
+ nn = symp->st_shndx;
+ if (nn > old_bss_index)
+ nn--;
+ old = ((symp->st_value - NEW_SECTION_H (symp->st_shndx).sh_addr)
+ + OLD_SECTION_H (nn).sh_offset + old_base);
+ memcpy (new, old, symp->st_size);
+ }
+#endif
+ }
}
/* This loop seeks out relocation sections for the data section, so