Android Studio 64 bit inline ARM assembly

自作多情 提交于 2021-01-29 20:00:54

问题


I am trying to run some inline assembly code for aarch64 from Android Studio 3.4.2 and I got a compilation error error: Don't know how to handle indirect register inputs yet for constraint 'r'.

My code snippet as follows

std::string system_file = "/system/bin/sh";
std::int64_t file_descriptor = -1;

#ifdef __aarch64__
    __asm__ volatile("mov x8, #180\n\t"
                     "mov x0, %1\n\t"
                     "mov x1, #0\n\t"
                     "svc #1\n\t"
                     "mov %0, x0\n\t"
                    :"=r"(file_descriptor)
                    :"r"(system_file)
                    :"x0","x1","x8"
                    );
#endif

ARM64 syscalls based on this article

https://reverseengineering.stackexchange.com/questions/16917/arm64-syscalls-table

and taken from

https://github.com/torvalds/linux/blob/v4.17/include/uapi/asm-generic/unistd.h

I am not sure if the error is due to Android Studio or am I doing something wrong here? Any advice is appreciated.

**** EDIT ****

I think I may have been looking at the wrong syscall number. Instead, I should be looking at

#define __NR_openat 56
__SC_COMP(__NR_openat, sys_openat, compat_sys_openat)

Now I am trying to do this and it seems to be wrong.

    std::string system_file = "/system/bin/sh";
    const char *ptr  = system_file.c_str();
    std::int64_t file_descriptor = 0;
    register std::int64_t x8 asm("x8") = 56;
    register std::int64_t x0 asm("x0") = 0;
    register std::int64_t x2 asm("x2") = 0;

    __asm__ volatile("svc #1"
    :"=r"(file_descriptor)
    :"r"(x0),"r"(ptr),"r"(x2),"r"(x8)
    :"memory"
    );

    __android_log_print(ANDROID_LOG_DEBUG,"native_code","file_descriptor: %i",file_descriptor);

I can see a number "56" returned in logcat but it is the same number regardless the file exists or not. Is it a coincidence that it is the same as the syscall number?


回答1:


As a general rule, you want to move as much of the code out of the inline asm as possible. In this case for instance, you are moving #180 to x8 to indicate the service number to invoke. But what if you want to open 2 files in a row, passing 180 in x8 both times? Ideally you'd want to avoid setting the identical value into the same register twice if you could, right? But by putting the mov inside the asm, you are forcing the value to be set every time.

You can avoid that by moving the assignments out of the asm. While I don't have an arm64 platform to run this on, the output from godbolt looks right:

std::string system_file = "/system/bin/sh";
const char *ptr  = system_file.c_str();
register std::int64_t file_descriptor asm("x0");
register std::int64_t x8 asm("x8") = 180;
register std::int64_t x1 asm("x1") = 0;

__asm__ volatile("svc #1"
                :"=r"(file_descriptor)
                :"0"(ptr),"r"(x1),"r"(x8)
                :"memory"
                );

Since x1 and x8 are listed as inputs (ie after the 2nd colon), gcc assumes their value is unchanged. And since the assignments took place in C code, it knows what values are there too.

The "0" might look a bit odd, but it's saying that ptr will be in the same place as parameter #0 (ie file_descriptor, which uses asm("x0")). So the input will be ptr, the output will be file_descriptor, and both use the same register.

I'll also mention that all the svc samples I've seen use svc #0.



来源:https://stackoverflow.com/questions/57355889/android-studio-64-bit-inline-arm-assembly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!