From: Petr Tesarik <ptesarik@suse.com>
Date: Fri Aug 28 11:04:58 2015 +0200
Subject: Use kernel config to check if a kernel is relocatable
References: bsc#941088
Git-commit 9ed2a1d91d332ea20a876bd4d05c1804947caeaa
Patch-mainline: v0.8.16

The ELF type is apparently always EXEC, regardless of whether
the kernel was compiled with CONFIG_RELOCATABLE=y, or not. So,
it is necessary to check the actual configuration.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>

diff --git a/kdumptool/kerneltool.cc b/kdumptool/kerneltool.cc
index a85b112..5d463ac 100644
--- a/kdumptool/kerneltool.cc
+++ b/kdumptool/kerneltool.cc
@@ -340,8 +340,8 @@ bool KernelTool::elfIsRelocatable() const
         throw KSystemError("Seek failed", errno);
     }
 
+    unsigned short machine;
     string arch;
-    bool reloc = false;
     if (e_ident[EI_CLASS] == ELFCLASS32) {
         Elf32_Ehdr hdr;
 
@@ -351,7 +351,6 @@ bool KernelTool::elfIsRelocatable() const
             throw KSystemError("Couldn't read ELF header", errno);
         }
 
-	unsigned short machine;
 	if (e_ident[EI_DATA] == ELFDATA2LSB)
 	    machine = le16toh(hdr.e_machine);
 	else if (e_ident[EI_DATA] == ELFDATA2MSB)
@@ -359,10 +358,6 @@ bool KernelTool::elfIsRelocatable() const
 	else
 	    throw KError("elfIsRelocatable(): Invalid ELF data encoding");
 
-        arch = archFromElfMachine(machine);
-
-        if (hdr.e_type == ET_DYN)
-            reloc = true;
     } else if (e_ident[EI_CLASS] == ELFCLASS64) {
         Elf64_Ehdr hdr;
 
@@ -372,27 +367,23 @@ bool KernelTool::elfIsRelocatable() const
             throw KSystemError("Couldn't read ELF header", errno);
         }
 
-        if (hdr.e_type == ET_DYN)
-            reloc = true;
-
-	unsigned short machine;
 	if (e_ident[EI_DATA] == ELFDATA2LSB)
 	    machine = le16toh(hdr.e_machine);
 	else if (e_ident[EI_DATA] == ELFDATA2MSB)
 	    machine = be16toh(hdr.e_machine);
 	else
 	    throw KError("elfIsRelocatable(): Invalid ELF data encoding");
-
-        arch = archFromElfMachine(machine);
     } else {
         throw KError("elfIsRelocatable(): Invalid ELF class");
     }
+    arch = archFromElfMachine(machine);
 
     gzclose(fp);
 
     Debug::debug()->dbg("Detected arch %s", arch.c_str());
 
-    return isArchAlwaysRelocatable(arch) || reloc;
+    return isArchAlwaysRelocatable(arch) ||
+      (hasConfigRelocatable(arch) && isConfigRelocatable());
 }
 
 // -----------------------------------------------------------------------------
@@ -403,6 +394,28 @@ bool KernelTool::isArchAlwaysRelocatable(const string &machine) const
 }
 
 // -----------------------------------------------------------------------------
+bool KernelTool::hasConfigRelocatable(const string &machine) const
+    throw ()
+{
+    return Util::isX86(machine) || machine == "ppc64" || machine == "ppc";
+}
+
+// -----------------------------------------------------------------------------
+bool KernelTool::isConfigRelocatable() const
+    throw (KError)
+{
+    try {
+    Kconfig *kconfig = retrieveKernelConfig();
+    KconfigValue kv = kconfig->get("CONFIG_RELOCATABLE");
+    return (kv.getType() == KconfigValue::T_TRISTATE &&
+	    kv.getTristateValue() == KconfigValue::ON);
+    } catch (KError &e) {
+	Debug::debug()->dbg("%s (assume non-relocatable)", e.what());
+	return false;
+    }
+}
+
+// -----------------------------------------------------------------------------
 string KernelTool::archFromElfMachine(unsigned long long et_machine) const
     throw ()
 {
diff --git a/kdumptool/kerneltool.h b/kdumptool/kerneltool.h
index 33e6c14..acf2aaf 100644
--- a/kdumptool/kerneltool.h
+++ b/kdumptool/kerneltool.h
@@ -163,6 +163,26 @@ class KernelTool {
         throw ();
 
         /**
+         * Checks if the architecture has CONFIG_RELOCATABLE.
+         *
+         * @param[in] machine the machine, e.g. "ppc64"
+         * @return @c true if it has CONFIG_RELOCATABLE option.
+         *         @c false otherwise
+         */
+        bool hasConfigRelocatable(const std::string &machine) const
+        throw ();
+
+        /**
+         * Checks if the kernel was compiled with CONFIG_RELOCATABLE.
+         *
+         * @param[in] machine the machine, e.g. "ppc64"
+         * @return @c true if configured with CONFIG_RELOCATABLE=y.
+         *         @c false otherwise
+         */
+        bool isConfigRelocatable() const
+        throw (KError);
+
+        /**
          * Checks if a ELF kernel image is relocatable.
          *
          * @return @c true if the ELF kernel is relocatable, @c false otherwise
