Android15借助Linux proc虚拟文件系统调试用户态实现

背景介绍

下面介绍一种Android系统调试方法,借助Linux proc虚拟文件系统将Android用户态的调试数据放到内核态进行显示,用于logcat不可用情况下调试Android系统。

主要是介绍Linux Kernel中如何实现这样一个/proc/debugprof节点供用户态访问。

环境描述:

  • ARM CotexA 64bit
  • Android15 Linux 6.6

具体实现

Android15 Linux Kernel(非GKI)Driver中实现一个proc节点,包括三个内容:

  1. debugprof模块驱动源码
  2. debugprof模块构建脚本
  3. debugprof模块设备树配置

debugprof目录结构大概是这个样子:

bash 复制代码
drivers/Xxx/Xxx_debug/
├── debugprof.c
├── Kconfig
└── Makefile

Linux Kernel实现debugprof

debugprof模块实现源码

cpp 复制代码
//drivers/xx/debugprof.c
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2026 Xxx Inc.
 */

#include <linux/proc_fs.h>
#include <linux/sched/clock.h>
#include <linux/seq_file.h>
#include <linux/kallsyms.h>
#include <linux/utsname.h>
#include <asm/uaccess.h>
#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/tracepoint.h>
#include <trace/events/initcall.h>
#include <linux/delay.h>
#include <linux/soc/xx/boot_param.h>
#include <linux/console.h>

#define SEQ_printf(m, x...)	    \
do {			    \
	if (m)		    \
		seq_printf(m, x);	\
	else		    \
		printk(x);	    \
} while (0)

//注意:这个是debugprof数据缓存大小,不能分配太大
#define DEBUG_BUF_SIZE (512)

typedef struct dg_debugprof {
    int data_size;
    char debug_buf[DEBUG_BUF_SIZE];  //用于存用户态传过来的数据
} dg_debugprof;

dg_debugprof dg_debug_stat;

static int dg_debugprof_show(struct seq_file *m, void *v)
{
	SEQ_printf(m, "----------------------------------------\n");
	SEQ_printf(m, "debug : %s\n", dg_debug_stat.debug_buf);
	SEQ_printf(m, "----------------------------------------\n");

	return 0;
}

static int dg_debug_open(struct inode *inode, struct file *file)
{
	return single_open(file, dg_debugprof_show, inode->i_private);
}

static ssize_t dg_debug_write(struct file *filp, const char __user *ubuf,
           size_t cnt, loff_t *data)
{
    char buf[DEBUG_BUF_SIZE];
    size_t copy_size = cnt;

    if (cnt >= sizeof(buf))
        copy_size = DEBUG_BUF_SIZE - 1;

    if (copy_from_user(&buf, ubuf, copy_size))
        return -EFAULT;

    buf[copy_size] = 0;
    strcpy((char *)&dg_debug_stat.debug_buf, buf);
	return cnt;
}

static const struct proc_ops dg_debug_fops = {
	.proc_open = dg_debug_open,
	.proc_write = dg_debug_write,  //重点实现这个接口,Android程序走这个接口将数据传过来
	.proc_read = seq_read,
	.proc_lseek = seq_lseek,
	.proc_release = single_release,
};

static int debugprof_probe(struct platform_device *pdev)
{
    struct proc_dir_entry *pe;

    //创建proc debugprof节点,dg_debug_fops是接口函数
	pe = proc_create("debugprof", 0664, NULL, &dg_debug_fops);
    if (!pe) {
        pr_err("debugprof_probe fail.");
        return -ENOMEM;
    }
    pr_info("debugprof_probe success.");
	return 0;
}

static int debugprof_remove(struct platform_device *pdev)
{
	return 0;
}

static const struct dev_pm_ops debugprof_pm_ops = {
};

static const struct of_device_id debugprof_match[] = {
	{.compatible = "Xxx,debugprof",},
	{},
};

static struct platform_driver debugprof_drv = {
	.driver = {
		.owner = THIS_MODULE,
		.name  = "debugprof",
		.of_match_table = debugprof_match,
		.pm = &debugprof_pm_ops,
	},

	.probe = debugprof_probe,
	.remove = debugprof_remove,
};

static int __init debugprof_init(void)
{
	return platform_driver_register(&debugprof_drv);
}

static void __exit debugprof_exit(void)
{
	platform_driver_unregister(&debugprof_drv);
}

core_initcall(debugprof_init);
module_exit(debugprof_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Xxx Boot Chart driver");
MODULE_AUTHOR("yuxi@Xxx.com");

debugprof模块构建

cpp 复制代码
//drivers/Xxx/Kconfig
source "drivers/Xxx/Xxx_debug/Kconfig"

//drivers/Xxx/Xxx_debug/Kconfig
config Xxx_DEBUGPROF
    tristate "Xxx debug info"
    default n
    help
        This option help you to debug

//arch/arm64/configs/Xxx.fragment
CONFIG_Xxx_DEBUGPROF=y
bash 复制代码
//drviers/Xxx/Makefile
obj-y += Xxx_debug/

debugprof模块dts

cpp 复制代码
//arch/arm64/boot/dts/Xxx/Xxx_platform.dts
{
    ...
    debugprof: debugprof {
        compatible = "Xxx,debugprof";
        status = "okay";
    };
    ...
}

Android15中访问/proc/debugprof

cpp 复制代码
//frameworks/base/tools/aapt2/cmd/Link_test.cpp
TEST_F(LinkTest, NoCompressAssets) {
    ...
    if (auto result = 
        WriteFile("/proc/debugprof", "^-^##;/odm/etc/init;/product/etc/init");
        !result.ok()) {
        //write fail
    }
}

实现效果

相关推荐
silvamux_16 分钟前
4款新模型商务邮件翻译横评:0.98到0.46
android·java·javascript
ynchyong30 分钟前
创建MySQL只读账号
android·数据库·mysql
朱涛的自习室11 小时前
我给 Gemini 4 和 DeepSeek 搞了套「末位淘汰」,AI 干活会更猛吗?(Day 3)
android·前端·后端
应用市场16 小时前
离线小游戏做“每日挑战”:日期当随机种子,整局存成 JSON,再加一个“我不是机器人”
android·kotlin·游戏开发
一铭1119917 小时前
海豹办公 1.9.15 跨端办公软件实践 文档兼容 Access 数据库与移动 WebView 排错
android·数据库·electron·开源软件·access
geats人山人海18 小时前
java 7异常
android·java·开发语言
2601_9620710019 小时前
Kimi K3 vs DeepSeek V4-Pro实测对比:2026年同一入口十道题,耗时与token消耗差在哪
android·java·数据库
右手吉他20 小时前
高通平台IA APN问题分析之二
android·物联网
夜雪一千20 小时前
MySQL 自增 ID 的底层原理与坑点
android·mysql·adb
不浪费一个字节21 小时前
一个纯 Python 实现的 APK 解析与设备操控工具箱
android