http://sourceware.org/ml/gdb-patches/2011-02/msg00630.html Subject: [patch] [i386] Fix {,un}prelinked libraries for attach/core-load Hi, please see comments in the patch. The adjusted testcase FAILs on i386. "Prelink", March 4, 2004 - by Jakub Jelinek: http://people.redhat.com/jakub/prelink.pdf primarily section 7 - REL to RELA conversion An example of unprelinked -> prelinked library change: Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align - LOAD 0x000000 0x00000000 0x00000000 0x00538 0x00538 R E 0x1000 - LOAD 0x000538 0x00001538 0x00001538 0x00100 0x00110 RW 0x1000 - DYNAMIC 0x000550 0x00001550 0x00001550 0x000c8 0x000c8 RW 0x4 - NOTE 0x0000f4 0x000000f4 0x000000f4 0x00024 0x00024 R 0x4 - GNU_EH_FRAME 0x0004e8 0x000004e8 0x000004e8 0x00014 0x00014 R 0x4 + LOAD 0x000000 0x411b3000 0x411b3000 0x00558 0x00558 R E 0x1000 + LOAD 0x000558 0x411b4558 0x411b4558 0x00100 0x00110 RW 0x1000 + DYNAMIC 0x000570 0x411b4570 0x411b4570 0x000c8 0x000c8 RW 0x4 + NOTE 0x0000f4 0x411b30f4 0x411b30f4 0x00024 0x00024 R 0x4 + GNU_EH_FRAME 0x000508 0x411b3508 0x411b3508 0x00014 0x00014 R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 So far GDB expected all such displacements will be always PAGE_SIZE aligned. This applies for example for re-prelinking of an already prelinked file. But it does not apply for prelinking of an unprelinked file or unprelinking of a prelinked file, there can be arbitrary displacement. It affects i386 (=i686, prelink doc reports also ARM and MIPS) which uses REL. x86_64 always uses RELA, therefore I have not noticed it so far. i386 still has to be supported. This affects both attachment to a PID and core file loads. This applies in real world if you transfer a core file between hosts and try to backtrace them, libraries of both hosts may differ whether they are / are not prelinked. I could implement some (displacement-forgiving and prelink-modifications forgiving) comparison of both DYNAMIC segments found. But I do not think it is useful, if the DYNAMIC address from linkmap vs. bfd do not match it is still a better chance to try a displacement to make them match. Keeping the file relocation cannot work anyway when the DYNAMIC address is verified as wrong. No regressions on {x86_64,x86_64-m32,i686}-fedora15-linux-gnu. Mostly do you agree the DYNAMIC content does not have to be verifed? Do you have any comments on the in-code long comments? Thanks, Jan gdb/ 2011-02-22 Jan Kratochvil Fix libraries displacement if they change whether they were prelinked. * solib-svr4.c (LM_ADDR_CHECK): Set L_ADDR even if the DYNAMIC pointer does not match. Comment why. gdb/testsuite/ 2011-02-22 Jan Kratochvil * gdb.base/break-interp-lib.c (v, vptr): New variables. * gdb.base/break-interp.exp (test_attach): New comment. --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -237,11 +237,11 @@ LM_ADDR_CHECK (struct so_list *so, bfd *abfd) Even on PPC it must be zero-aligned at least for MINPAGESIZE. */ + l_addr = l_dynaddr - dynaddr; + if ((l_addr & (minpagesize - 1)) == 0 && (l_addr & align) == ((l_dynaddr - dynaddr) & align)) { - l_addr = l_dynaddr - dynaddr; - if (info_verbose) printf_unfiltered (_("Using PIC (Position Independent Code) " "prelink displacement %s for \"%s\".\n"), @@ -249,9 +249,20 @@ LM_ADDR_CHECK (struct so_list *so, bfd *abfd) so->so_name); } else - warning (_(".dynamic section for \"%s\" " - "is not at the expected address " - "(wrong library or version mismatch?)"), so->so_name); + { + /* There is no way to verify the library file matches. prelink + can during prelinking of an unprelinked file (or unprelinking + of a prelinked file) shift the DYNAMIC segment by arbitrary + offset without any page size alignment. There is no way to + find out the ELF header and/or Program Headers for a limited + verification if it they match. One could do a verification + of the DYNAMIC segment. Still the found address is the best + one GDB could find. */ + + warning (_(".dynamic section for \"%s\" " + "is not at the expected address " + "(wrong library or version mismatch?)"), so->so_name); + } } set_addr: --- a/gdb/testsuite/gdb.base/break-interp-lib.c +++ b/gdb/testsuite/gdb.base/break-interp-lib.c @@ -20,6 +20,10 @@ #include #include +/* Force REL->RELA conversion on i386, see "Prelink", March 4, 2004. */ +volatile int v[2]; +volatile int *vptr = &v[1]; + void libfunc (const char *action) { --- a/gdb/testsuite/gdb.base/break-interp.exp +++ b/gdb/testsuite/gdb.base/break-interp.exp @@ -352,6 +352,14 @@ proc test_attach {file displacement {relink_args ""}} { # test simplicity, we merged this test and the test above by not # restoring $INTERP after $EXEC prelink. $INTERP gets restored # later below. + # + # `(wrong library or version mismatch?)' messages are printed for + # $binfile_lib on platforms converting REL->RELA relocations by + # prelink (such as on i386). There is no reliable way to verify + # the library file matches the running library in such case but + # GDB at least attempts to set the right displacement. We test + # `libfunc' is present in the backtrace and therefore the + # displacement has been guessed right. if [prelink$relink $relink_args [file tail $exec]] { # /proc/PID/exe cannot be loaded as it is "EXECNAME (deleted)".