Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

xlat.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
  3. * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
  4. * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
  5. * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
  6. * Copyright (c) 1999-2018 The strace developers.
  7. * All rights reserved.
  8. *
  9. * SPDX-License-Identifier: LGPL-2.1-or-later
  10. */
  11. #include "defs.h"
  12. #include "xstring.h"
  13. #include <stdarg.h>
  14. static inline enum xlat_style
  15. get_xlat_style(enum xlat_style style)
  16. {
  17. if (xlat_verbose(style) == XLAT_STYLE_DEFAULT)
  18. return style | xlat_verbosity;
  19. return style;
  20. }
  21. static inline const char *
  22. sprint_xlat_val(uint64_t val, enum xlat_style style)
  23. {
  24. static char buf[sizeof(val) * 3];
  25. switch (xlat_format(style)) {
  26. case XLAT_STYLE_FMT_D:
  27. xsprintf(buf, "%" PRId64, val);
  28. break;
  29. case XLAT_STYLE_FMT_U:
  30. xsprintf(buf, "%" PRIu64, val);
  31. break;
  32. case XLAT_STYLE_FMT_X:
  33. xsprintf(buf, "%#" PRIx64, val);
  34. break;
  35. }
  36. return buf;
  37. }
  38. static inline void
  39. print_xlat_val(uint64_t val, enum xlat_style style)
  40. {
  41. tprints(sprint_xlat_val(val, style));
  42. }
  43. const char *
  44. xlookup(const struct xlat *xlat, const uint64_t val)
  45. {
  46. static const struct xlat *pos;
  47. if (xlat)
  48. pos = xlat;
  49. for (; pos->str != NULL; pos++)
  50. if (pos->val == val)
  51. return pos->str;
  52. return NULL;
  53. }
  54. static int
  55. xlat_bsearch_compare(const void *a, const void *b)
  56. {
  57. const uint64_t val1 = *(const uint64_t *) a;
  58. const uint64_t val2 = ((const struct xlat *) b)->val;
  59. return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
  60. }
  61. const char *
  62. xlat_search(const struct xlat *xlat, const size_t nmemb, const uint64_t val)
  63. {
  64. static const struct xlat *pos;
  65. static size_t memb_left;
  66. if (xlat) {
  67. pos = xlat;
  68. memb_left = nmemb;
  69. }
  70. const struct xlat *e =
  71. bsearch((const void *) &val,
  72. pos, memb_left, sizeof(*pos), xlat_bsearch_compare);
  73. if (e) {
  74. memb_left -= e - pos;
  75. return e->str;
  76. } else {
  77. return NULL;
  78. }
  79. }
  80. /**
  81. * Print entry in struct xlat table, if there.
  82. *
  83. * @param val Value to search a literal representation for.
  84. * @param dflt String (abbreviated in comment syntax) which should be emitted
  85. * if no appropriate xlat value has been found.
  86. * @param style Style in which xlat value should be printed.
  87. * @param xlat (And the following arguments) Pointers to arrays of xlat values.
  88. * The last argument should be NULL.
  89. * @return 1 if appropriate xlat value has been found, 0 otherwise.
  90. */
  91. int
  92. printxvals_ex(const uint64_t val, const char *dflt, enum xlat_style style,
  93. const struct xlat *xlat, ...)
  94. {
  95. static const struct xlat *last;
  96. style = get_xlat_style(style);
  97. if (xlat_verbose(style) == XLAT_STYLE_RAW) {
  98. print_xlat_val(val, style);
  99. return 0;
  100. }
  101. const char *str = NULL;
  102. va_list args;
  103. va_start(args, xlat);
  104. if (!xlat)
  105. xlat = last;
  106. for (; xlat; xlat = va_arg(args, const struct xlat *)) {
  107. last = xlat;
  108. str = xlookup(xlat, val);
  109. if (str) {
  110. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
  111. print_xlat_val(val, style);
  112. tprints_comment(str);
  113. } else {
  114. tprints(str);
  115. }
  116. goto printxvals_ex_end;
  117. }
  118. }
  119. /* No hits -- print raw # instead. */
  120. print_xlat_val(val, style);
  121. tprints_comment(dflt);
  122. printxvals_ex_end:
  123. va_end(args);
  124. return !!str;
  125. }
  126. int
  127. sprintxval_ex(char *const buf, const size_t size, const struct xlat *const x,
  128. const unsigned int val, const char *const dflt,
  129. enum xlat_style style)
  130. {
  131. style = get_xlat_style(style);
  132. if (xlat_verbose(style) == XLAT_STYLE_RAW)
  133. return xsnprintf(buf, size, "%s", sprint_xlat_val(val, style));
  134. const char *const str = xlookup(x, val);
  135. if (str) {
  136. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE)
  137. return xsnprintf(buf, size, "%s /* %s */",
  138. sprint_xlat_val(val, style), str);
  139. else
  140. return xsnprintf(buf, size, "%s", str);
  141. }
  142. if (dflt)
  143. return xsnprintf(buf, size, "%s /* %s */",
  144. sprint_xlat_val(val, style), dflt);
  145. return xsnprintf(buf, size, "%s", sprint_xlat_val(val, style));
  146. }
  147. /**
  148. * Print entry in sorted struct xlat table, if it is there.
  149. *
  150. * @param xlat Pointer to an array of xlat values (not terminated with
  151. * XLAT_END).
  152. * @param xlat_size Number of xlat elements present in array (usually ARRAY_SIZE
  153. * if array is declared in the unit's scope and not
  154. * terminated with XLAT_END).
  155. * @param val Value to search literal representation for.
  156. * @param dflt String (abbreviated in comment syntax) which should be
  157. * emitted if no appropriate xlat value has been found.
  158. * @param style Style in which xlat value should be printed.
  159. * @param fn Search function.
  160. * @return 1 if appropriate xlat value has been found, 0
  161. * otherwise.
  162. */
  163. static int
  164. printxval_sized(const struct xlat *xlat, size_t xlat_size, uint64_t val,
  165. const char *dflt, enum xlat_style style,
  166. const char *(* fn)(const struct xlat *, size_t, uint64_t))
  167. {
  168. style = get_xlat_style(style);
  169. if (xlat_verbose(style) == XLAT_STYLE_RAW) {
  170. print_xlat_val(val, style);
  171. return 0;
  172. }
  173. const char *s = fn(xlat, xlat_size, val);
  174. if (s) {
  175. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
  176. print_xlat_val(val, style);
  177. tprints_comment(s);
  178. } else {
  179. tprints(s);
  180. }
  181. return 1;
  182. }
  183. print_xlat_val(val, style);
  184. tprints_comment(dflt);
  185. return 0;
  186. }
  187. int
  188. printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val,
  189. const char *dflt, enum xlat_style style)
  190. {
  191. return printxval_sized(xlat, xlat_size, val, dflt, style,
  192. xlat_search);
  193. }
  194. const char *
  195. xlat_idx(const struct xlat *xlat, size_t nmemb, uint64_t val)
  196. {
  197. static const struct xlat *pos;
  198. static size_t memb_left;
  199. if (xlat) {
  200. pos = xlat;
  201. memb_left = nmemb;
  202. }
  203. if (val >= memb_left)
  204. return NULL;
  205. if (val != pos[val].val) {
  206. if (pos[val].val == 0)
  207. return NULL; /* a hole in the index */
  208. error_func_msg("Unexpected xlat value %" PRIu64
  209. " at index %" PRIu64,
  210. pos[val].val, val);
  211. return NULL;
  212. }
  213. return pos[val].str;
  214. }
  215. int
  216. printxval_indexn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val,
  217. const char *dflt, enum xlat_style style)
  218. {
  219. return printxval_sized(xlat, xlat_size, val, dflt, style, xlat_idx);
  220. }
  221. /*
  222. * Interpret `xlat' as an array of flags.
  223. * Print to static string the entries whose bits are on in `flags'
  224. * Return static string. If 0 is provided as flags, and there is no flag that
  225. * has the value of 0 (it should be the first in xlat table), return NULL.
  226. *
  227. * Expected output:
  228. * +------------+------------+---------+------------+
  229. * | flags != 0 | xlat found | style | output |
  230. * +------------+------------+---------+------------+
  231. * | false | (any) | raw | <none> |
  232. * | true | (any) | raw | VAL |
  233. * +------------+------------+---------+------------+
  234. * | false | false | abbrev | <none> |
  235. * | true | false | abbrev | VAL |
  236. * | (any) | true | abbrev | XLAT |
  237. * +------------+------------+---------+------------+
  238. * | false | false | verbose | <none> |
  239. * | true | false | verbose | VAL |
  240. * | (any) | true | verbose | VAL (XLAT) |
  241. * +------------+------------+---------+------------+
  242. */
  243. const char *
  244. sprintflags_ex(const char *prefix, const struct xlat *xlat, uint64_t flags,
  245. enum xlat_style style)
  246. {
  247. static char outstr[1024];
  248. char *outptr;
  249. int found = 0;
  250. outptr = stpcpy(outstr, prefix);
  251. style = get_xlat_style(style);
  252. if (xlat_verbose(style) == XLAT_STYLE_RAW) {
  253. if (!flags)
  254. return NULL;
  255. outptr = xappendstr(outstr, outptr, "%s",
  256. sprint_xlat_val(flags, style));
  257. return outstr;
  258. }
  259. if (flags == 0 && xlat->val == 0 && xlat->str) {
  260. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
  261. outptr = xappendstr(outstr, outptr, "0 /* %s */",
  262. xlat->str);
  263. } else {
  264. strcpy(outptr, xlat->str);
  265. }
  266. return outstr;
  267. }
  268. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE && flags)
  269. outptr = xappendstr(outstr, outptr, "%s",
  270. sprint_xlat_val(flags, style));
  271. for (; flags && xlat->str; xlat++) {
  272. if (xlat->val && (flags & xlat->val) == xlat->val) {
  273. if (found)
  274. *outptr++ = '|';
  275. else if (xlat_verbose(style) == XLAT_STYLE_VERBOSE)
  276. outptr = stpcpy(outptr, " /* ");
  277. outptr = stpcpy(outptr, xlat->str);
  278. found = 1;
  279. flags &= ~xlat->val;
  280. }
  281. }
  282. if (flags) {
  283. if (found)
  284. *outptr++ = '|';
  285. if (found || xlat_verbose(style) != XLAT_STYLE_VERBOSE)
  286. outptr = xappendstr(outstr, outptr, "%s",
  287. sprint_xlat_val(flags, style));
  288. } else {
  289. if (!found)
  290. return NULL;
  291. }
  292. if (found && xlat_verbose(style) == XLAT_STYLE_VERBOSE)
  293. outptr = stpcpy(outptr, " */");
  294. return outstr;
  295. }
  296. /**
  297. * Print flags from multiple xlat tables.
  298. *
  299. * Expected output:
  300. * +------------+--------------+------------+---------+------------+
  301. * | flags != 0 | dflt != NULL | xlat found | style | output |
  302. * +------------+--------------+------------+---------+------------+
  303. * | false | false | (any) | raw | <none> |
  304. * | false | true | (any) | raw | VAL |
  305. * | true | (any) | (any) | raw | VAL |
  306. * +------------+--------------+------------+---------+------------+
  307. * | false | false | false | abbrev | <none> |
  308. * | false | true | false | abbrev | VAL |
  309. * | true | false | false | abbrev | VAL |
  310. * | true | true | false | abbrev | VAL (DFLT) |
  311. * | (any) | (any) | true | abbrev | XLAT |
  312. * +------------+--------------+------------+---------+------------+
  313. * | false | false | false | verbose | <none> |
  314. * | false | true | false | verbose | VAL |
  315. * | true | false | false | verbose | VAL |
  316. * | true | true | false | verbose | VAL (DFLT) |
  317. * | (any) | (any) | true | verbose | VAL (XLAT) |
  318. * +------------+--------------+------------+---------+------------+
  319. */
  320. int
  321. printflags_ex(uint64_t flags, const char *dflt, enum xlat_style style,
  322. const struct xlat *xlat, ...)
  323. {
  324. style = get_xlat_style(style);
  325. if (xlat_verbose(style) == XLAT_STYLE_RAW) {
  326. if (flags || dflt) {
  327. print_xlat_val(flags, style);
  328. return 1;
  329. }
  330. return 0;
  331. }
  332. const char *init_sep = "";
  333. unsigned int n = 0;
  334. va_list args;
  335. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
  336. init_sep = " /* ";
  337. if (flags)
  338. print_xlat_val(flags, style);
  339. }
  340. va_start(args, xlat);
  341. for (; xlat; xlat = va_arg(args, const struct xlat *)) {
  342. for (; (flags || !n) && xlat->str; ++xlat) {
  343. if ((flags == xlat->val) ||
  344. (xlat->val && (flags & xlat->val) == xlat->val)) {
  345. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE
  346. && !flags)
  347. tprints("0");
  348. tprintf("%s%s",
  349. (n++ ? "|" : init_sep), xlat->str);
  350. flags &= ~xlat->val;
  351. }
  352. if (!flags)
  353. break;
  354. }
  355. }
  356. va_end(args);
  357. if (n) {
  358. if (flags) {
  359. tprints("|");
  360. print_xlat_val(flags, style);
  361. n++;
  362. }
  363. if (xlat_verbose(style) == XLAT_STYLE_VERBOSE)
  364. tprints(" */");
  365. } else {
  366. if (flags) {
  367. if (xlat_verbose(style) != XLAT_STYLE_VERBOSE)
  368. print_xlat_val(flags, style);
  369. tprints_comment(dflt);
  370. } else {
  371. if (dflt)
  372. tprints("0");
  373. }
  374. }
  375. return n;
  376. }
  377. void
  378. print_xlat_ex(const uint64_t val, const char *str, enum xlat_style style)
  379. {
  380. bool default_str = style & PXF_DEFAULT_STR;
  381. style = get_xlat_style(style);
  382. switch (xlat_verbose(style)) {
  383. case XLAT_STYLE_ABBREV:
  384. if (str) {
  385. if (default_str) {
  386. print_xlat_val(val, style);
  387. tprints_comment(str);
  388. } else {
  389. tprints(str);
  390. }
  391. break;
  392. }
  393. ATTRIBUTE_FALLTHROUGH;
  394. case XLAT_STYLE_RAW:
  395. print_xlat_val(val, style);
  396. break;
  397. default:
  398. error_func_msg("Unexpected style value of %#x", style);
  399. ATTRIBUTE_FALLTHROUGH;
  400. case XLAT_STYLE_VERBOSE:
  401. print_xlat_val(val, style);
  402. tprints_comment(str);
  403. }
  404. }
  405. void
  406. printxval_dispatch_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val,
  407. const char *dflt, enum xlat_type xt,
  408. enum xlat_style style)
  409. {
  410. switch (xt) {
  411. case XT_NORMAL:
  412. printxvals_ex(val, dflt, style, xlat, NULL);
  413. break;
  414. case XT_SORTED:
  415. printxval_searchn_ex(xlat, xlat_size, val, dflt, style);
  416. break;
  417. case XT_INDEXED:
  418. printxval_indexn_ex(xlat, xlat_size, val, dflt, style);
  419. break;
  420. }
  421. }