Index: cfe/trunk/www/analyzer/annotations.html =================================================================== --- cfe/trunk/www/analyzer/annotations.html +++ cfe/trunk/www/analyzer/annotations.html @@ -60,6 +60,16 @@
  • Attribute 'ns_consumes_self'
  • +
  • Libkern Memory Management Annotations + + +
  • Custom Assertion Handlers @@ -482,6 +492,183 @@ which is functionally equivalent to the combination of NS_CONSUMES_SELF and NS_RETURNS_RETAINED shown above.

    +

    Libkern Memory Management Annotations

    + +

    Libkern +requires developers to inherit all heap allocated objects from OSObject +and to perform manual reference counting. +The reference counting model is very similar to MRR (manual retain-release) mode in +Objective-C +or to CoreFoundation reference counting. +Freshly-allocated objects start with a reference count of 1, +and calls to retain increment it, +while calls to release decrement it. +The object is deallocated whenever its reference count reaches zero.

    + +

    Manually incrementing and decrementing reference counts is error-prone: +over-retains lead to leaks, and over-releases lead to uses-after-free. +The analyzer can help the programmer to check for unbalanced +retain/release calls.

    + +

    The reference count checking is based on the principle of +locality: it should be possible to establish correctness +(lack of leaks/uses after free) by looking at each function body, +and the declarations (not the definitions) of all the functions it interacts +with.

    + +

    In order to support such reasoning, it should be possible to summarize +the behavior of each function, with respect to reference count +of its returned values and attributes.

    + +

    By default, the following summaries are assumed:

    + + +

    These summaries can be overriden with the following +attributes:

    + +

    Attribute 'os_returns_retained'

    + +

    The os_returns_retained attribute (accessed through the macro +LIBKERN_RETURNS_RETAINED) plays a role identical to ns_returns_retained for functions +returning OSObject subclasses. +The attribute indicates that it is a callers responsibility to release the +returned object. +

    + + +

    Attribute 'os_returns_not_retained'

    + +

    The os_returns_not_retained attribute (accessed through the macro +LIBKERN_RETURNS_NOT_RETAINED) plays a role identical to ns_returns_not_retained for functions +returning OSObject subclasses. +The attribute indicates that the caller should not change the retain +count of the returned object. +

    + +
    Example
    + +
    +class MyClass {
    +  OSObject *f;
    +  LIBKERN_RETURNS_NOT_RETAINED OSObject *myFieldGetter();
    +}
    + 
    + 
    +// Note that the annotation only has to be applied to the function declaration.
    +OSObject * MyClass::myFieldGetter() {
    +  return f;
    +}
    +
    + +

    Attribute 'os_consumed'

    + +

    Similarly to ns_consumed attribute, +os_consumed (accessed through LIBKERN_CONSUMED) attribute, +applied to a parameter, +indicates that the call to the function consumes the parameter: +the callee should either release it or store it and release it in the destructor, +while the caller should assume one is subtracted from the reference count +after the call.

    + +
    +IOReturn addToList(LIBKERN_CONSUMED IOPMinformee *newInformee);
    +
    + +

    Attribute 'os_consumes_this'

    + +

    Similarly to ns_consumes_self, +the os_consumes_self attribute indicates that the method call +consumes the implicit this argument: the caller +should assume one was subtracted from the reference count of the object +after the call, and the callee has on obligation to either +release the argument, or store it and eventually release it in the +destructor.

    + +
    +void addThisToList(OSArray *givenList) LIBKERN_CONSUMES_THIS;
    +
    + +

    Out Parameters

    + +A function can also return an object to a caller by a means of an out parameter +(a pointer-to-OSObject-pointer is passed, and a callee writes a pointer to an +object into an argument). +Currently the analyzer does not track unannotated out +parameters by default, but with annotations we distinguish four separate cases: + +

    1. Non-retained out parameters, identified using + LIBKERN_RETURNS_NOT_RETAINED applied to parameters, e.g.:

    + +
    +void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj)
    +
    + +

    Such functions write a non-retained object into an out parameter, and the +caller has no further obligations.

    + +

    2. Retained out parameters, +identified using LIBKERN_RETURNS_RETAINED:

    +
    +void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj)
    +
    +

    +In such cases a retained object is written into an out parameter, which the caller has then to release in order to avoid a leak. +

    + +

    These two cases are simple - but in practice a functions returning an out-parameter usually also return a return code, and then an out parameter may or may not be written, which conditionally depends on the exit code, e.g.:

    + +
    +bool maybeCreateObject(LIBKERN_RETURNS_RETAINED OSObject **obj);
    +
    + +

    For such functions, the usual semantics is that an object is written into on "success", and not written into on "failure".

    + +

    For LIBKERN_RETURNS_RETAINED we assume the following definition of +success:

    + +

    For functions returning OSReturn or IOReturn +(any typedef to kern_return_t) success is defined as having an output of zero (kIOReturnSuccess is zero). +For all others, success is non-zero (e.g. non-nullptr for pointers)

    + +

    3. Retained out parameters on zero return +The annotation LIBKERN_RETURNS_RETAINED_ON_ZERO states +that a retained object is written into if and only if the function returns a zero value:

    + +
    +bool OSUnserializeXML(void *data, LIBKERN_RETURNS_RETAINED_ON_ZERO OSString **errString);
    +
    + +

    Then the caller has to release an object if the function has returned zero.

    + +

    4. Retained out parameters on non-zero return +Similarly, LIBKERN_RETURNS_RETAINED_ON_NONZERO specifies that a +retained object is written into the parameter if and only if the function has +returned a non-zero value.

    + +

    Note that for non-retained out parameters conditionals do not matter, as the +caller has no obligations regardless of whether an object is written into or +not.

    Custom Assertion Handlers

    @@ -590,4 +777,3 @@ -