From 16e3655fbd0955748892fa2fc75acf82ce9a9665 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 12 Apr 2024 16:18:34 +0200 Subject: [PATCH] REORG: pool: move the area dump with symbol resolution to tools.c This function is particularly useful to dump unknown areas watching for opportunistic symbols, so let's move it to tools.c so that we can reuse it a little bit more. --- include/haproxy/tools.h | 2 ++ src/pool.c | 44 +--------------------------------- src/tools.c | 52 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index d76b2d13c..11082379c 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -1007,6 +1007,8 @@ int dump_binary(struct buffer *out, const char *buf, int bsize); int dump_text_line(struct buffer *out, const char *buf, int bsize, int len, int *line, int ptr); void dump_addr_and_bytes(struct buffer *buf, const char *pfx, const void *addr, int n); +void dump_area_with_syms(struct buffer *output, const void *base, const void *addr, + const void *special, const char *spec_type, const char *spec_name); void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len, int unsafe); int may_access(const void *ptr); const void *resolve_sym_name(struct buffer *buf, const char *pfx, const void *addr); diff --git a/src/pool.c b/src/pool.c index 65751b0dc..cc85faff3 100644 --- a/src/pool.c +++ b/src/pool.c @@ -1014,8 +1014,6 @@ void pool_inspect_item(const char *msg, struct pool_head *pool, const void *item } if (!the_pool) { - const char *start, *end, *p; - chunk_appendf(&trash, "Tag does not match any other pool.\n"); @@ -1025,47 +1023,7 @@ void pool_inspect_item(const char *msg, struct pool_head *pool, const void *item else chunk_appendf(&trash, " (no match).\n"); - chunk_appendf(&trash, - "Contents around address %p+%lu=%p:\n", - item, (ulong)((const void*)pool_mark - (const void*)item), - pool_mark); - - /* dump in word-sized blocks */ - start = (const void *)(((uintptr_t)pool_mark - 32) & -sizeof(void*)); - end = (const void *)(((uintptr_t)pool_mark + 32 + sizeof(void*) - 1) & -sizeof(void*)); - - while (start < end) { - dump_addr_and_bytes(&trash, " ", start, sizeof(void*)); - chunk_strcat(&trash, " ["); - for (p = start; p < start + sizeof(void*); p++) { - if (!may_access(p)) - chunk_strcat(&trash, "*"); - else if (isprint((unsigned char)*p)) - chunk_appendf(&trash, "%c", *p); - else - chunk_strcat(&trash, "."); - } - - if (may_access(start)) - tag = *(const void **)start; - else - tag = NULL; - - if (tag == pool) { - /* the pool can often be there so let's detect it */ - chunk_appendf(&trash, "] [pool:%s", pool->name); - } - else if (tag) { - /* print pointers that resolve to a symbol */ - size_t back_data = trash.data; - chunk_strcat(&trash, "] ["); - if (!resolve_sym_name(&trash, NULL, tag)) - trash.data = back_data; - } - - chunk_strcat(&trash, "]\n"); - start = p; - } + dump_area_with_syms(&trash, item, pool_mark, pool, "pool", pool->name); } } } diff --git a/src/tools.c b/src/tools.c index b08fb18ce..09de5db20 100644 --- a/src/tools.c +++ b/src/tools.c @@ -4909,6 +4909,58 @@ void dump_addr_and_bytes(struct buffer *buf, const char *pfx, const void *addr, } } +/* Dumps the 64 bytes around at the end of with symbols + * decoding. An optional special pointer may be recognized (special), in + * which case its type (spec_type) and name (spec_name) will be reported. + * This is convenient for pool names but could be used for list heads or + * anything in that vein. +*/ +void dump_area_with_syms(struct buffer *output, const void *base, const void *addr, + const void *special, const char *spec_type, const char *spec_name) +{ + const char *start, *end, *p; + const void *tag; + + chunk_appendf(output, "Contents around address %p+%lu=%p:\n", base, (ulong)(addr - base), addr); + + /* dump in word-sized blocks */ + start = (const void *)(((uintptr_t)addr - 32) & -sizeof(void*)); + end = (const void *)(((uintptr_t)addr + 32 + sizeof(void*) - 1) & -sizeof(void*)); + + while (start < end) { + dump_addr_and_bytes(output, " ", start, sizeof(void*)); + chunk_strcat(output, " ["); + for (p = start; p < start + sizeof(void*); p++) { + if (!may_access(p)) + chunk_strcat(output, "*"); + else if (isprint((unsigned char)*p)) + chunk_appendf(output, "%c", *p); + else + chunk_strcat(output, "."); + } + + if (may_access(start)) + tag = *(const void **)start; + else + tag = NULL; + + if (special && tag == special) { + /* the pool can often be there so let's detect it */ + chunk_appendf(output, "] [%s:%s", spec_type, spec_name); + } + else if (tag) { + /* print pointers that resolve to a symbol */ + size_t back_data = output->data; + chunk_strcat(output, "] ["); + if (!resolve_sym_name(output, NULL, tag)) + output->data = back_data; + } + + chunk_strcat(output, "]\n"); + start = p; + } +} + /* print a line of text buffer (limited to 70 bytes) to . The format is : * <2 spaces> <70 chars max> <\n> * which is 60 chars per line. Non-printable chars \t, \n, \r and \e are