[cfe-dev] How to extract a symbol stored in LazyCompoundVal?
Artem Dergachev via cfe-dev
cfe-dev at lists.llvm.org
Thu Jun 27 17:07:50 PDT 2019
Yes, totally, just take a MemRegionManager, construct the right
FieldRegion of the LCV's parent region, and then do getBinding() of that
region within the LCV's Store.
Small structures are unwrapped in RegionStoreManager::tryBindSmallStruct().
On 6/27/19 3:45 PM, Torry Chen wrote:
> I build my Clang in Release mode without assertions. For pos2, LCVal =
> StoreMgr.getDefaultBinding(*LCV) indeed returns None. I'm surprised
> LCVal->dump() didn't crash.
>
> So this seems to be an expected behavior for getDefaultBinding() due
> to small struct optimization. Can I retrieve the two field symbols for
> pos2 in this case (in evalCall or checkPreCall)? Or you could point me
> to the code where the small struct optimization happens with unwrapped
> binds.
>
> On Thu, 27 Jun 2019 at 14:32, Artem Dergachev <noqnoqneo at gmail.com
> <mailto:noqnoqneo at gmail.com>> wrote:
>
> (in my case it's None because of small struct optimization; you
> see the value as lazyCompoundVal{0x5d4bb38,pos1} in checkBind but
> during the actual bind it gets unwrapped into two symbols)
>
> On 6/27/19 2:22 PM, Artem Dergachev wrote:
>> Mmm, weird. I tried and for me it crashes unwrapping an empty
>> optional. My only guess is - do you build your clang with
>> assertions enabled? Otherwise your checker would behave in
>> undefined manner in this scenario. Could you check if the
>> optional actually does contain a value?
>>
>> On 6/25/19 9:10 PM, Torry Chen wrote:
>>> Thank you Artem! It seems StoreManager::getDefaultBinding()
>>> won't work if the struct variable is copied. As shown below,
>>> getDefaultBinding() returns an undefined SVal.
>>>
>>> I could go down into fields to get the derived symbols for X and
>>> Y respectively, and then use getParentSymbol() to get the symbol
>>> for the whole struct. This looks cumbersome though. Is there a
>>> more convenient way to get the symbol for the whole struct in
>>> this case?
>>>
>>> // checkBind: pos1 -> conj_$3{struct XY, LC1, S45418, #1}
>>> struct XY pos1 = next_pos(10, 20);
>>>
>>> // checkBind: pos2 -> lazyCompoundVal{0x5d4bb38,pos1}
>>> struct XY pos2 = pos1;
>>>
>>> move_to_pos(pos2);
>>>
>>> /** evalCall for move_to_pos():
>>> SVal Pos = C.getSVal(CE->getArg(0));
>>> ProgramStateRef State = C.getState();
>>> StoreManager &StoreMgr =
>>> State->getStateManager().getStoreManager();
>>> auto LCV = Pos.getAs<nonloc::LazyCompoundVal>();
>>> SVal LCSVal = *StoreMgr.getDefaultBinding(*LCV);
>>> LCSVal.dump() // <- Undefined
>>> ...
>>> const Store St = LCV->getCVData()->getStore();
>>> const SVal FieldSVal = StoreMgr.getBinding(St,
>>> loc::MemRegionVal(FieldReg));
>>> FieldSVal.dump(); // <- derived_$4{conj_$3{struct XY, LC1,
>>> S45418, #1},pos1->X}
>>>
>>> const auto *SD = dyn_cast<SymbolDerived>(FieldSVal.getAsSymbol());
>>> const auto ParentSym = SD->getParentSymbol();
>>> ParentSym.dump(); // <- conj_$3{struct XY, LC1, S45418, #1}
>>> **/
>>>
>>> On Tue, 25 Jun 2019 at 14:06, Artem Dergachev
>>> <noqnoqneo at gmail.com <mailto:noqnoqneo at gmail.com>> wrote:
>>>
>>> The "0x4aa1c58" part of "lazyCompoundVal{0x4aa1c58,pos1}" is
>>> a Store object. You can access it with getStore() and then
>>> read it with the help of a StoreManager.
>>>
>>> Hmm, we seem to already have a convenient API for that, you
>>> can do
>>> StoreManager::getDefaultBinding(nonloc::LazyCompoundVal)
>>> directly if all you need is a default-bound conjured symbol.
>>> But if you want to lookup, say, specific fields in the
>>> structure (X and Y separately), you'll need to do
>>> getBinding() on manually constructed FieldRegions (in your
>>> case it doesn't look very useful because the whole structure
>>> is conjured anyway).
>>>
>>> I guess at this point you might like the chapter 5 of my old
>>> workbook
>>> (https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf),
>>> as for now it seems to be the only place where different
>>> kinds of values are explained.
>>>
>>>
>>> On 6/25/19 2:35 AM, Torry Chen via cfe-dev wrote:
>>>> My project has a struct type as follows and I'm writing a
>>>> checker for some functions that take the struct value as an
>>>> argument. In the checkPreCall function I see the argument
>>>> is an LazyCompoundVal, not a symbol as it would be for a
>>>> primitive type. I tried a few ways to extract the symbol
>>>> from the LazyCompountVal with no luck. Hope to get some
>>>> help here.
>>>>
>>>> struct XY {
>>>> uint64_t X;
>>>> uint64_t Y;
>>>> };
>>>>
>>>> ...
>>>> // checkBind: pos1 -> conj_$3{struct XY, LC1, S63346, #1}
>>>> struct XY pos1 = next_pos(...);
>>>>
>>>> // checkPreCall: Arg0: lazyCompoundVal{0x4aa1c58,pos1}
>>>> move_to_pos(pos1);
>>>>
>>>> _______________________________________________
>>>> cfe-dev mailing list
>>>> cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
>>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20190627/c3d50979/attachment.html>
More information about the cfe-dev
mailing list