On 2017/3/15 23:27, Dave Anderson wrote:
----- Original Message -----
Hi Dave,
In my develop enviroment, kaslr offset will be stored in SoC on-chip memory
for debuging, but crash utility is not work if i only set kaslr offset by
command '--kaslr XXX', it also need correct kimage_voffset.
error message without the patch:
VA_BITS: 39
using 40000000 as phys_offset
kimage_voffset: 0
phys_offset: 40000000
.....cut....
<readmem: ffffff9381e074a0, KVADDR, "cpu_possible_mask", 8, (FOE),
7fffce0dfa48>
<read_ramdump: addr: ffffff9381e074a0 paddr: 13b9e074a0 cnt: 8>
read_ramdump: READ_ERROR: offset not found for paddr: 13b9e074a0
crash: read error: kernel virtual address: ffffff9381e074a0 type:
"cpu_possible_mask"
This patch add a function to auto calculate kimage_voffset by kaslr offset.
Please review it.
Thanks,
Yueyi Li
Hello Yueyi,
I have a few questions about this patch.
First, can you clarify the kernel version and the dumpfile type that
you are trying to address?
I understand the confusion, given that arm64 kdump/KASLR support is still being
debated upstream. Eventually, arm64 kdump-generated dumpfiles will have
"NUMBER(kimage_voffset)" and "NUMBER(PHYS_OFFSET)" VMCOREINFO entries, which
will simplify things significantly (and you can see that the crash utility
already has support for them in advance).
Actually, i use crash utility to analysis Android device crash, Linux kernel
version is 4.4. The ramdump file is not generated by kdump, it is whole DDR
SDRAM snapshot collected by another RTOS, so i don`t have vmcoreinfo to get
kimage_voffset & phys_offset. I my opinion, only set kaslr offset should work
well even if without vmcore file and kimage_voffse, it looks more reasonable.
It seems that this patch would only be applicable when looking at an ELF
dumpfile, given that your arch_calc_kimage_voffset() function calls
arm_kdump_phys_base() -- which only applies if you are looking at an
ELF dumpfile:
+static void
+arm64_calc_kimage_voffset(void)
+{
+ struct machine_specific *ms = machdep->machspec;
+ ulong kimage_offset;
+ ulong phys_offset;
+ struct syment *sp;
+
+ if (machdep->flags & KIMG_VOFFSET) /* --machdep override */
+ return;
+
+ if ((kt->flags2 & KASLR) && (kt->flags & RELOC_SET)){
+ arm_kdump_phys_base(&phys_offset);
+ ms->kimage_voffset = ms->vmalloc_start_addr + (kt->relocate *
-1) - phys_offset;
+ }
+
+}
Is that correct? And if so, why not call arm64_kdump_phys_base() instead?
Because I see in your "error message without the patch" above, the phys_base
seems to have been calculated correctly to be 40000000, so it looks like the
call from arm64_calc_phys_offset() to arm64_kdump_phys_base() must have worked.
(since arm64_kdump_phys_base() ultimately calls arm_kdump_phys_base() if nothing
else works)
So what would happen if you called arm64_calc_phys_offset() *before* your new
function? Wouldn't it correctly determine phys_offset? And then there would
be no need for you to call it in your new function:
@@ -324,6 +325,9 @@ arm64_init(int when)
machdep->init_kernel_pgd = arm64_init_kernel_pgd;
/* use machdep parameters */
+ arm64_calc_kimage_voffset();
+
+ /* use machdep parameters */
arm64_calc_phys_offset();
When kernel ASLR is enabled on arm64, the kernel image start address
can be randomized, phys_offset is no more equal the start address of
first memory block. It means, arm_kdump_phys_base() can not calculate
correctly address, we need kimage_voffset to calculate correctly
phys_offset, this is what arm64_calc_phys_offset() to do( just on
live system & ELF ramdump). So arm64_calc_kimage_voffset() should be
called first. This is why crash utility is not work if '-m kimage_voffset'
is not given.
debug log with the patch, kaslr offset is 0x1378e00000, start address of first
memory block is 0x40000000:
readmem: read_ramdump()
VA_BITS: 39
using ffffffd340000000 as phys_offset
kimage_voffset: ffffff9340e00000
phys_offset: ffffffd340000000
gdb vmlinux
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html><http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu
--target=aarch64-elf-linux"...
cpu_possible_mask: cpus: 0 1 2 3 4 5 6 7
cpu_present_mask: cpus: 0 1 2 3 4 5 6 7
cpu_online_mask: cpus: 0 1 2 3 4 5 6
cpu_active_mask: cpus: 0 1 2 3 4 5 6
xtime timespec.tv_sec: 58c27009: Fri Mar 10 17:21:13 2017
utsname:
sysname: Linux
nodename: localhost
release: 4.4.21-perf-g5ec6736-00564-gbdc7dcf
version: #1 SMP PREEMPT Wed Mar 8 23:02:12 CST 2017
machine: aarch64
domainname: localdomain
In addition, arm64_calc_phys_offset() also tries to determine the phys_offset
value
for compressed kdump dumpfiles and live systems. If the dumpfile has been
compressed (by the makedumpfile facility), or if you are running on a live
system,
then your patch would fail to determine phys_offset. But if you were to call
arm64_calc_phys_offset() instead, it would call diskdump_phys_base() for
compressed
dumpfiles, or try to determine the phys_offset value from /proc/iomem on live
systems.
Dave
I'm not familar with compressed dumpfiles, just add a judgment in my function.
For live system, if kimage_voffset has been calculated, arm64_calc_phys_offset
will use it calculate correctly phys_offset instead of read from /proc/iomem.
if ((machdep->flags & NEW_VMEMMAP) &&
ms->kimage_voffset && (sp = kernel_symbol_search("memstart_addr")))
{
paddr = sp->value - machdep->machspec->kimage_voffset;
if (READMEM(pc->mfd, &phys_offset, sizeof(phys_offset),
sp->value, paddr) > 0) {
ms->phys_offset = phys_offset;
return;
}
}
I have attached patch v2, Could you please review it?
Thanks,
Yueyi Li
>From 10d9a7879589888c8ffe24e8245062115dc16f1e Mon Sep 17 00:00:00 2001
From: Yueyi Li <liyueyi live com>
Date: Tue, 14 Mar 2017 21:25:21 +0800
Subject: [PATCH] [ARM64][patch] Auto calculate kimage_voffset by kaslr offset
ARM64 kimage_voffset can be calculated if kernel ASLR offset is known.
Add a function to auto calculate kimage_voffset when '--kaslr=<offset>'
was set.
---
arm64.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/arm64.c b/arm64.c
index 6eaf96d..b51b826 100644
--- a/arm64.c
+++ b/arm64.c
@@ -27,6 +27,7 @@
static struct machine_specific arm64_machine_specific = { 0 };
static int arm64_verify_symbol(const char *, ulong, char);
static void arm64_parse_cmdline_args(void);
+static void arm64_calc_kimage_voffset(void);
static void arm64_calc_phys_offset(void);
static void arm64_calc_virtual_memory_ranges(void);
static int arm64_kdump_phys_base(ulong *);
@@ -324,6 +325,9 @@ arm64_init(int when)
machdep->init_kernel_pgd = arm64_init_kernel_pgd;
/* use machdep parameters */
+ arm64_calc_kimage_voffset();
+
+ /* use machdep parameters */
arm64_calc_phys_offset();
if (CRASHDEBUG(1)) {
@@ -735,6 +739,23 @@ arm64_parse_cmdline_args(void)
}
}
+static void
+arm64_calc_kimage_voffset(void)
+{
+ struct machine_specific *ms = machdep->machspec;
+ ulong phys_offset;
+
+ if (ms->kimage_voffset) /* vmcoreinfo or --machdep override */
+ return;
+
+ if (DISKDUMP_DUMPFILE())
+ return;
+ else if ((kt->flags2 & KASLR) && (kt->flags & RELOC_SET)){
+ arm_kdump_phys_base(&phys_offset); /*get start address of
first memory block*/
+ ms->kimage_voffset = ms->vmalloc_start_addr + (kt->relocate *
-1) - phys_offset;
+ }
+
+}
In addition to DISKUMP_DUMPFILE(), it also needs to return on live systems
and any other dumpfile type. I need to see your pc->flags and pc->flags2
settings to see how your dumpfile is recognized -- what do you see when you
run this command against your RAM dump?:
crash> help -p | grep -A3 " flags:" | head -3
flags: 1010000210c06
(RUNTIME|TTY|HASH|SCROLL|GDB_INIT|READLINE|KDUMP|DATADEBUG)
flags2: 100400 (VMCOREINFO|REDZONE)
crash>
Thanks,
Dave
--
Crash-utility mailing list
[email protected]<mailto:[email protected]>
https://www.redhat.com/mailman/listinfo/crash-utility
Here is my pc->flags and pc->flags2:
crash> help -p | grep -A3 " flags:" | head -3
flags: 1010000210c06
(RUNTIME|TTY|HASH|SCROLL|GDB_INIT|READLINE|KDUMP|DATADEBUG)
flags2: 102000 (RAMDUMP|REDZONE)
On kaslr enabled live system,
cat /proc/iomem:
40000000-857fffff : System RAM
40080000-419fffff : Kernel code
42400000-42b2bfff : Kernel data
88f00000-8aafffff : System RAM
95100000-1bd7bffff : System RAM
dmesg |grep memory:
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] memory : 0xffffffd200000000 - 0xffffffd37d7c0000 ( 6103
MB)
Seems kimage_voffset also need re-calculate on live system. I have attached
patch v3 and full log.
Thanks,
Yueyi Li
From 13de0512b5aff94bde8e45204e9bc2dcb681c515 Mon Sep 17 00:00:00 2001 From: Yueyi Li <[email protected]> Date: Tue, 14 Mar 2017 21:25:21 +0800 Subject: [PATCH] [ARM64][patch] Auto calculate kimage_voffset by kaslr offset ARM64 kimage_voffset can be calculated if kernel ASLR offset is known. Add a function to auto calculate kimage_voffset when '--kaslr=<offset>' was set. --- arm64.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/arm64.c b/arm64.c index 6eaf96d..9ff9428 100644 --- a/arm64.c +++ b/arm64.c @@ -27,6 +27,7 @@ static struct machine_specific arm64_machine_specific = { 0 }; static int arm64_verify_symbol(const char *, ulong, char); static void arm64_parse_cmdline_args(void); +static void arm64_calc_kimage_voffset(void); static void arm64_calc_phys_offset(void); static void arm64_calc_virtual_memory_ranges(void); static int arm64_kdump_phys_base(ulong *); @@ -324,6 +325,9 @@ arm64_init(int when) machdep->init_kernel_pgd = arm64_init_kernel_pgd; /* use machdep parameters */ + arm64_calc_kimage_voffset(); + + /* use machdep parameters */ arm64_calc_phys_offset(); if (CRASHDEBUG(1)) { @@ -735,6 +739,68 @@ arm64_parse_cmdline_args(void) } } +static void +arm64_calc_kimage_voffset(void) +{ + struct machine_specific *ms = machdep->machspec; + ulong phys_offset; + + if (ms->kimage_voffset) /* vmcoreinfo or --machdep override */ + return; + + if (!(kt->flags2 & KASLR) || !(kt->flags & RELOC_SET)) /*Calculate kiamge_voffset when KASLR enabled.*/ + return; + + if(ACTIVE()){ + char buf[BUFSIZE]; + char *p1; + int errflag; + FILE *iomem; + + if ((iomem = fopen("/proc/iomem", "r")) == NULL) + return; + + /* + * Memory regions are sorted in ascending order. We take the + * first region which should be correct for most uses. + */ + errflag = 1; + while (fgets(buf, BUFSIZE, iomem)) { + if (strstr(buf, ": System RAM")) { + clean_line(buf); + errflag = 0; + break; + } + } + fclose(iomem); + + if (errflag) + return; + + if (!(p1 = strstr(buf, "-"))) + return; + + *p1 = NULLCHAR; + + phys_offset = htol(buf, RETURN_ON_ERROR | QUIET, &errflag); + if (errflag) + return; + }else if (DISKDUMP_DUMPFILE()) + return; + else if (KDUMP_DUMPFILE()) + arm_kdump_phys_base(&phys_offset); /*Get start address of first memory block*/ + else{ + error(WARNING, + "kimage_voffset cannot be determined from the dumpfile.\n"); + error(CONT, + "Using default value of 0. If this is not correct, then try\n"); + error(CONT, + "using the command line option: --machdep kimage_voffset=<addr>\n"); + return; + } + + ms->kimage_voffset = ms->vmalloc_start_addr + (kt->relocate * -1) - phys_offset; +} static void arm64_calc_phys_offset(void) -- 1.9.1
crash
DDRCS0_0.BIN@0x40000000,DDRCS0_1.BIN@0xc0000000,DDRCS1_0.BIN@0x100000000,DDRCS1_1.BIN@0x180000000
vmlinux --kaslr 0x1378e00000 -d 1
crash 7.1.8++
Copyright (C) 2002-2016 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.
creating temporary ELF header: /var/tmp/ramdump_elf_B86djh
vmcore_data:
flags: c0 (KDUMP_LOCAL|KDUMP_ELF64)
ndfd: 7
ofp: 7f51b404f400
header_size: 344
num_pt_load_segments: 4
pt_load_segment[0]:
file_offset: 158
phys_start: 40000000
phys_end: c0000000
zero_fill: 0
pt_load_segment[1]:
file_offset: 80000158
phys_start: c0000000
phys_end: 100000000
zero_fill: 0
pt_load_segment[2]:
file_offset: c0000158
phys_start: 100000000
phys_end: 180000000
zero_fill: 0
pt_load_segment[3]:
file_offset: 140000158
phys_start: 180000000
phys_end: 1c0000000
zero_fill: 0
elf_header: ef50e0
elf32: 0
notes32: 0
load32: 0
elf64: ef50e0
notes64: ef5120
load64: ef5158
nt_prstatus: 0
nt_prpsinfo: 0
nt_taskstruct: 0
task_struct: 0
page_size: 0
switch_stack: 0
xen_kdump_data: (unused)
num_prstatus_notes: 0
num_qemu_notes: 0
vmcoreinfo: 0
size_vmcoreinfo: 0
nt_prstatus_percpu:
nt_qemu_percpu:
backup_src_start: 0
backup_src_size: 0
backup_offset: 0
Elf64_Ehdr:
e_ident: \177ELF
e_ident[EI_CLASS]: 2 (ELFCLASS64)
e_ident[EI_DATA]: 1 (ELFDATA2LSB)
e_ident[EI_VERSION]: 1 (EV_CURRENT)
e_ident[EI_OSABI]: 3 (ELFOSABI_LINUX)
e_ident[EI_ABIVERSION]: 0
e_type: 4 (ET_CORE)
e_machine: 183 (EM_AARCH64)
e_version: 1 (EV_CURRENT)
e_entry: 0
e_phoff: 40
e_shoff: 0
e_flags: 0
e_ehsize: 40
e_phentsize: 38
e_phnum: 5
e_shentsize: 0
e_shnum: 0
e_shstrndx: 0
Elf64_Phdr:
p_type: 4 (PT_NOTE)
p_offset: 344 (158)
p_vaddr: 0
p_paddr: 0
p_filesz: 0 (0)
p_memsz: 0 (0)
p_flags: 0 ()
p_align: 0
Elf64_Phdr:
p_type: 1 (PT_LOAD)
p_offset: 344 (158)
p_vaddr: 0
p_paddr: 40000000
p_filesz: 2147483648 (80000000)
p_memsz: 2147483648 (80000000)
p_flags: 7 (PF_X|PF_W|PF_R)
p_align: 0
Elf64_Phdr:
p_type: 1 (PT_LOAD)
p_offset: 2147483992 (80000158)
p_vaddr: 0
p_paddr: c0000000
p_filesz: 1073741824 (40000000)
p_memsz: 1073741824 (40000000)
p_flags: 7 (PF_X|PF_W|PF_R)
p_align: 0
Elf64_Phdr:
p_type: 1 (PT_LOAD)
p_offset: 3221225816 (c0000158)
p_vaddr: 0
p_paddr: 100000000
p_filesz: 2147483648 (80000000)
p_memsz: 2147483648 (80000000)
p_flags: 7 (PF_X|PF_W|PF_R)
p_align: 0
Elf64_Phdr:
p_type: 1 (PT_LOAD)
p_offset: 5368709464 (140000158)
p_vaddr: 0
p_paddr: 180000000
p_filesz: 1073741824 (40000000)
p_memsz: 1073741824 (40000000)
p_flags: 7 (PF_X|PF_W|PF_R)
p_align: 0
ramdump data:
user_elf: (unused)
elf_default: /var/tmp/ramdump_elf_B86djh
nodes: 4
ramdump[0]:
path: DDRCS0_0.BIN
rfd: 3
start_paddr: 40000000
end_paddr: bfffffff
ramdump[1]:
path: DDRCS0_1.BIN
rfd: 4
start_paddr: c0000000
end_paddr: ffffffff
ramdump[2]:
path: DDRCS1_0.BIN
rfd: 5
start_paddr: 100000000
end_paddr: 17fffffff
ramdump[3]:
path: DDRCS1_1.BIN
rfd: 6
start_paddr: 180000000
end_paddr: 1bfffffff
readmem: read_ramdump()
VA_BITS: 39
using ffffffd340000000 as phys_offset
kimage_voffset: ffffff9340e00000
phys_offset: ffffffd340000000
gdb vmlinux
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu
--target=aarch64-elf-linux"...
cpu_possible_mask: cpus: 0 1 2 3 4 5 6 7
cpu_present_mask: cpus: 0 1 2 3 4 5 6 7
cpu_online_mask: cpus: 0 1 2 3 4 5 6
cpu_active_mask: cpus: 0 1 2 3 4 5 6
xtime timespec.tv_sec: 58c27009: Fri Mar 10 17:21:13 2017
utsname:
sysname: Linux
nodename: localhost
release: 4.4.21-perf-g5ec6736-00564-gbdc7dcf
version: #1 SMP PREEMPT Wed Mar 8 23:02:12 CST 2017
machine: aarch64
domainname: localdomain
base kernel version: 4.4.21
verify_namelist:
dumpfile /proc/version:
Linux version 4.4.21-perf-g5ec6736-00564-gbdc7dcf (builder@miphone-bsp-228-50)
(gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Mar 8
23:02:12 CST 2017
vmlinux:
Linux version 4.4.21-perf-g5ec6736-00564-gbdc7dcf (builder@miphone-bsp-228-50)
(gcc version 4.9 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Wed Mar 8
23:02:12 CST 2017
crash: get_cpus_present: present: 8
hypervisor: (undetermined)
crash: per_cpu_symbol_search(timer_bases): NULL
irq_stack:
type: TYPE_CODE_ARRAY
target_typecode: TYPE_CODE_INT
target_length: 8
length: 16384
kernel NR_CPUS: 8
PAGESIZE=4096
mem_section_size = 8192
NR_SECTION_ROOTS = 1024
NR_MEM_SECTIONS = 262144
SECTIONS_PER_ROOT = 256
SECTION_ROOT_MASK = 0xff
PAGES_PER_SECTION = 262144
node_online_map: [1] -> nodes online: 1
node_table[0]:
id: 0
pgdat: ffffff93833cb400
size: 1562560
present: 1505984
mem_map: ffffffbe74000000
start_paddr: 40000000
start_mapnr: 262144
NOTE: page_hash_table does not exist in this kernel
please wait... (gathering kmem slab cache data)
kmem_cache_downsize: 200 to 200
pageflags from pageflag_names:
00000001 locked
00000002 error
00000004 referenced
00000008 uptodate
00000010 dirty
00000020 lru
00000040 active
00000080 slab
00000100 owner_priv_1
00000200 arch_1
00000400 reserved
00000800 private
00001000 private_2
00002000 writeback
00004000 head
00008000 swapcache
00010000 mappedtodisk
00020000 reclaim
00040000 swapbacked
00080000 unevictable
00100000 mlocked
WARNING: cannot retrieve registers for active tasks
crash: get_cpus_online: online: 7
crash: cpus: 8 online: 7 NT_PRSTATUS notes: 0 (remapping)
please wait... (determining panic task)
crash: get_netdump_panic_task: failed
crash: get_active_set_panic_task: failed
WARNING: cannot determine starting stack frame for task ffffff9383215940
WARNING: cannot determine starting stack frame for task ffffffee762e8000
WARNING: cannot determine starting stack frame for task ffffffee762e8c80
WARNING: cannot determine starting stack frame for task ffffffee762e9900
WARNING: cannot determine starting stack frame for task ffffffee762ea580
WARNING: cannot determine starting stack frame for task ffffffee762eb200
WARNING: cannot determine starting stack frame for task ffffffee762ebe80
WARNING: cannot determine starting stack frame for task ffffffee762ecb00
foreach: panic_search: failed (via foreach bt)
foreach: get_panic_context: panic task not found
KERNEL: vmlinux
DUMPFILES: /var/tmp/ramdump_elf_B86djh [temporary ELF header]
DDRCS0_0.BIN
DDRCS0_1.BIN
DDRCS1_0.BIN
DDRCS1_1.BIN
CPUS: 8foreach: get_cpus_online: online: 7
foreach: get_cpus_online: online: 7
[OFFLINE: 1]
DATE: Fri Mar 10 17:21:13 2017
UPTIME: 21:28:15
LOAD AVERAGE: 104.22, 105.23, 104.94
TASKS: 3670
NODENAME: localhost
RELEASE: 4.4.21-perf-g5ec6736-00564-gbdc7dcf
VERSION: #1 SMP PREEMPT Wed Mar 8 23:02:12 CST 2017
MACHINE: aarch64 (unknown Mhz)
MEMORY: 5.7 GB
PANIC: ""
PID: 0
COMMAND: "swapper/0"
TASK: ffffff9383215940 (1 of 8) [THREAD_INFO: ffffff9383200000]
CPU: 0
STATE: TASK_RUNNING (ACTIVE)
WARNING: panic task not found
crash>
-- Crash-utility mailing list [email protected] https://www.redhat.com/mailman/listinfo/crash-utility
