mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
Fix bug in exception table allocation (PR13678)
Patch by Michael Muller. llvm-svn: 172214
This commit is contained in:
parent
f3a7087194
commit
738fbca845
@ -969,14 +969,24 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
||||
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;
|
||||
|
@ -161,7 +161,7 @@ public:
|
||||
uintptr_t ActualSizeResult;
|
||||
};
|
||||
std::vector<StartExceptionTableCall> startExceptionTableCalls;
|
||||
virtual uint8_t* startExceptionTable(const Function* F,
|
||||
virtual uint8_t *startExceptionTable(const Function *F,
|
||||
uintptr_t &ActualSize) {
|
||||
uintptr_t InitialActualSize = ActualSize;
|
||||
uint8_t *Result = Base->startExceptionTable(F, ActualSize);
|
||||
@ -203,14 +203,21 @@ bool LoadAssemblyInto(Module *M, const char *assembly) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -297,6 +304,46 @@ TEST(JIT, GlobalInFunction) {
|
||||
|
||||
#endif // !defined(__arm__) && !defined(__powerpc__)
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user