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

实现效果

相关推荐
Georgewu17 小时前
如何判断应用在鸿蒙卓易通或者出境易环境下?
android·harmonyos
localbob17 小时前
Pico 4XVR 1.10.13安装包下载与安装教程 ico 4XVR最新版下载、4XVR 1.10.13 APK安装包、Pico VR看电影软件、4XVR完整版安装教程、Pico 4播放器推荐、V
android·vr·vr播放器·vr眼镜播放器下载·pico 4xvr·4xvr下载·pico 4xvr最新版安装包
峥嵘life18 小时前
Android16 EDLA【CTS】CtsConnectivityMultiDevicesTestCases存在fail项
android·学习
大傻^18 小时前
SpringAI2.0 Null Safety 实战:JSpecify 注解体系与 Kotlin 互操作
android·开发语言·人工智能·kotlin·springai
游戏开发爱好者818 小时前
React Native iOS 代码如何加密,JS 打包 和 IPA 混淆
android·javascript·react native·ios·小程序·uni-app·iphone
kcuwu.18 小时前
Python判断及循环
android·java·python
轩情吖19 小时前
MySQL之索引
android·数据库·mysql·b+树·索引·page·
2501_9159184119 小时前
iOS mobileprovision 描述文件管理,新建、下载和内容查看
android·ios·小程序·https·uni-app·iphone·webview
00后程序员张19 小时前
iOS 应用程序使用历史记录和耗能记录怎么查?
android·ios·小程序·https·uni-app·iphone·webview
计算机与认知19 小时前
Linux UCLAMP机制深度分析
linux kernel