Blame src/backtrace.c

Packit 34410b
/*
Packit 34410b
 *
Packit 34410b
 *  BlueZ - Bluetooth protocol stack for Linux
Packit 34410b
 *
Packit 34410b
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
Packit 34410b
 *
Packit 34410b
 *
Packit 34410b
 *  This program is free software; you can redistribute it and/or modify
Packit 34410b
 *  it under the terms of the GNU General Public License as published by
Packit 34410b
 *  the Free Software Foundation; either version 2 of the License, or
Packit 34410b
 *  (at your option) any later version.
Packit 34410b
 *
Packit 34410b
 *  This program is distributed in the hope that it will be useful,
Packit 34410b
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 34410b
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 34410b
 *  GNU General Public License for more details.
Packit 34410b
 *
Packit 34410b
 *  You should have received a copy of the GNU General Public License
Packit 34410b
 *  along with this program; if not, write to the Free Software
Packit 34410b
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit 34410b
 *
Packit 34410b
 */
Packit 34410b
Packit 34410b
#ifdef HAVE_CONFIG_H
Packit 34410b
#include <config.h>
Packit 34410b
#endif
Packit 34410b
Packit 34410b
#include <unistd.h>
Packit 34410b
#include <inttypes.h>
Packit 34410b
Packit 34410b
#ifdef HAVE_BACKTRACE_SUPPORT
Packit 34410b
#include <execinfo.h>
Packit 34410b
#include <elfutils/libdwfl.h>
Packit 34410b
#endif
Packit 34410b
Packit 34410b
#include "src/log.h"
Packit 34410b
#include "src/backtrace.h"
Packit 34410b
Packit 34410b
void btd_backtrace_init(void)
Packit 34410b
{
Packit 34410b
#ifdef HAVE_BACKTRACE_SUPPORT
Packit 34410b
	void *frames[1];
Packit 34410b
Packit 34410b
	/*
Packit 34410b
	 * initialize the backtracer, since the ctor calls dlopen(), which
Packit 34410b
	 * calls malloc(), which isn't signal-safe.
Packit 34410b
	 */
Packit 34410b
	backtrace(frames, 1);
Packit 34410b
#endif
Packit 34410b
}
Packit 34410b
Packit 34410b
void btd_backtrace(uint16_t index)
Packit 34410b
{
Packit 34410b
#ifdef HAVE_BACKTRACE_SUPPORT
Packit 34410b
	char *debuginfo_path = NULL;
Packit 34410b
	const Dwfl_Callbacks callbacks = {
Packit 34410b
		.find_debuginfo = dwfl_standard_find_debuginfo,
Packit 34410b
		.find_elf = dwfl_linux_proc_find_elf,
Packit 34410b
		.debuginfo_path = &debuginfo_path,
Packit 34410b
	};
Packit 34410b
	Dwfl *dwfl;
Packit 34410b
	void *frames[48];
Packit 34410b
	int n, n_ptrs;
Packit 34410b
Packit 34410b
	dwfl = dwfl_begin(&callbacks);
Packit 34410b
Packit 34410b
	if (dwfl_linux_proc_report(dwfl, getpid()))
Packit 34410b
		goto done;
Packit 34410b
Packit 34410b
	dwfl_report_end(dwfl, NULL, NULL);
Packit 34410b
Packit 34410b
	n_ptrs = backtrace(frames, 48);
Packit 34410b
	if (n_ptrs < 1)
Packit 34410b
		goto done;
Packit 34410b
Packit 34410b
	btd_error(index, "++++++++ backtrace ++++++++");
Packit 34410b
Packit 34410b
	for (n = 1; n < n_ptrs; n++) {
Packit 34410b
		GElf_Addr addr = (uintptr_t) frames[n];
Packit 34410b
		GElf_Sym sym;
Packit 34410b
		GElf_Word shndx;
Packit 34410b
		Dwfl_Module *module = dwfl_addrmodule(dwfl, addr);
Packit 34410b
		Dwfl_Line *line;
Packit 34410b
		const char *name, *modname;
Packit 34410b
Packit 34410b
		if (!module) {
Packit 34410b
			btd_error(index, "#%-2u ?? [%#" PRIx64 "]", n, addr);
Packit 34410b
			continue;
Packit 34410b
		}
Packit 34410b
Packit 34410b
		name = dwfl_module_addrsym(module, addr, &sym, &shndx);
Packit 34410b
		if (!name) {
Packit 34410b
			modname = dwfl_module_info(module, NULL, NULL, NULL,
Packit 34410b
							NULL, NULL, NULL, NULL);
Packit 34410b
			btd_error(index, "#%-2u ?? (%s) [%#" PRIx64 "]",
Packit 34410b
							n, modname, addr);
Packit 34410b
			continue;
Packit 34410b
		}
Packit 34410b
Packit 34410b
		line = dwfl_module_getsrc(module, addr);
Packit 34410b
		if (line) {
Packit 34410b
			int lineno;
Packit 34410b
			const char *src = dwfl_lineinfo(line, NULL, &lineno,
Packit 34410b
							NULL, NULL, NULL);
Packit 34410b
Packit 34410b
			if (src) {
Packit 34410b
				btd_error(index, "#%-2u %s+%#" PRIx64 " "
Packit 34410b
						"(%s:%d) [%#" PRIx64 "]",
Packit 34410b
						n, name, addr - sym.st_value,
Packit 34410b
							src, lineno, addr);
Packit 34410b
				continue;
Packit 34410b
			}
Packit 34410b
		}
Packit 34410b
Packit 34410b
		modname = dwfl_module_info(module, NULL, NULL, NULL,
Packit 34410b
						NULL, NULL, NULL, NULL);
Packit 34410b
		btd_error(index, "#%-2u %s+%#" PRIx64 " (%s) [%#" PRIx64 "]",
Packit 34410b
						n, name, addr - sym.st_value,
Packit 34410b
								modname, addr);
Packit 34410b
	}
Packit 34410b
Packit 34410b
	btd_error(index, "+++++++++++++++++++++++++++");
Packit 34410b
Packit 34410b
done:
Packit 34410b
	dwfl_end(dwfl);
Packit 34410b
#endif
Packit 34410b
}
Packit 34410b
Packit 34410b
void btd_assertion_message_expr(const char *file, int line,
Packit 34410b
					const char *func, const char *expr)
Packit 34410b
{
Packit 34410b
	btd_error(0xffff, "Assertion failed: (%s) %s:%d in %s",
Packit 34410b
						expr, file, line, func);
Packit 34410b
	btd_backtrace(0xffff);
Packit 34410b
}