diff options
Diffstat (limited to 'tools/lib/traceevent/trace-seq.c')
-rw-r--r-- | tools/lib/traceevent/trace-seq.c | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c index d7f2e68bc5b9..ec3bd16a5488 100644 --- a/tools/lib/traceevent/trace-seq.c +++ b/tools/lib/traceevent/trace-seq.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <string.h> | 22 | #include <string.h> |
23 | #include <stdarg.h> | 23 | #include <stdarg.h> |
24 | 24 | ||
25 | #include <asm/bug.h> | ||
25 | #include "event-parse.h" | 26 | #include "event-parse.h" |
26 | #include "event-utils.h" | 27 | #include "event-utils.h" |
27 | 28 | ||
@@ -32,10 +33,21 @@ | |||
32 | #define TRACE_SEQ_POISON ((void *)0xdeadbeef) | 33 | #define TRACE_SEQ_POISON ((void *)0xdeadbeef) |
33 | #define TRACE_SEQ_CHECK(s) \ | 34 | #define TRACE_SEQ_CHECK(s) \ |
34 | do { \ | 35 | do { \ |
35 | if ((s)->buffer == TRACE_SEQ_POISON) \ | 36 | if (WARN_ONCE((s)->buffer == TRACE_SEQ_POISON, \ |
36 | die("Usage of trace_seq after it was destroyed"); \ | 37 | "Usage of trace_seq after it was destroyed")) \ |
38 | (s)->state = TRACE_SEQ__BUFFER_POISONED; \ | ||
37 | } while (0) | 39 | } while (0) |
38 | 40 | ||
41 | #define TRACE_SEQ_CHECK_RET_N(s, n) \ | ||
42 | do { \ | ||
43 | TRACE_SEQ_CHECK(s); \ | ||
44 | if ((s)->state != TRACE_SEQ__GOOD) \ | ||
45 | return n; \ | ||
46 | } while (0) | ||
47 | |||
48 | #define TRACE_SEQ_CHECK_RET(s) TRACE_SEQ_CHECK_RET_N(s, ) | ||
49 | #define TRACE_SEQ_CHECK_RET0(s) TRACE_SEQ_CHECK_RET_N(s, 0) | ||
50 | |||
39 | /** | 51 | /** |
40 | * trace_seq_init - initialize the trace_seq structure | 52 | * trace_seq_init - initialize the trace_seq structure |
41 | * @s: a pointer to the trace_seq structure to initialize | 53 | * @s: a pointer to the trace_seq structure to initialize |
@@ -45,7 +57,11 @@ void trace_seq_init(struct trace_seq *s) | |||
45 | s->len = 0; | 57 | s->len = 0; |
46 | s->readpos = 0; | 58 | s->readpos = 0; |
47 | s->buffer_size = TRACE_SEQ_BUF_SIZE; | 59 | s->buffer_size = TRACE_SEQ_BUF_SIZE; |
48 | s->buffer = malloc_or_die(s->buffer_size); | 60 | s->buffer = malloc(s->buffer_size); |
61 | if (s->buffer != NULL) | ||
62 | s->state = TRACE_SEQ__GOOD; | ||
63 | else | ||
64 | s->state = TRACE_SEQ__MEM_ALLOC_FAILED; | ||
49 | } | 65 | } |
50 | 66 | ||
51 | /** | 67 | /** |
@@ -71,17 +87,23 @@ void trace_seq_destroy(struct trace_seq *s) | |||
71 | { | 87 | { |
72 | if (!s) | 88 | if (!s) |
73 | return; | 89 | return; |
74 | TRACE_SEQ_CHECK(s); | 90 | TRACE_SEQ_CHECK_RET(s); |
75 | free(s->buffer); | 91 | free(s->buffer); |
76 | s->buffer = TRACE_SEQ_POISON; | 92 | s->buffer = TRACE_SEQ_POISON; |
77 | } | 93 | } |
78 | 94 | ||
79 | static void expand_buffer(struct trace_seq *s) | 95 | static void expand_buffer(struct trace_seq *s) |
80 | { | 96 | { |
97 | char *buf; | ||
98 | |||
99 | buf = realloc(s->buffer, s->buffer_size + TRACE_SEQ_BUF_SIZE); | ||
100 | if (WARN_ONCE(!buf, "Can't allocate trace_seq buffer memory")) { | ||
101 | s->state = TRACE_SEQ__MEM_ALLOC_FAILED; | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | s->buffer = buf; | ||
81 | s->buffer_size += TRACE_SEQ_BUF_SIZE; | 106 | s->buffer_size += TRACE_SEQ_BUF_SIZE; |
82 | s->buffer = realloc(s->buffer, s->buffer_size); | ||
83 | if (!s->buffer) | ||
84 | die("Can't allocate trace_seq buffer memory"); | ||
85 | } | 107 | } |
86 | 108 | ||
87 | /** | 109 | /** |
@@ -105,9 +127,9 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | |||
105 | int len; | 127 | int len; |
106 | int ret; | 128 | int ret; |
107 | 129 | ||
108 | TRACE_SEQ_CHECK(s); | ||
109 | |||
110 | try_again: | 130 | try_again: |
131 | TRACE_SEQ_CHECK_RET0(s); | ||
132 | |||
111 | len = (s->buffer_size - 1) - s->len; | 133 | len = (s->buffer_size - 1) - s->len; |
112 | 134 | ||
113 | va_start(ap, fmt); | 135 | va_start(ap, fmt); |
@@ -141,9 +163,9 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) | |||
141 | int len; | 163 | int len; |
142 | int ret; | 164 | int ret; |
143 | 165 | ||
144 | TRACE_SEQ_CHECK(s); | ||
145 | |||
146 | try_again: | 166 | try_again: |
167 | TRACE_SEQ_CHECK_RET0(s); | ||
168 | |||
147 | len = (s->buffer_size - 1) - s->len; | 169 | len = (s->buffer_size - 1) - s->len; |
148 | 170 | ||
149 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); | 171 | ret = vsnprintf(s->buffer + s->len, len, fmt, args); |
@@ -172,13 +194,15 @@ int trace_seq_puts(struct trace_seq *s, const char *str) | |||
172 | { | 194 | { |
173 | int len; | 195 | int len; |
174 | 196 | ||
175 | TRACE_SEQ_CHECK(s); | 197 | TRACE_SEQ_CHECK_RET0(s); |
176 | 198 | ||
177 | len = strlen(str); | 199 | len = strlen(str); |
178 | 200 | ||
179 | while (len > ((s->buffer_size - 1) - s->len)) | 201 | while (len > ((s->buffer_size - 1) - s->len)) |
180 | expand_buffer(s); | 202 | expand_buffer(s); |
181 | 203 | ||
204 | TRACE_SEQ_CHECK_RET0(s); | ||
205 | |||
182 | memcpy(s->buffer + s->len, str, len); | 206 | memcpy(s->buffer + s->len, str, len); |
183 | s->len += len; | 207 | s->len += len; |
184 | 208 | ||
@@ -187,11 +211,13 @@ int trace_seq_puts(struct trace_seq *s, const char *str) | |||
187 | 211 | ||
188 | int trace_seq_putc(struct trace_seq *s, unsigned char c) | 212 | int trace_seq_putc(struct trace_seq *s, unsigned char c) |
189 | { | 213 | { |
190 | TRACE_SEQ_CHECK(s); | 214 | TRACE_SEQ_CHECK_RET0(s); |
191 | 215 | ||
192 | while (s->len >= (s->buffer_size - 1)) | 216 | while (s->len >= (s->buffer_size - 1)) |
193 | expand_buffer(s); | 217 | expand_buffer(s); |
194 | 218 | ||
219 | TRACE_SEQ_CHECK_RET0(s); | ||
220 | |||
195 | s->buffer[s->len++] = c; | 221 | s->buffer[s->len++] = c; |
196 | 222 | ||
197 | return 1; | 223 | return 1; |
@@ -199,7 +225,7 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c) | |||
199 | 225 | ||
200 | void trace_seq_terminate(struct trace_seq *s) | 226 | void trace_seq_terminate(struct trace_seq *s) |
201 | { | 227 | { |
202 | TRACE_SEQ_CHECK(s); | 228 | TRACE_SEQ_CHECK_RET(s); |
203 | 229 | ||
204 | /* There's always one character left on the buffer */ | 230 | /* There's always one character left on the buffer */ |
205 | s->buffer[s->len] = 0; | 231 | s->buffer[s->len] = 0; |
@@ -208,5 +234,16 @@ void trace_seq_terminate(struct trace_seq *s) | |||
208 | int trace_seq_do_printf(struct trace_seq *s) | 234 | int trace_seq_do_printf(struct trace_seq *s) |
209 | { | 235 | { |
210 | TRACE_SEQ_CHECK(s); | 236 | TRACE_SEQ_CHECK(s); |
211 | return printf("%.*s", s->len, s->buffer); | 237 | |
238 | switch (s->state) { | ||
239 | case TRACE_SEQ__GOOD: | ||
240 | return printf("%.*s", s->len, s->buffer); | ||
241 | case TRACE_SEQ__BUFFER_POISONED: | ||
242 | puts("Usage of trace_seq after it was destroyed"); | ||
243 | break; | ||
244 | case TRACE_SEQ__MEM_ALLOC_FAILED: | ||
245 | puts("Can't allocate trace_seq buffer memory"); | ||
246 | break; | ||
247 | } | ||
248 | return -1; | ||
212 | } | 249 | } |