MonkOS  v0.1
A simple 64-bit operating system (x86_64)
dump.c
Go to the documentation of this file.
1 //============================================================================
2 /// @file dump.c
3 /// @brief Debugging memory and CPU state dump routines.
4 //
5 // Copyright 2016 Brett Vickers.
6 // Use of this source code is governed by a BSD-style license
7 // that can be found in the MonkOS LICENSE file.
8 //============================================================================
9 
10 #include <libc/stdio.h>
11 #include <kernel/debug/dump.h>
12 
13 static const char digit[] = "0123456789abcdef";
14 
15 int
16 dump_registers(char *buf, size_t bufsize, const registers_t *regs)
17 {
18  return snprintf(
19  buf, bufsize,
20  "RAX: %016lx RSI: %016lx R11: %016lx\n"
21  "RBX: %016lx RDI: %016lx R12: %016lx\n"
22  "RCX: %016lx R8: %016lx R13: %016lx\n"
23  "RDX: %016lx R9: %016lx R14: %016lx\n"
24  "RBP: %016lx R10: %016lx R15: %016lx\n",
25  regs->rax, regs->rsi, regs->r11,
26  regs->rbx, regs->rdi, regs->r12,
27  regs->rcx, regs->r8, regs->r13,
28  regs->rdx, regs->r9, regs->r14,
29  regs->rbp, regs->r10, regs->r15);
30 }
31 
32 int
33 dump_cpuflags(char *buf, size_t bufsize, uint64_t rflags)
34 {
35 #define B(F) ((rflags & F) ? 1 : 0)
36 
37  return snprintf(
38  buf, bufsize,
39  "CF=%u PF=%u AF=%u ZF=%u SF=%u "
40  "TF=%u IF=%u DF=%u OF=%u IOPL=%u\n",
44  B(CPU_EFLAGS_OVERFLOW), (rflags >> 12) & 3);
45 
46 #undef B
47 }
48 
49 int
50 dump_memory(char *buf, size_t bufsize, const void *mem, size_t memsize,
51  enum dumpstyle style)
52 {
53  char *b = buf;
54  char *bt = buf + bufsize;
55  const uint8_t *m = (const uint8_t *)mem;
56  const uint8_t *mt = (const uint8_t *)mem + memsize;
57 
58  while (b < bt && m < mt) {
59 
60  // Dump memory offset if requested.
61  if (style == DUMPSTYLE_OFFSET) {
62  if (b + 11 < bt) {
63  uint64_t o = (uint64_t)(m - (const uint8_t *)mem);
64  for (int i = 7; i >= 0; i--) {
65  b[i] = digit[o & 0xf];
66  o >>= 4;
67  }
68  b[8] = ':';
69  b[9] = b[10] = ' ';
70  }
71  b += 11;
72  }
73 
74  // Dump memory address if requested.
75  else if (style == DUMPSTYLE_ADDR) {
76  if (b + 20 < bt) {
77  uint64_t a = (uint64_t)m;
78  for (int i = 16; i > 8; i--) {
79  b[i] = digit[a & 0xf];
80  a >>= 4;
81  }
82  b[8] = '`'; // tick separator for readability
83  for (int i = 7; i >= 0; i--) {
84  b[i] = digit[a & 0xf];
85  a >>= 4;
86  }
87  b[17] = ':';
88  b[18] = b[19] = ' ';
89  }
90  b += 20;
91  }
92 
93  // Dump up to 16 hexadecimal byte values.
94  for (int j = 0; j < 16; j++) {
95  if (b + 2 < bt) {
96  if (m + j < mt) {
97  uint8_t v = m[j];
98  b[0] = digit[v >> 4];
99  b[1] = digit[v & 0xf];
100  }
101  else {
102  b[0] = b[1] = ' ';
103  }
104  }
105  b += 2;
106 
107  // Add a 1-space gutter between each group of 4 bytes.
108  if (((j + 1) & 3) == 0) {
109  if (b + 1 < bt) {
110  *b = ' ';
111  }
112  b++;
113  }
114  }
115 
116  // Add a gutter between hex and ascii displays.
117  if (b + 1 < bt) {
118  *b = ' ';
119  }
120  b++;
121 
122  // Dump up to 16 ASCII bytes.
123  for (int j = 0; j < 16; j++) {
124  if (b + 1 < bt) {
125  if (m + j < mt) {
126  uint8_t v = m[j];
127  *b = (v < 32 || v > 126) ? '.' : (char)v;
128  }
129  else {
130  *b = ' ';
131  }
132  }
133  b++;
134 
135  // Add a gutter between each group of 8 ascii characters.
136  if (j == 7) {
137  if (b + 1 < bt) {
138  *b = ' ';
139  }
140  b++;
141  }
142  }
143 
144  // Dump a carriage return.
145  if (b + 1 < bt) {
146  *b = '\n';
147  }
148  b++;
149 
150  m += 16;
151  }
152 
153  // Null-terminate the buffer.
154  if (b < bt) {
155  *b = 0;
156  }
157  else if (bufsize > 0) {
158  b[bufsize - 1] = 0;
159  }
160 
161  // Return the number of bytes (that would have been) added to the buffer,
162  // even if the buffer was too small.
163  return (int)(b - buf);
164 }
#define B(F)
#define CPU_EFLAGS_PARITY
Definition: cpu.h:16
int dump_registers(char *buf, size_t bufsize, const registers_t *regs)
Dump the contents of a CPU registers structure to a string buffer.
Definition: dump.c:16
static const char digit[]
Definition: dump.c:13
uint64_t r14
Definition: cpu.h:53
A record describing all 64-bit general-purpose registers.
Definition: cpu.h:38
#define CPU_EFLAGS_SIGN
Definition: cpu.h:19
uint64_t rdx
Definition: cpu.h:43
Include address offset in memory dump.
Definition: dump.h:52
uint64_t rsi
Definition: cpu.h:44
uint64_t rcx
Definition: cpu.h:42
#define CPU_EFLAGS_INTERRUPT
Definition: cpu.h:21
int snprintf(char *buf, size_t n, const char *format,...)
Compose a printf-formatted string into the target buffer.
int dump_memory(char *buf, size_t bufsize, const void *mem, size_t memsize, enum dumpstyle style)
Dump the contents of memory.
Definition: dump.c:50
uint64_t r10
Definition: cpu.h:49
dumpstyle
Memory dump output style.
Definition: dump.h:48
uint64_t r15
Definition: cpu.h:54
uint64_t rbx
Definition: cpu.h:41
uint64_t r8
Definition: cpu.h:47
int dump_cpuflags(char *buf, size_t bufsize, uint64_t rflags)
Dump the contents of the CPU flags register.
Definition: dump.c:33
uint64_t rax
Definition: cpu.h:40
#define CPU_EFLAGS_CARRY
Definition: cpu.h:15
#define CPU_EFLAGS_ADJUST
Definition: cpu.h:17
#define CPU_EFLAGS_ZERO
Definition: cpu.h:18
uint64_t r9
Definition: cpu.h:48
Debugging memory and CPU state dump routines.
uint64_t r12
Definition: cpu.h:51
Standard i/o library.
Include full address in memory dump.
Definition: dump.h:51
#define CPU_EFLAGS_DIRECTION
Definition: cpu.h:22
uint64_t rbp
Definition: cpu.h:46
uint64_t rdi
Definition: cpu.h:45
#define CPU_EFLAGS_OVERFLOW
Definition: cpu.h:23
uint64_t r13
Definition: cpu.h:52
#define CPU_EFLAGS_TRAP
Definition: cpu.h:20
uint64_t r11
Definition: cpu.h:50