tools/perf/util/dso.c

Source file repositories/reference/linux-study-clean/tools/perf/util/dso.c

File Facts

System
Linux kernel
Corpus path
tools/perf/util/dso.c
Extension
.c
Size
49777 bytes
Lines
2007
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct find_file_offset_data {
	u64 ip;
	u64 offset;
};

/* This will be called for each PHDR in an ELF binary */
static int find_file_offset(u64 start, u64 len, u64 pgoff, void *arg)
{
	struct find_file_offset_data *data = arg;

	if (start <= data->ip && data->ip < start + len) {
		data->offset = pgoff + data->ip - start;
		return 1;
	}
	return 0;
}

static const u8 *__dso__read_symbol(struct dso *dso, const char *symfs_filename,
				    u64 start, size_t len,
				    u8 **out_buf, u64 *out_buf_len, bool *is_64bit)
{
	struct nscookie nsc;
	int fd;
	ssize_t count;
	struct find_file_offset_data data = {
		.ip = start,
	};
	u8 *code_buf = NULL;
	int saved_errno;

	nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
	fd = open(symfs_filename, O_RDONLY);
	saved_errno = errno;
	nsinfo__mountns_exit(&nsc);
	if (fd < 0) {
		errno = saved_errno;
		return NULL;
	}
	if (file__read_maps(fd, /*exe=*/true, find_file_offset, &data, is_64bit) <= 0) {
		close(fd);
		errno = ENOENT;
		return NULL;
	}
	code_buf = malloc(len);
	if (code_buf == NULL) {
		close(fd);
		errno = ENOMEM;
		return NULL;
	}
	count = pread(fd, code_buf, len, data.offset);
	saved_errno = errno;
	close(fd);
	if ((u64)count != len) {
		free(code_buf);
		errno = saved_errno;
		return NULL;
	}
	*out_buf = code_buf;
	*out_buf_len = len;
	return code_buf;
}

/*
 * Read a symbol into memory for disassembly by a library like capstone of
 * libLLVM. If memory is allocated out_buf holds it.
 */
const u8 *dso__read_symbol(struct dso *dso, const char *symfs_filename,
			   const struct map *map, const struct symbol *sym,
			   u8 **out_buf, u64 *out_buf_len, bool *is_64bit)
{
	u64 start = map__rip_2objdump(map, sym->start);
	u64 end = map__rip_2objdump(map, sym->end);
	size_t len = end - start;

	*out_buf = NULL;
	*out_buf_len = 0;
	*is_64bit = false;

	if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) {
		/*
		 * Note, there is fallback BPF image disassembly in the objdump
		 * version but it currently does nothing.
		 */
		errno = EOPNOTSUPP;
		return NULL;
	}
	if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) {
#ifdef HAVE_LIBBPF_SUPPORT
		struct bpf_prog_info_node *info_node;
		struct perf_bpil *info_linear;

Annotation

Implementation Notes