linux-user: correct core dump format

This patch allows to really use the core dumped by qemu with guest
architecture tools.

- it adds a missing bswap_phdr() for the program headers
  of memory regions.

  "objdump -x" sample:

BEFORE:

0x1000000 off    0x00200000 vaddr 0x00000400 paddr 0x00000000 align 2**21
         filesz 0x00000000 memsz 0x00100000 flags ---
0x1000000 off    0x00200000 vaddr 0x00100400 paddr 0x00000000 align 2**21
         filesz 0x00000000 memsz 0x00080000 flags --- 6000000

AFTER:

    LOAD off    0x00002000 vaddr 0x00040000 paddr 0x00000000 align 2**13
         filesz 0x00000000 memsz 0x00001000 flags ---
    LOAD off    0x00002000 vaddr 0x00041000 paddr 0x00000000 align 2**13
         filesz 0x00000000 memsz 0x00000800 flags rw-

- it doesn't pad the note size to sizeof(int32_t).
  On m68k the NT_PRSTATUS note size is 154 and
  must not be rounded up to 156, because this value is checked by
  objdump and gdb.

  "gdb" symptoms:

      "warning: Couldn't find general-purpose registers in core file."

  "objdump -x" sample:

BEFORE:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 note0         000001c4  00000000  00000000  000003b4  2**0
                  CONTENTS, READONLY
  1 .auxv         00000070  00000000  00000000  00000508  2**2
                  CONTENTS
  2 proc1         00100000  00000400  00000000  00200000  2**10
                  READONLY

AFTER:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 note0         000001c4  00000000  00000000  000003b4  2**0
                  CONTENTS, READONLY
  1 .reg/19022    00000050  00000000  00000000  0000040e  2**2
                  CONTENTS
  2 .reg          00000050  00000000  00000000  0000040e  2**2
                  CONTENTS
  3 .auxv         00000070  00000000  00000000  00000508  2**2
                  CONTENTS
  4 load1         00000000  00040000  00000000  00002000  2**13
                  ALLOC, READONLY

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Riku Voipio <riku.voipio@nokia.com>
master
Laurent Vivier 2011-02-13 23:37:35 +01:00 committed by Riku Voipio
parent c2e3dee6e0
commit 80f5ce758a
1 changed files with 18 additions and 16 deletions

View File

@ -103,13 +103,13 @@ enum {
typedef target_ulong target_elf_greg_t; typedef target_ulong target_elf_greg_t;
#ifdef USE_UID16 #ifdef USE_UID16
typedef uint16_t target_uid_t; typedef target_ushort target_uid_t;
typedef uint16_t target_gid_t; typedef target_ushort target_gid_t;
#else #else
typedef uint32_t target_uid_t; typedef target_uint target_uid_t;
typedef uint32_t target_gid_t; typedef target_uint target_gid_t;
#endif #endif
typedef int32_t target_pid_t; typedef target_int target_pid_t;
#ifdef TARGET_I386 #ifdef TARGET_I386
@ -1761,19 +1761,20 @@ struct memelfnote {
size_t namesz_rounded; size_t namesz_rounded;
int type; int type;
size_t datasz; size_t datasz;
size_t datasz_rounded;
void *data; void *data;
size_t notesz; size_t notesz;
}; };
struct target_elf_siginfo { struct target_elf_siginfo {
int si_signo; /* signal number */ target_int si_signo; /* signal number */
int si_code; /* extra code */ target_int si_code; /* extra code */
int si_errno; /* errno */ target_int si_errno; /* errno */
}; };
struct target_elf_prstatus { struct target_elf_prstatus {
struct target_elf_siginfo pr_info; /* Info associated with signal */ struct target_elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */ target_short pr_cursig; /* Current signal */
target_ulong pr_sigpend; /* XXX */ target_ulong pr_sigpend; /* XXX */
target_ulong pr_sighold; /* XXX */ target_ulong pr_sighold; /* XXX */
target_pid_t pr_pid; target_pid_t pr_pid;
@ -1785,7 +1786,7 @@ struct target_elf_prstatus {
struct target_timeval pr_cutime; /* XXX Cumulative user time */ struct target_timeval pr_cutime; /* XXX Cumulative user time */
struct target_timeval pr_cstime; /* XXX Cumulative system time */ struct target_timeval pr_cstime; /* XXX Cumulative system time */
target_elf_gregset_t pr_reg; /* GP registers */ target_elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* XXX */ target_int pr_fpvalid; /* XXX */
}; };
#define ELF_PRARGSZ (80) /* Number of chars for args */ #define ELF_PRARGSZ (80) /* Number of chars for args */
@ -2036,7 +2037,9 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
note->namesz = namesz; note->namesz = namesz;
note->namesz_rounded = roundup(namesz, sizeof (int32_t)); note->namesz_rounded = roundup(namesz, sizeof (int32_t));
note->type = type; note->type = type;
note->datasz = roundup(sz, sizeof (int32_t));; note->datasz = sz;
note->datasz_rounded = roundup(sz, sizeof (int32_t));
note->data = data; note->data = data;
/* /*
@ -2044,7 +2047,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
* ELF document. * ELF document.
*/ */
note->notesz = sizeof (struct elf_note) + note->notesz = sizeof (struct elf_note) +
note->namesz_rounded + note->datasz; note->namesz_rounded + note->datasz_rounded;
} }
static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
@ -2264,7 +2267,7 @@ static int write_note(struct memelfnote *men, int fd)
return (-1); return (-1);
if (dump_write(fd, men->name, men->namesz_rounded) != 0) if (dump_write(fd, men->name, men->namesz_rounded) != 0)
return (-1); return (-1);
if (dump_write(fd, men->data, men->datasz) != 0) if (dump_write(fd, men->data, men->datasz_rounded) != 0)
return (-1); return (-1);
return (0); return (0);
@ -2480,7 +2483,7 @@ static int elf_core_dump(int signr, const CPUState *env)
* ELF specification wants data to start at page boundary so * ELF specification wants data to start at page boundary so
* we align it here. * we align it here.
*/ */
offset = roundup(offset, ELF_EXEC_PAGESIZE); data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
/* /*
* Write program headers for memory regions mapped in * Write program headers for memory regions mapped in
@ -2503,6 +2506,7 @@ static int elf_core_dump(int signr, const CPUState *env)
phdr.p_flags |= PF_X; phdr.p_flags |= PF_X;
phdr.p_align = ELF_EXEC_PAGESIZE; phdr.p_align = ELF_EXEC_PAGESIZE;
bswap_phdr(&phdr, 1);
dump_write(fd, &phdr, sizeof (phdr)); dump_write(fd, &phdr, sizeof (phdr));
} }
@ -2514,8 +2518,6 @@ static int elf_core_dump(int signr, const CPUState *env)
goto out; goto out;
/* align data to page boundary */ /* align data to page boundary */
data_offset = lseek(fd, 0, SEEK_CUR);
data_offset = TARGET_PAGE_ALIGN(data_offset);
if (lseek(fd, data_offset, SEEK_SET) != data_offset) if (lseek(fd, data_offset, SEEK_SET) != data_offset)
goto out; goto out;