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