emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Your patch on src/unexelf.c causes Emacs can't dump twice


From: Alan Modra
Subject: Re: Your patch on src/unexelf.c causes Emacs can't dump twice
Date: Tue, 17 Nov 2015 07:34:22 +1030
User-agent: Mutt/1.5.23 (2014-03-12)

On Wed, Nov 11, 2015 at 02:54:07PM +0800, Old K wrote:
> I don't know why developers decide Emacs can not call
> '(dump-emacs "newname" "path/to/emacs")' anymore, but if you apply the
> following patch, you can dump emacs again, which is a useful feature
> for me:
> 
> --- a/src/emacs.c
> +++ b/src/emacs.c
> @@ -2045,9 +2045,6 @@ You must run Emacs in batch mode in order to dump
> it.  */)
>    if (! noninteractive)
>      error ("Dumping Emacs works only in batch mode");
> 
> -  if (!might_dump)
> -    error ("Emacs can be dumped only once");
> -
>  #ifdef GNU_LINUX
> 
>    /* Warn if the gap between BSS end and heap start is larger than this.
> */
> 
> 
> You can get more information about 'dump-emacs' at
> http://www.emacswiki.org/emacs/DumpingEmacs
> (And you may have to run Emacs under GDB to dump it again.)
> 
> After applying your patch set, this no longer works.  Namely the last
> two patch may not proper handle .bss properly when emacs dump again.

I think that disabling the might_dump test in emacs.c is dangerous and
you will find that dumping emacs more than once is unreliable.  See
https://lists.gnu.org/archive/html/emacs-devel/2014-01/msg01698.html

However, the following might work for you.  Please report back to the
list whether it does.  I haven't tested this patch beyond checking
that it doesn't break the first emacs dump.

diff --git a/src/unexelf.c b/src/unexelf.c
index c10c7f2..d2aca0c 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -310,24 +310,39 @@ unexec (const char *new_name, const char *old_name)
   /* Note that old_bss_addr may be lower than the first bss section
      address, since the section may need aligning.  */
   old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
-  old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
   old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
 
-  /* Find the last bss style section in the bss segment range.  */
+  /* Find the last section in old_bss_seg.  */
   old_bss_index = -1;
   for (n = old_file_h->e_shnum; --n > 0; )
     {
       ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
-      if (shdr->sh_type == SHT_NOBITS
-         && shdr->sh_addr >= old_bss_addr
-         && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
-         && (old_bss_index == -1
-             || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
-       old_bss_index = n;
+      if (shdr->sh_addr >= old_bss_seg->p_vaddr
+         && (shdr->sh_addr + shdr->sh_size
+             <= old_bss_seg->p_vaddr + old_bss_seg->p_memsz))
+       {
+         if (old_bss_index == -1
+             || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr)
+           old_bss_index = n;
+
+         if (old_bss_size == 0)
+           {
+             /* If we are dumping emacs a second time then the bss
+                region has been converted to have file backing.  */
+             if (old_section_names[shdr->sh_name] == ','
+                 && old_bss_addr > shdr->sh_addr)
+               old_bss_addr = shdr->sh_addr;
+           }
+       }
     }
 
   if (old_bss_index == -1)
-    fatal ("no bss section found");
+    fatal ("no section in last segment");
+
+  old_bss_offset = (old_bss_seg->p_offset
+                   + (old_bss_addr - old_bss_seg->p_vaddr));
+  old_bss_size = (old_bss_seg->p_memsz
+                 - (old_bss_addr - old_bss_seg->p_vaddr));
 
   new_break = sbrk (0);
   new_bss_addr = (ElfW (Addr)) new_break;
@@ -408,8 +423,7 @@ unexec (const char *new_name, const char *old_name)
       ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
       ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
 
-      if (new_shdr->sh_type == SHT_NOBITS
-         && new_shdr->sh_addr >= old_bss_addr
+      if (new_shdr->sh_addr >= old_bss_addr
          && (new_shdr->sh_addr + new_shdr->sh_size
              <= old_bss_addr + old_bss_size))
        {

-- 
Alan Modra
Australia Development Lab, IBM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]