aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf.c
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2007-07-06 05:39:49 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-06 13:23:43 -0400
commitef7320edb1dd2cf6c969d1dcef4a9499a42f24da (patch)
treede5ea3131e5ff2a150a073434bee94586e8515e3 /fs/binfmt_elf.c
parent7e8767dddf3ad863a7013c334392e09177b48e2c (diff)
Fix elf_core_dump() when writing arch specific notes (spu coredumps)
elf_core_dump() supports dumping arch specific ELF notes, via the #define ELF_CORE_WRITE_EXTRA_NOTES. Currently the only user of this is the powerpc spu coredump code. There is a bug in the handling of foffset WRT the arch notes, which causes us to erroneously increment foffset by the size of the arch notes, leaving a block of zeroes in the file, and causing all subsequent data in the file to be at <supposed position> + <arch note size>. eg: LOAD 0x050000 0x00100000 0x00000000 0x20000 0x20000 R E 0x10000 Tells us we should have a chunk of data at 0x50000. The truth is the data is at 0x90dbc = 0x50000 + 0x40dbc (the size of the arch notes). This bug prevents gdb from reading the core file correctly. The simplest fix is to simply remember the size of the arch notes, and add it to foffset after we've written the arch notes. The only drawback is that if the arch code doesn't write as many bytes as it said it would, we end up with a broken core dump again. For now I think that's a reasonable requirement. Tested on a Cell blade, gdb no longer complains about the core file being bogus. While I'm here I should point out that the spu coredump code does not work if we're dumping to a pipe - we'll have to wait for 23 to fix that. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Acked-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r--fs/binfmt_elf.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fa8ea33ab0be..08e4414b8374 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1499,6 +1499,9 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1499#endif 1499#endif
1500 int thread_status_size = 0; 1500 int thread_status_size = 0;
1501 elf_addr_t *auxv; 1501 elf_addr_t *auxv;
1502#ifdef ELF_CORE_WRITE_EXTRA_NOTES
1503 int extra_notes_size;
1504#endif
1502 1505
1503 /* 1506 /*
1504 * We no longer stop all VM operations. 1507 * We no longer stop all VM operations.
@@ -1628,7 +1631,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1628 sz += thread_status_size; 1631 sz += thread_status_size;
1629 1632
1630#ifdef ELF_CORE_WRITE_EXTRA_NOTES 1633#ifdef ELF_CORE_WRITE_EXTRA_NOTES
1631 sz += ELF_CORE_EXTRA_NOTES_SIZE; 1634 extra_notes_size = ELF_CORE_EXTRA_NOTES_SIZE;
1635 sz += extra_notes_size;
1632#endif 1636#endif
1633 1637
1634 fill_elf_note_phdr(&phdr, sz, offset); 1638 fill_elf_note_phdr(&phdr, sz, offset);
@@ -1674,6 +1678,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
1674 1678
1675#ifdef ELF_CORE_WRITE_EXTRA_NOTES 1679#ifdef ELF_CORE_WRITE_EXTRA_NOTES
1676 ELF_CORE_WRITE_EXTRA_NOTES; 1680 ELF_CORE_WRITE_EXTRA_NOTES;
1681 foffset += extra_notes_size;
1677#endif 1682#endif
1678 1683
1679 /* write out the thread status notes section */ 1684 /* write out the thread status notes section */