Skip to contentSkip to conversation

vmcore-dmesg: Determine correct machine pointer size

PATCH Applied Vivek Goyal 4 participants 4 messages Nov 13, 2012 – Nov 14, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 vmcore-dmesg: Determine correct machine pointer size

A 32bit arch can prepare ELF64 headers. For example for PAE case to preresent file offsets 64bit but data size at the offset still remains 32bit. If we just base our decision based on EI_CLASS, then we will try to read 64bit data from file and can run into various issues.

We ran into following issue when we tried to run vmcore-dmesg on a 32bit PAE system vmcore which had 64bit elf headers.

No program header covering vaddr 0xc0a6a688c0b89100found kexec bug?

Basically we try to read value of log_buf variable from address log_buf_vaddr. We read in 64bit value and then pass that value again to vaddr_to_offset() in an attempt to get to actual log_buf start and get error message.

So determine the machine pointer size based on ELF class and arch and read the bytes from file accordingly.

v2: Fixed the code as per suggestion from Eric.

---
 vmcore-dmesg/vmcore-dmesg.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)
vmcore-dmesg/vmcore-dmesg.c +20 -1
Index: kexec-tools/vmcore-dmesg/vmcore-dmesg.c
===================================================================
@@ -89,6 +89,24 @@ static uint64_t vaddr_to_offset(uint64_t
 	exit(30);
 }
 
+static unsigned machine_pointer_bits(void)
+{
+	uint8_t bits = 0;
+
+	/* Default to the size of the elf class */
+	switch(ehdr.e_ident[EI_CLASS]) {
+	case ELFCLASS32:        bits = 32; break;
+	case ELFCLASS64:        bits = 64; break;
+	}
+
+	/* Report the architectures pointer size */
+	switch(ehdr.e_machine) {
+	case EM_386:            bits = 32; break;
+	}
+
+        return bits;
+}
+
 static void read_elf32(int fd)
 {
 	Elf32_Ehdr ehdr32;
@@ -389,7 +407,8 @@ static uint64_t read_file_pointer(int fd
 {
 	uint64_t result;
 	ssize_t ret;
-	if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+
+	if (machine_pointer_bits() == 64) {
 		uint64_t scratch;
 		ret = pread(fd, &scratch, sizeof(scratch), addr);
 		if (ret != sizeof(scratch)) {

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Acked-by on v2 1/1
#1 lore raw
Quoted 15 lines · Vivek Goyal

A 32bit arch can prepare ELF64 headers. For example for PAE case to preresent file offsets 64bit but data size at the offset still remains 32bit. If we just base our decision based on EI_CLASS, then we will try to read 64bit data from file and can run into various issues.

We ran into following issue when we tried to run vmcore-dmesg on a 32bit PAE system vmcore which had 64bit elf headers.

No program header covering vaddr 0xc0a6a688c0b89100found kexec bug?

Basically we try to read value of log_buf variable from address log_buf_vaddr. We read in 64bit value and then pass that value again to vaddr_to_offset() in an attempt to get to actual log_buf start and get error message.

Quoted 4 lines

So determine the machine pointer size based on ELF class and arch and read the bytes from file accordingly.

v2: Fixed the code as per suggestion from Eric.

Looks good to me.

I suspect we will need to list 32bit arm and all of the other arches that implement PAE at some point. But the code is clean and clear so that should be easy when the time comes.

Eric

Quoted 35 lines
---
 vmcore-dmesg/vmcore-dmesg.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

Index: kexec-tools/vmcore-dmesg/vmcore-dmesg.c
===================================================================

vmcore-dmesg/vmcore-dmesg.c +18 -0
@@ -89,6 +89,24 @@ static uint64_t vaddr_to_offset(uint64_t
 	exit(30);
 }
 
+static unsigned machine_pointer_bits(void)
+{
+	uint8_t bits = 0;
+
+	/* Default to the size of the elf class */
+	switch(ehdr.e_ident[EI_CLASS]) {
+	case ELFCLASS32:        bits = 32; break;
+	case ELFCLASS64:        bits = 64; break;
+	}
+
+	/* Report the architectures pointer size */
+	switch(ehdr.e_machine) {
+	case EM_386:            bits = 32; break;
+	}
+
+        return bits;
+}
+
 static void read_elf32(int fd)
 {
 	Elf32_Ehdr ehdr32;

vmcore-dmesg/vmcore-dmesg.c static uint64_t read_file_pointer(int fd · line 414

Quoted 9 lines
vmcore-dmesg/vmcore-dmesg.c +2 -1
@@ -389,7 +407,8 @@ static uint64_t read_file_pointer(int fd
 {
 	uint64_t result;
 	ssize_t ret;
-	if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+
+	if (machine_pointer_bits() == 64) {
 		uint64_t scratch;
 		ret = pread(fd, &scratch, sizeof(scratch), addr);
 		if (ret != sizeof(scratch)) {

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#2 lore raw
In reply to Vivek Goyal
Quoted 15 lines · Vivek Goyal

A 32bit arch can prepare ELF64 headers. For example for PAE case to preresent file offsets 64bit but data size at the offset still remains 32bit. If we just base our decision based on EI_CLASS, then we will try to read 64bit data from file and can run into various issues.

We ran into following issue when we tried to run vmcore-dmesg on a 32bit PAE system vmcore which had 64bit elf headers.

No program header covering vaddr 0xc0a6a688c0b89100found kexec bug?

Basically we try to read value of log_buf variable from address log_buf_vaddr. We read in 64bit value and then pass that value again to vaddr_to_offset() in an attempt to get to actual log_buf start and get error message.

Quoted 6 lines

So determine the machine pointer size based on ELF class and arch and read the bytes from file accordingly.

v2: Fixed the code as per suggestion from Eric.

Ack

Quoted 48 lines
---
 vmcore-dmesg/vmcore-dmesg.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

Index: kexec-tools/vmcore-dmesg/vmcore-dmesg.c
===================================================================

vmcore-dmesg/vmcore-dmesg.c +20 -1
@@ -89,6 +89,24 @@ static uint64_t vaddr_to_offset(uint64_t
 	exit(30);
 }
 
+static unsigned machine_pointer_bits(void)
+{
+	uint8_t bits = 0;
+
+	/* Default to the size of the elf class */
+	switch(ehdr.e_ident[EI_CLASS]) {
+	case ELFCLASS32:        bits = 32; break;
+	case ELFCLASS64:        bits = 64; break;
+	}
+
+	/* Report the architectures pointer size */
+	switch(ehdr.e_machine) {
+	case EM_386:            bits = 32; break;
+	}
+
+        return bits;
+}
+
 static void read_elf32(int fd)
 {
 	Elf32_Ehdr ehdr32;
@@ -389,7 +407,8 @@ static uint64_t read_file_pointer(int fd
 {
 	uint64_t result;
 	ssize_t ret;
-	if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+
+	if (machine_pointer_bits() == 64) {
 		uint64_t scratch;
 		ret = pread(fd, &scratch, sizeof(scratch), addr);
 		if (ret != sizeof(scratch)) {

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Signature · 7 lines
Thanks
Dave

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Applied
#3 lore raw
Quoted 20 lines · Dave Young
Quoted 18 lines · Vivek Goyal

A 32bit arch can prepare ELF64 headers. For example for PAE case to preresent file offsets 64bit but data size at the offset still remains 32bit. If we just base our decision based on EI_CLASS, then we will try to read 64bit data from file and can run into various issues.

We ran into following issue when we tried to run vmcore-dmesg on a 32bit PAE system vmcore which had 64bit elf headers.

No program header covering vaddr 0xc0a6a688c0b89100found kexec bug?

Basically we try to read value of log_buf variable from address log_buf_vaddr. We read in 64bit value and then pass that value again to vaddr_to_offset() in an attempt to get to actual log_buf start and get error message.

So determine the machine pointer size based on ELF class and arch and read the bytes from file accordingly.

Quoted 6 lines
Quoted 3 lines

v2: Fixed the code as per suggestion from Eric.

Ack

Thanks, applied.

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec