Bug 450218 - dwfl_module_getdwarf shouldn't align the base address for bias
Summary: dwfl_module_getdwarf shouldn't align the base address for bias
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Fedora
Classification: Fedora
Component: elfutils
Version: 10
Hardware: All
OS: Linux
low
low
Target Milestone: ---
Assignee: Roland McGrath
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: 173278
TreeView+ depends on / blocked
 
Reported: 2008-06-05 21:56 UTC by Andrew Cagney
Modified: 2009-12-18 06:12 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2009-12-18 06:12:01 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)
don't align module's load address (1.12 KB, patch)
2008-06-07 12:23 UTC, Andrew Cagney
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Sourceware 6599 0 None None None Never

Description Andrew Cagney 2008-06-05 21:56:43 UTC
From dwfl_module_getdwarf:

@@ -96,11 +100,18 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file)
          goto elf_error;
        if (ph->p_type == PT_LOAD)
          {
-           file->bias = ((mod->low_addr & -ph->p_align)
-                         - (ph->p_vaddr & -ph->p_align));
+           // Align the vaddr.
+           fprintf(stderr, "mod->low_addr 0x%lx\n", mod->low_addr);
+           fprintf(stderr, "ph->p_align 0x%lx\n", ph->p_align);
+           Dwarf_Addr vaddr = ph->p_vaddr & -ph->p_align;
+           fprintf(stderr, "vaddr 0x%lx\n", vaddr);
+           file->bias = (mod->low_addr - (ph->p_vaddr & -ph->p_align));
+           fprintf(stderr, "setting file bias to something complex 0x%lx\n",
+                   file->bias);
            break;
          }
       }
+  }

Comment 1 Andrew Cagney 2008-06-05 21:58:03 UTC
for instance, an solib mapped at:

  low 0x2aaab0508000 high 0x2aaab07dc000

with alignment 0x200000, will result in a bias of 0x2aaab0400000, when it should
just be the low address

Comment 2 Andrew Cagney 2008-06-07 12:23:09 UTC
Created attachment 308608 [details]
don't align module's load address

Comment 3 Denys Vlasenko 2008-09-05 14:45:22 UTC
Andrew, your patch looks sensible to me. Having a testcase would be a plus.

How did you triggered this code path? I tried a few things and I invariably find mod->main.elf != NULL here, thus open_elf (where you fixed file->bias calculation) is not reached:


find_file (Dwfl_Module *mod)
{
  if (mod->main.elf != NULL     /* Already done.  */
      || mod->elferr != DWFL_E_NOERROR) /* Cached failure.  */
    return;

  mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod),
                                                    &mod->main.name,
                                                    &mod->main.elf);
  mod->elferr = open_elf (mod, &mod->main);

Comment 4 Andrew Cagney 2008-09-05 15:44:45 UTC
(In reply to comment #3)
> Andrew, your patch looks sensible to me. Having a testcase would be a plus.
> 
> How did you triggered this code path? I tried a few things and I invariably
> find mod->main.elf != NULL here, thus open_elf (where you fixed file->bias
> calculation) is not reached:

Good question, my only note is that it occures with a shared executable, not the main program.

Comment 5 Denys Vlasenko 2008-09-08 14:57:45 UTC
I was trying to find a way to trigger this bug using freshly built elfutils.
The closest thing I came up with is:

Make a split debug info out of a .so file

foo=src/libld_elf_i386.so
cp $foo $foo.backup
objcopy --only-keep-debug $foo $foo.dbg
objcopy --strip-debug $foo
objcopy --add-gnu-debuglink=$foo.dbg $foo

and then run readelf on it:

LD_LIBRARY_PATH=libelf:libdw:backends src/readelf -w src/libld_elf_i386.so

My instrumented version prints:

__libdwfl_report_elf: entered
__libdwfl_report_elf: ET_DYN
__libdwfl_report_elf: default
base 0x0
ph->p_align 0x200000
start 0x0
bias 0x0
ZZ ->main.elf:=0x11bb070, ->main.bias:=0
HERE2: dwfl_module_getelf
HERE3: dwfl_module_getelf
HERE4: find_file mod->main.elf:0x11bb070
HERE4: find_file mod->main.elf:0x11bb070
find_debuglink: return 'libld_elf_i386.so.dbg'
HERE6: open_elf
open_elf:63
open_elf:66
open_elf: file->name:'(null)' return CBFAIL
src/readelf: cannot get debug context descriptor: No DWARF information found

Had open_elf() non-NULL finename, it would open it and try
to calculate bias. But readelf seems to be restricted to not read
separate debug infos, thus it has NULL name there.

Comment 7 Bug Zapper 2008-11-26 10:49:19 UTC
This message is a reminder that Fedora 8 is nearing its end of life.
Approximately 30 (thirty) days from now Fedora will stop maintaining
and issuing updates for Fedora 8.  It is Fedora's policy to close all
bug reports from releases that are no longer maintained.  At that time
this bug will be closed as WONTFIX if it remains open with a Fedora 
'version' of '8'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version prior to Fedora 8's end of life.

Bug Reporter: Thank you for reporting this issue and we are sorry that 
we may not be able to fix it before Fedora 8 is end of life.  If you 
would still like to see this bug fixed and are able to reproduce it 
against a later version of Fedora please change the 'version' of this 
bug to the applicable version.  If you are unable to change the version, 
please add a comment here and someone will do it for you.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events.  Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

The process we are following is described here: 
http://fedoraproject.org/wiki/BugZappers/HouseKeeping

Comment 8 Roland McGrath 2008-12-11 23:07:56 UTC
Still a bug I think, should cons a proper test case.

Comment 9 Mark Wielaard 2009-07-27 17:15:25 UTC
Constructing a testcase is slightly hard since it seems to involve (according to comment #1) a shared library with a PT_LOAD address (the mod->low_addr) that is not aligned according to  ph->p_align. I am unsure how to construct such a thing.

The best I can do is something like in comment #5, take any library foo and do something like:

cp $foo $foo.backup
objcopy --only-keep-debug $foo $foo.dbg
objcopy --strip-debug $foo
objcopy --add-gnu-debuglink=$foo.dbg $foo
prelink -v -r 0x650000 $foo

except that last command will not work:
prelink: liblibrary.so: PT_LOAD 00000000 0650000 0x200000 would be not properly aligned

But the above would give you something which you can then process with:

cat rh450218.c

#include <stdio.h>
#include <stdlib.h>
#include <elfutils/libdw.h>
#include <elfutils/libdwfl.h>

static void
error ()
{
  printf ("dwfl_errmsg: %s\n", dwfl_errmsg(-1));
  abort ();
}

static int
query_module (Dwfl_Module *mod,
              void **user,
              const char *name,
              Dwarf_Addr base,
              void *arg)
{
  Dwarf_Addr dwarf_bias;
  Dwarf *dwarf = dwfl_module_getdwarf(mod, &dwarf_bias);

  if (! dwarf) error();
  printf("dwarf_bias: %#llx\n", (unsigned long long int) dwarf_bias);

  Dwarf_Addr start, end, dwbias, symbias;
  const char *mainfile, *debugfile;
  const char *info = dwfl_module_info (mod, NULL, &start, &end,
				       &dwbias, &symbias,
				       &mainfile, &debugfile);
  printf("Module: %s@%#llx\n", name, (unsigned long long int) base);
  printf("info: %s, start@%#llx, end@%#llx\n", info,
	 (unsigned long long int) start, (unsigned long long int) end);
  printf(" dwbias:%#llx, symbias:%#llx\n",
	 (unsigned long long int) dwbias, (unsigned long long int) symbias);
  printf(" %s:%s\n", mainfile, debugfile);

  return DWARF_CB_OK;
}

int
main (int argc, const char **argv)
{
  int i, r;

  printf("Processing... %s\n", argv[1]);
  
  static char *debugpath = "+:.debug:/usr/lib/debug:build";
  static const Dwfl_Callbacks user_callbacks =
  {
    NULL,
    dwfl_standard_find_debuginfo,
    dwfl_offline_section_address,
    &debugpath
  };

  Dwfl *dwfl = dwfl_begin (&user_callbacks);
  if (! dwfl) error ();
  dwfl_report_begin (dwfl);
  for (i = 1; i < argc; i++)
    {
      Dwfl_Module *m = dwfl_report_offline (dwfl, argv[i], argv[i], -1);
      if (! m) error ();
    }
  r = dwfl_report_end (dwfl, NULL, NULL);
  if (r != 0) error();

  r = dwfl_getmodules (dwfl, &query_module, NULL, 0);
  if (r == -1) error();

  printf ("Done...\n");
  return 0;
}

gcc -ldw -o rh450218 rh450218.c
./rh450218 liblibrary.so
Processing... liblibrary.so
dwarf_bias: 0x64200000
Module: liblibrary.so@0x64200000
info: liblibrary.so, start@0x64200000, end@0x64400860
 dwbias:0x64200000, symbias:0xffffffffffffffff
 liblibrary.so:liblibrary.so.dbg
Done...

Comment 10 Roland McGrath 2009-07-27 17:56:48 UTC
Right, prelink won't do it, but it could happen at runtime.
p_align says the smallest alignment that we can assume at build time (and prelink time) the system will enforce when it uses the object.  The actual alignment (i.e. page size) used at run time might be smaller than that (but never larger).  prelink correctly refuses to leave the binary on disk such that it would require a smaller largest page size than the original binary did.

So the test you need is using a Dwfl not in offline mode but some other way, where you can arrange that the runtime load address is off-aligned.  You could create that with an explicit mmap of a DSO (doesn't really matter if it is loaded properly, just mapped into memory makes libdwfl see it) using MAP_FIXED, and then use -p or suchlike.  Probably simplest is to just create the situation synthetically using dwfl_report_elf with a chosen address.

Comment 11 Mark Wielaard 2009-07-28 16:40:58 UTC
I see frysk used elf_from_remote_memory () supplying its own read_memory () implementation to feed libdwfl either a ptraced proc or core file. But elf_from_remote_memory doesn't seem to actually be provided in any header though it is exported. Using that is extremely sneaky. You won't get something like that even with dwfl_report_elf () since it will sanitize the given base against ph->p_align for ET_DYN and just ignore it for ET_EXEC and ET_CORE.

Comment 12 Roland McGrath 2009-07-28 19:01:34 UTC
Oh, dwfl_report_elf shaving the address more than dwfl->segment_align is a bug.

Comment 13 Bug Zapper 2009-11-18 12:32:45 UTC
This message is a reminder that Fedora 10 is nearing its end of life.
Approximately 30 (thirty) days from now Fedora will stop maintaining
and issuing updates for Fedora 10.  It is Fedora's policy to close all
bug reports from releases that are no longer maintained.  At that time
this bug will be closed as WONTFIX if it remains open with a Fedora 
'version' of '10'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version prior to Fedora 10's end of life.

Bug Reporter: Thank you for reporting this issue and we are sorry that 
we may not be able to fix it before Fedora 10 is end of life.  If you 
would still like to see this bug fixed and are able to reproduce it 
against a later version of Fedora please change the 'version' of this 
bug to the applicable version.  If you are unable to change the version, 
please add a comment here and someone will do it for you.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events.  Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

The process we are following is described here: 
http://fedoraproject.org/wiki/BugZappers/HouseKeeping

Comment 14 Bug Zapper 2009-12-18 06:12:01 UTC
Fedora 10 changed to end-of-life (EOL) status on 2009-12-17. Fedora 10 is 
no longer maintained, which means that it will not receive any further 
security or bug fix updates. As a result we are closing this bug.

If you can reproduce this bug against a currently maintained version of 
Fedora please feel free to reopen this bug against that version.

Thank you for reporting this bug and we are sorry it could not be fixed.


Note You need to log in before you can comment on or make changes to this bug.