PMD工具(Ptrace-based Memory Dump)源代码(注释版)

PMD是一款基于ptrace的Android内存dump工具,用于获取特定进程的内存映射及数据。本文涵盖工具使用、编译方法及源代码注释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. PMD工具

PMD工具是基于ptrace的Android手机内存dump工具,其能够获取Android手机指定进程的内存,并生成相应的map文件和mem文件。

Usage: pid out_dir [-s <image> <offset>]

PMD工具的编译与使用见我的另一篇博客:
http://blog.youkuaiyun.com/rzwinters/article/details/75517107

2. Android.mk与Application.mk

  • Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := pmd
LOCAL_SRC_FILES := pmd.c
LOCAL_CPPFLAGS := -O3 -Wall -fPIE
LOCAL_LDLIBS := -O3 -llog -fPIE -pie
LOCAL_C_INCLUDES := /home/richard/android-ndk-r15b/platforms/android-19/arch-arm/usr/include/

include $(BUILD_EXECUTABLE)
  • Application.mk
APP_ABI := armeabi
APP_PLATFORM := android-19

3. 源代码(注释版)

#define _LARGEFILE64_SOURCE //for using function lseek64

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <linux/user.h>
#include <dirent.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

#define DROID_VERSION
#ifdef DROID_VERSION
# include <android/log.h>
#endif

//#define LOG_ON //for LOG
#undef LOG_ON

/* Variadic macros for printing log and err info */
#ifdef DROID_VERSION
# define PMD_LOG(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "[pmd]", "%s: "fmt, __func__, ##__VA_ARGS__)
#else
# define PMD_LOG(fmt, ...) fprintf(stderr, "[ ] "__func__ fmt, ##__VA_ARGS__)
#endif
#define PMD_ERR(prefix, ...) PMD_LOG(prefix": %s\n", ##__VA_ARGS__, strerror(errno))




#define n_ARRAY(array) (sizeof(array)/sizeof(array[0]))

/* Segments need to be skipped when dumping memory */
const char *skip_segments[] = {
 "/dev/kgsl-3d0"
};

/* Segements must be injected when dumping memory */
const char *must_injects[] = {
 "/dev/ashmem"
};

static inline int 
is_in_string_list (const char* s,
                   const char* strings[],
                   unsigned n_strings)
{
  unsigned i;
  /* Check if s is in the strings */
  for(i = 0; i < n_strings; i++)
  {
    if(strcmp(strings[i], s) == 0) return 1;
  }
  return 0;
}

#define is_in_skip_segments(s) is_in_string_list(s, skip_segments, n_ARRAY(skip_segments))
#define is_in_must_inject(s)   is_in_string_list(s, must_injects, n_ARRAY(must_injects))


static inline size_t
get_tids(pid_t **const listptr, size_t *const sizeptr, const pid_t pid)
{
    char     dirname[64];
    DIR     *dir;
    pid_t   *list;
    size_t   size, used = 0;
    list = *listptr = NULL;
    size = *sizeptr = 0;

    /* Open the task dir of the target process in proc filesystem */
    sprintf(dirname, "/proc/%d/task/", (int)pid); 
    dir = opendir(dirname);
    if (!dir) {
        PMD_ERR("open task dir");
        return 0;
    }

    while (1) {
        struct dirent *ent;
        int            value;
        char           dummy;

        /* Read the entries in the task dir */
        ent = readdir(dir);
        if (!ent)
            break;
        /* Parse TIDs. Ignore non-numeric entries. */
        if (sscanf(ent->d_name, "%d%c", &value, &dummy) != 1)
            continue;
        /* Ignore obviously invalid entries. */
        if (value < 1)
            continue;
        /* Make sure there is room for another TID. */
        if (used >= size) {
            size = (used | 127) + 128;
            list = realloc(list, size * sizeof list[0]); //expansion
            *listptr = list; //write back
            *sizeptr = size; //write back
        }
        /* Add to list. */
        list[used++] = (pid_t)value;
    }
    closedir(dir); 
    return used; //return, write back
}


static inline void
check_new_tids(pid_t **const listptr, size_t *const usedptr, size_t *const sizeptr,
               const pid_t pid, const unsigned char let_run) 
{
  int used = *usedptr;
  int max = *sizeptr;
  pid_t *list = *listptr;

  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值