]> xenbits.xensource.com Git - people/wipawel/livepatch-build-tools/commitdiff
Backport "handle reference to end of section"
authorRoss Lagerwall <ross.lagerwall@citrix.com>
Tue, 17 Nov 2015 08:06:41 +0000 (08:06 +0000)
committerRoss Lagerwall <ross.lagerwall@citrix.com>
Wed, 20 Jan 2016 13:48:25 +0000 (13:48 +0000)
Backport fffbb85b811e21d92f4517e78ead5fb3373185e6:
    create-diff-object: handle reference to end of section
from upstream.

Also edit it to work with Xen's code because it is compiled with -fpic.

create-diff-object.c

index 686834fb54c15efbafc273690bfd606f9dd471ae..6153e7b495cf0e3c3ccfb691daa6a17335ec6bc4 100644 (file)
@@ -174,8 +174,47 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
                                start = sym->sym.st_value;
                                end = sym->sym.st_value + sym->sym.st_size;
 
-                               if (rela->addend + add_off < start ||
-                                   rela->addend + add_off >= end)
+                               if (!is_text_section(sym->sec) &&
+                                   (rela->type == R_X86_64_32S ||
+                                    rela->type == R_X86_64_PC32 ||
+                                    rela->type == R_X86_64_PLT32) &&
+                                   (rela->addend + add_off) == sym->sec->sh.sh_size &&
+                                   end == sym->sec->sh.sh_size) {
+
+                                       /*
+                                        * A special case where gcc needs a
+                                        * pointer to the address at the end of
+                                        * a data section.
+                                        *
+                                        * This is usually used with a compare
+                                        * instruction to determine when to end
+                                        * a loop.  The code doesn't actually
+                                        * dereference the pointer so this is
+                                        * "normal" and we just replace the
+                                        * section reference with a reference
+                                        * to the last symbol in the section.
+                                        *
+                                        * Note that this only catches the
+                                        * issue when it happens at the end of
+                                        * a section.  It can also happen in
+                                        * the middle of a section.  In that
+                                        * case, the wrong symbol will be
+                                        * associated with the reference.  But
+                                        * that's ok because:
+                                        *
+                                        * 1) This situation only occurs when
+                                        *    gcc is trying to get the address
+                                        *    of the symbol, not the contents
+                                        *    of its data; and
+                                        *
+                                        * 2) Because kpatch doesn't allow data
+                                        *    sections to change,
+                                        *    &(var1+sizeof(var1)) will always
+                                        *    be the same as &var2.
+                                        */
+
+                               } else if (rela->addend + add_off < start ||
+                                          rela->addend + add_off >= end)
                                        continue;
 
                                log_debug("%s: replacing %s+%d reference with %s+%d\n",