[PATCH v2] Remove the VOID_PTR facilitator macro
by Petr Tesarik
I've been wondering about the intended use of this facilitator macro
for some time and concluded that it is plainly wrong. It should
take a pointer value from a buffer, but what is the use of a pointer
that pointed to something on the target machine?
Since it cannot be meaningfully dereferenced on the host, the only
(arguable) advantage is the ability to do pointer arithmetics on the
variables. This second patch does the correct thing wherever pointer
arithmetics was done, making the actual calculations more explicit.
Signed-off-by: Petr Tesarik <ptesarik(a)suse.cz>
---
memory.c | 47 +++++++++++++++++++++++++----------------------
1 file changed, 25 insertions(+), 22 deletions(-)
--- a/memory.c
+++ b/memory.c
@@ -26,8 +26,8 @@ struct meminfo { /* general pu
ulong c_offset;
ulong c_num;
ulong s_mem;
- void *s_freep;
- ulong *s_index;
+ ulong s_freep;
+ ulong s_index;
ulong s_inuse;
ulong cpucached_cache;
ulong cpucached_slab;
@@ -139,7 +139,7 @@ static int next_kpage(ulong, ulong *);
static ulong last_vmalloc_address(void);
static ulong next_vmlist_vaddr(ulong);
static int next_identity_mapping(ulong, ulong *);
-static int vm_area_page_dump(ulong, ulong, ulong, ulong, void *,
+static int vm_area_page_dump(ulong, ulong, ulong, ulong, ulong,
struct reference *);
static int dump_swap_info(ulong, ulong *, ulong *);
static void swap_info_init(void);
@@ -3138,7 +3138,7 @@ vm_area_dump(ulong task, ulong flag, ulo
ulong vma;
ulong vm_start;
ulong vm_end;
- void *vm_next, *vm_mm;
+ ulong vm_next, vm_mm;
char *dentry_buf, *vma_buf, *file_buf;
ulong vm_flags;
ulong vm_file, inode;
@@ -3202,7 +3202,7 @@ vm_area_dump(ulong task, ulong flag, ulo
!DO_REF_SEARCH(ref))
fprintf(fp, vma_header);
- for (found = FALSE; vma; vma = (ulong)vm_next) {
+ for (found = FALSE; vma; vma = vm_next) {
if ((flag & PHYSADDR) && !DO_REF_SEARCH(ref))
fprintf(fp, "%s", vma_header);
@@ -3211,9 +3211,9 @@ vm_area_dump(ulong task, ulong flag, ulo
BZERO(buf1, BUFSIZE);
vma_buf = fill_vma_cache(vma);
- vm_mm = VOID_PTR(vma_buf + OFFSET(vm_area_struct_vm_mm));
+ vm_mm = ULONG(vma_buf + OFFSET(vm_area_struct_vm_mm));
vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
- vm_next = VOID_PTR(vma_buf + OFFSET(vm_area_struct_vm_next));
+ vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
vm_flags = SIZE(vm_area_struct_vm_flags) == sizeof(short) ?
USHORT(vma_buf+ OFFSET(vm_area_struct_vm_flags)) :
@@ -3335,7 +3335,7 @@ vm_area_page_dump(ulong vma,
ulong task,
ulong start,
ulong end,
- void *mm,
+ ulong mm,
struct reference *ref)
{
physaddr_t paddr;
@@ -3347,7 +3347,7 @@ vm_area_page_dump(ulong vma,
char buf3[BUFSIZE];
char buf4[BUFSIZE];
- if ((ulong)mm == symbol_value("init_mm"))
+ if (mm == symbol_value("init_mm"))
return FALSE;
if (!ref || DO_REF_DISPLAY(ref))
@@ -9720,9 +9720,9 @@ dump_slab(struct meminfo *si)
return;
}
- si->s_freep = VOID_PTR(si->slab_buf + OFFSET(kmem_slab_s_s_freep));
+ si->s_freep = ULONG(si->slab_buf + OFFSET(kmem_slab_s_s_freep));
si->s_inuse = ULONG(si->slab_buf + OFFSET(kmem_slab_s_s_inuse));
- si->s_index = ULONG_PTR(si->slab_buf + OFFSET(kmem_slab_s_s_index));
+ si->s_index = ULONG(si->slab_buf + OFFSET(kmem_slab_s_s_index));
s_offset = USHORT(si->slab_buf + OFFSET(kmem_slab_s_s_offset));
if (!(si->flags & ADDRESS_SPECIFIED)) {
@@ -9850,7 +9850,7 @@ dump_slab_percpu_v2(struct meminfo *si)
static void
gather_slab_free_list(struct meminfo *si)
{
- ulong *next, obj;
+ ulong next, obj;
ulong expected, cnt;
BNEG(si->addrlist, sizeof(ulong) * (si->c_num+1));
@@ -9885,16 +9885,18 @@ gather_slab_free_list(struct meminfo *si
*/
if (si->c_flags & SLAB_CFLGS_BUFCTL)
- obj = si->s_mem + ((next - si->s_index) * si->c_offset);
+ obj = si->s_mem +
+ ((next - si->s_index) / sizeof(ulong)
+ * si->c_offset);
else
- obj = (ulong)next - si->c_offset;
+ obj = next - si->c_offset;
si->addrlist[cnt] = obj;
if (si->flags & ADDRESS_SPECIFIED) {
if (INSLAB(next, si) &&
- (si->spec_addr >= (ulong)next) &&
- (si->spec_addr < (ulong)(next + 1))) {
+ (si->spec_addr >= next) &&
+ (si->spec_addr < next + sizeof(ulong))) {
si->found = KMEM_BUFCTL_ADDR;
return;
}
@@ -9909,7 +9911,7 @@ gather_slab_free_list(struct meminfo *si
si->errors++;
}
- readmem((ulong)next, KVADDR, &next, sizeof(void *),
+ readmem(next, KVADDR, &next, sizeof(ulong),
"s_freep chain entry", FAULT_ON_ERROR);
} while (next);
@@ -10057,7 +10059,7 @@ static void
dump_slab_objects(struct meminfo *si)
{
int i, j;
- ulong *next;
+ ulong next;
int on_free_list;
ulong cnt, expected;
ulong bufctl, obj;
@@ -10088,7 +10090,8 @@ dump_slab_objects(struct meminfo *si)
if (si->c_flags & SLAB_CFLGS_BUFCTL) {
for (i = 0, next = si->s_index; i < si->c_num; i++, next++) {
obj = si->s_mem +
- ((next - si->s_index) * si->c_offset);
+ ((next - si->s_index) / sizeof(ulong)
+ * si->c_offset);
DUMP_SLAB_OBJECT();
}
} else {
@@ -11561,7 +11564,7 @@ next_upage(struct task_context *tc, ulon
int found;
char *vma_buf;
ulong vm_start, vm_end;
- void *vm_next;
+ ulong vm_next;
if (!tc->mm_struct)
return FALSE;
@@ -11575,12 +11578,12 @@ next_upage(struct task_context *tc, ulon
vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */
- for (found = FALSE; vma; vma = (ulong)vm_next) {
+ for (found = FALSE; vma; vma = vm_next) {
vma_buf = fill_vma_cache(vma);
vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
- vm_next = VOID_PTR(vma_buf + OFFSET(vm_area_struct_vm_next));
+ vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
if (vaddr <= vm_start) {
*nextvaddr = vm_start;
13 years, 10 months
[PATCH] crash: Support a dumpfile in the flattened format.
by Ken'ichi Ohmichi
Hi Dave,
makedumpfile command can create a dumpfile in the flattened format by -F
option, the format is useful for transporting the dump data by SSH.
But the crash utility could not read the dumpfile directly, so a user
should create a readable dumpfile by -R option of makedumpfile.
That was not userfriendly, and this patch is the solution for it.
If applying this patch to the crash utility, it can read a dumpfile in
the flattened format directly.
Thanks,
Ken'ichi Ohmichi
---
Signed-off-by: Ken'ichi Ohmichi <oomichi(a)mxs.nes.nec.co.jp>
diff --git a/Makefile b/Makefile
index 5fb52d6..d5eac0a 100644
--- a/Makefile
+++ b/Makefile
@@ -78,7 +78,7 @@ INSTALLDIR=${DESTDIR}/usr/bin
GENERIC_HFILES=defs.h xen_hyper_defs.h
MCORE_HFILES=va_server.h vas_crash.h
-REDHAT_HFILES=netdump.h diskdump.h xendump.h kvmdump.h qemu-load.h
+REDHAT_HFILES=netdump.h diskdump.h makedumpfile.h xendump.h kvmdump.h qemu-load.h
LKCD_DUMP_HFILES=lkcd_vmdump_v1.h lkcd_vmdump_v2_v3.h lkcd_dump_v5.h \
lkcd_dump_v7.h lkcd_dump_v8.h
LKCD_OBSOLETE_HFILES=lkcd_fix_mem.h
@@ -93,7 +93,7 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \
extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \
lkcd_common.c lkcd_v1.c lkcd_v2_v3.c lkcd_v5.c lkcd_v7.c lkcd_v8.c\
lkcd_fix_mem.c s390_dump.c lkcd_x86_trace.c \
- netdump.c diskdump.c xendump.c unwind.c unwind_decoder.c \
+ netdump.c diskdump.c makedumpfile.c xendump.c unwind.c unwind_decoder.c \
unwind_x86_32_64.c unwind_arm.c \
xen_hyper.c xen_hyper_command.c xen_hyper_global_data.c \
xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c
@@ -109,7 +109,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \
arm.o \
extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \
lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \
- lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o xendump.o \
+ lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o makedumpfile.o xendump.o \
lkcd_x86_trace.o unwind_v1.o unwind_v2.o unwind_v3.o \
unwind_x86_32_64.o unwind_arm.o \
xen_hyper.o xen_hyper_command.o xen_hyper_global_data.o \
@@ -453,6 +453,9 @@ netdump_daemon.o: ${GENERIC_HFILES} ${REDHAT_HFILES} netdump.c
diskdump.o: ${GENERIC_HFILES} ${REDHAT_HFILES} diskdump.c
cc -c ${CRASH_CFLAGS} diskdump.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+makedumpfile.o: ${GENERIC_HFILES} ${REDHAT_HFILES} makedumpfile.c
+ cc -c ${CRASH_CFLAGS} makedumpfile.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+
xendump.o: ${GENERIC_HFILES} ${REDHAT_HFILES} xendump.c
cc -c ${CRASH_CFLAGS} xendump.c ${WARNING_OPTIONS} ${WARNING_ERROR}
diff --git a/defs.h b/defs.h
index 22f876b..27ee9cd 100755
--- a/defs.h
+++ b/defs.h
@@ -4559,6 +4559,12 @@ int dumpfile_is_split(void);
void show_split_dumpfiles(void);
/*
+ * makedumpfile.c
+ */
+void check_flattened_format(char *file);
+int read_dump_file(int fd, off_t offset, void *buf, size_t size);
+
+/*
* xendump.c
*/
int is_xendump(char *);
diff --git a/diskdump.c b/diskdump.c
index fca4a50..ebb3838 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -207,15 +207,8 @@ restart:
if ((header = realloc(header, block_size)) == NULL)
error(FATAL, "diskdump / compressed kdump: cannot malloc block_size buffer\n");
- if (lseek(dd->dfd, 0, SEEK_SET) == failed) {
- if (CRASHDEBUG(1))
- error(INFO, "diskdump / compressed kdump: cannot lseek dump header\n");
- goto err;
- }
-
- if (read(dd->dfd, header, block_size) < block_size) {
- if (CRASHDEBUG(1))
- error(INFO, "diskdump / compressed kdump: cannot read dump header\n");
+ if (!read_dump_file(dd->dfd, 0, header, block_size)) {
+ error(FATAL, "diskdump / compressed kdump: cannot read header\n");
goto err;
}
@@ -280,19 +273,12 @@ restart:
/* read sub header */
offset = (off_t)block_size;
- if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
- error(INFO, "%s: cannot lseek dump sub header\n",
- DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
-
- goto err;
- }
if (DISKDUMP_VALID()) {
if ((sub_header = malloc(block_size)) == NULL)
error(FATAL, "diskdump: cannot malloc sub_header buffer\n");
- if (read(dd->dfd, sub_header, block_size)
- < block_size) {
+ if (!read_dump_file(dd->dfd, offset, sub_header, block_size)) {
error(INFO, "diskdump: cannot read dump sub header\n");
goto err;
}
@@ -301,8 +287,7 @@ restart:
if ((sub_header_kdump = malloc(block_size)) == NULL)
error(FATAL, "compressed kdump: cannot malloc sub_header_kdump buffer\n");
- if (read(dd->dfd, sub_header_kdump, block_size)
- < block_size) {
+ if (!read_dump_file(dd->dfd, offset, sub_header_kdump, block_size)) {
error(INFO, "compressed kdump: cannot read dump sub header\n");
goto err;
}
@@ -314,24 +299,18 @@ restart:
dd->bitmap_len = bitmap_len;
offset = (off_t)block_size * (1 + header->sub_hdr_size);
- if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
- error(INFO, "%s: cannot lseek memory bitmap\n",
- DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
-
- goto err;
- }
if ((dd->bitmap = malloc(bitmap_len)) == NULL)
error(FATAL, "%s: cannot malloc bitmap buffer\n",
DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
dd->dumpable_bitmap = calloc(bitmap_len, 1);
- if (read(dd->dfd, dd->bitmap, bitmap_len) < bitmap_len) {
+
+ if (!read_dump_file(dd->dfd, offset, dd->bitmap, bitmap_len)) {
error(INFO, "%s: cannot read memory bitmap\n",
DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
goto err;
}
-
if (dump_is_partial(header))
memcpy(dd->dumpable_bitmap, dd->bitmap + bitmap_len/2,
bitmap_len/2);
@@ -370,17 +349,11 @@ restart:
size = sub_header_kdump->size_note;
offset = sub_header_kdump->offset_note;
- if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
- error(INFO, "compressed kdump: cannot lseek dump elf"
- " notes\n");
- goto err;
- }
-
if ((notes_buf = malloc(size)) == NULL)
error(FATAL, "compressed kdump: cannot malloc notes"
" buffer\n");
- if (read(dd->dfd, notes_buf, size) < size) {
+ if (!read_dump_file(dd->dfd, offset, notes_buf, size)) {
error(INFO, "compressed kdump: cannot read notes data"
"\n");
goto err;
@@ -624,21 +597,17 @@ cache_page(physaddr_t paddr)
desc_pos = pfn_to_pos(pfn);
seek_offset = dd->data_offset
+ (off_t)(desc_pos - 1)*sizeof(page_desc_t);
- lseek(dd->dfd, seek_offset, SEEK_SET);
/* read page descriptor */
- if (read(dd->dfd, &pd, sizeof(pd)) != sizeof(pd))
+ if (!read_dump_file(dd->dfd, seek_offset, &pd, sizeof(pd)))
return READ_ERROR;
/* sanity check */
if (pd.size > block_size)
return READ_ERROR;
- if (lseek(dd->dfd, pd.offset, SEEK_SET) == failed)
- return SEEK_ERROR;
-
/* read page data */
- if (read(dd->dfd, dd->compressed_page, pd.size) != pd.size)
+ if (!read_dump_file(dd->dfd, pd.offset, dd->compressed_page, pd.size))
return READ_ERROR;
if (pd.flags & DUMP_DH_COMPRESSED) {
@@ -833,17 +802,12 @@ static void dump_vmcoreinfo(FILE *fp)
off_t offset = dd->sub_header_kdump->offset_vmcoreinfo;
const off_t failed = (off_t)-1;
- if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
- error(INFO, "compressed kdump: cannot lseek dump vmcoreinfo\n");
- return;
- }
-
if ((buf = malloc(size_vmcoreinfo)) == NULL) {
error(FATAL, "compressed kdump: cannot malloc vmcoreinfo"
" buffer\n");
}
- if (read(dd->dfd, buf, size_vmcoreinfo) < size_vmcoreinfo) {
+ if (!read_dump_file(dd->dfd, offset, buf, size_vmcoreinfo)) {
error(INFO, "compressed kdump: cannot read vmcoreinfo data\n");
goto err;
}
diff --git a/main.c b/main.c
index 892eb4e..d65a13a 100755
--- a/main.c
+++ b/main.c
@@ -379,6 +379,8 @@ main(int argc, char **argv)
} else if (!(pc->flags & KERNEL_DEBUG_QUERY)) {
+ check_flattened_format(argv[optind]);
+
if (STREQ(argv[optind], "/dev/mem")) {
if (pc->flags & MEMORY_SOURCES) {
error(INFO,
diff --git a/makedumpfile.c b/makedumpfile.c
new file mode 100644
index 0000000..e1add9a
--- /dev/null
+++ b/makedumpfile.c
@@ -0,0 +1,297 @@
+/*
+ * makedumpfile.c
+ *
+ * This code is for reading a dumpfile ganarated by makedumpfile command.
+ *
+ * Copyright (C) 2011 NEC Soft, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author: Ken'ichi Ohmichi <oomichi(a)mxs.nes.nec.co.jp>
+ */
+
+#include "defs.h"
+#include "makedumpfile.h"
+#include <byteswap.h>
+
+int is_flattened_format = 0;
+
+struct flat_data {
+ int64_t off_flattened;
+ int64_t off_rearranged; /* offset which will be rearranged. */
+ int64_t buf_size;
+};
+
+struct all_flat_data {
+ unsigned long long num_array;
+ struct flat_data *array;
+ size_t file_size;
+};
+
+struct all_flat_data afd;
+
+static int
+is_bigendian(void)
+{
+ int i = 0x12345678;
+
+ if (*(char *)&i == 0x12)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static unsigned long long
+store_flat_data_array(char *file, struct flat_data **fda)
+{
+ int result = FALSE, fd;
+ int64_t offset_fdh;
+ unsigned long long num_allocated = 0;
+ unsigned long long num_stored = 0;
+ unsigned long long size_allocated;
+ struct flat_data *ptr = NULL, *cur;
+ struct makedumpfile_data_header fdh;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ error(INFO, "unable to open dump file %s", file);
+ return -1;
+ }
+ if (lseek(fd, MAX_SIZE_MDF_HEADER, SEEK_SET) < 0) {
+ error(INFO, "unable to seek dump file %s", file);
+ close(fd);
+ return -1;
+ }
+ while (1) {
+ if (num_allocated <= num_stored) {
+ num_allocated += 100;
+ size_allocated = sizeof(struct flat_data)
+ * num_allocated;
+ ptr = realloc(ptr, size_allocated);
+ if (ptr == NULL) {
+ error(INFO, "unable to allocate");
+ break;
+ }
+ }
+ offset_fdh = lseek(fd, 0x0, SEEK_CUR);
+
+ if (read(fd, &fdh, sizeof(fdh)) < 0) {
+ error(INFO, "unable to read dump file %s", file);
+ break;
+ }
+ if (!is_bigendian()){
+ fdh.offset = bswap_64(fdh.offset);
+ fdh.buf_size = bswap_64(fdh.buf_size);
+ }
+ if (fdh.offset == END_FLAG_FLAT_HEADER) {
+ result = TRUE;
+ break;
+ }
+ cur = ptr + num_stored;
+ cur->off_flattened = offset_fdh + sizeof(fdh);
+ cur->off_rearranged = fdh.offset;
+ cur->buf_size = fdh.buf_size;
+ num_stored++;
+
+ /* seek for next makedumpfile_data_header. */
+ if (lseek(fd, fdh.buf_size, SEEK_CUR) < 0) {
+ error(INFO, "unable to seek dump file %s", file);
+ break;
+ }
+ }
+ close(fd);
+ if (result == FALSE) {
+ free(ptr);
+ return -1;
+ }
+ *fda = ptr;
+
+ return num_stored;
+}
+
+static void
+sort_flat_data_array(struct flat_data **fda, unsigned long long num_fda)
+{
+ unsigned long long i, j;
+ struct flat_data tmp, *cur_i, *cur_j;
+
+ for (i = 0; i < num_fda - 1; i++) {
+ for (j = i + 1; j < num_fda; j++) {
+ cur_i = *fda + i;
+ cur_j = *fda + j;
+
+ if (cur_i->off_rearranged < cur_j->off_rearranged)
+ continue;
+
+ tmp.off_flattened = cur_i->off_flattened;
+ tmp.off_rearranged = cur_i->off_rearranged;
+ tmp.buf_size = cur_i->buf_size;
+
+ cur_i->off_flattened = cur_j->off_flattened;
+ cur_i->off_rearranged = cur_j->off_rearranged;
+ cur_i->buf_size = cur_j->buf_size;
+
+ cur_j->off_flattened = tmp.off_flattened;
+ cur_j->off_rearranged = tmp.off_rearranged;
+ cur_j->buf_size = tmp.buf_size;
+ }
+ }
+}
+
+static int
+read_all_makedumpfile_data_header(char *file)
+{
+ unsigned long long num;
+ struct flat_data *fda;
+
+ num = store_flat_data_array(file, &fda);
+ if (num < 0)
+ return FALSE;
+
+ sort_flat_data_array(&fda, num);
+
+ afd.num_array = num;
+ afd.array = fda;
+
+ return TRUE;
+}
+
+void
+check_flattened_format(char *file)
+{
+ int fd;
+ struct makedumpfile_header fh;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ error(INFO, "unable to open dump file %s", file);
+ return;
+ }
+ if (read(fd, &fh, sizeof(fh)) < 0) {
+ error(INFO, "unable to read dump file %s", file);
+ close(fd);
+ return;
+ }
+ close(fd);
+
+ if (!is_bigendian()){
+ fh.type = bswap_64(fh.type);
+ fh.version = bswap_64(fh.version);
+ }
+ if ((strncmp(fh.signature, MAKEDUMPFILE_SIGNATURE, sizeof(MAKEDUMPFILE_SIGNATURE)) != 0) ||
+ (fh.type != TYPE_FLAT_HEADER))
+ return;
+
+ if (!read_all_makedumpfile_data_header(file))
+ return;
+
+ is_flattened_format = TRUE;
+}
+
+static int
+read_raw_dump_file(int fd, off_t offset, void *buf, size_t size)
+{
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ if (CRASHDEBUG(1))
+ error(INFO, "cannot lseek dump file\n");
+ return FALSE;
+ }
+ if (read(fd, buf, size) < size) {
+ if (CRASHDEBUG(1))
+ error(INFO, "cannot read dump file\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+read_flattened_dump_file(int fd, off_t offset, void *buf, size_t size)
+{
+ unsigned long long index, index_start, index_end;
+ int64_t range_start, range_end;
+ size_t read_size, remain_size;
+ off_t offset_read;
+ struct flat_data *ptr;
+
+ index_start = 0;
+ index_end = afd.num_array;
+
+ while (1) {
+ index = (index_start + index_end) / 2;
+ ptr = afd.array + index;
+ range_start = ptr->off_rearranged;
+ range_end = ptr->off_rearranged + ptr->buf_size;
+
+ if ((range_start <= offset) && (offset < range_end)) {
+ /* Found a corresponding array. */
+ offset_read = (offset - range_start) + ptr->off_flattened;
+
+ if (offset + size < range_end) {
+ if (!read_raw_dump_file(fd, offset_read, buf, size))
+ return FALSE;
+ break;
+ }
+
+ /* Searh other array corresponding to remaining data. */
+ read_size = range_end - offset;
+ remain_size = size - read_size;
+ if (!read_raw_dump_file(fd, offset_read, buf, read_size))
+ return FALSE;
+ if (!read_flattened_dump_file(fd, offset + read_size,
+ (char *)buf + read_size, remain_size))
+ return FALSE;
+ break;
+
+ } else if ((index == index_start) &&
+ (index_start + 1 == index_end)) {
+ /*
+ * Try to read not-written area. That is a common case,
+ * because the area might be skipped by lseek().
+ * This area should be the data filled with zero.
+ */
+ ptr = afd.array + index_end;
+ if (offset + size < ptr->off_rearranged) {
+ memset(buf, 0x0, size);
+ } else {
+ read_size = ptr->off_rearranged - offset;
+ remain_size = size - read_size;
+ memset(buf, 0x0, read_size);
+ if (!read_flattened_dump_file(fd,
+ offset + read_size,
+ (char *)buf + read_size,
+ remain_size))
+ return FALSE;
+ }
+ break;
+
+ } else if (offset < ptr->off_rearranged)
+ index_end = index;
+ else
+ index_start = index;
+ }
+ return TRUE;
+}
+
+int
+read_dump_file(int fd, off_t offset, void *buf, size_t size)
+{
+ if (is_flattened_format) {
+ if (!read_flattened_dump_file(fd, offset, buf, size))
+ return FALSE;
+ } else {
+ if (!read_raw_dump_file(fd, offset, buf, size))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
diff --git a/makedumpfile.h b/makedumpfile.h
new file mode 100644
index 0000000..fdff4c4
--- /dev/null
+++ b/makedumpfile.h
@@ -0,0 +1,46 @@
+/*
+ * makedumpfile.h
+ *
+ * This code is for reading a dumpfile ganarated by makedumpfile command.
+ *
+ * Copyright (C) 2011 NEC Soft, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author: Ken'ichi Ohmichi <oomichi(a)mxs.nes.nec.co.jp>
+ */
+
+/*
+ * makedumpfile header
+ * For re-arranging the dump data on different architecture, all the
+ * variables are defined by 64bits. The size of signature is aligned
+ * to 64bits, and change the values to big endian.
+ */
+#define MAKEDUMPFILE_SIGNATURE "makedumpfile"
+#define NUM_SIG_MDF (sizeof(MAKEDUMPFILE_SIGNATURE) - 1)
+#define SIZE_SIG_MDF roundup(sizeof(char) * NUM_SIG_MDF, 8)
+#define SIG_LEN_MDF (SIZE_SIG_MDF / sizeof(char))
+#define MAX_SIZE_MDF_HEADER (4096) /* max size of makedumpfile_header */
+#define TYPE_FLAT_HEADER (1) /* type of flattened format */
+#define VERSION_FLAT_HEADER (1) /* current version of flattened format */
+#define END_FLAG_FLAT_HEADER (-1)
+
+struct makedumpfile_header {
+ char signature[SIG_LEN_MDF]; /* = "makedumpfile" */
+ int64_t type;
+ int64_t version;
+};
+
+struct makedumpfile_data_header {
+ int64_t offset;
+ int64_t buf_size;
+};
+
diff --git a/netdump.c b/netdump.c
index c6e7ad9..8244f51 100644
--- a/netdump.c
+++ b/netdump.c
@@ -121,11 +121,8 @@ is_netdump(char *file, ulong source_query)
}
size = MIN_NETDUMP_ELF_HEADER_SIZE;
- if (read(fd, eheader, size) != size) {
- sprintf(buf, "%s: read", file);
- perror(buf);
+ if (!read_dump_file(fd, 0, eheader, size))
goto bailout;
- }
if (lseek(fd, 0, SEEK_SET) != 0) {
sprintf(buf, "%s: lseek", file);
@@ -290,12 +287,10 @@ is_netdump(char *file, ulong source_query)
clean_exit(1);
}
- if (read(fd, tmp_elf_header, size) != size) {
- sprintf(buf, "%s: read", file);
- perror(buf);
+ if (!read_dump_file(fd, 0, tmp_elf_header, size)) {
free(tmp_elf_header);
- goto bailout;
- }
+ goto bailout;
+ }
nd->ndfd = fd;
nd->elf_header = tmp_elf_header;
@@ -393,12 +388,12 @@ file_elf_version(char *file)
}
size = MIN_NETDUMP_ELF_HEADER_SIZE;
- if (read(fd, header, size) != size) {
- sprintf(buf, "%s: read", file);
- perror(buf);
+
+ if (!read_dump_file(fd, 0, header, size)) {
close(fd);
return -1;
}
+
close(fd);
elf32 = (Elf32_Ehdr *)&header[0];
@@ -523,11 +518,8 @@ read_netdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
break;
}
- if (lseek(nd->ndfd, offset, SEEK_SET) == -1)
- return SEEK_ERROR;
-
- if (read(nd->ndfd, bufptr, cnt) != cnt)
- return READ_ERROR;
+ if (!read_dump_file(nd->ndfd, offset, bufptr, cnt))
+ return READ_ERROR;
return cnt;
}
13 years, 10 months
Cleanup: GDB does not need struct syment
by Petr Tesarik
The syment struct is not used for anything by the embedded GDB,
so we can remove it completely.
Signed-off-by: Petr Tesarik <ptesarik(a)suse.cz>
---
defs.h | 5 ++---
gdb-7.0.patch | 4 +---
2 files changed, 3 insertions(+), 6 deletions(-)
--- a/defs.h
+++ b/defs.h
@@ -1963,9 +1963,6 @@ struct alias_data { /* c
retaddr[i] = 0; \
}
-#endif /* !GDB_COMMON */
-
-
#define SYMBOL_NAME_USED (0x1)
#define MODULE_SYMBOL (0x2)
#define IS_MODULE_SYMBOL(SYM) ((SYM)->flags & MODULE_SYMBOL)
@@ -1981,6 +1978,8 @@ struct syment {
unsigned char pad2;
};
+#endif /* !GDB_COMMON */
+
#define NAMESPACE_INIT (1)
#define NAMESPACE_REUSE (2)
#define NAMESPACE_FREE (3)
--- a/gdb-7.0.patch
+++ b/gdb-7.0.patch
@@ -468,7 +468,7 @@
return returnval;
}
-@@ -4783,3 +4790,619 @@ Valid values are \"ask\", \"all\", \"can
+@@ -4783,3 +4790,617 @@ Valid values are \"ask\", \"all\", \"can
observer_attach_executable_changed (symtab_observer_executable_changed);
}
@@ -880,8 +880,6 @@
+ register struct objfile *objfile;
+ register struct minimal_symbol *m;
+ struct load_module *lm;
-+ struct syment *sp;
-+ struct syment *spx;
+ int external, subsequent, found;
+ off_t offset;
+ ulong value, adjusted;
13 years, 10 months
[PATCH 1/2] ARM: update some comments
by Mika Westerberg
There are few comments which are not relevant anymore. Update the
comments to reflect the current situation.
Signed-off-by: Mika Westerberg <ext-mika.1.westerberg(a)nokia.com>
---
arm.c | 3 ---
unwind_arm.c | 5 ++---
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/arm.c b/arm.c
index 4e6ab3d..1752f62 100644
--- a/arm.c
+++ b/arm.c
@@ -1048,9 +1048,6 @@ arm_get_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
/*
* Get the starting point for the active cpu in a diskdump.
- *
- * Note that we currently support only UP machines. In future we might want to
- * support SMP machines as well.
*/
static int
arm_get_dumpfile_stack_frame(struct bt_info *bt, ulong *nip, ulong *ksp)
diff --git a/unwind_arm.c b/unwind_arm.c
index 58fb5da..18fdad9 100644
--- a/unwind_arm.c
+++ b/unwind_arm.c
@@ -250,9 +250,8 @@ read_module_unwind_table(struct unwind_table *tbl, ulong addr)
idx_size = idx_stop - idx_start;
/*
- * We know the size of the index table. Allocate memory for the table
- * (including the EH table) and read the contents from the kernel
- * memory.
+ * We know the size of the index table. Allocate memory for
+ * the table and read the contents from the kernel memory.
*/
tbl->idx = calloc(idx_size, 1);
if (!tbl->idx)
--
1.7.3.2
13 years, 10 months
[PATCH] Cleanup GDB_CONF_FLAGS settings
by Petr Tesarik
Set up GDB_CONF_FLAGS from the configure utility. This avoids duplication of
logic between configure.c and Makefile. Additionally, the new method ensures
that the gdb target always matches the configured crash target. This may
become useful when we allow cross-compiling crash for a different target
(think of arm on x86, for example).
Signed-off-by: Petr Tesarik <ptesarik(a)suse.cz>
---
Makefile | 18 ++----------------
configure.c | 32 +++++++++++++++++++++++++++++---
2 files changed, 31 insertions(+), 19 deletions(-)
--- a/configure.c
+++ b/configure.c
@@ -18,14 +18,14 @@
/*
* define, clear and undef dynamically update the top-level Makefile:
*
- * -b define: TARGET, GDB, GDB_FILES, GDB_OFILES, GDB_PATCH_FILES,
TARGET_CFLAGS and GPL_FILES
+ * -b define: TARGET, GDB, GDB_FILES, GDB_OFILES, GDB_PATCH_FILES,
TARGET_CFLAGS, GDB_CONF_FLAGS and GPL_FILES
* create: build_data.c
*
- * -d define: TARGET, GDB, GDB_FILES, GDB_OFILES, GDB_PATCH_FILES,
TARGET_CFLAGS, and
+ * -d define: TARGET, GDB, GDB_FILES, GDB_OFILES, GDB_PATCH_FILES,
TARGET_CFLAGS, GDB_CONF_FLAGS and
* PROGRAM (for daemon)
* create: build_data.c
*
- * -u clear: TARGET, GDB, GDB_FILES, GDB_OFILES, VERSION,
GDB_PATCH_FILES, TARGET_CFLAGS and GPL_FILES
+ * -u clear: TARGET, GDB, GDB_FILES, GDB_OFILES, VERSION,
GDB_PATCH_FILES, TARGET_CFLAGS, GDB_CONF_FLAGS and GPL_FILES
* undef: WARNING_ERROR, WARNING_OPTIONS
*
* -r define: GDB_FILES, VERSION, GDB_PATCH_FILES GPL_FILES
@@ -131,6 +131,16 @@ int name_to_target(char *);
#define TARGET_CFLAGS_ARM_ON_X86_64 "TARGET_CFLAGS=-m32 -
D_FILE_OFFSET_BITS=64"
#define TARGET_CFLAGS_X86_ON_X86_64 "TARGET_CFLAGS=-m32 -
D_FILE_OFFSET_BITS=64"
+#define GDB_TARGET_X86 "GDB_CONF_FLAGS=--target=i686-pc-linux-gnu"
+#define GDB_TARGET_ALPHA "GDB_CONF_FLAGS=--target=alpha-linux-gnu"
+#define GDB_TARGET_PPC "GDB_CONF_FLAGS=--target=powerpc-linux-gnu"
+#define GDB_TARGET_IA64 "GDB_CONF_FLAGS=--target=ia64-linux-gnu"
+#define GDB_TARGET_S390 "GDB_CONF_FLAGS=--target=s390-ibm-linux-gnu"
+#define GDB_TARGET_S390X "GDB_CONF_FLAGS=--target=s390x-ibm-linux-gnu"
+#define GDB_TARGET_PPC64 "GDB_CONF_FLAGS=--target=powerpc64-linux-gnu"
+#define GDB_TARGET_X86_64 "GDB_CONF_FLAGS=--target=x86_64-pc-linux-gnu"
+#define GDB_TARGET_ARM "GDB_CONF_FLAGS=--target=arm-elf-linux-gnu"
+
/*
* The original plan was to allow the use of a particular version
* of gdb for a given architecture. But for practical purposes,
@@ -512,6 +522,7 @@ build_configure(struct supported_gdb_ver
char buf[512];
char *target;
char *target_CFLAGS;
+ char *gdb_conf_flags;
get_current_configuration(sp);
@@ -525,34 +536,42 @@ build_configure(struct supported_gdb_ver
target_CFLAGS = TARGET_CFLAGS_X86_ON_X86_64;
else
target_CFLAGS = TARGET_CFLAGS_X86;
+ gdb_conf_flags = GDB_TARGET_X86;
break;
case ALPHA:
target = TARGET_ALPHA;
target_CFLAGS = TARGET_CFLAGS_ALPHA;
+ gdb_conf_flags = GDB_TARGET_ALPHA;
break;
case PPC:
target = TARGET_PPC;
target_CFLAGS = TARGET_CFLAGS_PPC;
+ gdb_conf_flags = GDB_TARGET_PPC;
break;
case IA64:
target = TARGET_IA64;
target_CFLAGS = TARGET_CFLAGS_IA64;
+ gdb_conf_flags = GDB_TARGET_IA64;
break;
case S390:
target = TARGET_S390;
target_CFLAGS = TARGET_CFLAGS_S390;
+ gdb_conf_flags = GDB_TARGET_S390;
break;
case S390X:
target = TARGET_S390X;
target_CFLAGS = TARGET_CFLAGS_S390X;
+ gdb_conf_flags = GDB_TARGET_S390X;
break;
case PPC64:
target = TARGET_PPC64;
target_CFLAGS = TARGET_CFLAGS_PPC64;
+ gdb_conf_flags = GDB_TARGET_PPC64;
break;
case X86_64:
target = TARGET_X86_64;
target_CFLAGS = TARGET_CFLAGS_X86_64;
+ gdb_conf_flags = GDB_TARGET_X86_64;
break;
case ARM:
target = TARGET_ARM;
@@ -562,6 +581,7 @@ build_configure(struct supported_gdb_ver
target_CFLAGS = TARGET_CFLAGS_ARM_ON_X86_64;
else
target_CFLAGS = TARGET_CFLAGS_ARM;
+ gdb_conf_flags = GDB_TARGET_ARM;
break;
}
@@ -573,6 +593,9 @@ build_configure(struct supported_gdb_ver
else if (strncmp(buf, "TARGET_CFLAGS=",
strlen("TARGET_CFLAGS=")) == 0)
fprintf(fp2, "%s\n", target_CFLAGS);
+ else if (strncmp(buf, "GDB_CONF_FLAGS=",
+ strlen("GDB_CONF_FLAGS=")) == 0)
+ fprintf(fp2, "%s\n", gdb_conf_flags);
else if (strncmp(buf, "GDB_FILES=",strlen("GDB_FILES=")) == 0)
fprintf(fp2, "%s\n", sp->GDB_FILES);
else if (strncmp(buf, "GDB_OFILES=",strlen("GDB_OFILES=")) == 0)
@@ -745,6 +768,9 @@ unconfigure(void)
else if (strncmp(buf, "TARGET_CFLAGS=",
strlen("TARGET_CFLAGS=")) == 0)
fprintf(fp2, "TARGET_CFLAGS=\n");
+ else if (strncmp(buf, "GDB_CONF_FLAGS=",
+ strlen("GDB_CONF_FLAGS=")) == 0)
+ fprintf(fp2, "GDB_CONF_FLAGS=\n");
else if (strncmp(buf, "GDB_FILES=",strlen("GDB_FILES=")) ==
0)
fprintf(fp2, "GDB_FILES=\n");
else if (strncmp(buf, "GDB_OFILES=",strlen("GDB_OFILES=")) ==
0)
--- a/Makefile
+++ b/Makefile
@@ -23,30 +23,16 @@ PROGRAM=crash
#
# Supported targets: X86 ALPHA PPC IA64 PPC64
-# TARGET will be configured automatically by configure
+# TARGET and GDB_CONF_FLAGS will be configured automatically by configure
#
TARGET=
+GDB_CONF_FLAGS=
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e
s/arm.*/arm/ -e s/sa110/arm/)
ifeq ($(ARCH), ppc64)
CONF_FLAGS = -m64
endif
-ifeq ($(TARGET), ARM)
-ifeq ($(ARCH), i386)
-GDB_CONF_FLAGS = --target=arm-elf-linux
-endif
-ifeq ($(ARCH), x86_64)
-GDB_CONF_FLAGS = --target=arm-elf-linux CFLAGS=-m32
-endif
-endif
-
-ifeq ($(TARGET), X86)
-ifeq ($(ARCH), x86_64)
-GDB_CONF_FLAGS = --target=i686-pc-linux-gnu CFLAGS=-m32
-endif
-endif
-
#
# GDB, GDB_FILES, GDB_OFILES and GDB_PATCH_FILES will be configured
automatically by configure
#
13 years, 10 months
[PATCH] Remove the VOID_PTR facilitator macro
by Petr Tesarik
I've been wondering about the intended use of this facilitator macro
for some time and concluded that it is plainly wrong. It should
take a pointer value from a buffer, but what is the use of a pointer
that pointed to something on the _target_ machine? It cannot be
meaningfully dereferenced on the host.
Okay, pointer arithmetics is done in one place, but IMO it is better
to explicitly state the object size there, because that's how things
are done elsewhere in the code, so it is less surprising for anybody
reading the code.
The irony is underlined by the fact that all three uses of the macro
need a subsequent typecast to ulong, which proves the whole concept
flawed.
Signed-off-by: Petr Tesarik <ptesarik(a)suse.cz>
---
defs.h | 1 -
memory.c | 42 +++++++++++++++++++++---------------------
2 files changed, 21 insertions(+), 22 deletions(-)
--- a/defs.h
+++ b/defs.h
@@ -1760,7 +1760,6 @@ struct builtin_debug_table {
#define ULONG_PTR(ADDR) *((ulong **)((char *)(ADDR)))
#define USHORT(ADDR) *((ushort *)((char *)(ADDR)))
#define SHORT(ADDR) *((short *)((char *)(ADDR)))
-#define VOID_PTR(ADDR) *((void **)((char *)(ADDR)))
struct node_table {
int node_id;
--- a/memory.c
+++ b/memory.c
@@ -26,8 +26,8 @@ struct meminfo { /* general pu
ulong c_offset;
ulong c_num;
ulong s_mem;
- void *s_freep;
- ulong *s_index;
+ ulong s_freep;
+ ulong s_index;
ulong s_inuse;
ulong cpucached_cache;
ulong cpucached_slab;
@@ -139,7 +139,7 @@ static int next_kpage(ulong, ulong *);
static ulong last_vmalloc_address(void);
static ulong next_vmlist_vaddr(ulong);
static int next_identity_mapping(ulong, ulong *);
-static int vm_area_page_dump(ulong, ulong, ulong, ulong, void *,
+static int vm_area_page_dump(ulong, ulong, ulong, ulong, ulong,
struct reference *);
static int dump_swap_info(ulong, ulong *, ulong *);
static void swap_info_init(void);
@@ -3138,7 +3138,7 @@ vm_area_dump(ulong task, ulong flag, ulo
ulong vma;
ulong vm_start;
ulong vm_end;
- void *vm_next, *vm_mm;
+ ulong vm_next, vm_mm;
char *dentry_buf, *vma_buf, *file_buf;
ulong vm_flags;
ulong vm_file, inode;
@@ -3202,7 +3202,7 @@ vm_area_dump(ulong task, ulong flag, ulo
!DO_REF_SEARCH(ref))
fprintf(fp, vma_header);
- for (found = FALSE; vma; vma = (ulong)vm_next) {
+ for (found = FALSE; vma; vma = vm_next) {
if ((flag & PHYSADDR) && !DO_REF_SEARCH(ref))
fprintf(fp, "%s", vma_header);
@@ -3211,9 +3211,9 @@ vm_area_dump(ulong task, ulong flag, ulo
BZERO(buf1, BUFSIZE);
vma_buf = fill_vma_cache(vma);
- vm_mm = VOID_PTR(vma_buf + OFFSET(vm_area_struct_vm_mm));
+ vm_mm = ULONG(vma_buf + OFFSET(vm_area_struct_vm_mm));
vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
- vm_next = VOID_PTR(vma_buf + OFFSET(vm_area_struct_vm_next));
+ vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
vm_flags = SIZE(vm_area_struct_vm_flags) == sizeof(short) ?
USHORT(vma_buf+ OFFSET(vm_area_struct_vm_flags)) :
@@ -3335,7 +3335,7 @@ vm_area_page_dump(ulong vma,
ulong task,
ulong start,
ulong end,
- void *mm,
+ ulong mm,
struct reference *ref)
{
physaddr_t paddr;
@@ -3347,7 +3347,7 @@ vm_area_page_dump(ulong vma,
char buf3[BUFSIZE];
char buf4[BUFSIZE];
- if ((ulong)mm == symbol_value("init_mm"))
+ if (mm == symbol_value("init_mm"))
return FALSE;
if (!ref || DO_REF_DISPLAY(ref))
@@ -9720,9 +9720,9 @@ dump_slab(struct meminfo *si)
return;
}
- si->s_freep = VOID_PTR(si->slab_buf + OFFSET(kmem_slab_s_s_freep));
+ si->s_freep = ULONG(si->slab_buf + OFFSET(kmem_slab_s_s_freep));
si->s_inuse = ULONG(si->slab_buf + OFFSET(kmem_slab_s_s_inuse));
- si->s_index = ULONG_PTR(si->slab_buf + OFFSET(kmem_slab_s_s_index));
+ si->s_index = ULONG(si->slab_buf + OFFSET(kmem_slab_s_s_index));
s_offset = USHORT(si->slab_buf + OFFSET(kmem_slab_s_s_offset));
if (!(si->flags & ADDRESS_SPECIFIED)) {
@@ -9850,7 +9850,7 @@ dump_slab_percpu_v2(struct meminfo *si)
static void
gather_slab_free_list(struct meminfo *si)
{
- ulong *next, obj;
+ ulong next, obj;
ulong expected, cnt;
BNEG(si->addrlist, sizeof(ulong) * (si->c_num+1));
@@ -9885,16 +9885,16 @@ gather_slab_free_list(struct meminfo *si
*/
if (si->c_flags & SLAB_CFLGS_BUFCTL)
- obj = si->s_mem + ((next - si->s_index) * si->c_offset);
+ obj = si->s_mem + (next - si->s_index) * si->c_offset;
else
- obj = (ulong)next - si->c_offset;
+ obj = next - si->c_offset;
si->addrlist[cnt] = obj;
if (si->flags & ADDRESS_SPECIFIED) {
if (INSLAB(next, si) &&
- (si->spec_addr >= (ulong)next) &&
- (si->spec_addr < (ulong)(next + 1))) {
+ (si->spec_addr >= next) &&
+ (si->spec_addr < next + sizeof(ulong))) {
si->found = KMEM_BUFCTL_ADDR;
return;
}
@@ -9909,7 +9909,7 @@ gather_slab_free_list(struct meminfo *si
si->errors++;
}
- readmem((ulong)next, KVADDR, &next, sizeof(void *),
+ readmem(next, KVADDR, &next, sizeof(ulong),
"s_freep chain entry", FAULT_ON_ERROR);
} while (next);
@@ -10057,7 +10057,7 @@ static void
dump_slab_objects(struct meminfo *si)
{
int i, j;
- ulong *next;
+ ulong next;
int on_free_list;
ulong cnt, expected;
ulong bufctl, obj;
@@ -11561,7 +11561,7 @@ next_upage(struct task_context *tc, ulon
int found;
char *vma_buf;
ulong vm_start, vm_end;
- void *vm_next;
+ ulong vm_next;
if (!tc->mm_struct)
return FALSE;
@@ -11575,12 +11575,12 @@ next_upage(struct task_context *tc, ulon
vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */
- for (found = FALSE; vma; vma = (ulong)vm_next) {
+ for (found = FALSE; vma; vma = vm_next) {
vma_buf = fill_vma_cache(vma);
vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
- vm_next = VOID_PTR(vma_buf + OFFSET(vm_area_struct_vm_next));
+ vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
if (vaddr <= vm_start) {
*nextvaddr = vm_start;
13 years, 10 months
RFC: Improving crash's search speed
by Bob Montgomery
I like using the search command in crash, but noticed that it takes much
longer than my own dump search tools.
As an example, on a level 31 (lots of exclusions) dump from a 4 GB
x86_64 system, this search command in (benchmarked with a command file)
finds these results and takes almost 2 minutes:
$ cat cmdfile2
search -k 0xffff88012491b240
$ time crash-5.1.1 kernel_link dump.201101161845 <cmdfile2
...
ffff88012491b280: ffff88012491b240
ffff880126dcca18: ffff88012491b240
ffff880126dcca20: ffff88012491b240
ffff880126dcca30: ffff88012491b240
ffff880126dcca88: ffff88012491b240
ffff880126eca148: ffff88012491b240
ffffc9000468d148: ffff88012491b240
real 1m52.834s
user 1m50.571s
sys 0m2.220s
When you watch it search, the first 6 results come out in a few seconds,
then nothing happens for a long time.
The first six are coming from searching the identity mapped region which
covers every page in the dump. Note the forms of the addresses for the
first six hits.
The majority of the search time is spent going through the kernel
vmalloc address range and checking to see if pages are mapped to any of
those addresses. Any page searched through these addresses should have
already been searched in the identity mapped search.
So, for the last hit: (ffffc9000468d148: ffff88012491b240), converting
to physical, and then back to identity-mapped virtual gives:
crash-5.1.1> vtop 0xffffc9000468d148
VIRTUAL PHYSICAL
ffffc9000468d148 126eca148
...
And:
crash-5.1.1> ptov 0x126eca148
VIRTUAL PHYSICAL
ffff880126eca148 126eca148
And so the hit at 0xffffc9000468d148 was already caught by the earlier
hit in the identity-mapped range:
ffff880126eca148: ffff88012491b240
If you don't want to wait, you can find the vmalloc_start_addr from
"help -m" and use it to restrict the search range:
$ cat cmdfile2a
search -k -e 0xffffc90000000000 0xffff88012491b240
$ time crash-5.1.1 dump.201101161845 kernel_link <cmdfile2a
...
ffff88012491b280: ffff88012491b240
ffff880126dcca18: ffff88012491b240
ffff880126dcca20: ffff88012491b240
ffff880126dcca30: ffff88012491b240
ffff880126dcca88: ffff88012491b240
ffff880126eca148: ffff88012491b240
real 0m4.243s
user 0m4.088s
sys 0m0.156s
This command finishes with the first 6 hits in 4 seconds.
Once you have those hits, if you have to know if any virtual mappings
exist, you can use kmem on the physical address:
crash-5.1.1> vtop 0xffff880126eca148
VIRTUAL PHYSICAL
ffff880126eca148 126eca148
...
crash-5.1.1> kmem -v 126eca148
VM_STRUCT ADDRESS RANGE SIZE
ffff8801277f8180 ffffc90004682000 - 1052672
Which shows the virtual range that contains the mapping for the page.
Then this command takes no time:
crash-5.1.1> search -k -s ffffc90004682000 -e ffffc90004783000
ffff88012491b240
ffffc9000468d148: ffff88012491b240
I think the drastic reduction of search time from 2 minutes to 4 seconds
is interesting enough to warrant a shortcut.
The attached patch implements the -K option that is the same as doing
"-k -e <vmalloc_start_addr>".
Comments?
Bob Montgomery
13 years, 10 months
[PATCH 00/12] make crash-trace-command compatible for many different kernels
by Lai Jiangshan
The crash tools and the extensions must work for all various kernels.
The trace.so is for rhel6 kernel(2.6.32) original, it is outdated,
these patches fix it. Now it works for all 2.6.xx kernels(including
2.6.38-RC1) which have ftrace.
The major difference between current kernel and old kernel is that,
struct ftrace_event_class was introduced to ftrace
as Jeff noted. So these patches add a lot of
struct ftrace_event_class related code, thanks to Jeff.
Also thanks to Dave for many suggestions.
All the code were applied to:
git://github.com/laijs/tracing-extension-module-for-crash.git
Thanks a lot.
Lai
13 years, 10 months
[PATCH 12/12] crash-trace-command: support old kernel that has no print_fmt
by Lai Jiangshan
very old kernel has no print_fmt field, use "Unknown print_fmt"
instead.
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
diff --git a/extensions/trace.c b/extensions/trace.c
index e04c504..714765e 100755
--- a/extensions/trace.c
+++ b/extensions/trace.c
@@ -1080,8 +1080,10 @@ int ftrace_get_event_type_print_fmt(ulong call, char **print_fmt)
fmt_offset = MEMBER_OFFSET("ftrace_event_call", "print_fmt");
}
- if (fmt_offset < 0)
- return -1;
+ if (fmt_offset < 0) {
+ *print_fmt = strdup("Unknown print_fmt");
+ return 0;
+ }
if (!readmem(call + fmt_offset, KVADDR, &fmt_addr, sizeof(fmt_addr),
"read ftrace_event_call fmt_addr", RETURN_ON_ERROR))
13 years, 10 months
[PATCH 11/12] crash-trace-command: implement older syscall_get_exit_fields()
by Lai Jiangshan
Older kernel use older syscall_get_exit_fields().
Implement(emulate) for it!
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
diff --git a/extensions/trace.c b/extensions/trace.c
index 3bad4af..e04c504 100755
--- a/extensions/trace.c
+++ b/extensions/trace.c
@@ -697,6 +697,38 @@ work:
return 0;
}
+static int syscall_get_exit_fields_old(ulong call, ulong *fields)
+{
+ static int inited;
+ static int data_offset;
+ static int exit_fields_offset;
+
+ ulong metadata;
+
+ if (inited)
+ goto work;
+
+ inited = 1;
+ data_offset = MEMBER_OFFSET("ftrace_event_call", "data");
+ if (data_offset < 0)
+ return -1;
+
+ exit_fields_offset = MEMBER_OFFSET("syscall_metadata", "exit_fields");
+ if (exit_fields_offset < 0)
+ return -1;
+
+work:
+ if (data_offset < 0 || exit_fields_offset < 0)
+ return -1;
+
+ if (!readmem(call + data_offset, KVADDR, &metadata, sizeof(metadata),
+ "read ftrace_event_call data", RETURN_ON_ERROR))
+ return -1;
+
+ *fields = metadata + exit_fields_offset;
+ return 0;
+}
+
static int syscall_get_exit_fields(ulong call, ulong *fields)
{
static int inited;
@@ -714,7 +746,7 @@ static int syscall_get_exit_fields(ulong call, ulong *fields)
}
if (inited == -1)
- return -1;
+ return syscall_get_exit_fields_old(call, fields);
*fields = syscall_exit_fields_value;
13 years, 10 months