Commit e6593596 authored by Jiong Wang's avatar Jiong Wang Committed by Daniel Borkmann

tools: bpftool: improve architecture detection by using ifindex

The current architecture detection method in bpftool is designed for host
case.

For offload case, we can't use the architecture of "bpftool" itself.
Instead, we could call the existing "ifindex_to_name_ns" to get DEVNAME,
then read pci id from /sys/class/dev/DEVNAME/device/vendor, finally we map
vendor id to bfd arch name which will finally be used to select bfd backend
for the disassembler.
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarJiong Wang <jiong.wang@netronome.com>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent eb1d7db9
......@@ -34,6 +34,7 @@
/* Author: Jakub Kicinski <kubakici@wp.pl> */
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
#include <libgen.h>
#include <mntent.h>
......@@ -433,6 +434,77 @@ ifindex_to_name_ns(__u32 ifindex, __u32 ns_dev, __u32 ns_ino, char *buf)
return if_indextoname(ifindex, buf);
}
static int read_sysfs_hex_int(char *path)
{
char vendor_id_buf[8];
int len;
int fd;
fd = open(path, O_RDONLY);
if (fd < 0) {
p_err("Can't open %s: %s", path, strerror(errno));
return -1;
}
len = read(fd, vendor_id_buf, sizeof(vendor_id_buf));
close(fd);
if (len < 0) {
p_err("Can't read %s: %s", path, strerror(errno));
return -1;
}
if (len >= (int)sizeof(vendor_id_buf)) {
p_err("Value in %s too long", path);
return -1;
}
vendor_id_buf[len] = 0;
return strtol(vendor_id_buf, NULL, 0);
}
static int read_sysfs_netdev_hex_int(char *devname, const char *entry_name)
{
char full_path[64];
snprintf(full_path, sizeof(full_path), "/sys/class/net/%s/device/%s",
devname, entry_name);
return read_sysfs_hex_int(full_path);
}
const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino)
{
char devname[IF_NAMESIZE];
int vendor_id;
int device_id;
if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) {
p_err("Can't get net device name for ifindex %d: %s", ifindex,
strerror(errno));
return NULL;
}
vendor_id = read_sysfs_netdev_hex_int(devname, "vendor");
if (vendor_id < 0) {
p_err("Can't get device vendor id for %s", devname);
return NULL;
}
switch (vendor_id) {
case 0x19ee:
device_id = read_sysfs_netdev_hex_int(devname, "device");
if (device_id != 0x4000 &&
device_id != 0x6000 &&
device_id != 0x6003)
p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
return "NFP-6xxx";
default:
p_err("Can't get bfd arch name for device vendor id 0x%04x",
vendor_id);
return NULL;
}
}
void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
{
char name[IF_NAMESIZE];
......
......@@ -76,7 +76,8 @@ static int fprintf_json(void *out, const char *fmt, ...)
return 0;
}
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch)
{
disassembler_ftype disassemble;
struct disassemble_info info;
......@@ -100,6 +101,19 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
else
init_disassemble_info(&info, stdout,
(fprintf_ftype) fprintf);
/* Update architecture info for offload. */
if (arch) {
const bfd_arch_info_type *inf = bfd_scan_arch(arch);
if (inf) {
bfdf->arch_info = inf;
} else {
p_err("No libfd support for %s", arch);
return;
}
}
info.arch = bfd_get_arch(bfdf);
info.mach = bfd_get_mach(bfdf);
info.buffer = image;
......
......@@ -121,7 +121,10 @@ int do_cgroup(int argc, char **arg);
int prog_parse_fd(int *argc, char ***argv);
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes);
void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
const char *arch);
void print_hex_data_json(uint8_t *data, size_t len);
const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino);
#endif
......@@ -776,7 +776,17 @@ static int do_dump(int argc, char **argv)
}
} else {
if (member_len == &info.jited_prog_len) {
disasm_print_insn(buf, *member_len, opcodes);
const char *name = NULL;
if (info.ifindex) {
name = ifindex_to_bfd_name_ns(info.ifindex,
info.netns_dev,
info.netns_ino);
if (!name)
goto err_free;
}
disasm_print_insn(buf, *member_len, opcodes, name);
} else {
kernel_syms_load(&dd);
if (json_output)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment