func dump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, syms []Sym, textData []byte, textStart uint64) { stdout := bufio.NewWriter(os.Stdout) defer stdout.Flush() printed := false for _, sym := range syms { if sym.Code != 'T' || sym.Size == 0 || sym.Name == "_text" || sym.Name == "text" || sym.Addr < textStart || symRE != nil && !symRE.MatchString(sym.Name) { continue } if sym.Addr >= textStart+uint64(len(textData)) || sym.Addr+uint64(sym.Size) > textStart+uint64(len(textData)) { break } if printed { fmt.Fprintf(stdout, "\n") } else { printed = true } file, _, _ := tab.PCToLine(sym.Addr) fmt.Fprintf(stdout, "TEXT %s(SB) %s\n", sym.Name, file) tw := tabwriter.NewWriter(stdout, 1, 8, 1, '\t', 0) start := sym.Addr end := sym.Addr + uint64(sym.Size) for pc := start; pc < end; { i := pc - textStart text, size := disasm(textData[i:end-textStart], pc, lookup) file, line, _ := tab.PCToLine(pc) fmt.Fprintf(tw, "\t%s:%d\t%#x\t%x\t%s\n", base(file), line, pc, textData[i:i+uint64(size)], text) pc += uint64(size) } tw.Flush() } }
func gnuDump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, textData []byte, textStart uint64) { start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 16, 64) if err != nil { log.Fatalf("invalid start PC: %v", err) } end, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(2), "0x"), 16, 64) if err != nil { log.Fatalf("invalid end PC: %v", err) } if start < textStart { start = textStart } if end < start { end = start } if end > textStart+uint64(len(textData)) { end = textStart + uint64(len(textData)) } stdout := bufio.NewWriter(os.Stdout) defer stdout.Flush() // For now, find spans of same PC/line/fn and // emit them as having dummy instructions. var ( spanPC uint64 spanFile string spanLine int spanFn *gosym.Func ) flush := func(endPC uint64) { if spanPC == 0 { return } fmt.Fprintf(stdout, "%s:%d\n", spanFile, spanLine) for pc := spanPC; pc < endPC; { text, size := disasm(textData[pc-textStart:], pc, lookup) fmt.Fprintf(stdout, " %x: %s\n", pc, text) pc += uint64(size) } spanPC = 0 } for pc := start; pc < end; pc++ { file, line, fn := tab.PCToLine(pc) if file != spanFile || line != spanLine || fn != spanFn { flush(pc) spanPC, spanFile, spanLine, spanFn = pc, file, line, fn } } flush(end) }
func dump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, goarch string, syms []Sym, textData []byte, textStart uint64) { stdout := bufio.NewWriter(os.Stdout) defer stdout.Flush() printed := false for _, sym := range syms { if sym.Code != 'T' || sym.Size == 0 || sym.Name == "_text" || sym.Name == "text" || sym.Addr < textStart || symRE != nil && !symRE.MatchString(sym.Name) { continue } if sym.Addr >= textStart+uint64(len(textData)) || sym.Addr+uint64(sym.Size) > textStart+uint64(len(textData)) { break } if printed { fmt.Fprintf(stdout, "\n") } else { printed = true } file, _, _ := tab.PCToLine(sym.Addr) fmt.Fprintf(stdout, "TEXT %s(SB) %s\n", sym.Name, file) tw := tabwriter.NewWriter(stdout, 1, 8, 1, '\t', 0) start := sym.Addr end := sym.Addr + uint64(sym.Size) for pc := start; pc < end; { i := pc - textStart text, size := disasm(textData[i:end-textStart], pc, lookup) file, line, _ := tab.PCToLine(pc) // ARM is word-based, so show actual word hex, not byte hex. // Since ARM is little endian, they're different. if goarch == "arm" && size == 4 { fmt.Fprintf(tw, "\t%s:%d\t%#x\t%08x\t%s\n", base(file), line, pc, binary.LittleEndian.Uint32(textData[i:i+uint64(size)]), text) } else { fmt.Fprintf(tw, "\t%s:%d\t%#x\t%x\t%s\n", base(file), line, pc, textData[i:i+uint64(size)], text) } pc += uint64(size) } tw.Flush() } }