diff options
-rw-r--r-- | mm/kmemleak.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 8172154502a6..1d7645b0a97c 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c | |||
@@ -162,6 +162,15 @@ struct kmemleak_object { | |||
162 | /* flag set on newly allocated objects */ | 162 | /* flag set on newly allocated objects */ |
163 | #define OBJECT_NEW (1 << 3) | 163 | #define OBJECT_NEW (1 << 3) |
164 | 164 | ||
165 | /* number of bytes to print per line; must be 16 or 32 */ | ||
166 | #define HEX_ROW_SIZE 16 | ||
167 | /* number of bytes to print at a time (1, 2, 4, 8) */ | ||
168 | #define HEX_GROUP_SIZE 1 | ||
169 | /* include ASCII after the hex output */ | ||
170 | #define HEX_ASCII 1 | ||
171 | /* max number of lines to be printed */ | ||
172 | #define HEX_MAX_LINES 2 | ||
173 | |||
165 | /* the list of all allocated objects */ | 174 | /* the list of all allocated objects */ |
166 | static LIST_HEAD(object_list); | 175 | static LIST_HEAD(object_list); |
167 | /* the list of gray-colored objects (see color_gray comment below) */ | 176 | /* the list of gray-colored objects (see color_gray comment below) */ |
@@ -259,6 +268,35 @@ static void kmemleak_disable(void); | |||
259 | } while (0) | 268 | } while (0) |
260 | 269 | ||
261 | /* | 270 | /* |
271 | * Printing of the objects hex dump to the seq file. The number of lines to be | ||
272 | * printed is limited to HEX_MAX_LINES to prevent seq file spamming. The | ||
273 | * actual number of printed bytes depends on HEX_ROW_SIZE. It must be called | ||
274 | * with the object->lock held. | ||
275 | */ | ||
276 | static void hex_dump_object(struct seq_file *seq, | ||
277 | struct kmemleak_object *object) | ||
278 | { | ||
279 | const u8 *ptr = (const u8 *)object->pointer; | ||
280 | int i, len, remaining; | ||
281 | unsigned char linebuf[HEX_ROW_SIZE * 5]; | ||
282 | |||
283 | /* limit the number of lines to HEX_MAX_LINES */ | ||
284 | remaining = len = | ||
285 | min(object->size, (size_t)(HEX_MAX_LINES * HEX_ROW_SIZE)); | ||
286 | |||
287 | seq_printf(seq, " hex dump (first %d bytes):\n", len); | ||
288 | for (i = 0; i < len; i += HEX_ROW_SIZE) { | ||
289 | int linelen = min(remaining, HEX_ROW_SIZE); | ||
290 | |||
291 | remaining -= HEX_ROW_SIZE; | ||
292 | hex_dump_to_buffer(ptr + i, linelen, HEX_ROW_SIZE, | ||
293 | HEX_GROUP_SIZE, linebuf, sizeof(linebuf), | ||
294 | HEX_ASCII); | ||
295 | seq_printf(seq, " %s\n", linebuf); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /* | ||
262 | * Object colors, encoded with count and min_count: | 300 | * Object colors, encoded with count and min_count: |
263 | * - white - orphan object, not enough references to it (count < min_count) | 301 | * - white - orphan object, not enough references to it (count < min_count) |
264 | * - gray - not orphan, not marked as false positive (min_count == 0) or | 302 | * - gray - not orphan, not marked as false positive (min_count == 0) or |
@@ -308,6 +346,7 @@ static void print_unreferenced(struct seq_file *seq, | |||
308 | object->pointer, object->size); | 346 | object->pointer, object->size); |
309 | seq_printf(seq, " comm \"%s\", pid %d, jiffies %lu\n", | 347 | seq_printf(seq, " comm \"%s\", pid %d, jiffies %lu\n", |
310 | object->comm, object->pid, object->jiffies); | 348 | object->comm, object->pid, object->jiffies); |
349 | hex_dump_object(seq, object); | ||
311 | seq_printf(seq, " backtrace:\n"); | 350 | seq_printf(seq, " backtrace:\n"); |
312 | 351 | ||
313 | for (i = 0; i < object->trace_len; i++) { | 352 | for (i = 0; i < object->trace_len; i++) { |