Bug 9378 - Invalid relocation if executable is marked as ET_DYN
Summary: Invalid relocation if executable is marked as ET_DYN
Status: ASSIGNED
Alias: None
Product: gdb
Classification: Unclassified
Component: corefiles (show other bugs)
Version: 6.5
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-06-18 13:08 UTC by bwalle
Modified: 2010-08-30 10:26 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
gdb 6.5 does not open linux kernel core file properly.eml (3.50 KB, application/octet-stream)
, bwalle
Details

Note You need to log in before you can comment on or make changes to this bug.
Description bwalle 2007-06-18 13:08:01 UTC
[Converted from Gnats 2273]

I am using gdb to open a linux kernel core file generated for x86_64 platform.
But gdb is not analyzing the dumps properly. Its getting the wrong symbol
values. For example, following case prints two different values for same
symbol panic_timeout.

#gdb vmlinux
(gdb) p &panic_timeout
$1 = (int *) 0xffffffff808a1fa8


#gdb vmlinux vmcore
(gdb) p &panic_timeout
$1 = (int *) 0xffffffff008aaebf

First one is the right value. Why gdb is giving incorrect results while
opened with vmcore?

The bug can be reproduced with mainline GDB 6.6. This problem is not present
in gdb 6.4. It works perfectly fine. 

Note, this vmlinux file is of ET_DYN type. It has been compiled as an
executable and then an external program changes elf type to ET_DYN because
this is a fully relocatable executable and can be loaded at any physical
address. The patch to build such a kernel is attached to the bug report.

vmlinux ELF header is as follows.

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x200000
  Start of program headers:          64 (bytes into file)
  Start of section headers:          61579848 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         5
  Size of section headers:           64 (bytes)
  Number of section headers:         51
  Section header string table index: 48

vmcore ELF header and PT_LOAD headers are as follows.

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              CORE (Core file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         6
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0
There are no sections in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  NOTE           0x0000000000000190 0x0000000000000000 0x0000000000000000
                 0x0000000000000b20 0x0000000000000b20         0
  LOAD           0x0000000000000cb0 0xffffffff80200000 0x0000000000200000
                 0x0000000000742000 0x0000000000742000  RWE    0
  LOAD           0x0000000000742cb0 0xffff810000000000 0x0000000000000000
                 0x00000000000a0000 0x00000000000a0000  RWE    0
  LOAD           0x00000000007e2cb0 0xffff810000100000 0x0000000000100000
                 0x0000000000f00000 0x0000000000f00000  RWE    0
  LOAD           0x00000000016e2cb0 0xffff810009000000 0x0000000009000000
                 0x00000000c6f8dc80 0x00000000c6f8dc80  RWE    0
  LOAD           0x00000000c8670930 0xffff810100000000 0x0000000100000000
                 0x0000000130000000 0x0000000130000000  RWE    0

I found out that the error appeared with following change:

cvs diff -u -D "2006-01-24 22:30:00 -0000" -D "2006-01-24 22:40:00 -0000"
(Patch is attached.)

The problem is svr4_solib_create_inferior_hook() -> svr4_relocate_main_executable().
If I comment out this function, everything works fine. ;-)

Release:
6.5

Environment:
GNU/Linux
Comment 1 bwalle 2007-06-18 13:21:26 UTC
From: Bernhard Walle <bwalle@suse.de>
To: gdb-gnats@sources.redhat.com
Cc:  
Subject: Re: corefiles/2273: Invalid relocation if executable is marked as ET_DYN
Date: Mon, 18 Jun 2007 15:21:26 +0200

 As I don't know how to send multiple attachments, here's the kernel
 patch inline:
 
 -----
 From ebiederm@xmission.com  Wed May 30 23:15:10 2007
 Date: Mon, 30 Apr 2007 09:12:39 -0600
 From: "Eric W. Biederman" <ebiederm@xmission.com>
 To: Andi Kleen <ak@suse.de>, Andrew Morton <akpm@linux-foundation.org>
 Cc: Helge Hafting <helgehaf@aitel.hist.no>, Horms <horms@verge.net.au>,
 	Kexec Mailing List <kexec@lists.infradead.org>,
 	Jurriaan <thunder7@xs4all.nl>, linux-kernel@vger.kernel.org
 Subject: [PATCH 1/2] x86_64: Reflect the relocatability of the kernel in the
 	ELF header.
 
 
 Currently because vmlinux does not reflect that the kernel is relocatable
 we still have to support CONFIG_PHYSICAL_START.  So this patch adds a small
 c program to do what we cannot do with a linker script set the elf header
 type to ET_DYN.
 
 Since last time I have fixed the type to be in my code ET_DYN (oops),
 and verified this works with kexec.  I realized while testing that we
 don't have anyway of identifying a kernel vmlinux as linux so we
 probably want to add an ELF note but that will be another patch.
 
 Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
 ---
  arch/x86_64/Kconfig  |    4 +++
  arch/x86_64/Makefile |   10 +++++++
  scripts/Makefile     |   11 ++++---
  scripts/mketrel.c    |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++
  4 files changed, 90 insertions(+), 5 deletions(-)
  create mode 100644 scripts/mketrel.c
 
 diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
 index b00adb9..95949c3 100644
 --- a/arch/x86_64/Kconfig
 +++ b/arch/x86_64/Kconfig
 @@ -121,6 +121,10 @@ config ARCH_HAS_ILOG2_U64
  	bool
  	default n
  
 +config ELF_RELOCATABLE
 +	bool
 +	default y
 +
  source "init/Kconfig"
  
  
 diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
 index a81a84a..7c0434c 100644
 --- a/arch/x86_64/Makefile
 +++ b/arch/x86_64/Makefile
 @@ -125,6 +125,16 @@ define archhelp
    echo  '  isoimage     - Create a boot CD-ROM image'
  endef
  
 +ifeq ($(CONFIG_RELOCATABLE),y)
 +define cmd_vmlinux__
 +      $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
 +      -T $(vmlinux-lds) $(vmlinux-init)		\
 +      --start-group $(vmlinux-main) --end-group	\
 +      $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^) \
 +      && scripts/mketrel $@
 +endef
 +endif
 +
  CLEAN_FILES += arch/$(ARCH)/boot/fdimage \
  	       arch/$(ARCH)/boot/image.iso \
  	       arch/$(ARCH)/boot/mtools.conf
 diff --git a/scripts/Makefile b/scripts/Makefile
 index 1c73c5a..ddba550 100644
 --- a/scripts/Makefile
 +++ b/scripts/Makefile
 @@ -7,11 +7,12 @@
  # conmakehash:   Create chartable
  # conmakehash:	 Create arrays for initializing the kernel console tables
  
 -hostprogs-$(CONFIG_KALLSYMS)     += kallsyms
 -hostprogs-$(CONFIG_LOGO)         += pnmtologo
 -hostprogs-$(CONFIG_VT)           += conmakehash
 -hostprogs-$(CONFIG_PROM_CONSOLE) += conmakehash
 -hostprogs-$(CONFIG_IKCONFIG)     += bin2c
 +hostprogs-$(CONFIG_KALLSYMS)        += kallsyms
 +hostprogs-$(CONFIG_LOGO)            += pnmtologo
 +hostprogs-$(CONFIG_VT)              += conmakehash
 +hostprogs-$(CONFIG_PROM_CONSOLE)    += conmakehash
 +hostprogs-$(CONFIG_IKCONFIG)        += bin2c
 +hostprogs-$(CONFIG_ELF_RELOCATABLE) += mketrel
  
  always		:= $(hostprogs-y) $(hostprogs-m)
  
 diff --git a/scripts/mketrel.c b/scripts/mketrel.c
 new file mode 100644
 index 0000000..aa0408a
 --- /dev/null
 +++ b/scripts/mketrel.c
 @@ -0,0 +1,70 @@
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <fcntl.h>
 +#include <unistd.h>
 +#include <elf.h>
 +#include <stdio.h>
 +#include <errno.h>
 +#include <string.h>
 +#include <stdarg.h>
 +#include <stdlib.h>
 +
 +static int fd;
 +unsigned char e_ident[EI_NIDENT];
 +
 +void die(const char * str, ...)
 +{
 +	va_list args;
 +	va_start(args, str);
 +	vfprintf(stderr, str, args);
 +	fputc('\n', stderr);
 +	exit(1);
 +}
 +
 +void file_open(const char *name)
 +{
 +	if ((fd = open(name, O_RDWR, 0)) < 0)
 +		die("Unable to open `%s': %m", name);
 +}
 +
 +static void mketrel(void)
 +{
 +	unsigned char e_type[2];
 +	if (read(fd, &e_ident, sizeof(e_ident)) != sizeof(e_ident))
 +		die("Cannot read ELF header: %s\n", strerror(errno));
 +
 +	if (memcmp(e_ident, ELFMAG, 4) != 0)
 +		die("No ELF magic\n");
 +
 +	if ((e_ident[EI_CLASS] != ELFCLASS64) &&
 +	    (e_ident[EI_CLASS] != ELFCLASS32))
 +		die("Unrecognized ELF class: %x\n", e_ident[EI_CLASS]);
 +	
 +	if ((e_ident[EI_DATA] != ELFDATA2LSB) &&
 +	    (e_ident[EI_DATA] != ELFDATA2MSB))
 +		die("Unrecognized ELF data encoding: %x\n", e_ident[EI_DATA]);
 +
 +	if (e_ident[EI_VERSION] != EV_CURRENT)
 +		die("Unknown ELF version: %d\n", e_ident[EI_VERSION]);
 +
 +	if (e_ident[EI_DATA] == ELFDATA2LSB) {
 +		e_type[0] = ET_DYN & 0xff;
 +		e_type[1] = ET_DYN >> 8;
 +	} else {
 +		e_type[1] = ET_DYN & 0xff;
 +		e_type[0] = ET_DYN >> 8;
 +	}
 +
 +	if (write(fd, &e_type, sizeof(e_type)) != sizeof(e_type))
 +		die("Cannot write ELF type: %s\n", strerror(errno));
 +}
 +
 +int main(int argc, char **argv)
 +{
 +	if (argc != 2)
 +		die("Usage: mketrel: vmlinux");
 +	file_open(argv[1]);
 +	mketrel();
 +	close(fd);
 +	return 0;
 +}
 -- 
 1.5.1.1.181.g2de0
 
 
 _______________________________________________
 kexec mailing list
 kexec@lists.infradead.org
 http://lists.infradead.org/mailman/listinfo/kexec