Understanding virtual to physical memory translation in Android

18 Views Asked by At

I am using a simple shell script to read out data from /proc/pid/mem.

Setup: This is done through android studio by using adb shell and su. Then, I use /proc/pid/maps to read out a memory range, starting with the beginning of the mmap region. Finally, I run print_pagemap.sh with arguments for pid, start and end address. The memory is populated using mmap and a random char generator.

    void* ptr = mmap(NULL, mmapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);

    if (ptr == NULL) {
        // Memory allocation failed, ptr is not a valid virtual address
        LOGI("malloc failed");
        return NULL;
    } else {
        // Memory allocation successful, ptr is a valid virtual address
        LOGI("Virtual address: %p", ptr);
    }
    // Fill all of mmap with random chars
    for (size_t i = 0; i < mmapSize; ++i) {
        ((char*)ptr)[i] = 'A' + rand() % 95 + 32; // Generate printable ASCII characters
    }

The Question: I get the output of various memory sections in hexadecimal format, but it does not seem to comply with what would be expected when looking at documentation. Some entries do not have the 63rd bit set to 1 and the bits 60-57 to zero. How is this possible? I've read up that little endian representation is the standard for this setup.

redfin:/data/local/tmp # ./print_pagemap.sh 24708 0x7c437ae000 0x7c437ae100                                                                                                                                                        
00000000: a69cb9b4aa6b8270 76918d87b271ad80 8889706d8f7b6762 6f8f8b899a676380  .....k.pv....q....pm.{gbo....gc.
00000020: 9fbb728a63939679 61639cb070867097 ae7fa47b96a77ca2 76a36bafa66e6d86  ..r.c..yac..p.p....{..|.v.k..nm.
00000040: 667bac66ad827eaa 81b69a907da66768 62a77f958e9b77a1 7b7e9062889c848b  f{.f..~.....}.ghb.....w.{~.b....
00000060: b67090a091aa88b1 a0be7eb9a581bea3 697d7893b48e746d a9a16b717a8e9b6e  .p........~.....i}x...tm..kqz..n
00000080: 9d68ad6bb175b88f 717685b593809898 9dad6c8e7b7c9a61 b9a172746fa981a8  .h.k.u..qv........l.{|.a..rto...
000000a0: ae6bb29c7da76b8d b98d7f8da9b66583 a36db1bb8688b87f 6a679278b0af619e  .k..}.k.......e..m......jg.x..a.
000000c0: baaf7a749482a08d abbeb694b1bbb792 68a58a8d6d82a976 897b8b766888b062  ..zt............h...m..v.{.vh..b
000000e0: 746a75a788b17270 af68a19d63986f68 7d959186b77a9c7d 926792998e82979e  tju...rp.h..c.oh}....z.}.g......

print_pagemap.sh

#!/system/bin/sh

# Make sure three arguments are provided
if [ "$#" -ne 3 ]; then
    echo "Usage: $0 <pid> <start_address> <end_address>"
    exit 1
fi

# Extract arguments
pid="$1"
start_address="$2"
end_address="$3"

# Convert hexadecimal addresses to decimal
start_address_dec=$(printf "%d" $start_address)
end_address_dec=$(printf "%d" $end_address)

# Use dd to read data between the addresses
dd if="/proc/$pid/mem" bs=1 skip=$start_address_dec count=$(($end_address_dec - $start_address_dec)) status=none | xxd -g 8 -c 32 | grep -v '0000000000000000 0000000000000000 0000000000000000 0000000000000000'

The output of the shell script should be little endian as well. Since it is printing from the pagemap file, it should follow the rules written out in the documentation. Am I misinterpreting the content of what I print?

0

There are 0 best solutions below