brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · 19acf47 Raw
206 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * DWARF debug information handling code.  Copied from probe-finder.c.4 *5 * Written by Masami Hiramatsu <mhiramat@redhat.com>6 */7 8#include <errno.h>9#include <fcntl.h>10#include <stdio.h>11#include <stdlib.h>12#include <string.h>13#include <unistd.h>14#include <linux/zalloc.h>15 16#include "build-id.h"17#include "dso.h"18#include "debug.h"19#include "debuginfo.h"20#include "symbol.h"21 22#ifdef HAVE_DEBUGINFOD_SUPPORT23#include <elfutils/debuginfod.h>24#endif25 26/* Dwarf FL wrappers */27static char *debuginfo_path;	/* Currently dummy */28 29static const Dwfl_Callbacks offline_callbacks = {30	.find_debuginfo = dwfl_standard_find_debuginfo,31	.debuginfo_path = &debuginfo_path,32 33	.section_address = dwfl_offline_section_address,34 35	/* We use this table for core files too.  */36	.find_elf = dwfl_build_id_find_elf,37};38 39/* Get a Dwarf from offline image */40static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,41					 const char *path)42{43	GElf_Addr dummy;44	int fd;45 46	fd = open(path, O_RDONLY);47	if (fd < 0)48		return fd;49 50	dbg->dwfl = dwfl_begin(&offline_callbacks);51	if (!dbg->dwfl)52		goto error;53 54	dwfl_report_begin(dbg->dwfl);55	dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);56	if (!dbg->mod)57		goto error;58 59	dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);60	if (!dbg->dbg)61		goto error;62 63	dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy);64 65	dwfl_report_end(dbg->dwfl, NULL, NULL);66 67	return 0;68error:69	if (dbg->dwfl)70		dwfl_end(dbg->dwfl);71	else72		close(fd);73	memset(dbg, 0, sizeof(*dbg));74 75	return -ENOENT;76}77 78static struct debuginfo *__debuginfo__new(const char *path)79{80	struct debuginfo *dbg = zalloc(sizeof(*dbg));81	if (!dbg)82		return NULL;83 84	if (debuginfo__init_offline_dwarf(dbg, path) < 0)85		zfree(&dbg);86	if (dbg)87		pr_debug("Open Debuginfo file: %s\n", path);88	return dbg;89}90 91enum dso_binary_type distro_dwarf_types[] = {92	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,93	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,94	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,95	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,96	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,97	DSO_BINARY_TYPE__NOT_FOUND,98};99 100struct debuginfo *debuginfo__new(const char *path)101{102	enum dso_binary_type *type;103	char buf[PATH_MAX], nil = '\0';104	struct dso *dso;105	struct debuginfo *dinfo = NULL;106	struct build_id bid;107 108	/* Try to open distro debuginfo files */109	dso = dso__new(path);110	if (!dso)111		goto out;112 113	/* Set the build id for DSO_BINARY_TYPE__BUILDID_DEBUGINFO */114	if (is_regular_file(path) && filename__read_build_id(path, &bid) > 0)115		dso__set_build_id(dso, &bid);116 117	for (type = distro_dwarf_types;118	     !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;119	     type++) {120		if (dso__read_binary_type_filename(dso, *type, &nil,121						   buf, PATH_MAX) < 0)122			continue;123		dinfo = __debuginfo__new(buf);124	}125	dso__put(dso);126 127out:128	/* if failed to open all distro debuginfo, open given binary */129	return dinfo ? : __debuginfo__new(path);130}131 132void debuginfo__delete(struct debuginfo *dbg)133{134	if (dbg) {135		if (dbg->dwfl)136			dwfl_end(dbg->dwfl);137		free(dbg);138	}139}140 141/* For the kernel module, we need a special code to get a DIE */142int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,143				bool adjust_offset)144{145	int n, i;146	Elf32_Word shndx;147	Elf_Scn *scn;148	Elf *elf;149	GElf_Shdr mem, *shdr;150	const char *p;151 152	elf = dwfl_module_getelf(dbg->mod, &dbg->bias);153	if (!elf)154		return -EINVAL;155 156	/* Get the number of relocations */157	n = dwfl_module_relocations(dbg->mod);158	if (n < 0)159		return -ENOENT;160	/* Search the relocation related .text section */161	for (i = 0; i < n; i++) {162		p = dwfl_module_relocation_info(dbg->mod, i, &shndx);163		if (strcmp(p, ".text") == 0) {164			/* OK, get the section header */165			scn = elf_getscn(elf, shndx);166			if (!scn)167				return -ENOENT;168			shdr = gelf_getshdr(scn, &mem);169			if (!shdr)170				return -ENOENT;171			*offs = shdr->sh_addr;172			if (adjust_offset)173				*offs -= shdr->sh_offset;174		}175	}176	return 0;177}178 179#ifdef HAVE_DEBUGINFOD_SUPPORT180int get_source_from_debuginfod(const char *raw_path,181			       const char *sbuild_id, char **new_path)182{183	debuginfod_client *c = debuginfod_begin();184	const char *p = raw_path;185	int fd;186 187	if (!c)188		return -ENOMEM;189 190	fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id,191				0, p, new_path);192	pr_debug("Search %s from debuginfod -> %d\n", p, fd);193	if (fd >= 0)194		close(fd);195	debuginfod_end(c);196	if (fd < 0) {197		pr_debug("Failed to find %s in debuginfod (%s)\n",198			raw_path, sbuild_id);199		return -ENOENT;200	}201	pr_debug("Got a source %s\n", *new_path);202 203	return 0;204}205#endif /* HAVE_DEBUGINFOD_SUPPORT */206