[llvm-commits] [llvm] r58673 - in /llvm/trunk: include/llvm/CodeGen/Passes.h lib/CodeGen/LLVMTargetMachine.cpp lib/CodeGen/StackProtector.cpp

Chris Lattner clattner at apple.com
Thu Nov 6 10:35:25 PST 2008


On Nov 4, 2008, at 11:40 AM, Bill Wendling wrote:
>>> @@ -165,6 +170,8 @@
>>>  if (!Fast)
>>>    PM.add(createCodeGenPreparePass(getTargetLowering()));
>>>
>>> +  PM.add(createStackProtectorPass(EnableStackProtector));
>>
>> Why do you add the pass even when it is not enabled?  Have you looked
>> at whether adding this pass ends up breaking analysis chains, and
>> requiring them to be run multiple times?  For example, does  
>> dominators
>> end up being run more frequently with this?  If so, the pass should
>> update dominators instead of invalidating it.
>>
> Okay. No. Don't know.

Can you check?  Just pass -debug-pass=Structure to llc with and  
without the pass.

>>> +// random value in it is stored onto the stack before the local
>>> variables are
>>> +// allocated. Upon exitting the block, the stored value is checked.
>>> If it's
>>
>> typo exiting.
>>
>>> +// Enable stack protectors.
>>> +static cl::opt<unsigned>
>>> +SSPBufferSize("ssp-buffer-size", cl::init(8),
>>> +              cl::desc("The lower bound for a buffer to be
>>> considered for "
>>> +                       "stack smashing protection."));
>>
>> why the contraction ssp?  Please use something like "stack-protector-
>> buffer-size" or something like that, for similarity with the enable-
>> stack-protector option.
>>
> It's the same name that's used in GCC. I'm not tied to the name, and
> I'm not expecting this to be used much at all.

I understand, but gcc and llc don't agree on many options.  I'd prefer  
to keep the llc options regular where possible, even if gcc is strange.

>>> +/// InsertStackProtectorPrologue - Insert code into the entry block
>>> that stores
>>> +/// the __stack_chk_guard variable onto the stack.
>>> +void StackProtector::InsertStackProtectorPrologue() {
>>> +  BasicBlock &Entry = F->getEntryBlock();
>>> +  Instruction &InsertPt = Entry.front();
>>> +
>>> +  const char *StackGuardStr = "__stack_chk_guard";
>>> +  StackGuardVar = M->getNamedGlobal(StackGuardStr)
>>
>> If the module already has a '__stack_chk_guard' global with the wrong
>> type, I think this code will crash, see below:
>>
> Hrh?

Nevermind, getOrInsertGlobal fixes this.

>>> +  if (!StackGuardVar)
>>> +    StackGuardVar = new
>>> GlobalVariable(PointerType::getUnqual(Type::Int8Ty),
>>> +                                       false,
>>> GlobalValue::ExternalLinkage,
>>> +                                       0, StackGuardStr, M);
>>
>> We really want a Module::getOrInsertGlobal() method that works like
>> getOrInsertFunction.  It would do the bitcast to solve the problem
>> above and factor away this code.  Can you please add this?
>>
> Sure. That would be nice.

Awesome, thanks for doing this!

>>> +  StackProtFrameSlot = new
>>> AllocaInst(PointerType::getUnqual(Type::Int8Ty),
>>> +                                      "StackProt_Frame",  
>>> &InsertPt);
>>
>> What ensures that this alloca ends up in the right place in the stack
>> frame at codegen time?
>>
> We looked at the code in code gen -- the lowering of allocas. It's
> doing the "right thing" with regard to this. There might be some
> special magic that needs to be done, though.

I'd prefer to have something a little bit less magic than this.  Does  
the canary go before spill slots for callee save regs, could the frame  
packing pass move the field?  If we had a pass that sorted the fields  
based on size, it would move it.  Instead of ending up a normal frame  
index, we really want the canary to be a fixed frame index pinned to  
be right next to the retaddr.

>>> +  Function::iterator I = F->begin(), E = F->end();
>>> +  std::vector<BasicBlock*> ReturnBBs;
>>> +  ReturnBBs.reserve(F->size());
>>> +
>>> +  for (; I != E; ++I)
>>> +    if (isa<ReturnInst>((*I).getTerminator()))
>>> +      ReturnBBs.push_back(I);
>>
>> Two things: first, use I->getTerminator.  Second, why do you make a
>> vector of returns and iterate over the vector?  You should be able to
>> handle all of these with one pass over the function without the
>> intermediate vector.  Also, F->size() is linear time, so that itself
>> does a pass over the function.
>>
> I'm modifying the Function (inserting new blocks). Won't that
> invalidate the iterators?

No, linked list iterators don't get invalided like that.  The problem  
you'll have is that you'll rewrite the return block infinitely  
(because you split the block, and it might point to the block before  
the return, so you rediscover the return again), just increment the  
iterator once extra to solve that problem.

Thanks for working on this Bill, I really like this implementation  
approach!

-Chris



More information about the llvm-commits mailing list