Respect Addend when processing MCJIT relocations to local/global symbols.
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 5 Apr 2013 13:29:04 +0000 (13:29 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 5 Apr 2013 13:29:04 +0000 (13:29 +0000)
When the RuntimeDyldELF::processRelocationRef routine finds the target
symbol of a relocation in the local or global symbol table, it performs
a section-relative relocation:

    Value.SectionID = lsi->second.first;
    Value.Addend = lsi->second.second;

At this point, however, any Addend that might have been specified in
the original relocation record is lost.  This is somewhat difficult to
trigger for relocations within the code section since they usually
do not contain non-zero Addends (when built with the default JIT code
model, in any case).  However, the problem can be reliably triggered
by a relocation within the data section caused by code like:

 int test[2] = { -1, 0 };
 int *p = &test[1];

The initializer of "p" will need a relocation to "test + 4".  On
platforms using RelA relocations this means an Addend of 4 is required.
Current code ignores this addend when processing the relocation,
resulting in incorrect execution.

Fixed by taking the Addend into account when processing relocations
to symbols found in the local or global symbol table.

Tested on x86_64-linux and powerpc64-linux.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178869 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
test/ExecutionEngine/MCJIT/2013-04-04-RelocAddend.ll [new file with mode: 0644]

index b8537b1f2f9c20bb3559560910ff64ab01dd4f40..0b23b2bdb4b475648641500a1981354fd3bdb5bf 100644 (file)
@@ -617,14 +617,14 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
   Symbol.getType(SymType);
   if (lsi != Symbols.end()) {
     Value.SectionID = lsi->second.first;
-    Value.Addend = lsi->second.second;
+    Value.Addend = lsi->second.second + Addend;
   } else {
     // Search for the symbol in the global symbol table
     SymbolTableMap::const_iterator gsi =
         GlobalSymbolTable.find(TargetName.data());
     if (gsi != GlobalSymbolTable.end()) {
       Value.SectionID = gsi->second.first;
-      Value.Addend = gsi->second.second;
+      Value.Addend = gsi->second.second + Addend;
     } else {
       switch (SymType) {
         case SymbolRef::ST_Debug: {
diff --git a/test/ExecutionEngine/MCJIT/2013-04-04-RelocAddend.ll b/test/ExecutionEngine/MCJIT/2013-04-04-RelocAddend.ll
new file mode 100644 (file)
index 0000000..3f402c5
--- /dev/null
@@ -0,0 +1,25 @@
+; RUN: %lli_mcjit %s
+;
+; Verify relocations to global symbols with addend work correctly.
+;
+; Compiled from this C code:
+;
+; int test[2] = { -1, 0 };
+; int *p = &test[1];
+; 
+; int main (void)
+; {
+;   return *p;
+; }
+; 
+
+@test = global [2 x i32] [i32 -1, i32 0], align 4
+@p = global i32* getelementptr inbounds ([2 x i32]* @test, i64 0, i64 1), align 8
+
+define i32 @main() {
+entry:
+  %0 = load i32** @p, align 8
+  %1 = load i32* %0, align 4
+  ret i32 %1
+}
+