[PATCH] Kdump: Align 64-bit ELF crash notes correctly (x86_64, powerpc)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Kdump: Align 64-bit ELF crash notes correctly (x86_64, powerpc)

The current ELF code aligns data to 32-bit addresses, regardless if ELFCLASS32
or ELFCLASS64 is used. This works well for the 32-bit case, but for 64-bit 
notes we should (of course) align to 64-bit addresses. At least if we intend 
to follow the "ELF-64 Object File Format, Version 1.5 Draft 2, May 27, 1998".

Unfortunately this change affects 3 pieces of code:
- The regular Linux kernel: See x86_64 and powerpc changes below.
- The "crash" kernel: Needs to align properly when merging notes, see below.
- The utilities that read the vmcore files: Crash, GDB and so on.

I am sure that this change will cause all sorts of trouble if someone is using
a certain combination of kernels and tools, but I believe the best long-term
solution is simply to fix this properly as soon as possible and live with the 
fact that 64-bit vmcore files may have been broken up until now.

Signed-off-by: Magnus Damm <[email protected]>
---

 Compiles on x86_64, powerpc code only dry-coded.
 Applies on top of 2.6.19-rc3.

 arch/powerpc/kernel/crash.c |   18 +++++++++++-------
 arch/x86_64/kernel/crash.c  |   14 +++++++-------
 fs/proc/vmcore.c            |    4 ++--
 3 files changed, 20 insertions(+), 16 deletions(-)

--- 0001/arch/powerpc/kernel/crash.c
+++ work/arch/powerpc/kernel/crash.c	2006-10-26 17:09:33.000000000 +0900
@@ -41,12 +41,16 @@
 #define DBG(fmt...)
 #endif
 
+#define ELF_ALIGN(x) ((x + (sizeof(elf_addr_t) - 1)) \
+                        & ~(sizeof(elf_addr_t) - 1))
+
 /* This keeps a track of which one is crashing cpu. */
 int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
 cpumask_t cpus_in_sr = CPU_MASK_NONE;
 
-static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+static unsigned char *
+append_elf_note(unsigned char *buf, char *name, unsigned type, void *data,
 							       size_t data_len)
 {
 	struct elf_note note;
@@ -55,16 +59,16 @@ static u32 *append_elf_note(u32 *buf, ch
 	note.n_descsz = data_len;
 	note.n_type   = type;
 	memcpy(buf, &note, sizeof(note));
-	buf += (sizeof(note) +3)/4;
+	buf += ELF_ALIGN(sizeof(note));
 	memcpy(buf, name, note.n_namesz);
-	buf += (note.n_namesz + 3)/4;
+	buf += ELF_ALIGN(note.n_namesz);
 	memcpy(buf, data, note.n_descsz);
-	buf += (note.n_descsz + 3)/4;
+	buf += ELF_ALIGN(note.n_descsz);
 
 	return buf;
 }
 
-static void final_note(u32 *buf)
+static void final_note(unsigned char *buf)
 {
 	struct elf_note note;
 
@@ -77,7 +81,7 @@ static void final_note(u32 *buf)
 static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
 {
 	struct elf_prstatus prstatus;
-	u32 *buf;
+	unsigned char *buf;
 
 	if ((cpu < 0) || (cpu >= NR_CPUS))
 		return;
@@ -89,7 +93,7 @@ static void crash_save_this_cpu(struct p
 	 * squirrelled away.  ELF notes happen to provide
 	 * all of that that no need to invent something new.
 	 */
-	buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+	buf = (unsigned char *)per_cpu_ptr(crash_notes, cpu);
 	if (!buf) 
 		return;
 
--- 0002/arch/x86_64/kernel/crash.c
+++ work/arch/x86_64/kernel/crash.c	2006-10-26 16:58:18.000000000 +0900
@@ -28,7 +28,7 @@
 /* This keeps a track of which one is crashing cpu. */
 static int crashing_cpu;
 
-static u32 *append_elf_note(u32 *buf, char *name, unsigned type,
+static u64 *append_elf_note(u64 *buf, char *name, unsigned type,
 						void *data, size_t data_len)
 {
 	struct elf_note note;
@@ -37,16 +37,16 @@ static u32 *append_elf_note(u32 *buf, ch
 	note.n_descsz = data_len;
 	note.n_type   = type;
 	memcpy(buf, &note, sizeof(note));
-	buf += (sizeof(note) +3)/4;
+	buf += (sizeof(note) + 7) / 8;
 	memcpy(buf, name, note.n_namesz);
-	buf += (note.n_namesz + 3)/4;
+	buf += (note.n_namesz + 7) / 8;
 	memcpy(buf, data, note.n_descsz);
-	buf += (note.n_descsz + 3)/4;
+	buf += (note.n_descsz + 7) / 8;
 
 	return buf;
 }
 
-static void final_note(u32 *buf)
+static void final_note(u64 *buf)
 {
 	struct elf_note note;
 
@@ -59,7 +59,7 @@ static void final_note(u32 *buf)
 static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
 {
 	struct elf_prstatus prstatus;
-	u32 *buf;
+	u64 *buf;
 
 	if ((cpu < 0) || (cpu >= NR_CPUS))
 		return;
@@ -72,7 +72,7 @@ static void crash_save_this_cpu(struct p
 	 * all of that, no need to invent something new.
 	 */
 
-	buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+	buf = (u64*)per_cpu_ptr(crash_notes, cpu);
 
 	if (!buf)
 		return;
--- 0001/fs/proc/vmcore.c
+++ work/fs/proc/vmcore.c	2006-10-26 17:31:36.000000000 +0900
@@ -256,8 +256,8 @@ static int __init merge_note_headers_elf
 			if (nhdr_ptr->n_namesz == 0)
 				break;
 			sz = sizeof(Elf64_Nhdr) +
-				((nhdr_ptr->n_namesz + 3) & ~3) +
-				((nhdr_ptr->n_descsz + 3) & ~3);
+				((nhdr_ptr->n_namesz + 7) & ~7) +
+				((nhdr_ptr->n_descsz + 7) & ~7);
 			real_sz += sz;
 			nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
 		}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux