OSLog.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines APIs for determining the layout of the data buffer for
  15. // os_log() and os_trace().
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_AST_OSLOG_H
  19. #define LLVM_CLANG_AST_OSLOG_H
  20. #include "clang/AST/ASTContext.h"
  21. #include "clang/AST/Expr.h"
  22. namespace clang {
  23. 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 {
  27. public:
  28. enum Kind {
  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().
  31. ScalarKind = 0,
  32. // The item is a count, which describes the length of the following item to
  33. // be copied. A count may only be followed by an item of kind StringKind,
  34. // WideStringKind, or PointerKind.
  35. CountKind,
  36. // The item is a pointer to a C string. If preceded by a count 'n',
  37. // os_log() will copy at most 'n' bytes from the pointer.
  38. StringKind,
  39. // The item is a pointer to a block of raw data. This item must be preceded
  40. // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.
  41. PointerKind,
  42. // The item is a pointer to an Objective-C object. os_log() may retain the
  43. // object for later processing.
  44. ObjCObjKind,
  45. // The item is a pointer to wide-char string.
  46. WideStringKind,
  47. // The item is corresponding to the '%m' format specifier, no value is
  48. // populated in the buffer and the runtime is loading the errno value.
  49. ErrnoKind,
  50. // The item is a mask type.
  51. MaskKind
  52. };
  53. enum {
  54. // The item is marked "private" in the format string.
  55. IsPrivate = 0x1,
  56. // The item is marked "public" in the format string.
  57. IsPublic = 0x2,
  58. // The item is marked "sensitive" in the format string.
  59. IsSensitive = 0x4 | IsPrivate
  60. };
  61. private:
  62. Kind TheKind = ScalarKind;
  63. const Expr *TheExpr = nullptr;
  64. CharUnits ConstValue;
  65. CharUnits Size; // size of the data, not including the header bytes
  66. unsigned Flags = 0;
  67. StringRef MaskType;
  68. public:
  69. OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags,
  70. StringRef maskType = StringRef())
  71. : TheKind(kind), TheExpr(expr), Size(size), Flags(flags),
  72. MaskType(maskType) {
  73. assert(((Flags == 0) || (Flags == IsPrivate) || (Flags == IsPublic) ||
  74. (Flags == IsSensitive)) &&
  75. "unexpected privacy flag");
  76. }
  77. OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
  78. : TheKind(CountKind), ConstValue(value),
  79. Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
  80. unsigned char getDescriptorByte() const {
  81. unsigned char result = Flags;
  82. result |= ((unsigned)getKind()) << 4;
  83. return result;
  84. }
  85. unsigned char getSizeByte() const { return size().getQuantity(); }
  86. Kind getKind() const { return TheKind; }
  87. bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
  88. const Expr *getExpr() const { return TheExpr; }
  89. CharUnits getConstValue() const { return ConstValue; }
  90. CharUnits size() const { return Size; }
  91. StringRef getMaskType() const { return MaskType; }
  92. };
  93. class OSLogBufferLayout {
  94. public:
  95. SmallVector<OSLogBufferItem, 4> Items;
  96. enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
  97. CharUnits size() const {
  98. CharUnits result;
  99. result += CharUnits::fromQuantity(2); // summary byte, num-args byte
  100. for (auto &item : Items) {
  101. // descriptor byte, size byte
  102. result += item.size() + CharUnits::fromQuantity(2);
  103. }
  104. return result;
  105. }
  106. bool hasPrivateItems() const {
  107. return llvm::any_of(
  108. Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
  109. }
  110. bool hasNonScalarOrMask() const {
  111. return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
  112. return Item.getKind() != OSLogBufferItem::ScalarKind ||
  113. !Item.getMaskType().empty();
  114. });
  115. }
  116. unsigned char getSummaryByte() const {
  117. unsigned char result = 0;
  118. if (hasPrivateItems())
  119. result |= HasPrivateItems;
  120. if (hasNonScalarOrMask())
  121. result |= HasNonScalarItems;
  122. return result;
  123. }
  124. unsigned char getNumArgsByte() const { return Items.size(); }
  125. };
  126. // Given a call 'E' to one of the builtins __builtin_os_log_format() or
  127. // __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
  128. // the call will write into and store it in 'layout'. Returns 'false' if there
  129. // was some error encountered while computing the layout, and 'true' otherwise.
  130. bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
  131. OSLogBufferLayout &layout);
  132. } // namespace analyze_os_log
  133. } // namespace clang
  134. #endif
  135. #ifdef __GNUC__
  136. #pragma GCC diagnostic pop
  137. #endif