瀏覽代碼

[Pal] db_rtld.c: Fix GDB on PIE executables by fixing mapstart/mapend

Previously, there was a latent bug in db_rtld.c: add_elf_object() --
the mapstart variable was incorrectly initialized to zero. This led to
PIE executables (which typically have two LOAD segments, the code
segment starting with 0x0 and the GOT/PLT/dynamic segment starting with
e.g. 0x200000) to incorrectly set mapstart to the higher-LOAD-segment
address (and not the code address). This in turn confused GDB which
tried to add executable symbols from the wrong offset.

This commit fixes this bug by initializing mapstart to the highest
possible value ("~0") and removing the check for zero. This is similar
to what the Glibc code does. Also, mapend is fixed in a similar way.
Dmitrii Kuvaiskii 6 年之前
父節點
當前提交
b0b29c54c8
共有 1 個文件被更改,包括 4 次插入3 次删除
  1. 4 3
      Pal/src/db_rtld.c

+ 4 - 3
Pal/src/db_rtld.c

@@ -521,7 +521,8 @@ int add_elf_object(void * addr, PAL_HANDLE handle, int type)
     map->l_phdr  = (void *) header->e_phoff;
     map->l_phdr  = (void *) header->e_phoff;
     map->l_phnum = header->e_phnum;
     map->l_phnum = header->e_phnum;
 
 
-    ElfW(Addr) mapstart = 0, mapend = 0;
+    ElfW(Addr) mapstart = ~0;  /* start with the highest possible address */
+    ElfW(Addr) mapend = 0;     /* start with the lowest possible address */
 
 
     for (ph = phdr; ph < &phdr[map->l_phnum]; ++ph)
     for (ph = phdr; ph < &phdr[map->l_phnum]; ++ph)
         switch (ph->p_type) {
         switch (ph->p_type) {
@@ -534,9 +535,9 @@ int add_elf_object(void * addr, PAL_HANDLE handle, int type)
                         ALLOC_ALIGNDOWN(map->l_addr + ph->p_vaddr);
                         ALLOC_ALIGNDOWN(map->l_addr + ph->p_vaddr);
                 ElfW(Addr) end = (ElfW(Addr))
                 ElfW(Addr) end = (ElfW(Addr))
                         ALLOC_ALIGNUP(map->l_addr + ph->p_vaddr + ph->p_memsz);
                         ALLOC_ALIGNUP(map->l_addr + ph->p_vaddr + ph->p_memsz);
-                if (!mapstart || start < mapstart)
+                if (start < mapstart)
                     mapstart = start;
                     mapstart = start;
-                if (!mapend || end > mapend)
+                if (end > mapend)
                     mapend = end;
                     mapend = end;
             }
             }
         }
         }