【记录一个问题】没用任何用处的解决了libtask的context.c在32位NDK下的编译问题
阅读原文时间:2023年07月11日阅读:1

32位下用ndk编译libtask出现这样的错误:

[armeabi-v7a] Compile thumb  : task <= context.c
/Users/ahfu/code/android/android-ndk-r14b/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -MMD -MP -MF /Users/ahfu/code/gitcode/ahfuzhang/daily_coding/source_code/libtask-master/libtask//obj/local/armeabi-v7a/objs-debug/task/context.o.d -gcc-toolchain /Users/ahfu/code/android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 -fpic -ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -fno-integrated-as -g -target armv7-none-linux-androideabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -O0 -UNDEBUG -fno-limit-debug-info  -mfpu=neon -I./ -I./ -DANDROID -g -pie -fPIC -DANDROID_ARM_NEON=TRUE -DANDROID_TOOLCHAIN=arm-linux-androideabi-gcc -O2 -Wa,--noexecstack -Wformat -Werror=format-security    --sysroot /Users/ahfu/code/android/android-ndk-r14b/platforms/android-21/arch-arm  -c  .//context.c -o /Users/ahfu/code/gitcode/ahfuzhang/daily_coding/source_code/libtask-master/libtask//obj/local/armeabi-v7a/objs-debug/task/context.o
.//context.c:124:19: error: no member named 'regs' in 'struct sigcontext'
                uc->uc_mcontext.regs[i] = va_arg(arg, uint);
                ~~~~~~~~~~~~~~~ ^
.//context.c:127:18: error: no member named 'regs' in 'struct sigcontext'
        uc->uc_mcontext.regs[13] = (uint)sp;
        ~~~~~~~~~~~~~~~ ^
.//context.c:128:18: error: no member named 'regs' in 'struct sigcontext'
        uc->uc_mcontext.regs[14] = (uint)fn;
        ~~~~~~~~~~~~~~~ ^
3 errors generated.

通过查看头文件 /Users/ahfu/code/android/android-ndk-r14b/platforms/android-24/arch-arm/usr/include/asm/sigcontext.h

发现结构体的定义与上面使用的结构体并不相同:

#ifndef _ASMARM_SIGCONTEXT_H
#define _ASMARM_SIGCONTEXT_H
struct sigcontext {
 unsigned long trap_no;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 unsigned long error_code;
 unsigned long oldmask;
 unsigned long arm_r0;
 unsigned long arm_r1;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 unsigned long arm_r2;
 unsigned long arm_r3;
 unsigned long arm_r4;
 unsigned long arm_r5;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 unsigned long arm_r6;
 unsigned long arm_r7;
 unsigned long arm_r8;
 unsigned long arm_r9;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 unsigned long arm_r10;
 unsigned long arm_fp;
 unsigned long arm_ip;
 unsigned long arm_sp;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 unsigned long arm_lr;
 unsigned long arm_pc;
 unsigned long arm_cpsr;
 unsigned long fault_address;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
#endif

于是context.c中这样修改代码,解决了32位下的编译问题:

#ifdef NEEDARMMAKECONTEXT

#if defined(__linux__) && defined(__arm__)

void
makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
{
    int i, *sp;
    va_list arg;
    sp = (int *)uc->uc_stack.ss_sp + uc->uc_stack.ss_size / 4;
    va_start(arg, argc);
    for (i = 0; i < 4 && i < argc; ++i) {
        switch (i){
        case 0:
            uc->uc_mcontext.arm_r0 = va_arg(arg, uint);
            break;
        case 1:
            uc->uc_mcontext.arm_r1 = va_arg(arg, uint);
            break;
        case 2:
            uc->uc_mcontext.arm_r2 = va_arg(arg, uint);
            break;
        case 3:
            uc->uc_mcontext.arm_r3 = va_arg(arg, uint);
            break;
        }
    }
    va_end(arg);
    uc->uc_mcontext.arm_sp = (uint)sp;
    uc->uc_mcontext.arm_lr = (uint)fn;
}

#elif defined(__linux__) && (defined(__arm64__) || defined(__aarch64__))

void
makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
{
    int i, *sp;
    va_list arg;
    sp = (int *)uc->uc_stack.ss_sp + uc->uc_stack.ss_size / 4;
    va_start(arg, argc);
    for (i = 0; i < 4 && i < argc; ++i) {
        uc->uc_mcontext.regs[i] = va_arg(arg, uint);
    }
    va_end(arg);
    uc->uc_mcontext.regs[13] = (uint)sp;
    uc->uc_mcontext.regs[14] = (uint)fn;
}

#else
#error unknown platform
#endif

#endif

总结:

  • arm32与arm64的寄存器结构差异较大
  • libtask号称支持ARM,但是ndk编译的时候一堆问题。
  • 相比之下,32位的libtask有可能编译并最终投入使用;arm64因为无法访问pc寄存器,这个难度略高。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章