mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 03:59:40 +02:00
qcom: debug-symbol: Add debug-symbol feature
Use kallsyms address provided by debug-kinfo driver, symbol address can be searched by traversing kallsyms table. So the new debug-symbol feature is added and can replace android_debug_symbols approach. Change-Id: I27fb788ef3d17426bb0d40afb8bf58f2427a4649 Signed-off-by: Huang Yiwei <quic_hyiwei@quicinc.com>
This commit is contained in:
parent
f7bb27227f
commit
3a24de7bce
|
|
@ -825,6 +825,14 @@ config QCOM_ICC_BWMON
|
|||
the fixed bandwidth votes from cpufreq (CPU nodes) thus achieve high
|
||||
memory throughput even with lower CPU frequencies.
|
||||
|
||||
config QCOM_DEBUG_SYMBOL
|
||||
tristate "Enable Debug Symbol Support"
|
||||
help
|
||||
This enables Debug Symbol Support. This driver is based on
|
||||
Google Debug Kinfo driver, according to the provided info, this
|
||||
driver allows other modules to get symbol addresses by traversing
|
||||
kallsyms table for debug usage.
|
||||
|
||||
source "drivers/soc/qcom/mem_buf/Kconfig"
|
||||
source "drivers/soc/qcom/tmecom/Kconfig"
|
||||
|
||||
|
|
|
|||
|
|
@ -80,3 +80,4 @@ wcd_usbss_i2c-y += wcd-usbss-tables.o
|
|||
wcd_usbss_i2c-y += wcd-usbss-utils.o
|
||||
wcd_usbss_i2c-y += wcd939x-i2c.o
|
||||
obj-$(CONFIG_QCOM_PANEL_EVENT_NOTIFIER) += panel_event_notifier.o
|
||||
obj-$(CONFIG_QCOM_DEBUG_SYMBOL) += debug_symbol.o
|
||||
|
|
|
|||
227
drivers/soc/qcom/debug_symbol.c
Normal file
227
drivers/soc/qcom/debug_symbol.c
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
|
||||
*
|
||||
* Rewritten and vastly simplified by Rusty Russell for in-kernel
|
||||
* module loader:
|
||||
* Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
|
||||
*
|
||||
* ChangeLog:
|
||||
*
|
||||
* (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
|
||||
* Changed the compression method from stem compression to "table lookup"
|
||||
* compression (see scripts/kallsyms.c for a more complete description)
|
||||
*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* This driver is based on Google Debug Kinfo Driver
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "DebugSymbol: " fmt
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include "debug_symbol.h"
|
||||
#include "../../android/debug_kinfo.h"
|
||||
|
||||
struct debug_symbol_data {
|
||||
const unsigned long *addresses;
|
||||
const int *offsets;
|
||||
const u8 *names;
|
||||
unsigned int num_syms;
|
||||
unsigned long relative_base;
|
||||
const char *token_table;
|
||||
const u16 *token_index;
|
||||
const unsigned int *markers;
|
||||
};
|
||||
|
||||
static struct debug_symbol_data debug_symbol;
|
||||
static void *debug_symbol_vaddr;
|
||||
|
||||
int debug_symbol_available(void)
|
||||
{
|
||||
struct kernel_all_info *kainfo;
|
||||
struct kernel_info *kinfo;
|
||||
|
||||
if (!debug_symbol_vaddr)
|
||||
return -EINVAL;
|
||||
|
||||
kainfo = (struct kernel_all_info *)debug_symbol_vaddr;
|
||||
kinfo = &(kainfo->info);
|
||||
|
||||
if (kainfo->magic_number != DEBUG_KINFO_MAGIC) {
|
||||
pr_debug("debug_symbol is not available now\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
if (!debug_symbol.addresses) {
|
||||
debug_symbol.addresses = (unsigned long *)
|
||||
__phys_to_kimg(kinfo->_addresses_pa);
|
||||
debug_symbol.offsets = (int *)
|
||||
__phys_to_kimg(kinfo->_offsets_pa);
|
||||
debug_symbol.names = (u8 *)
|
||||
__phys_to_kimg(kinfo->_names_pa);
|
||||
debug_symbol.num_syms = kinfo->num_syms;
|
||||
debug_symbol.relative_base =
|
||||
__phys_to_kimg(kinfo->_relative_pa);
|
||||
debug_symbol.token_table = (char *)
|
||||
__phys_to_kimg(kinfo->_token_table_pa);
|
||||
debug_symbol.token_index = (u16 *)
|
||||
__phys_to_kimg(kinfo->_token_index_pa);
|
||||
debug_symbol.markers = (unsigned int *)
|
||||
__phys_to_kimg(kinfo->_markers_pa);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(debug_symbol_available);
|
||||
|
||||
/* In line with kallsyms_expand_symbol from kernel/kallsyms.c */
|
||||
static unsigned int debug_symbol_expand_symbol(unsigned int off,
|
||||
char *result, size_t maxlen)
|
||||
{
|
||||
int len, skipped_first = 0;
|
||||
const char *tptr;
|
||||
const u8 *data;
|
||||
|
||||
data = &debug_symbol.names[off];
|
||||
len = *data;
|
||||
data++;
|
||||
|
||||
off += len + 1;
|
||||
|
||||
while (len) {
|
||||
tptr = &debug_symbol.token_table[debug_symbol.token_index[*data]];
|
||||
data++;
|
||||
len--;
|
||||
|
||||
while (*tptr) {
|
||||
if (skipped_first) {
|
||||
if (maxlen <= 1)
|
||||
goto tail;
|
||||
*result = *tptr;
|
||||
result++;
|
||||
maxlen--;
|
||||
} else
|
||||
skipped_first = 1;
|
||||
tptr++;
|
||||
}
|
||||
}
|
||||
|
||||
tail:
|
||||
if (maxlen)
|
||||
*result = '\0';
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
/* In line with kallsyms_sym_address from kernel/kallsyms.c */
|
||||
static unsigned long debug_symbol_sym_address(int idx)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
|
||||
return debug_symbol.addresses[idx];
|
||||
|
||||
if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
|
||||
return debug_symbol.relative_base + (u32)debug_symbol.offsets[idx];
|
||||
|
||||
if (debug_symbol.offsets[idx] >= 0)
|
||||
return debug_symbol.offsets[idx];
|
||||
|
||||
return debug_symbol.relative_base - 1 - debug_symbol.offsets[idx];
|
||||
}
|
||||
|
||||
/* In line with cleanup_symbol_name from kernel/kallsyms.c */
|
||||
static bool cleanup_symbol_name(char *s)
|
||||
{
|
||||
char *res;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_LTO_CLANG))
|
||||
return false;
|
||||
|
||||
res = strnchr(s, KSYM_NAME_LEN, '.');
|
||||
if (res) {
|
||||
*res = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_CFI_CLANG) ||
|
||||
!IS_ENABLED(CONFIG_LTO_CLANG_THIN) ||
|
||||
CONFIG_CLANG_VERSION >= 130000)
|
||||
return false;
|
||||
|
||||
res = strrchr(s, '$');
|
||||
if (res) {
|
||||
*res = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* In line with kallsyms_lookup_name from kernel/kallsyms.c */
|
||||
unsigned long debug_symbol_lookup_name(const char *name)
|
||||
{
|
||||
char namebuf[KSYM_NAME_LEN];
|
||||
unsigned long i;
|
||||
unsigned int off;
|
||||
|
||||
if (!*name)
|
||||
return 0;
|
||||
|
||||
for (i = 0, off = 0; i < debug_symbol.num_syms; i++) {
|
||||
off = debug_symbol_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
|
||||
|
||||
if (strcmp(namebuf, name) == 0)
|
||||
return debug_symbol_sym_address(i);
|
||||
|
||||
if (cleanup_symbol_name(namebuf) && strcmp(namebuf, name) == 0)
|
||||
return debug_symbol_sym_address(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(debug_symbol_lookup_name);
|
||||
|
||||
static int __init debug_symbol_init(void)
|
||||
{
|
||||
struct device_node *rmem_node;
|
||||
struct reserved_mem *rmem;
|
||||
|
||||
rmem_node = of_find_compatible_node(NULL, NULL, "google,debug-kinfo");
|
||||
if (!rmem_node) {
|
||||
pr_err("cannot get compatible node\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rmem_node = of_parse_phandle(rmem_node, "memory-region", 0);
|
||||
if (!rmem_node) {
|
||||
pr_err("cannot get memory region\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rmem = of_reserved_mem_lookup(rmem_node);
|
||||
if (!rmem) {
|
||||
pr_err("cannot get reserved memory\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
debug_symbol_vaddr = memremap(rmem->base, rmem->size, MEMREMAP_WB);
|
||||
if (!debug_symbol_vaddr) {
|
||||
pr_err("failed to map reserved memory\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(debug_symbol_vaddr, 0, sizeof(struct kernel_all_info));
|
||||
rmem->priv = debug_symbol_vaddr;
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(debug_symbol_init);
|
||||
|
||||
MODULE_DESCRIPTION("QCOM Debug Symbol driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
27
drivers/soc/qcom/debug_symbol.h
Normal file
27
drivers/soc/qcom/debug_symbol.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DEBUG_SYMBOL_H
|
||||
#define _DEBUG_SYMBOL_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_DEBUG_SYMBOL)
|
||||
extern int debug_symbol_available(void);
|
||||
extern unsigned long debug_symbol_lookup_name(const char *name);
|
||||
#else
|
||||
static inline int debug_symbol_available(void)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline unsigned long debug_symbol_lookup_name(const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_QCOM_DEBUG_SYMBOL */
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user