[patch] bfd/: bfd_elf_bfd_from_remote_memory 32bit &= 0xffffffff

Jan Kratochvil
2010-02-11T11:57:41Z

Hi,

CORE_ADDR can be 64bit while gdb (bfd) can handle 32bit inferiors (either when
gdb host is e.g. x86_64 or when --enable-64-bit-bfd is in use). Currently gdb
(bfd) leaves garbage at the bits 32..63 and clear it only at the last moment
when required (such as when calling ptrace or printing it to the user).

There has been a conclusion gdb (bfd) should rather keep the bits cleared (so
that for example addr1 == addr2 is easily possible):

http://sourceware.org/ml/gdb-patches/2010-01/msg00497.html
# Wouldn't it be more natural to force a canonical representation at
# the time the address is *determined* in the first place?
http://sourceware.org/ml/gdb-patches/2006-09/msg00197.html
# If we have garbage in the high bits, that's a problem already.

Asking if bfd will follow this policy; otherwise the result from
bfd_elf_bfd_from_remote_memory can be also only masked in gdb/.

I had to fixup gdb/ as currently it worked thanksfully due to bfd/ returning
the right magic bits 32..63.
(gdb) p/x loadbase
$1 = 0xffffffff0033b000
(There will follow a gdb/-only patch to handle 64->32 more systematically.)

No regressions on {x86_64,i686}-fedora12-linux-gnu for binutils. But binutils
itself does not call bfd_from_remote_memory at all. No regressions on
{x86_64,x86_64-m32,i686}-fedora12-linux-gnu for gdb with the gdb/ part.

bfd/
2010-02-11 Jan Kratochvil <jan.kratochvil@redhat.com>

Clear unused bits 32..63 for ELFCLASS32.
* elfcode.h (NAME(_bfd_elf,bfd_from_remote_memory)): New variable vaddr,
use it for target_read_memory.
(NAME(_bfd_elf,bfd_from_remote_memory) <ELFCLASS == ELFCLASS32>): New.

gdb/
2010-02-11 Jan Kratochvil <jan.kratochvil@redhat.com>

* symfile-mem.c: (symbol_file_add_from_memory): New variable addr_bit.
Mask sai->other[i].addr with it.

--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1745,6 +1745,8 @@ NAME(_bfd_elf,bfd_from_remote_memory)
if (!loadbase_set && (i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
{
loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
+ if (ELFCLASS == ELFCLASS32)
+ loadbase &= 0xffffffff;
loadbase_set = TRUE;
}

@@ -1789,11 +1791,13 @@ NAME(_bfd_elf,bfd_from_remote_memory)
bfd_vma start = i_phdrs[i].p_offset & -i_phdrs[i].p_align;
bfd_vma end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
+ i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align;
+ bfd_vma vaddr = (i_phdrs[i].p_vaddr + loadbase) & -i_phdrs[i].p_align;
+
+ if (ELFCLASS == ELFCLASS32)
+ vaddr &= 0xffffffff;
if (end > (bfd_vma) contents_size)
end = contents_size;
- err = target_read_memory ((loadbase + i_phdrs[i].p_vaddr)
- & -i_phdrs[i].p_align,
- contents + start, end - start);
+ err = target_read_memory (vaddr, contents + start, end - start);
if (err)
{
free (x_phdrs);
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -72,6 +73,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
bfd_vma loadbase;
struct section_addr_info *sai;
unsigned int i;
+ int addr_bit = gdbarch_addr_bit (target_gdbarch);

if (bfd_get_flavour (templ) != bfd_target_elf_flavour)
error (_("add-symbol-file-from-memory not supported for this target"));
@@ -103,6 +105,9 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, char *name,
if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0)
{
sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase;
+ if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
+ sai->other[i].addr &= ((ULONGEST) 1 << addr_bit) - 1;
+
sai->other[i].name = (char *) bfd_get_section_name (nbfd, sec);
sai->other[i].sectindex = sec->index;
++i;