[llvm-commits] Fwd: Re: [LLVMdev] [PATCH] Fix for bug in JIT exception table allocation

Michael Muller mmuller at enduden.com
Thu Sep 13 10:26:52 PDT 2012


Thanks, Duncan -

> Hi Michael,
> 
> > --- lib/ExecutionEngine/JIT/JITEmitter.cpp  (revision 163478)
> > +++ lib/ExecutionEngine/JIT/JITEmitter.cpp  (working copy)
> > @@ -974,14 +974,24 @@
> >      SavedBufferBegin = BufferBegin;
> >      SavedBufferEnd = BufferEnd;
> >      SavedCurBufferPtr = CurBufferPtr;
> > +    uint8_t *FrameRegister;
> >
> > -    BufferBegin = CurBufferPtr =
> > MemMgr->startExceptionTable(F.getFunction(),
> > -                                                             ActualSize);
> > -    BufferEnd = BufferBegin+ActualSize;
> > -    EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
> > -    uint8_t *EhStart;
> > -    uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd,
> > -                                                EhStart);
> > +    while (true) {
> > +      BufferBegin = CurBufferPtr =
> > MemMgr->startExceptionTable(F.getFunction(),
> > +
> > ActualSize);
> > +      BufferEnd = BufferBegin+ActualSize;
> > +      EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
> > +      uint8_t *EhStart;
> > +      FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd,
> > EhStart);
> > +
> > +      // If we've run out of memory, try again with twice as much space.
> > +      if (CurBufferPtr == BufferEnd) {
> > +        ActualSize = (CurBufferPtr-BufferBegin)*2;
> > +        MemMgr->deallocateExceptionTable(BufferBegin);
> > +      } else {
> > +        break;
> > +      }
> 
> here I think it would be more conformant with LLVM style to do:
> 
>         // If the buffer was large enough to hold the table then we are
>         done.
>         if (CurBufferPtr != BufferEnd)
>           break;
> 
>         // Try again with twice as much space.
>         ActualSize = (CurBufferPtr-BufferBegin)*2;
>         MemMgr->deallocateExceptionTable(BufferBegin);

Done.  New patch attached.

> 
> Otherwise looks good to me, though that's not saying much since I don't know
> this part of LLVM.


It looks like that code segment has been touched by a number of people:


  147615     rafael   if (JITExceptionHandling) {
   49924   geoffray     uintptr_t ActualSize = 0;
   91464   jyasskin     SavedBufferBegin = BufferBegin;
   91464   jyasskin     SavedBufferEnd = BufferEnd;
   91464   jyasskin     SavedCurBufferPtr = CurBufferPtr;
   82418        rnk 
   47079   geoffray     BufferBegin = CurBufferPtr =
  MemMgr->startExceptionTable(F.getFunction(),
   47079   geoffray
  ActualSize);
   47079   geoffray     BufferEnd = BufferBegin+ActualSize;
   84651   jyasskin     EmittedFunctions[F.getFunction()].ExceptionTable =
  BufferBegin;
   82418        rnk     uint8_t *EhStart;
   82418        rnk     uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this,
  FnStart, FnEnd,
   82418        rnk                                                 EhStart);
   48019    lattner     MemMgr->endExceptionTable(F.getFunction(), BufferBegin,
  CurBufferPtr,
   48019    lattner                               FrameRegister);
   91464   jyasskin     BufferBegin = SavedBufferBegin;
   91464   jyasskin     BufferEnd = SavedBufferEnd;
   91464   jyasskin     CurBufferPtr = SavedCurBufferPtr;
   47079   geoffray 
  102865   baldrick     if (JITExceptionHandling) {
  127047   echristo       TheJIT->RegisterTable(F.getFunction(), FrameRegister);
   82418        rnk     }
   47079   geoffray   }

Any suggestions as to who would be the best qualified to look at it?


> 
> Ciao, Duncan.
> 
> > +    }
> >      MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
> >                                FrameRegister);
> >      BufferBegin = SavedBufferBegin;


=============================================================================
michaelMuller = mmuller at enduden.com | http://www.mindhog.net/~mmuller
-----------------------------------------------------------------------------
Government is not reason, it is not eloquence; it is force.  Like fire, it
is a dangerous servant and a fearsome master.  - George Washington
=============================================================================
-------------- next part --------------
Index: unittests/ExecutionEngine/JIT/JITTest.cpp
===================================================================
--- unittests/ExecutionEngine/JIT/JITTest.cpp	(revision 163809)
+++ unittests/ExecutionEngine/JIT/JITTest.cpp	(working copy)
@@ -203,14 +203,21 @@
 
 class JITTest : public testing::Test {
  protected:
+  virtual RecordingJITMemoryManager* CreateMemoryManager() {
+    return new RecordingJITMemoryManager;
+  }
+
   virtual void SetUp() {
     M = new Module("<main>", Context);
-    RJMM = new RecordingJITMemoryManager;
+    RJMM = CreateMemoryManager();
     RJMM->setPoisonMemory(true);
     std::string Error;
+    TargetOptions Options;
+    Options.JITExceptionHandling = true;
     TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
                  .setJITMemoryManager(RJMM)
-                 .setErrorStr(&Error).create());
+                 .setErrorStr(&Error)
+                 .setTargetOptions(Options).create());
     ASSERT_TRUE(TheJIT.get() != NULL) << Error;
   }
 
@@ -292,6 +299,46 @@
   EXPECT_EQ(3, *GPtr);
 }
 
+// Regression test for a bug.  The JITEmitter wasn't checking to verify that
+// it hadn't run out of space while generating the DWARF exception information
+// for an emitted function.
+
+class ExceptionMemoryManagerMock : public RecordingJITMemoryManager {
+ public:
+  virtual uint8_t* startExceptionTable(const Function* F,
+                                       uintptr_t &ActualSize) {
+    // force an insufficient size the first time through.
+    bool ChangeActualSize = false;
+    if (ActualSize == 0)
+      ChangeActualSize = true;;
+    uint8_t* result =
+      RecordingJITMemoryManager::startExceptionTable(F, ActualSize);
+    if (ChangeActualSize)
+      ActualSize = 1;
+    return result;
+  }
+};
+
+class JITExceptionMemoryTest : public JITTest {
+ protected:
+  virtual RecordingJITMemoryManager* CreateMemoryManager() {
+    return new ExceptionMemoryManagerMock;
+  }
+};
+
+TEST_F(JITExceptionMemoryTest, ExceptionTableOverflow) {
+  Function *F = Function::Create(TypeBuilder<void(void), false>::get(Context),
+                                 Function::ExternalLinkage,
+                                 "func1", M);
+  BasicBlock *Block = BasicBlock::Create(Context, "block", F);
+  IRBuilder<> Builder(Block);
+  Builder.CreateRetVoid();
+  TheJIT->getPointerToFunction(F);
+  ASSERT_TRUE(RJMM->startExceptionTableCalls.size() == 2);
+  ASSERT_TRUE(RJMM->deallocateExceptionTableCalls.size() == 1);
+  ASSERT_TRUE(RJMM->endExceptionTableCalls.size() == 1);
+}
+
 int PlusOne(int arg) {
   return arg + 1;
 }
Index: lib/ExecutionEngine/JIT/JITEmitter.cpp
===================================================================
--- lib/ExecutionEngine/JIT/JITEmitter.cpp	(revision 163809)
+++ lib/ExecutionEngine/JIT/JITEmitter.cpp	(working copy)
@@ -974,14 +974,24 @@
     SavedBufferBegin = BufferBegin;
     SavedBufferEnd = BufferEnd;
     SavedCurBufferPtr = CurBufferPtr;
+    uint8_t *FrameRegister;
 
-    BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
-                                                             ActualSize);
-    BufferEnd = BufferBegin+ActualSize;
-    EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
-    uint8_t *EhStart;
-    uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd,
-                                                EhStart);
+    while (true) {
+      BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
+                                                              ActualSize);
+      BufferEnd = BufferBegin+ActualSize;
+      EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
+      uint8_t *EhStart;
+      FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, EhStart);
+
+      // If the buffer was large enough to hold the table then we are done.
+      if (CurBufferPtr != BufferEnd)
+        break;
+
+      // Try again with twice as much space.
+      ActualSize = (CurBufferPtr-BufferBegin)*2;
+      MemMgr->deallocateExceptionTable(BufferBegin);
+    }
     MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
                               FrameRegister);
     BufferBegin = SavedBufferBegin;


More information about the llvm-commits mailing list