1 //= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines APIs for determining the layout of the data buffer for
11 // os_log() and os_trace().
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
16 #define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/Expr.h"
22 namespace analyze_os_log {
24 /// An OSLogBufferItem represents a single item in the data written by a call
25 /// to os_log() or os_trace().
26 class OSLogBufferItem {
29 // The item is a scalar (int, float, raw pointer, etc.). No further copying
30 // is required. This is the only kind allowed by os_trace().
33 // The item is a count, which describes the length of the following item to
34 // be copied. A count may only be followed by an item of kind StringKind,
35 // WideStringKind, or PointerKind.
38 // The item is a pointer to a C string. If preceded by a count 'n',
39 // os_log() will copy at most 'n' bytes from the pointer.
42 // The item is a pointer to a block of raw data. This item must be preceded
43 // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.
46 // The item is a pointer to an Objective-C object. os_log() may retain the
47 // object for later processing.
50 // The item is a pointer to wide-char string.
53 // The item is corresponding to the '%m' format specifier, no value is
54 // populated in the buffer and the runtime is loading the errno value.
59 // The item is marked "private" in the format string.
62 // The item is marked "public" in the format string.
67 Kind TheKind = ScalarKind;
68 const Expr *TheExpr = nullptr;
70 CharUnits Size; // size of the data, not including the header bytes
74 OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)
75 : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}
77 OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
78 : TheKind(CountKind), ConstValue(value),
79 Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
81 unsigned char getDescriptorByte() const {
82 unsigned char result = 0;
87 result |= ((unsigned)getKind()) << 4;
91 unsigned char getSizeByte() const { return size().getQuantity(); }
93 Kind getKind() const { return TheKind; }
94 bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
95 bool getIsPublic() const { return (Flags & IsPublic) != 0; }
97 const Expr *getExpr() const { return TheExpr; }
98 CharUnits getConstValue() const { return ConstValue; }
99 CharUnits size() const { return Size; }
102 class OSLogBufferLayout {
104 SmallVector<OSLogBufferItem, 4> Items;
106 enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
108 CharUnits size() const {
110 result += CharUnits::fromQuantity(2); // summary byte, num-args byte
111 for (auto &item : Items) {
112 // descriptor byte, size byte
113 result += item.size() + CharUnits::fromQuantity(2);
118 bool hasPrivateItems() const {
120 Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
123 bool hasPublicItems() const {
125 Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });
128 bool hasNonScalar() const {
129 return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
130 return Item.getKind() != OSLogBufferItem::ScalarKind;
134 unsigned char getSummaryByte() const {
135 unsigned char result = 0;
136 if (hasPrivateItems())
137 result |= HasPrivateItems;
139 result |= HasNonScalarItems;
143 unsigned char getNumArgsByte() const { return Items.size(); }
146 // Given a call 'E' to one of the builtins __builtin_os_log_format() or
147 // __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
148 // the call will write into and store it in 'layout'. Returns 'false' if there
149 // was some error encountered while computing the layout, and 'true' otherwise.
150 bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
151 OSLogBufferLayout &layout);
153 } // namespace analyze_os_log