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
    }
}

实现效果

相关推荐
不爱说话郭德纲2 小时前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
Sinclair6 小时前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
雮尘10 小时前
手把手带你玩转Android gRPC:一篇搞定原理、配置与客户端开发
android·前端·grpc
ktl11 小时前
Android 编译加速/优化 80%:一个文件搞定,零侵入零配置
android
alexhilton1 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
冬奇Lab1 天前
InputManagerService:输入事件分发与ANR机制
android·源码阅读
张小潇1 天前
AOSP15 Input专题InputManager源码分析
android·操作系统
RdoZam1 天前
Android-封装基类Activity\Fragment,从0到1记录
android·kotlin
奥陌陌1 天前
android 打印函数调用堆栈
android
用户985120035831 天前
Compose Navigation 3 深度解析(二):基础用法
android·android jetpack