Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf annotate: Add support to use libcapstone in powerpc

Now perf uses the capstone library to disassemble the instructions in
x86. capstone is used (if available) for perf annotate to speed up.

Currently it only supports x86 architecture.

This patch includes changes to enable this in powerpc.

For now, only for data type sort keys, this method is used and only
binary code (raw instruction) is read. This is because powerpc approach
to understand instructions and reg fields uses raw instruction.

The "cs_disasm" is currently not enabled. While attempting to do
cs_disasm, observation is that some of the instructions were not
identified (ex: extswsli, maddld) and it had to fallback to use objdump.

Hence enabling "cs_disasm" is added in comment section as a TODO for
powerpc.

Reviewed-by: Kajol Jain <kjain@linux.ibm.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Tested-by: Kajol Jain <kjain@linux.ibm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Akanksha J N <akanksha@linux.ibm.com>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Disha Goel <disgoel@linux.vnet.ibm.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Segher Boessenkool <segher@kernel.crashing.org>
Link: https://lore.kernel.org/lkml/20240718084358.72242-15-atrajeev@linux.vnet.ibm.com
[ Use dso__nsinfo(dso) as required to match EXTRA_CFLAGS=-DREFCNT_CHECKING=1 build expectations ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Athira Rajeev and committed by
Arnaldo Carvalho de Melo
c5d60de1 f1e9347c

+143
+143
tools/perf/util/disasm.c
··· 1614 1614 } 1615 1615 } 1616 1616 1617 + static int symbol__disassemble_capstone_powerpc(char *filename, struct symbol *sym, 1618 + struct annotate_args *args) 1619 + { 1620 + struct annotation *notes = symbol__annotation(sym); 1621 + struct map *map = args->ms.map; 1622 + struct dso *dso = map__dso(map); 1623 + struct nscookie nsc; 1624 + u64 start = map__rip_2objdump(map, sym->start); 1625 + u64 end = map__rip_2objdump(map, sym->end); 1626 + u64 len = end - start; 1627 + u64 offset; 1628 + int i, fd, count; 1629 + bool is_64bit = false; 1630 + bool needs_cs_close = false; 1631 + u8 *buf = NULL; 1632 + struct find_file_offset_data data = { 1633 + .ip = start, 1634 + }; 1635 + csh handle; 1636 + char disasm_buf[512]; 1637 + struct disasm_line *dl; 1638 + u32 *line; 1639 + bool disassembler_style = false; 1640 + 1641 + if (args->options->objdump_path) 1642 + return -1; 1643 + 1644 + nsinfo__mountns_enter(dso__nsinfo(dso), &nsc); 1645 + fd = open(filename, O_RDONLY); 1646 + nsinfo__mountns_exit(&nsc); 1647 + if (fd < 0) 1648 + return -1; 1649 + 1650 + if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, 1651 + &is_64bit) == 0) 1652 + goto err; 1653 + 1654 + if (!args->options->disassembler_style || 1655 + !strcmp(args->options->disassembler_style, "att")) 1656 + disassembler_style = true; 1657 + 1658 + if (capstone_init(maps__machine(args->ms.maps), &handle, is_64bit, disassembler_style) < 0) 1659 + goto err; 1660 + 1661 + needs_cs_close = true; 1662 + 1663 + buf = malloc(len); 1664 + if (buf == NULL) 1665 + goto err; 1666 + 1667 + count = pread(fd, buf, len, data.offset); 1668 + close(fd); 1669 + fd = -1; 1670 + 1671 + if ((u64)count != len) 1672 + goto err; 1673 + 1674 + line = (u32 *)buf; 1675 + 1676 + /* add the function address and name */ 1677 + scnprintf(disasm_buf, sizeof(disasm_buf), "%#"PRIx64" <%s>:", 1678 + start, sym->name); 1679 + 1680 + args->offset = -1; 1681 + args->line = disasm_buf; 1682 + args->line_nr = 0; 1683 + args->fileloc = NULL; 1684 + args->ms.sym = sym; 1685 + 1686 + dl = disasm_line__new(args); 1687 + if (dl == NULL) 1688 + goto err; 1689 + 1690 + annotation_line__add(&dl->al, &notes->src->source); 1691 + 1692 + /* 1693 + * TODO: enable disassm for powerpc 1694 + * count = cs_disasm(handle, buf, len, start, len, &insn); 1695 + * 1696 + * For now, only binary code is saved in disassembled line 1697 + * to be used in "type" and "typeoff" sort keys. Each raw code 1698 + * is 32 bit instruction. So use "len/4" to get the number of 1699 + * entries. 1700 + */ 1701 + count = len/4; 1702 + 1703 + for (i = 0, offset = 0; i < count; i++) { 1704 + args->offset = offset; 1705 + sprintf(args->line, "%x", line[i]); 1706 + 1707 + dl = disasm_line__new(args); 1708 + if (dl == NULL) 1709 + goto err; 1710 + 1711 + annotation_line__add(&dl->al, &notes->src->source); 1712 + 1713 + offset += 4; 1714 + } 1715 + 1716 + /* It failed in the middle */ 1717 + if (offset != len) { 1718 + struct list_head *list = &notes->src->source; 1719 + 1720 + /* Discard all lines and fallback to objdump */ 1721 + while (!list_empty(list)) { 1722 + dl = list_first_entry(list, struct disasm_line, al.node); 1723 + 1724 + list_del_init(&dl->al.node); 1725 + disasm_line__free(dl); 1726 + } 1727 + count = -1; 1728 + } 1729 + 1730 + out: 1731 + if (needs_cs_close) 1732 + cs_close(&handle); 1733 + free(buf); 1734 + return count < 0 ? count : 0; 1735 + 1736 + err: 1737 + if (fd >= 0) 1738 + close(fd); 1739 + if (needs_cs_close) { 1740 + struct disasm_line *tmp; 1741 + 1742 + /* 1743 + * It probably failed in the middle of the above loop. 1744 + * Release any resources it might add. 1745 + */ 1746 + list_for_each_entry_safe(dl, tmp, &notes->src->source, al.node) { 1747 + list_del(&dl->al.node); 1748 + free(dl); 1749 + } 1750 + } 1751 + count = -1; 1752 + goto out; 1753 + } 1754 + 1617 1755 static int symbol__disassemble_capstone(char *filename, struct symbol *sym, 1618 1756 struct annotate_args *args) 1619 1757 { ··· 2106 1968 err = symbol__disassemble_raw(symfs_filename, sym, args); 2107 1969 if (err == 0) 2108 1970 goto out_remove_tmp; 1971 + #ifdef HAVE_LIBCAPSTONE_SUPPORT 1972 + err = symbol__disassemble_capstone_powerpc(symfs_filename, sym, args); 1973 + if (err == 0) 1974 + goto out_remove_tmp; 1975 + #endif 2109 1976 } 2110 1977 } 2111 1978