Skip to content

Commit

Permalink
elf coredump: replace ELF_CORE_EXTRA_* macros by functions
Browse files Browse the repository at this point in the history
elf_core_dump() and elf_fdpic_core_dump() use #ifdef and the corresponding
macro for hiding _multiline_ logics in functions.  This patch removes
#ifdef and replaces ELF_CORE_EXTRA_* by corresponding functions.  For
architectures not implemeonting ELF_CORE_EXTRA_*, we use weak functions in
order to reduce a range of modification.

This cleanup is for my next patches, but I think this cleanup itself is
worth doing regardless of my firnal purpose.

Signed-off-by: Daisuke HATAYAMA <d.hatayama@jp.fujitsu.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Greg Ungerer <gerg@snapgear.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Daisuke HATAYAMA authored and torvalds committed Mar 6, 2010
1 parent 088e7af commit 1fcccba
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 109 deletions.
48 changes: 0 additions & 48 deletions arch/ia64/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,54 +219,6 @@ do { \
NEW_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long) GATE_EHDR); \
} while (0)


/*
* These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
* extra segments containing the gate DSO contents. Dumping its
* contents makes post-mortem fully interpretable later without matching up
* the same kernel and hardware config to see what PC values meant.
* Dumping its extra ELF program headers includes all the other information
* a debugger needs to easily find how the gate DSO was being used.
*/
#define ELF_CORE_EXTRA_PHDRS (GATE_EHDR->e_phnum)
#define ELF_CORE_WRITE_EXTRA_PHDRS \
do { \
const struct elf_phdr *const gate_phdrs = \
(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); \
int i; \
Elf64_Off ofs = 0; \
for (i = 0; i < GATE_EHDR->e_phnum; ++i) { \
struct elf_phdr phdr = gate_phdrs[i]; \
if (phdr.p_type == PT_LOAD) { \
phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
phdr.p_filesz = phdr.p_memsz; \
if (ofs == 0) { \
ofs = phdr.p_offset = offset; \
offset += phdr.p_filesz; \
} \
else \
phdr.p_offset = ofs; \
} \
else \
phdr.p_offset += ofs; \
phdr.p_paddr = 0; /* match other core phdrs */ \
DUMP_WRITE(&phdr, sizeof(phdr)); \
} \
} while (0)
#define ELF_CORE_WRITE_EXTRA_DATA \
do { \
const struct elf_phdr *const gate_phdrs = \
(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); \
int i; \
for (i = 0; i < GATE_EHDR->e_phnum; ++i) { \
if (gate_phdrs[i].p_type == PT_LOAD) { \
DUMP_WRITE((void *) gate_phdrs[i].p_vaddr, \
PAGE_ALIGN(gate_phdrs[i].p_memsz)); \
break; \
} \
} \
} while (0)

/*
* format for entries in the Global Offset Table
*/
Expand Down
2 changes: 2 additions & 0 deletions arch/ia64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ endif
obj-$(CONFIG_DMAR) += pci-dma.o
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o

obj-$(CONFIG_BINFMT_ELF) += elfcore.o

# fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31

Expand Down
64 changes: 64 additions & 0 deletions arch/ia64/kernel/elfcore.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <linux/elf.h>
#include <linux/coredump.h>
#include <linux/fs.h>
#include <linux/mm.h>

#include <asm/elf.h>


Elf64_Half elf_core_extra_phdrs(void)
{
return GATE_EHDR->e_phnum;
}

int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
unsigned long limit)
{
const struct elf_phdr *const gate_phdrs =
(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
int i;
Elf64_Off ofs = 0;

for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
struct elf_phdr phdr = gate_phdrs[i];

if (phdr.p_type == PT_LOAD) {
phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);
phdr.p_filesz = phdr.p_memsz;
if (ofs == 0) {
ofs = phdr.p_offset = offset;
offset += phdr.p_filesz;
} else {
phdr.p_offset = ofs;
}
} else {
phdr.p_offset += ofs;
}
phdr.p_paddr = 0; /* match other core phdrs */
*size += sizeof(phdr);
if (*size > limit || !dump_write(file, &phdr, sizeof(phdr)))
return 0;
}
return 1;
}

int elf_core_write_extra_data(struct file *file, size_t *size,
unsigned long limit)
{
const struct elf_phdr *const gate_phdrs =
(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
int i;

for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
if (gate_phdrs[i].p_type == PT_LOAD) {
void *addr = (void *)gate_phdrs[i].p_vaddr;
size_t memsz = PAGE_ALIGN(gate_phdrs[i].p_memsz);

*size += memsz;
if (*size > limit || !dump_write(file, addr, memsz))
return 0;
break;
}
}
return 1;
}
2 changes: 2 additions & 0 deletions arch/um/sys-i386/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
sys_call_table.o tls.o

obj-$(CONFIG_BINFMT_ELF) += elfcore.o

subarch-obj-y = lib/semaphore_32.o lib/string_32.o
subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
subarch-obj-$(CONFIG_MODULES) += kernel/module.o
Expand Down
43 changes: 0 additions & 43 deletions arch/um/sys-i386/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,47 +116,4 @@ do { \
} \
} while (0)

/*
* These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
* extra segments containing the vsyscall DSO contents. Dumping its
* contents makes post-mortem fully interpretable later without matching up
* the same kernel and hardware config to see what PC values meant.
* Dumping its extra ELF program headers includes all the other information
* a debugger needs to easily find how the vsyscall DSO was being used.
*/
#define ELF_CORE_EXTRA_PHDRS \
(vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )

#define ELF_CORE_WRITE_EXTRA_PHDRS \
if ( vsyscall_ehdr ) { \
const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr; \
const struct elf_phdr *const phdrp = \
(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); \
int i; \
Elf32_Off ofs = 0; \
for (i = 0; i < ehdrp->e_phnum; ++i) { \
struct elf_phdr phdr = phdrp[i]; \
if (phdr.p_type == PT_LOAD) { \
ofs = phdr.p_offset = offset; \
offset += phdr.p_filesz; \
} \
else \
phdr.p_offset += ofs; \
phdr.p_paddr = 0; /* match other core phdrs */ \
DUMP_WRITE(&phdr, sizeof(phdr)); \
} \
}
#define ELF_CORE_WRITE_EXTRA_DATA \
if ( vsyscall_ehdr ) { \
const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr; \
const struct elf_phdr *const phdrp = \
(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); \
int i; \
for (i = 0; i < ehdrp->e_phnum; ++i) { \
if (phdrp[i].p_type == PT_LOAD) \
DUMP_WRITE((void *) phdrp[i].p_vaddr, \
phdrp[i].p_filesz); \
} \
}

#endif
67 changes: 67 additions & 0 deletions arch/um/sys-i386/elfcore.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <linux/elf.h>
#include <linux/coredump.h>
#include <linux/fs.h>
#include <linux/mm.h>

#include <asm/elf.h>


Elf32_Half elf_core_extra_phdrs(void)
{
return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
}

int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
unsigned long limit)
{
if ( vsyscall_ehdr ) {
const struct elfhdr *const ehdrp =
(struct elfhdr *) vsyscall_ehdr;
const struct elf_phdr *const phdrp =
(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
int i;
Elf32_Off ofs = 0;

for (i = 0; i < ehdrp->e_phnum; ++i) {
struct elf_phdr phdr = phdrp[i];

if (phdr.p_type == PT_LOAD) {
ofs = phdr.p_offset = offset;
offset += phdr.p_filesz;
} else {
phdr.p_offset += ofs;
}
phdr.p_paddr = 0; /* match other core phdrs */
*size += sizeof(phdr);
if (*size > limit
|| !dump_write(file, &phdr, sizeof(phdr)))
return 0;
}
}
return 1;
}

int elf_core_write_extra_data(struct file *file, size_t *size,
unsigned long limit)
{
if ( vsyscall_ehdr ) {
const struct elfhdr *const ehdrp =
(struct elfhdr *) vsyscall_ehdr;
const struct elf_phdr *const phdrp =
(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
int i;

for (i = 0; i < ehdrp->e_phnum; ++i) {
if (phdrp[i].p_type == PT_LOAD) {
void *addr = (void *) phdrp[i].p_vaddr;
size_t filesz = phdrp[i].p_filesz;

*size += filesz;
if (*size > limit
|| !dump_write(file, addr, filesz))
return 0;
}
}
}
return 1;
}
14 changes: 5 additions & 9 deletions fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1878,9 +1878,7 @@ static int elf_core_dump(struct coredump_params *cprm)
* Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
*/
segs = current->mm->map_count;
#ifdef ELF_CORE_EXTRA_PHDRS
segs += ELF_CORE_EXTRA_PHDRS;
#endif
segs += elf_core_extra_phdrs();

gate_vma = get_gate_vma(current);
if (gate_vma != NULL)
Expand Down Expand Up @@ -1958,9 +1956,8 @@ static int elf_core_dump(struct coredump_params *cprm)
goto end_coredump;
}

#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
ELF_CORE_WRITE_EXTRA_PHDRS;
#endif
if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
goto end_coredump;

/* write out the notes section */
if (!write_note_info(&info, cprm->file, &foffset))
Expand Down Expand Up @@ -1999,9 +1996,8 @@ static int elf_core_dump(struct coredump_params *cprm)
}
}

#ifdef ELF_CORE_WRITE_EXTRA_DATA
ELF_CORE_WRITE_EXTRA_DATA;
#endif
if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
goto end_coredump;

end_coredump:
set_fs(fs);
Expand Down
14 changes: 5 additions & 9 deletions fs/binfmt_elf_fdpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1664,9 +1664,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);

segs = current->mm->map_count;
#ifdef ELF_CORE_EXTRA_PHDRS
segs += ELF_CORE_EXTRA_PHDRS;
#endif
segs += elf_core_extra_phdrs();

/* Set up header */
fill_elf_fdpic_header(elf, segs + 1); /* including notes section */
Expand Down Expand Up @@ -1773,9 +1771,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
goto end_coredump;
}

#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
ELF_CORE_WRITE_EXTRA_PHDRS;
#endif
if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
goto end_coredump;

/* write out the notes section */
for (i = 0; i < numnote; i++)
Expand All @@ -1799,9 +1796,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
mm_flags) < 0)
goto end_coredump;

#ifdef ELF_CORE_WRITE_EXTRA_DATA
ELF_CORE_WRITE_EXTRA_DATA;
#endif
if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
goto end_coredump;

if (cprm->file->f_pos != offset) {
/* Sanity check */
Expand Down
2 changes: 2 additions & 0 deletions fs/compat_binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@

#undef elfhdr
#undef elf_phdr
#undef elf_shdr
#undef elf_note
#undef elf_addr_t
#define elfhdr elf32_hdr
#define elf_phdr elf32_phdr
#define elf_shdr elf32_shdr
#define elf_note elf32_note
#define elf_addr_t Elf32_Addr

Expand Down
2 changes: 2 additions & 0 deletions include/linux/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ extern Elf32_Dyn _DYNAMIC [];
#define elf_phdr elf32_phdr
#define elf_note elf32_note
#define elf_addr_t Elf32_Off
#define Elf_Half Elf32_Half

#else

Expand All @@ -404,6 +405,7 @@ extern Elf64_Dyn _DYNAMIC [];
#define elf_phdr elf64_phdr
#define elf_note elf64_note
#define elf_addr_t Elf64_Off
#define Elf_Half Elf64_Half

#endif

Expand Down
16 changes: 16 additions & 0 deletions include/linux/elfcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <linux/user.h>
#endif
#include <linux/ptrace.h>
#include <linux/elf.h>
#include <linux/fs.h>

struct elf_siginfo
{
Expand Down Expand Up @@ -150,5 +152,19 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregse

#endif /* __KERNEL__ */

/*
* These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out
* extra segments containing the gate DSO contents. Dumping its
* contents makes post-mortem fully interpretable later without matching up
* the same kernel and hardware config to see what PC values meant.
* Dumping its extra ELF program headers includes all the other information
* a debugger needs to easily find how the gate DSO was being used.
*/
extern Elf_Half elf_core_extra_phdrs(void);
extern int
elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
unsigned long limit);
extern int
elf_core_write_extra_data(struct file *file, size_t *size, unsigned long limit);

#endif /* _LINUX_ELFCORE_H */
3 changes: 3 additions & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o
obj-$(CONFIG_BINFMT_ELF) += elfcore.o
obj-$(CONFIG_COMPAT_BINFMT_ELF) += elfcore.o
obj-$(CONFIG_BINFMT_ELF_FDPIC) += elfcore.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
obj-$(CONFIG_TRACING) += trace/
obj-$(CONFIG_X86_DS) += trace/
Expand Down

0 comments on commit 1fcccba

Please sign in to comment.