【问题标题】:Inlined ARM64 system call giving the wrong return value内联 ARM64 系统调用给出错误的返回值
【发布时间】:2020-04-14 23:42:36
【问题描述】:

这是我的代码。

long doSystemCall(const char *path) {
    register long x0 asm("x0") = 0;
    register long x1 asm("x1") = (long) path;
    register long x2 asm("x2") = 0;
    register long x3 asm("x3") = 0;
    register long x8 asm("x8") = __NR_faccessat;

    __asm__ volatile("svc #0"
    :"=r"(x0)
    :"0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8)
    :"memory"
    );

    __android_log_print(ANDROID_LOG_INFO, "SYSCALL", "Result: %li", x0);

    return x0;
}

它给出的返回值是0-2-13,但是faccessat 应该只返回0-1。我该如何解决这个问题?

我的代码反编译后的伪代码是这样的。

signed __int64 __fastcall sub_E558(const char *a1)
{
  signed __int64 v1; // ST30_8
  v1 = linux_eabi_syscall(__NR_faccessat, 0, a1, 0, 0);
  __android_log_print(4LL, "SYSCALL", "Result: %li", v1);
  return v1;
}

这些是函数的说明。

SUB             SP, SP, #0x50
STP             X29, X30, [SP,#0x40+var_s0]
ADD             X29, SP, #0x40
STUR            X0, [X29,#var_8]
MOV             X0, XZR
STUR            X0, [X29,#var_10]
LDUR            X8, [X29,#var_8]
STUR            X8, [X29,#var_18]
STR             X0, [SP,#0x40+var_20]
STR             X0, [SP,#0x40+var_28]
MOV             W9, #0x30
MOV             W8, W9
STR             X8, [SP,#0x40+var_30]
LDUR            X0, [X29,#var_10]
LDUR            X1, [X29,#var_18]
LDR             X2, [SP,#0x40+var_20]
LDR             X3, [SP,#0x40+var_28]
LDR             X8, [SP,#0x40+var_30]
SVC             0
STUR            X0, [X29,#var_10]
LDUR            X3, [X29,#var_10]
ADRP            X1, #aSyscall@PAGE ; "SYSCALL"
ADD             X1, X1, #aSyscall@PAGEOFF ; "SYSCALL"
ADRP            X2, #aResultLi@PAGE ; "Result: %li"
ADD             X2, X2, #aResultLi@PAGEOFF ; "Result: %li"
MOV             W0, #4
BL              .__android_log_print
LDUR            X8, [X29,#var_10]
STR             W0, [SP,#0x40+var_34]
MOV             X0, X8
LDP             X29, X30, [SP,#0x40+var_s0]
ADD             SP, SP, #0x50
RET

【问题讨论】:

  • 您使用的是什么操作系统?为什么你认为它应该只返回 0 或 -1 (EPERM)?根据 Linux 手册页,它可能返回 EACCESS(-13)、ELOOP、ENAMETOOLONG、ENOENT(-2)、ENOTDIR、EROFS、EFAULT、EINVAL、EIO、ENOMEM、EXTBUSY 或 EBADF。甚至没有提到 EPERM。

标签: c gcc assembly inline-assembly arm64


【解决方案1】:

您将 libc 包装器 API 与直接系统调用 ABI 混淆了——只有 libc 包装器在 errno 中返回错误。至少在 Linux 上,直接系统调用将返回一个小的负值(带有错误代码)。 libc 包装器将测试返回值,如果是 -4096..-1 范围,则将其取反并将其存储在 errno 中(然后返回 -1)。其他 UNIX 变体 (BSD) 在一个标志(通常是进位标志)中返回错误指示,错误值在返回寄存器中。

【讨论】:

    猜你喜欢
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 2018-04-13
    • 2016-07-19
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多