1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Implementation of runtime/debug.WriteHeapDump. Writes all
6 // objects in the heap plus additional info (roots, threads,
7 // finalizers, etc.) to a file.
9 // The format of the dumped file is described at
10 // http://code.google.com/p/go-wiki/wiki/heapdump14
13 #include "arch_GOARCH.h"
19 #include "zaexperiment.h"
22 extern byte runtime·data[];
23 extern byte runtime·edata[];
24 extern byte runtime·bss[];
25 extern byte runtime·ebss[];
44 TagQueuedFinalizer = 11,
53 static uintptr* playgcprog(uintptr offset, uintptr *prog, void (*callback)(void*,uintptr,uintptr), void *arg);
54 static void dumpfields(BitVector bv);
55 static void dumpbvtypes(BitVector *bv, byte *base);
56 static BitVector makeheapobjbv(byte *p, uintptr size);
58 // fd to write the dump to.
59 static uintptr dumpfd;
61 #pragma dataflag NOPTR /* tmpbuf not a heap pointer at least */
63 static uintptr tmpbufsize;
65 // buffer of pending write data
69 #pragma dataflag NOPTR
70 static byte buf[BufSize];
74 write(byte *data, uintptr len)
76 if(len + nbuf <= BufSize) {
77 runtime·memmove(buf + nbuf, data, len);
81 runtime·write(dumpfd, buf, nbuf);
83 runtime·write(dumpfd, data, len);
86 runtime·memmove(buf, data, len);
94 runtime·write(dumpfd, buf, nbuf);
98 // Cache of types that have been serialized already.
99 // We use a type's hash field to pick a bucket.
100 // Inside a bucket, we keep a list of types that
101 // have been serialized so far, most recently used first.
102 // Note: when a bucket overflows we may end up
103 // serializing a type more than once. That's ok.
105 TypeCacheBuckets = 256, // must be a power of 2
108 typedef struct TypeCacheBucket TypeCacheBucket;
109 struct TypeCacheBucket {
110 Type *t[TypeCacheAssoc];
112 #pragma dataflag NOPTR /* only initialized and used while world is stopped */
113 static TypeCacheBucket typecache[TypeCacheBuckets];
115 // dump a uint64 in a varint format parseable by encoding/binary
136 // dump varint uint64 length followed by memory contents
138 dumpmemrange(byte *data, uintptr len)
147 dumpmemrange(s.str, s.len);
153 dumpmemrange((byte*)c, runtime·findnull((byte*)c));
156 // dump information for a type
167 // If we've definitely serialized the type before,
168 // no need to do it again.
169 b = &typecache[t->hash & (TypeCacheBuckets-1)];
170 if(t == b->t[0]) return;
171 for(i = 1; i < TypeCacheAssoc; i++) {
174 for(j = i; j > 0; j--) {
181 // Might not have been dumped yet. Dump it and
182 // remember we did so.
183 for(j = TypeCacheAssoc-1; j > 0; j--) {
192 if(t->x == nil || t->x->pkgPath == nil || t->x->name == nil) {
195 dumpint(t->x->pkgPath->len + 1 + t->x->name->len);
196 write(t->x->pkgPath->str, t->x->pkgPath->len);
197 write((byte*)".", 1);
198 write(t->x->name->str, t->x->name->len);
200 dumpbool((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0);
205 dumpobj(byte *obj, uintptr size, BitVector bv)
207 dumpbvtypes(&bv, obj);
209 dumpint((uintptr)obj);
210 dumpmemrange(obj, size);
215 dumpotherroot(int8 *description, byte *to)
217 dumpint(TagOtherRoot);
218 dumpcstr(description);
219 dumpint((uintptr)to);
223 dumpfinalizer(byte *obj, FuncVal *fn, Type* fint, PtrType *ot)
225 dumpint(TagFinalizer);
226 dumpint((uintptr)obj);
227 dumpint((uintptr)fn);
228 dumpint((uintptr)fn->fn);
229 dumpint((uintptr)fint);
230 dumpint((uintptr)ot);
233 typedef struct ChildInfo ChildInfo;
235 // Information passed up from the callee frame about
236 // the layout of the outargs region.
237 uintptr argoff; // where the arguments start in the frame
238 uintptr arglen; // size of args region
239 BitVector args; // if args.n >= 0, pointer map of args region
241 byte *sp; // callee sp
242 uintptr depth; // depth in call stack (0 == most recent)
245 // dump kinds & offsets of interesting fields in bv
247 dumpbv(BitVector *bv, uintptr offset)
251 for(i = 0; i < bv->n; i += BitsPerPointer) {
252 switch(bv->bytedata[i/8] >> i%8 & 3) {
254 // BitsDead has already been processed in makeheapobjbv.
255 // We should only see it in stack maps, in which case we should continue processing.
260 dumpint(FieldKindPtr);
261 dumpint(offset + i / BitsPerPointer * PtrSize);
264 runtime·throw("bumpbv unexpected garbage collection bits");
270 dumpframe(Stkframe *s, void *arg)
274 uintptr pc, off, size;
280 child = (ChildInfo*)arg;
283 // Figure out what we can about our stack map
287 pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, pc);
289 // We do not have a valid pcdata value but there might be a
290 // stackmap for this function. It is likely that we are looking
291 // at the function prologue, assume so and hope for the best.
294 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
296 // Dump any types we will need to resolve Efaces.
297 if(child->args.n >= 0)
298 dumpbvtypes(&child->args, (byte*)s->sp + child->argoff);
299 if(stackmap != nil && stackmap->n > 0) {
300 bv = runtime·stackmapdata(stackmap, pcdata);
301 dumpbvtypes(&bv, (byte*)(s->varp - bv.n / BitsPerPointer * PtrSize));
306 // Dump main body of stack frame.
307 dumpint(TagStackFrame);
308 dumpint(s->sp); // lowest address in frame
309 dumpint(child->depth); // # of frames deep on the stack
310 dumpint((uintptr)child->sp); // sp of child, or 0 if bottom of stack
311 dumpmemrange((byte*)s->sp, s->fp - s->sp); // frame contents
314 dumpint(s->continpc);
315 name = runtime·funcname(f);
317 name = "unknown function";
320 // Dump fields in the outargs section
321 if(child->args.n >= 0) {
322 dumpbv(&child->args, child->argoff);
324 // conservative - everything might be a pointer
325 for(off = child->argoff; off < child->argoff + child->arglen; off += PtrSize) {
326 dumpint(FieldKindPtr);
331 // Dump fields in the local vars section
332 if(stackmap == nil) {
333 // No locals information, dump everything.
334 for(off = child->arglen; off < s->varp - s->sp; off += PtrSize) {
335 dumpint(FieldKindPtr);
338 } else if(stackmap->n < 0) {
339 // Locals size information, dump just the locals.
341 for(off = s->varp - size - s->sp; off < s->varp - s->sp; off += PtrSize) {
342 dumpint(FieldKindPtr);
345 } else if(stackmap->n > 0) {
346 // Locals bitmap information, scan just the pointers in
348 dumpbv(&bv, s->varp - bv.n / BitsPerPointer * PtrSize - s->sp);
350 dumpint(FieldKindEol);
352 // Record arg info for parent.
353 child->argoff = s->argp - s->fp;
354 child->arglen = s->arglen;
355 child->sp = (byte*)s->sp;
357 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
359 child->args = runtime·stackmapdata(stackmap, pcdata);
372 bool (*fn)(Stkframe*, void*);
374 if(gp->syscallsp != (uintptr)nil) {
384 dumpint(TagGoRoutine);
385 dumpint((uintptr)gp);
386 dumpint((uintptr)sp);
389 dumpint(runtime·readgstatus(gp));
390 dumpbool(gp->issystem);
391 dumpbool(false); // isbackground
392 dumpint(gp->waitsince);
393 dumpstr(gp->waitreason);
394 dumpint((uintptr)gp->sched.ctxt);
395 dumpint((uintptr)gp->m);
396 dumpint((uintptr)gp->defer);
397 dumpint((uintptr)gp->panic);
405 runtime·gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, &fn, &child, 0);
407 // dump defer & panic records
408 for(d = gp->defer; d != nil; d = d->link) {
411 dumpint((uintptr)gp);
412 dumpint((uintptr)d->argp);
413 dumpint((uintptr)d->pc);
414 dumpint((uintptr)d->fn);
415 dumpint((uintptr)d->fn->fn);
416 dumpint((uintptr)d->link);
418 for (p = gp->panic; p != nil; p = p->link) {
421 dumpint((uintptr)gp);
422 dumpint((uintptr)p->arg.type);
423 dumpint((uintptr)p->arg.data);
424 dumpint(0); // was p->defer, no longer recorded
425 dumpint((uintptr)p->link);
436 // goroutines & stacks
437 for(i = 0; i < runtime·allglen; i++) {
438 gp = runtime·allg[i];
439 status = runtime·readgstatus(gp); // The world is stopped so gp will not be in a scan state.
442 runtime·printf("runtime: unexpected G.status %d\n", status);
443 runtime·throw("dumpgs in STW - bad status");
456 finq_callback(FuncVal *fn, byte *obj, uintptr nret, Type *fint, PtrType *ot)
458 dumpint(TagQueuedFinalizer);
459 dumpint((uintptr)obj);
460 dumpint((uintptr)fn);
461 dumpint((uintptr)fn->fn);
462 dumpint((uintptr)fint);
463 dumpint((uintptr)ot);
471 MSpan *s, **allspans;
474 SpecialFinalizer *spf;
478 dumpbvtypes(&runtime·gcdatamask, runtime·data);
480 dumpint((uintptr)runtime·data);
481 dumpmemrange(runtime·data, runtime·edata - runtime·data);
482 dumpfields(runtime·gcdatamask);
485 dumpbvtypes(&runtime·gcbssmask, runtime·bss);
487 dumpint((uintptr)runtime·bss);
488 dumpmemrange(runtime·bss, runtime·ebss - runtime·bss);
489 dumpfields(runtime·gcbssmask);
492 allspans = runtime·mheap.allspans;
493 for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
494 s = allspans[spanidx];
495 if(s->state == MSpanInUse) {
497 for(sp = s->specials; sp != nil; sp = sp->next) {
498 if(sp->kind != KindSpecialFinalizer)
500 spf = (SpecialFinalizer*)sp;
501 p = (byte*)((s->start << PageShift) + spf->special.offset);
502 dumpfinalizer(p, spf->fn, spf->fint, spf->ot);
508 runtime·iterate_finq(finq_callback);
511 // Bit vector of free marks.
512 // Needs to be as big as the largest number of objects per span.
513 #pragma dataflag NOPTR
514 static byte free[PageSize/8];
519 uintptr i, j, size, n;
524 for(i = 0; i < runtime·mheap.nspan; i++) {
525 s = runtime·mheap.allspans[i];
526 if(s->state != MSpanInUse)
528 p = (byte*)(s->start << PageShift);
530 n = (s->npages << PageShift) / size;
532 runtime·throw("free array doesn't have enough entries");
533 for(l = s->freelist; l != nil; l = l->next)
534 free[((byte*)l - p) / size] = true;
535 for(j = 0; j < n; j++, p += size) {
540 dumpobj(p, size, makeheapobjbv(p, size));
553 dumpbool(false); // little-endian ptrs
555 dumpbool(true); // big-endian ptrs
557 dumpint((uintptr)runtime·mheap.arena_start);
558 dumpint((uintptr)runtime·mheap.arena_used);
560 dumpcstr(GOEXPERIMENT);
561 dumpint(runtime·ncpu);
565 itab_callback(Itab *tab)
570 // Dump a map from itab* to the type of its data field.
571 // We want this map so we can deduce types of interface referents.
572 if((t->kind & KindDirectIface) == 0) {
573 // indirect - data slot is a pointer to t.
576 dumpint((uintptr)tab);
577 dumpint((uintptr)t->ptrto);
578 } else if((t->kind & KindNoPointers) == 0) {
579 // t is pointer-like - data slot is a t.
582 dumpint((uintptr)tab);
585 // Data slot is a scalar. Dump type just for fun.
586 // With pointer-only interfaces, this shouldn't happen.
589 dumpint((uintptr)tab);
600 runtime·iterate_itabs(&fn);
608 for(mp = runtime·allm; mp != nil; mp = mp->alllink) {
609 dumpint(TagOSThread);
610 dumpint((uintptr)mp);
621 dumpint(TagMemStats);
622 dumpint(mstats.alloc);
623 dumpint(mstats.total_alloc);
625 dumpint(mstats.nlookup);
626 dumpint(mstats.nmalloc);
627 dumpint(mstats.nfree);
628 dumpint(mstats.heap_alloc);
629 dumpint(mstats.heap_sys);
630 dumpint(mstats.heap_idle);
631 dumpint(mstats.heap_inuse);
632 dumpint(mstats.heap_released);
633 dumpint(mstats.heap_objects);
634 dumpint(mstats.stacks_inuse);
635 dumpint(mstats.stacks_sys);
636 dumpint(mstats.mspan_inuse);
637 dumpint(mstats.mspan_sys);
638 dumpint(mstats.mcache_inuse);
639 dumpint(mstats.mcache_sys);
640 dumpint(mstats.buckhash_sys);
641 dumpint(mstats.gc_sys);
642 dumpint(mstats.other_sys);
643 dumpint(mstats.next_gc);
644 dumpint(mstats.last_gc);
645 dumpint(mstats.pause_total_ns);
646 for(i = 0; i < 256; i++)
647 dumpint(mstats.pause_ns[i]);
648 dumpint(mstats.numgc);
652 dumpmemprof_callback(Bucket *b, uintptr nstk, uintptr *stk, uintptr size, uintptr allocs, uintptr frees)
664 for(i = 0; i < nstk; i++) {
666 f = runtime·findfunc(pc);
668 runtime·snprintf(buf, sizeof(buf), "%X", (uint64)pc);
669 dumpcstr((int8*)buf);
673 dumpcstr(runtime·funcname(f));
674 // TODO: Why do we need to back up to a call instruction here?
675 // Maybe profiler should do this.
676 if(i > 0 && pc > f->entry) {
677 if(thechar == '6' || thechar == '8')
682 line = runtime·funcline(f, pc, &file);
694 MSpan *s, **allspans;
699 void (*fn)(Bucket*, uintptr, uintptr*, uintptr, uintptr, uintptr);
701 fn = dumpmemprof_callback;
702 runtime·iterate_memprof(&fn);
704 allspans = runtime·mheap.allspans;
705 for(spanidx=0; spanidx<runtime·mheap.nspan; spanidx++) {
706 s = allspans[spanidx];
707 if(s->state != MSpanInUse)
709 for(sp = s->specials; sp != nil; sp = sp->next) {
710 if(sp->kind != KindSpecialProfile)
712 spp = (SpecialProfile*)sp;
713 p = (byte*)((s->start << PageShift) + spp->special.offset);
714 dumpint(TagAllocSample);
716 dumpint((uintptr)spp->b);
728 // make sure we're done sweeping
729 for(i = 0; i < runtime·mheap.nspan; i++) {
730 s = runtime·mheap.allspans[i];
731 if(s->state == MSpanInUse)
732 runtime·MSpan_EnsureSwept(s);
735 runtime·memclr((byte*)&typecache[0], sizeof(typecache));
736 hdr = (byte*)"go1.4 heap dump\n";
737 write(hdr, runtime·findnull(hdr));
751 runtime·writeheapdump_m(void)
755 fd = g->m->scalararg[0];
756 g->m->scalararg[0] = 0;
758 runtime·casgstatus(g->m->curg, Grunning, Gwaiting);
759 g->waitreason = runtime·gostringnocopy((byte*)"dumping heap");
761 // Update stats so we can dump them.
762 // As a side effect, flushes all the MCaches so the MSpan.freelist
763 // lists contain all the free objects.
764 runtime·updatememstats(nil);
769 // Call dump routine.
775 runtime·SysFree(tmpbuf, tmpbufsize, &mstats.other_sys);
780 runtime·casgstatus(g->m->curg, Gwaiting, Grunning);
783 // dumpint() the kind & offset of each field in an object.
785 dumpfields(BitVector bv)
788 dumpint(FieldKindEol);
791 // The heap dump reader needs to be able to disambiguate
792 // Eface entries. So it needs to know every type that might
793 // appear in such an entry. The following routine accomplishes that.
795 // Dump all the types that appear in the type field of
796 // any Eface described by this bit vector.
798 dumpbvtypes(BitVector *bv, byte *base)
802 for(i = 0; i < bv->n; i += BitsPerPointer) {
803 if((bv->bytedata[i/8] >> i%8 & 3) != BitsMultiWord)
805 switch(bv->bytedata[(i+BitsPerPointer)/8] >> (i+BitsPerPointer)%8 & 3) {
807 runtime·throw("unexpected garbage collection bits");
812 dumptype(*(Type**)(base + i / BitsPerPointer * PtrSize));
820 makeheapobjbv(byte *p, uintptr size)
822 uintptr off, nptr, i;
823 byte shift, *bitp, bits;
826 // Extend the temp buffer if necessary.
828 if(tmpbufsize < nptr*BitsPerPointer/8+1) {
830 runtime·SysFree(tmpbuf, tmpbufsize, &mstats.other_sys);
831 tmpbufsize = nptr*BitsPerPointer/8+1;
832 tmpbuf = runtime·sysAlloc(tmpbufsize, &mstats.other_sys);
834 runtime·throw("heapdump: out of memory");
837 // Copy and compact the bitmap.
839 for(i = 0; i < nptr; i++) {
840 off = (uintptr*)(p + i*PtrSize) - (uintptr*)runtime·mheap.arena_start;
841 bitp = runtime·mheap.arena_start - off/wordsPerBitmapByte - 1;
842 shift = (off % wordsPerBitmapByte) * gcBits;
843 bits = (*bitp >> (shift + 2)) & BitsMask;
844 if(!mw && bits == BitsDead)
845 break; // end of heap object
846 mw = !mw && bits == BitsMultiWord;
847 tmpbuf[i*BitsPerPointer/8] &= ~(BitsMask<<((i*BitsPerPointer)%8));
848 tmpbuf[i*BitsPerPointer/8] |= bits<<((i*BitsPerPointer)%8);
850 return (BitVector){i*BitsPerPointer, tmpbuf};