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

实现效果

相关推荐
BoomHe1 天前
Android AOSP13 原生 Launcher3 壁纸获取方式
android
Digitally1 天前
如何将联系人从 Android 转移到 Android
android
李小枫1 天前
webflux接收application/x-www-form-urlencoded参数
android·java·开发语言
爱丽_1 天前
MySQL `EXPLAIN`:看懂执行计划、判断索引是否生效与排错套路
android·数据库·mysql
NPE~1 天前
[App逆向]环境搭建下篇 — — 逆向源码+hook实战
android·javascript·python·教程·逆向·hook·逆向分析
yewq-cn1 天前
AOSP 下载
android
cch89181 天前
Laravel vs ThinkPHP:PHP框架终极对决
android·php·laravel
米码收割机1 天前
【Android】基于安卓app的汽车租赁管理系统(源码+部署方式+论文)[独一无二]
android·汽车
流星雨在线1 天前
安卓使用 Startup 管理三方 SDK 初始化
android·startup
jwn9991 天前
Laravel3.x:PHP框架的经典里程碑
android