Commit d46d26aa authored by Tony Luck's avatar Tony Luck Committed by David Mosberger

[PATCH] ia64: make kcore work

/proc/kcore is what you need, but it is broken on ia64 (and
has been since the dawn of time for access to region 5) because
it assumes that all kernel virtual addresses are above PAGE+AF8-OFFSET.
This isn't true on ia64, VMALLOC+AF8-START is smaller than PAGE+AF8-OFFSET.

Attached is a patch (applies to 2.4.19 and to 2.5.39) that fixes the
assumption.  After applying you'll be able to use:

        +ACM- gdb vmlinux /proc/kcore

and happily ask gdb to examine addresses in region 5.
parent 42389210
...@@ -99,6 +99,12 @@ static ssize_t read_kcore(struct file *file, char *buf, size_t count, loff_t *pp ...@@ -99,6 +99,12 @@ static ssize_t read_kcore(struct file *file, char *buf, size_t count, loff_t *pp
} }
#else /* CONFIG_KCORE_AOUT */ #else /* CONFIG_KCORE_AOUT */
#if VMALLOC_START < PAGE_OFFSET
#define KCORE_BASE VMALLOC_START
#else
#define KCORE_BASE PAGE_OFFSET
#endif
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
/* An ELF note in memory */ /* An ELF note in memory */
...@@ -118,7 +124,7 @@ static size_t get_kcore_size(int *num_vma, size_t *elf_buflen) ...@@ -118,7 +124,7 @@ static size_t get_kcore_size(int *num_vma, size_t *elf_buflen)
struct vm_struct *m; struct vm_struct *m;
*num_vma = 0; *num_vma = 0;
size = ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE); size = ((size_t)high_memory - KCORE_BASE + PAGE_SIZE);
if (!vmlist) { if (!vmlist) {
*elf_buflen = PAGE_SIZE; *elf_buflen = PAGE_SIZE;
return (size); return (size);
...@@ -126,15 +132,15 @@ static size_t get_kcore_size(int *num_vma, size_t *elf_buflen) ...@@ -126,15 +132,15 @@ static size_t get_kcore_size(int *num_vma, size_t *elf_buflen)
for (m=vmlist; m; m=m->next) { for (m=vmlist; m; m=m->next) {
try = (size_t)m->addr + m->size; try = (size_t)m->addr + m->size;
if (try > size) if (try > KCORE_BASE + size)
size = try; size = try - KCORE_BASE;
*num_vma = *num_vma + 1; *num_vma = *num_vma + 1;
} }
*elf_buflen = sizeof(struct elfhdr) + *elf_buflen = sizeof(struct elfhdr) +
(*num_vma + 2)*sizeof(struct elf_phdr) + (*num_vma + 2)*sizeof(struct elf_phdr) +
3 * sizeof(struct memelfnote); 3 * sizeof(struct memelfnote);
*elf_buflen = PAGE_ALIGN(*elf_buflen); *elf_buflen = PAGE_ALIGN(*elf_buflen);
return (size - PAGE_OFFSET + *elf_buflen); return size + *elf_buflen;
} }
...@@ -237,7 +243,7 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff) ...@@ -237,7 +243,7 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff)
offset += sizeof(struct elf_phdr); offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD; phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X; phdr->p_flags = PF_R|PF_W|PF_X;
phdr->p_offset = dataoff; phdr->p_offset = PAGE_OFFSET - KCORE_BASE + dataoff;
phdr->p_vaddr = PAGE_OFFSET; phdr->p_vaddr = PAGE_OFFSET;
phdr->p_paddr = __pa(PAGE_OFFSET); phdr->p_paddr = __pa(PAGE_OFFSET);
phdr->p_filesz = phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET); phdr->p_filesz = phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET);
...@@ -254,7 +260,7 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff) ...@@ -254,7 +260,7 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff)
phdr->p_type = PT_LOAD; phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X; phdr->p_flags = PF_R|PF_W|PF_X;
phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + dataoff; phdr->p_offset = (size_t)m->addr - KCORE_BASE + dataoff;
phdr->p_vaddr = (size_t)m->addr; phdr->p_vaddr = (size_t)m->addr;
phdr->p_paddr = __pa(m->addr); phdr->p_paddr = __pa(m->addr);
phdr->p_filesz = phdr->p_memsz = m->size; phdr->p_filesz = phdr->p_memsz = m->size;
...@@ -385,9 +391,9 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t ...@@ -385,9 +391,9 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t
/* /*
* Fill the remainder of the buffer from kernel VM space. * Fill the remainder of the buffer from kernel VM space.
* We said in the ELF header that the data which starts * We said in the ELF header that the data which starts
* at 'elf_buflen' is virtual address PAGE_OFFSET. --rmk * at 'elf_buflen' is virtual address KCORE_BASE. --rmk
*/ */
start = PAGE_OFFSET + (*fpos - elf_buflen); start = KCORE_BASE + (*fpos - elf_buflen);
if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen) if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
tsz = buflen; tsz = buflen;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment