Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:40

0001 //= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines APIs for determining the layout of the data buffer for
0010 // os_log() and os_trace().
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_AST_OSLOG_H
0015 #define LLVM_CLANG_AST_OSLOG_H
0016 
0017 #include "clang/AST/ASTContext.h"
0018 #include "clang/AST/Expr.h"
0019 
0020 namespace clang {
0021 namespace analyze_os_log {
0022 
0023 /// An OSLogBufferItem represents a single item in the data written by a call
0024 /// to os_log() or os_trace().
0025 class OSLogBufferItem {
0026 public:
0027   enum Kind {
0028     // The item is a scalar (int, float, raw pointer, etc.). No further copying
0029     // is required. This is the only kind allowed by os_trace().
0030     ScalarKind = 0,
0031 
0032     // The item is a count, which describes the length of the following item to
0033     // be copied. A count may only be followed by an item of kind StringKind,
0034     // WideStringKind, or PointerKind.
0035     CountKind,
0036 
0037     // The item is a pointer to a C string. If preceded by a count 'n',
0038     // os_log() will copy at most 'n' bytes from the pointer.
0039     StringKind,
0040 
0041     // The item is a pointer to a block of raw data. This item must be preceded
0042     // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.
0043     PointerKind,
0044 
0045     // The item is a pointer to an Objective-C object. os_log() may retain the
0046     // object for later processing.
0047     ObjCObjKind,
0048 
0049     // The item is a pointer to wide-char string.
0050     WideStringKind,
0051 
0052     // The item is corresponding to the '%m' format specifier, no value is
0053     // populated in the buffer and the runtime is loading the errno value.
0054     ErrnoKind,
0055 
0056     // The item is a mask type.
0057     MaskKind
0058   };
0059 
0060   enum {
0061     // The item is marked "private" in the format string.
0062     IsPrivate = 0x1,
0063 
0064     // The item is marked "public" in the format string.
0065     IsPublic = 0x2,
0066 
0067     // The item is marked "sensitive" in the format string.
0068     IsSensitive = 0x4 | IsPrivate
0069   };
0070 
0071 private:
0072   Kind TheKind = ScalarKind;
0073   const Expr *TheExpr = nullptr;
0074   CharUnits ConstValue;
0075   CharUnits Size; // size of the data, not including the header bytes
0076   unsigned Flags = 0;
0077   StringRef MaskType;
0078 
0079 public:
0080   OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags,
0081                   StringRef maskType = StringRef())
0082       : TheKind(kind), TheExpr(expr), Size(size), Flags(flags),
0083         MaskType(maskType) {
0084     assert(((Flags == 0) || (Flags == IsPrivate) || (Flags == IsPublic) ||
0085             (Flags == IsSensitive)) &&
0086            "unexpected privacy flag");
0087   }
0088 
0089   OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
0090       : TheKind(CountKind), ConstValue(value),
0091         Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
0092 
0093   unsigned char getDescriptorByte() const {
0094     unsigned char result = Flags;
0095     result |= ((unsigned)getKind()) << 4;
0096     return result;
0097   }
0098 
0099   unsigned char getSizeByte() const { return size().getQuantity(); }
0100 
0101   Kind getKind() const { return TheKind; }
0102   bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
0103 
0104   const Expr *getExpr() const { return TheExpr; }
0105   CharUnits getConstValue() const { return ConstValue; }
0106   CharUnits size() const { return Size; }
0107 
0108   StringRef getMaskType() const { return MaskType; }
0109 };
0110 
0111 class OSLogBufferLayout {
0112 public:
0113   SmallVector<OSLogBufferItem, 4> Items;
0114 
0115   enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
0116 
0117   CharUnits size() const {
0118     CharUnits result;
0119     result += CharUnits::fromQuantity(2); // summary byte, num-args byte
0120     for (auto &item : Items) {
0121       // descriptor byte, size byte
0122       result += item.size() + CharUnits::fromQuantity(2);
0123     }
0124     return result;
0125   }
0126 
0127   bool hasPrivateItems() const {
0128     return llvm::any_of(
0129         Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
0130   }
0131 
0132   bool hasNonScalarOrMask() const {
0133     return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
0134       return Item.getKind() != OSLogBufferItem::ScalarKind ||
0135              !Item.getMaskType().empty();
0136     });
0137   }
0138 
0139   unsigned char getSummaryByte() const {
0140     unsigned char result = 0;
0141     if (hasPrivateItems())
0142       result |= HasPrivateItems;
0143     if (hasNonScalarOrMask())
0144       result |= HasNonScalarItems;
0145     return result;
0146   }
0147 
0148   unsigned char getNumArgsByte() const { return Items.size(); }
0149 };
0150 
0151 // Given a call 'E' to one of the builtins __builtin_os_log_format() or
0152 // __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
0153 // the call will write into and store it in 'layout'. Returns 'false' if there
0154 // was some error encountered while computing the layout, and 'true' otherwise.
0155 bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
0156                               OSLogBufferLayout &layout);
0157 
0158 } // namespace analyze_os_log
0159 } // namespace clang
0160 #endif