db_struct.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /* $OpenBSD: db_struct.c,v 1.3 2013/10/19 21:02:50 guenther Exp $ */
  2. /*
  3. * Copyright (c) 2009 Miodrag Vallat.
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /*
  18. * ddb routines to describe struct information
  19. */
  20. #include <sys/param.h>
  21. #include <sys/systm.h>
  22. #include <machine/db_machdep.h>
  23. #include <ddb/db_lex.h>
  24. #include <ddb/db_output.h>
  25. #include <ddb/db_access.h>
  26. #include <ddb/db_command.h>
  27. #include <ddb/db_extern.h>
  28. #include <ddb/db_interface.h>
  29. #include <ddb/db_var.h>
  30. #include "db_structinfo.h"
  31. void db_struct_print_field(uint, int, db_expr_t);
  32. /*
  33. * Flags to pass db_struct_printf().
  34. */
  35. #define DBSP_STRUCT_NAME 0x01 /* prepend struct name */
  36. #define DBSP_VALUE 0x02 /* display field value */
  37. void
  38. db_struct_print_field(uint fidx, int flags, db_expr_t baseaddr)
  39. {
  40. const struct ddb_field_info *field;
  41. const struct ddb_struct_info *struc;
  42. db_expr_t value;
  43. uint tmp;
  44. size_t namelen;
  45. int width, basecol, curcol;
  46. char tmpfmt[28];
  47. field = &ddb_field_info[fidx];
  48. basecol = 0;
  49. if (ISSET(flags, DBSP_STRUCT_NAME)) {
  50. struc = &ddb_struct_info[field->sidx];
  51. namelen = strlen(ddb_structfield_strings + struc->name);
  52. db_printf("%-30s ", ddb_structfield_strings + struc->name);
  53. if (namelen > 30)
  54. basecol += namelen + 1;
  55. else
  56. basecol += 30 + 1;
  57. }
  58. namelen = strlen(ddb_structfield_strings + field->name);
  59. if (field->nitems == 1) {
  60. db_printf("%-30s ", ddb_structfield_strings + field->name);
  61. if (namelen > 30)
  62. basecol += namelen + 1;
  63. else
  64. basecol += 30 + 1;
  65. } else {
  66. width = 30 - 2;
  67. tmp = field->nitems;
  68. while (tmp != 0) {
  69. width--;
  70. tmp /= 10;
  71. }
  72. if (namelen >= width) {
  73. db_printf("%s[%hu] ",
  74. ddb_structfield_strings + field->name,
  75. field->nitems);
  76. basecol += namelen + (30 - width) + 1;
  77. } else {
  78. db_printf("%s[%hu]%*s ",
  79. ddb_structfield_strings + field->name,
  80. field->nitems, width - (int)namelen, "");
  81. /* namelen + (30-width) + (width-namelen) + 1 */
  82. basecol += 30 + 1;
  83. }
  84. }
  85. if (field->size == 0) {
  86. db_printf("bitfield");
  87. /* basecol irrelevant from there on */
  88. } else {
  89. snprintf(tmpfmt, sizeof tmpfmt, "%u", (u_int)field->size);
  90. basecol += strlen(tmpfmt) + 1;
  91. db_printf("%s ", tmpfmt);
  92. }
  93. if (ISSET(flags, DBSP_VALUE)) {
  94. /* only print the field value if it has a friendly size. */
  95. switch (field->size) {
  96. case 1:
  97. width = 4;
  98. break;
  99. case 2:
  100. width = 8;
  101. break;
  102. case 4:
  103. width = 12;
  104. break;
  105. #ifdef __LP64__
  106. case 8:
  107. width = 20;
  108. break;
  109. #endif
  110. default:
  111. width = 0;
  112. }
  113. if (width != 0) {
  114. baseaddr += field->offs;
  115. curcol = basecol;
  116. for (tmp = field->nitems; tmp != 0; tmp--) {
  117. value = db_get_value(baseaddr, field->size,
  118. FALSE); /* assume unsigned */
  119. db_format(tmpfmt, sizeof tmpfmt, (long)value,
  120. DB_FORMAT_N, 0, width);
  121. if (field->nitems > 1)
  122. db_printf("%s", tmpfmt);
  123. else
  124. db_printf("%20s", tmpfmt);
  125. baseaddr += field->size;
  126. /*
  127. * Try to fit array elements on as few lines
  128. * as possible.
  129. */
  130. if (field->nitems > 1 && tmp > 1) {
  131. curcol += width + 1;
  132. if (basecol >= db_max_width ||
  133. curcol + width >= db_max_width) {
  134. /* new line */
  135. db_printf("\n");
  136. if (basecol + width >=
  137. db_max_width) {
  138. db_printf("\t");
  139. curcol = 8;
  140. } else {
  141. db_printf("%*s",
  142. basecol, "");
  143. curcol = basecol;
  144. }
  145. } else
  146. db_printf(" ");
  147. }
  148. }
  149. }
  150. }
  151. db_printf("\n");
  152. }
  153. /*
  154. * show offset <value>: displays the list of struct fields which exist
  155. * at that particular offset from the beginning of the struct.
  156. */
  157. void
  158. db_struct_offset_cmd(db_expr_t addr, int have_addr, db_expr_t count,
  159. char *modifiers)
  160. {
  161. db_expr_t offset = 0;
  162. const struct ddb_field_offsets *field;
  163. const ddb_field_off *fidx;
  164. uint oidx;
  165. int width;
  166. char tmpfmt[28];
  167. /*
  168. * Read the offset from the debuggger input.
  169. * We don't want to get it from the standard parsing code, because
  170. * this would set `dot' to this value, which doesn't make sense.
  171. */
  172. if (!db_expression(&offset) || offset < 0) {
  173. db_printf("not a valid offset\n");
  174. db_flush_lex();
  175. return;
  176. }
  177. db_skip_to_eol();
  178. for (field = ddb_field_offsets, oidx = 0; oidx < NOFFS; field++, oidx++)
  179. if (field->offs == (size_t)offset)
  180. break;
  181. if (oidx == NOFFS) {
  182. db_format(tmpfmt, sizeof tmpfmt, (long)offset,
  183. DB_FORMAT_N, 0, width);
  184. db_printf("no known structure element at offset %-*s\n",
  185. width, tmpfmt);
  186. db_flush_lex();
  187. return;
  188. }
  189. db_printf("%-30s %-30s size\n", "struct", "member");
  190. for (fidx = ddb_fields_by_offset + field->list; *fidx != 0; fidx++)
  191. db_struct_print_field(*fidx, DBSP_STRUCT_NAME, 0);
  192. }
  193. /*
  194. * show struct <struct name> [addr]: displays the data starting at addr
  195. * (`dot' if unspecified) as a struct of the given type.
  196. */
  197. void
  198. db_struct_layout_cmd(db_expr_t addr, int have_addr, db_expr_t count,
  199. char *modifiers)
  200. {
  201. const struct ddb_struct_info *struc;
  202. uint sidx, fidx;
  203. int t;
  204. /*
  205. * Read the struct name from the debugger input.
  206. */
  207. t = db_read_token();
  208. if (t != tIDENT) {
  209. db_printf("Bad struct name\n");
  210. db_flush_lex();
  211. return;
  212. }
  213. for (struc = ddb_struct_info, sidx = 0; sidx < NSTRUCT;
  214. struc++, sidx++)
  215. if (strcmp(ddb_structfield_strings + struc->name,
  216. db_tok_string) == 0)
  217. break;
  218. if (sidx == NSTRUCT) {
  219. db_printf("unknown struct %s\n", db_tok_string);
  220. db_flush_lex();
  221. return;
  222. }
  223. /*
  224. * Read the address, if any, from the debugger input.
  225. * In that case, update `dot' value.
  226. */
  227. if (db_expression(&addr)) {
  228. db_dot = (db_addr_t)addr;
  229. db_last_addr = db_dot;
  230. } else
  231. addr = (db_expr_t)db_dot;
  232. db_skip_to_eol();
  233. /*
  234. * Display the structure contents.
  235. */
  236. db_printf("struct %s at %p (%u bytes)\n",
  237. ddb_structfield_strings + struc->name, (void *)addr,
  238. (u_int)struc->size);
  239. for (fidx = struc->fmin; fidx <= struc->fmax; fidx++)
  240. db_struct_print_field(fidx, DBSP_VALUE, addr);
  241. }