diff options
Diffstat (limited to '')
-rw-r--r-- | .gdbinit | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..8879865 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,598 @@ +# gdb macros which may be useful for folks using gdb to debug +# apache. Delete it if it bothers you. + +define dump_table + set $t = (apr_table_entry_t *)((apr_array_header_t *)$arg0)->elts + set $n = ((apr_array_header_t *)$arg0)->nelts + set $i = 0 + while $i < $n + if $t[$i].val == (void *)0L + printf "[%u] '%s'=>NULL\n", $i, $t[$i].key + else + printf "[%u] '%s'='%s' [%p]\n", $i, $t[$i].key, $t[$i].val, $t[$i].val + end + set $i = $i + 1 + end +end +document dump_table + Print the key/value pairs in a table. +end + +define dump_skiplist + set $sl = (apr_skiplist *)$arg0 + set $m = $sl->bottom + printf "skiplist@%p: size=%lu: height=%d\n", $sl, $sl->size, $sl->height + while ($m) + printf "(%p,%.12lx)", $m, $m->data + set $u = $m->up + while ($u) + printf " (%p,%.12lx)", $u, $u->data + set $u = $u->up + end + printf "\n" + set $m = $m->next + end +end +document dump_skiplist + Print the nodes/values in a skiplist +end + +define dump_string_hash + set $h = $arg0->array + set $n = $arg0->max + set $i = 0 + while $i < $n + set $ent = $h[$i] + while $ent != (void *)0L + printf "'%s' => '%p'\n", $ent->key, $ent->val + set $ent = $ent->next + end + set $i = $i + 1 + end +end +document dump_string_hash + Print the entries in a hash table indexed by strings +end + +define dump_string_shash + set $h = $arg0->array + set $n = $arg0->max + set $i = 0 + while $i < $n + set $ent = $h[$i] + while $ent != (void *)0L + printf "'%s' => '%s'\n", $ent->key, $ent->val + set $ent = $ent->next + end + set $i = $i + 1 + end +end +document dump_string_shash + Print the entries in a hash table indexed by strings with string values +end + +define ro + run -DONE_PROCESS +end + +define dump_string_array + set $a = (char **)((apr_array_header_t *)$arg0)->elts + set $n = (int)((apr_array_header_t *)$arg0)->nelts + set $i = 0 + while $i < $n + printf "[%u] '%s'\n", $i, $a[$i] + set $i = $i + 1 + end +end +document dump_string_array + Print all of the elements in an array of strings. +end + +define printmemn + set $i = 0 + while $i < $arg1 + if $arg0[$i] < 0x20 || $arg0[$i] > 0x7e + printf "~" + else + printf "%c", $arg0[$i] + end + set $i = $i + 1 + end +end + +define print_bkt_datacol + # arg0 == column name + # arg1 == format + # arg2 == value + # arg3 == suppress header? + set $suppressheader = $arg3 + + if !$suppressheader + printf " " + printf $arg0 + printf "=" + else + printf " | " + end + printf $arg1, $arg2 +end + +define dump_bucket_ex + # arg0 == bucket + # arg1 == suppress header? + set $bucket = (struct apr_bucket *)$arg0 + set $sh = $arg1 + set $refcount = -1 + + print_bkt_datacol "bucket" "%-9s" $bucket->type->name $sh + printf "(%12lx)", (unsigned long)$bucket + print_bkt_datacol "length" "%-6ld" (long)($bucket->length) $sh + print_bkt_datacol "data" "%12lx" $bucket->data $sh + + if !$sh + printf "\n " + end + + if (($bucket->type == &apr_bucket_type_eos) || \ + ($bucket->type == &apr_bucket_type_flush)) + + # metadata buckets, no content + print_bkt_datacol "contents" "%c" ' ' $sh + printf " " + print_bkt_datacol "rc" "n/%c" 'a' $sh + + else + if ($bucket->type == &ap_bucket_type_error) + + # metadata bucket, no content but it does have an error code in it + print_bkt_datacol "contents" "%c" ' ' $sh + set $status = ((ap_bucket_error *)$bucket->data)->status + printf " (status=%3d) ", $status + print_bkt_datacol "rc" "n/%c" 'a' $sh + + else + if ($bucket->type == &apr_bucket_type_file) + + # file bucket, can show fd and refcount + set $fd = ((apr_bucket_file*)$bucket->data)->fd->filedes + print_bkt_datacol "contents" "[***file***] fd=%-6ld" (long)$fd $sh + set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount + print_bkt_datacol "rc" "%-3d" $refcount $sh + + else + if (($bucket->type == &apr_bucket_type_heap) || \ + ($bucket->type == &apr_bucket_type_pool) || \ + ($bucket->type == &apr_bucket_type_mmap) || \ + ($bucket->type == &apr_bucket_type_transient) || \ + ($bucket->type == &apr_bucket_type_immortal)) + + # in-memory buckets + + if $bucket->type == &apr_bucket_type_heap + set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount + set $p = (apr_bucket_heap *)$bucket->data + set $data = $p->base+$bucket->start + + else + if $bucket->type == &apr_bucket_type_pool + set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount + set $p = (apr_bucket_pool *)$bucket->data + if !$p->pool + set $p = (apr_bucket_heap *)$bucket->data + end + set $data = $p->base+$bucket->start + + else + if $bucket->type == &apr_bucket_type_mmap + # is this safe if not APR_HAS_MMAP? + set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount + set $p = (apr_bucket_mmap *)$bucket->data + set $data = ((char *)$p->mmap->mm)+$bucket->start + + else + if (($bucket->type == &apr_bucket_type_transient) || \ + ($bucket->type == &apr_bucket_type_immortal)) + set $data = ((char *)$bucket->data)+$bucket->start + + end + end + end + end + + if $sh + printf " | [" + else + printf " contents=[" + end + set $datalen = $bucket->length + if $isValidAddress($data) == 1 + if $datalen > 17 + printmem $data 17 + printf "..." + set $datalen = 20 + else + printmemn $data $datalen + end + printf "]" + while $datalen < 20 + printf " " + set $datalen = $datalen + 1 + end + else + printf "Iv addr %12lx]", $data + end + + if $refcount != -1 + print_bkt_datacol "rc" "%-3d" $refcount $sh + else + print_bkt_datacol "rc" "n/%c" 'a' $sh + end + + else + if ($bucket->type == &apr_bucket_type_pipe) + + # pipe bucket, can show fd + set $fd = ((apr_file_t*)$bucket->data)->filedes + print_bkt_datacol "contents" "[***pipe***] fd=%-3ld" (long)$fd $sh + + else + if ($bucket->type == &apr_bucket_type_socket) + + # file bucket, can show fd + set $fd = ((apr_socket_t*)$bucket->data)->socketdes + print_bkt_datacol "contents" "[**socket**] fd=%-3ld" (long)$fd $sh + + else + + # 3rd-party bucket type + print_bkt_datacol "contents" "[**opaque**]%-7c" ' ' $sh + end + end + + # no refcount + printf " " + print_bkt_datacol "rc" "n/%c" 'a' $sh + end + end + end + end + + printf "\n" + +end + +define dump_bucket + dump_bucket_ex $arg0 0 +end +document dump_bucket + Print bucket info +end + +define dump_brigade + set $bb = (apr_bucket_brigade *)$arg0 + set $bucket = $bb->list.next + set $sentinel = ((char *)((&($bb->list)) \ + - ((size_t) &((struct apr_bucket *)0)->link))) + printf "dump of brigade 0x%lx\n", (unsigned long)$bb + + printf " | type (address) | length | " + printf "data address | contents | rc\n" + printf "-------------------------------------------" + printf "----------------------------------------\n" + + if $bucket == $sentinel + printf "brigade is empty\n" + end + + set $j = 0 + set $brigade_length = 0 + while $bucket != $sentinel + printf "%2d", $j + dump_bucket_ex $bucket 1 + set $j = $j + 1 + if $bucket->length > 0 + set $brigade_length = $brigade_length + $bucket->length + end + set $bucket = $bucket->link.next + end + printf "end of brigade\n" + printf "Length of brigade (excluding buckets of unknown length): %u\n", $brigade_length +end +document dump_brigade + Print bucket brigade info +end + +define dump_filters + set $f = $arg0 + while $f + printf "%s(0x%lx): ctx=0x%lx, r=0x%lx, c=0x%lx\n", \ + $f->frec->name, (unsigned long)$f, (unsigned long)$f->ctx, \ + $f->r, $f->c + set $f = $f->next + end +end +document dump_filters + Print filter chain info +end + +define dump_filter_chain + set $r = $arg0 + set $f = $r->output_filters + while $f + if $f == $r->output_filters + printf "r->output_filters =>\n" + end + if $f == $r->proto_output_filters + printf "r->proto_output_filters =>\n" + end + if $f == $r->connection->output_filters + printf "r->connection->output_filters =>\n" + end + + printf " %s(0x%lx): type=%d, ctx=0x%lx, r=%s(0x%lx), c=0x%lx\n", \ + $f->frec->name, (unsigned long)$f, $f->frec->ftype, (unsigned long)$f->ctx, \ + $f->r == $r ? "r" : ($f->r == 0L ? "null" : \ + ($f->r == $r->main ? "r->main" : \ + ($r->main && $f->r == $r->main->main ? "r->main->main" : "????"))), \ + $f->r, $f->c + + set $f = $f->next + end +end +document dump_filter_chain + Print filter chain info given a request_rec pointer +end + +define dump_process_rec + set $p = $arg0 + printf "process_rec=0x%lx:\n", (unsigned long)$p + printf " pool=0x%lx, pconf=0x%lx\n", \ + (unsigned long)$p->pool, (unsigned long)$p->pconf +end +document dump_process_rec + Print process_rec info +end + +define dump_server_addr_recs + set $sa_ = $arg0 + set $san_ = 0 + while $sa_ + ### need to call apr_sockaddr_info_getbuf to print ->host_addr properly + ### which is a PITA since we need a buffer :( + printf " addr#%d: vhost=%s -> :%d\n", $san_++, $sa_->virthost, $sa_->host_port + set $sa_ = $sa_->next + end +end +document dump_server_addr_recs + Print server_addr_rec info +end + + +define dump_server_rec + set $s = $arg0 + printf "name=%s:%d (0x%lx)\n", \ + $s->server_hostname, $s->port, $s + dump_server_addr_recs $s->addrs + dump_process_rec($s->process) +end +document dump_server_rec + Print server_rec info +end + +define dump_servers + set $s = $arg0 + while $s + dump_server_rec($s) + printf "\n" + set $s = $s->next + end +end +document dump_servers + Print server_rec list info +end + +define dump_request_tree + set $r = $arg0 + set $i + while $r + printf "r=(0x%lx): uri=%s, handler=%s, r->main=0x%lx\n", \ + $r, $r->unparsed_uri, $r->handler ? $r->handler : "(none)", $r->main + set $r = $r->main + end +end + +define dump_scoreboard + # Need to reserve size of array first before string literals could be + # put in + set $status = {0, 1, 2, 3, 4 ,5 ,6 ,7 ,8 ,9 ,10} + set $status = {"DEAD", "STARTING", "READY", "BUSY_READ", "BUSY_WRITE", "BUSY_KEEPALIVE", "BUSY_LOG", "BUSY_DNS", "CLOSING", "GRACEFUL", "IDLE_KILL"} + set $i = 0 + while ($i < server_limit) + if ap_scoreboard_image->servers[$i][0].pid != 0 + set $j = 0 + while ($j < threads_per_child) + set $ws = ap_scoreboard_image->servers[$i][$j] + printf "pid: %d, tid: 0x%lx, status: %s\n", $ws.pid, $ws.tid, $status[$ws.status] + set $j = $j +1 + end + end + set $i = $i +1 + end +end +document dump_scoreboard + Dump the scoreboard +end + +define dump_allocator + printf "Allocator current_free_index = %d, max_free_index = %d\n", \ + ($arg0)->current_free_index, ($arg0)->max_free_index + printf "Allocator free list:\n" + set $i = 0 + set $max =(sizeof $arg0->free)/(sizeof $arg0->free[0]) + set $kb = 0 + while $i < $max + set $node = $arg0->free[$i] + if $node != 0 + printf " #%2d: ", $i + while $node != 0 + printf "%d, ", ($node->index + 1) << 12 + set $kb = $kb + (($node->index + 1) << 2) + set $node = $node->next + end + printf "ends.\n" + end + set $i = $i + 1 + end + printf "Sum of free blocks: %dkiB\n", $kb +end +document dump_allocator + Print status of an allocator and its freelists. +end + +define dump_one_pool + set $p = $arg0 + set $size = 0 + set $free = 0 + set $nodes = 0 + set $node = $arg0->active + set $done = 0 + while $done == 0 + set $size = $size + (($node->index + 1) << 12) + set $free = $free + ($node->endp - $node->first_avail) + set $nodes = $nodes + 1 + set $node = $node->next + if $node == $arg0->active + set $done = 1 + end + end + printf "Pool '" + if $p->tag + printf "%s", $p->tag + else + printf "no tag" + end + printf "' [%p]: %d/%d free (%d blocks)\n", $p, $free, $size, $nodes +end + +define dump_all_pools + if $argc > 0 + set $root = $arg0 + else + set $root = ap_pglobal + end + while $root->parent + set $root = $root->parent + end + dump_pool_and_children $root +end +document dump_all_pools + Dump the whole pool hierarchy starting from apr_global_pool. Optionally takes an arbitrary pool as starting parameter. +end + +python + +from __future__ import print_function + +class DumpPoolAndChilds (gdb.Command): + """Dump the whole pool hierarchy starting from the given pool.""" + + def __init__ (self): + super (DumpPoolAndChilds, self).__init__ ("dump_pool_and_children", gdb.COMMAND_USER) + + def _allocator_free_blocks(self, alloc): + salloc = "%s" % (alloc) + if self.total_free_blocks.get(salloc) != None: + return self.total_free_blocks[salloc] + i = 0 + dalloc = alloc.dereference() + max =(dalloc['free'].type.sizeof)/(dalloc['free'][0].type.sizeof) + kb = 0 + while i < max: + node = dalloc['free'][i] + if node != 0: + while node != 0: + noded = node.dereference() + kb = kb + ((int(noded['index']) + 1) << 2) + node = noded['next'] + i = i + 1 + self.total_free_blocks[salloc] = kb + return kb + + + def _dump_one_pool(self, arg): + size = 0 + free = 0 + nodes = 0 + darg = arg.dereference() + active = darg['active'] + node = active + done = 0 + while done == 0: + noded = node.dereference() + size = size + ((int(noded['index']) + 1) << 12) + free = free + (noded['endp'] - noded['first_avail']) + nodes = nodes + 1 + node = noded['next'] + if node == active: + done = 1 + if darg['tag'] != 0: + tag = darg['tag'].string() + else: + tag = "No tag" + print("Pool '%s' [%s]: %d/%d free (%d blocks) allocator: %s free blocks in allocator: %i kiB" % (tag, arg, free, size, nodes, darg['allocator'], self._allocator_free_blocks(darg['allocator']))) + self.free = self.free + free + self.size = self.size + size + self.nodes = self.nodes + nodes + + def _dump(self, arg, depth): + pool = arg + while pool: + print("%*c" % (depth * 4 + 1, " "), end="") + self._dump_one_pool(pool) + if pool['child'] != 0: + self._dump(pool['child'], depth + 1) + pool = pool['sibling'] + + def invoke (self, arg, from_tty): + pool = gdb.parse_and_eval(arg) + self.free = 0 + self.size = 0 + self.nodes = 0 + self.total_free_blocks = {} + self._dump(pool, 0) + print("Total %d/%d free (%d blocks)" % (self.free, self.size, self.nodes)) + sum = 0 + for key in self.total_free_blocks: + sum = sum + self.total_free_blocks[key] + print("Total free allocator blocks: %i kiB" % (sum)) + +DumpPoolAndChilds () +end +document dump_pool_and_children + Dump the whole pool hierarchy starting from the given pool. +end + +python + +class isValidAddress (gdb.Function): + """Determines if the argument is a valid address.""" + + def __init__(self): + super(isValidAddress, self).__init__("isValidAddress") + + def invoke(self, address): + inf = gdb.inferiors()[0] + result = 1 + try: + inf.read_memory(address, 8) + except: + result = 0 + return result + +isValidAddress() + +end + +# Set sane defaults for common signals: +handle SIGPIPE noprint pass nostop +handle SIGUSR1 print pass nostop |