btf_iter.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  2. /* Copyright (c) 2021 Facebook */
  3. /* Copyright (c) 2024, Oracle and/or its affiliates. */
  4. #ifdef __KERNEL__
  5. #include <linux/bpf.h>
  6. #include <linux/btf.h>
  7. #define btf_var_secinfos(t) (struct btf_var_secinfo *)btf_type_var_secinfo(t)
  8. #else
  9. #include "btf.h"
  10. #include "libbpf_internal.h"
  11. #endif
  12. int btf_field_iter_init(struct btf_field_iter *it, struct btf_type *t,
  13. enum btf_field_iter_kind iter_kind)
  14. {
  15. it->p = NULL;
  16. it->m_idx = -1;
  17. it->off_idx = 0;
  18. it->vlen = 0;
  19. switch (iter_kind) {
  20. case BTF_FIELD_ITER_IDS:
  21. switch (btf_kind(t)) {
  22. case BTF_KIND_UNKN:
  23. case BTF_KIND_INT:
  24. case BTF_KIND_FLOAT:
  25. case BTF_KIND_ENUM:
  26. case BTF_KIND_ENUM64:
  27. it->desc = (struct btf_field_desc) {};
  28. break;
  29. case BTF_KIND_FWD:
  30. case BTF_KIND_CONST:
  31. case BTF_KIND_VOLATILE:
  32. case BTF_KIND_RESTRICT:
  33. case BTF_KIND_PTR:
  34. case BTF_KIND_TYPEDEF:
  35. case BTF_KIND_FUNC:
  36. case BTF_KIND_VAR:
  37. case BTF_KIND_DECL_TAG:
  38. case BTF_KIND_TYPE_TAG:
  39. it->desc = (struct btf_field_desc) { 1, {offsetof(struct btf_type, type)} };
  40. break;
  41. case BTF_KIND_ARRAY:
  42. it->desc = (struct btf_field_desc) {
  43. 2, {sizeof(struct btf_type) + offsetof(struct btf_array, type),
  44. sizeof(struct btf_type) + offsetof(struct btf_array, index_type)}
  45. };
  46. break;
  47. case BTF_KIND_STRUCT:
  48. case BTF_KIND_UNION:
  49. it->desc = (struct btf_field_desc) {
  50. 0, {},
  51. sizeof(struct btf_member),
  52. 1, {offsetof(struct btf_member, type)}
  53. };
  54. break;
  55. case BTF_KIND_FUNC_PROTO:
  56. it->desc = (struct btf_field_desc) {
  57. 1, {offsetof(struct btf_type, type)},
  58. sizeof(struct btf_param),
  59. 1, {offsetof(struct btf_param, type)}
  60. };
  61. break;
  62. case BTF_KIND_DATASEC:
  63. it->desc = (struct btf_field_desc) {
  64. 0, {},
  65. sizeof(struct btf_var_secinfo),
  66. 1, {offsetof(struct btf_var_secinfo, type)}
  67. };
  68. break;
  69. default:
  70. return -EINVAL;
  71. }
  72. break;
  73. case BTF_FIELD_ITER_STRS:
  74. switch (btf_kind(t)) {
  75. case BTF_KIND_UNKN:
  76. it->desc = (struct btf_field_desc) {};
  77. break;
  78. case BTF_KIND_INT:
  79. case BTF_KIND_FLOAT:
  80. case BTF_KIND_FWD:
  81. case BTF_KIND_ARRAY:
  82. case BTF_KIND_CONST:
  83. case BTF_KIND_VOLATILE:
  84. case BTF_KIND_RESTRICT:
  85. case BTF_KIND_PTR:
  86. case BTF_KIND_TYPEDEF:
  87. case BTF_KIND_FUNC:
  88. case BTF_KIND_VAR:
  89. case BTF_KIND_DECL_TAG:
  90. case BTF_KIND_TYPE_TAG:
  91. case BTF_KIND_DATASEC:
  92. it->desc = (struct btf_field_desc) {
  93. 1, {offsetof(struct btf_type, name_off)}
  94. };
  95. break;
  96. case BTF_KIND_ENUM:
  97. it->desc = (struct btf_field_desc) {
  98. 1, {offsetof(struct btf_type, name_off)},
  99. sizeof(struct btf_enum),
  100. 1, {offsetof(struct btf_enum, name_off)}
  101. };
  102. break;
  103. case BTF_KIND_ENUM64:
  104. it->desc = (struct btf_field_desc) {
  105. 1, {offsetof(struct btf_type, name_off)},
  106. sizeof(struct btf_enum64),
  107. 1, {offsetof(struct btf_enum64, name_off)}
  108. };
  109. break;
  110. case BTF_KIND_STRUCT:
  111. case BTF_KIND_UNION:
  112. it->desc = (struct btf_field_desc) {
  113. 1, {offsetof(struct btf_type, name_off)},
  114. sizeof(struct btf_member),
  115. 1, {offsetof(struct btf_member, name_off)}
  116. };
  117. break;
  118. case BTF_KIND_FUNC_PROTO:
  119. it->desc = (struct btf_field_desc) {
  120. 1, {offsetof(struct btf_type, name_off)},
  121. sizeof(struct btf_param),
  122. 1, {offsetof(struct btf_param, name_off)}
  123. };
  124. break;
  125. default:
  126. return -EINVAL;
  127. }
  128. break;
  129. default:
  130. return -EINVAL;
  131. }
  132. if (it->desc.m_sz)
  133. it->vlen = btf_vlen(t);
  134. it->p = t;
  135. return 0;
  136. }
  137. __u32 *btf_field_iter_next(struct btf_field_iter *it)
  138. {
  139. if (!it->p)
  140. return NULL;
  141. if (it->m_idx < 0) {
  142. if (it->off_idx < it->desc.t_off_cnt)
  143. return it->p + it->desc.t_offs[it->off_idx++];
  144. /* move to per-member iteration */
  145. it->m_idx = 0;
  146. it->p += sizeof(struct btf_type);
  147. it->off_idx = 0;
  148. }
  149. /* if type doesn't have members, stop */
  150. if (it->desc.m_sz == 0) {
  151. it->p = NULL;
  152. return NULL;
  153. }
  154. if (it->off_idx >= it->desc.m_off_cnt) {
  155. /* exhausted this member's fields, go to the next member */
  156. it->m_idx++;
  157. it->p += it->desc.m_sz;
  158. it->off_idx = 0;
  159. }
  160. if (it->m_idx < it->vlen)
  161. return it->p + it->desc.m_offs[it->off_idx++];
  162. it->p = NULL;
  163. return NULL;
  164. }