From e25004764456e20d8121f9ccc105fb7d408f1948 Mon Sep 17 00:00:00 2001 From: Yueyi Li 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=' was set. --- arm64.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/arm64.c b/arm64.c index 6eaf96d..01e43e5 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,83 @@ arm64_parse_cmdline_args(void) } } +static void +arm64_calc_kimage_voffset(void) +{ + struct machine_specific *ms = machdep->machspec; + ulong 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; + ulong kernel_code_range; + ulong memory_end; + ulong memory_start; + + if ((iomem = fopen("/proc/iomem", "r")) == NULL) + return; + + kernel_code_range = symbol_value("__init_begin") - symbol_value("_text"); + + errflag = 1; + while (fgets(buf, BUFSIZE, iomem)) { + if (strstr(buf, ": System RAM")) { + clean_line(buf); + + /*get end address of system ram region*/ + if (!(p1 = strstr(buf, ":"))) + continue; + *(p1-1) = NULLCHAR; + if (!(p1 = strstr(buf, "-"))) + continue; + memory_end = htol(p1+1, RETURN_ON_ERROR | QUIET, NULL); + if (BADADDR == memory_end) + continue; + + /*get start address of system ram region*/ + *p1 = NULLCHAR; + memory_start = htol(buf, RETURN_ON_ERROR | QUIET, NULL); + if (BADADDR == memory_start) + continue; + + /* system ram region is too small to load kernel code, find next region*/ + if((memory_end - memory_start) < kernel_code_range) + continue; + + errflag = 0; + break; + } + } + fclose(iomem); + + if (errflag) + return; + + offset = memory_start; + }else if (DISKDUMP_DUMPFILE()) + return; + else if (KDUMP_DUMPFILE()) + arm_kdump_phys_base(&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=\n"); + return; + } + + ms->kimage_voffset = ms->vmalloc_start_addr + (kt->relocate * -1) - offset; +} static void arm64_calc_phys_offset(void) @@ -817,6 +898,7 @@ arm64_calc_phys_offset(void) } + /* * Determine PHYS_OFFSET either by reading VMCOREINFO or the kernel * symbol, otherwise borrow the 32-bit ARM functionality. -- 1.9.1