是否可以在 64 位 Linux 的同一个可执行文件中同时使用 64 位和 32 位指令? [英] Is it possible to use both 64 bit and 32 bit instructions in the same executable in 64 bit Linux?

查看:32
本文介绍了是否可以在 64 位 Linux 的同一个可执行文件中同时使用 64 位和 32 位指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

64 位 CPU (amd64) 在兼容模式下支持 32 位 Intel 指令.此外,如果 ELF 标头表明它是 32 位可执行文件,则 64 位 Linux 安装允许运行包含 32 位指令的 ELF.

A 64 bit CPU (amd64) supports 32 bit Intel instructions in the compatibility mode. Also, a 64 bit Linux installation allows running ELFs containing 32 bit instructions if the ELF header says it is a 32 bit executable.

我想知道是否可以在 ELF 中放入一些汇编指令,以便在程序中间将 CPU 切换到 32 位兼容模式(然后再返回)?如果内核不允许这些汇编指令,是否有什么办法可以让内核将已经运行的进程切换到 32 位?

I was wondering if it is possible to put some assembly instructions inside the ELF which switches the CPU to 32 bit compatibility mode in the middle of a program (and then later back again)? If these assembly instructions are not permitted by the kernel, is there perhaps some way we can get the kernel to switch an already running process to 32 bit?

这主要是出于好奇而提出的问题,因为我真的看不到它的任何用例.

This is mainly a question out of curiosity since I cannot really see any use-cases for it.

推荐答案

长模式和兼容模式的切换是通过改变 CS 来完成的.用户模式代码不能修改描述符表,但它可以对已存在于描述符表中的代码段执行远跳转或远调用.我认为在 Linux(例如)中存在所需的兼容模式描述符.

Switching between long mode and compatibility mode is done by changing CS. User mode code cannot modify the descriptor table, but it can perform a far jump or far call to a code segment that is already present in the descriptor table. I think that in Linux (for example) the required compatibility mode descriptor is present.

这是 Linux (Ubuntu) 的示例代码.使用

Here is sample code for Linux (Ubuntu). Build with

$ gcc -no-pie switch_mode.c switch_cs.s

switch_mode.c:

switch_mode.c:

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

extern bool switch_cs(int cs, bool (*f)());
extern bool check_mode();

int main(int argc, char **argv)
{
    int cs = 0x23;
    if (argc > 1)
        cs = strtoull(argv[1], 0, 16);
    printf("switch to CS=%02x
", cs);

    bool r = switch_cs(cs, check_mode);

    if (r)
        printf("cs=%02x: 64-bit mode
", cs);
    else
        printf("cs=%02x: 32-bit mode
", cs);

    return 0;
}

switch_cs.s:

switch_cs.s:

        .intel_syntax noprefix
        .code64
        .text
        .globl switch_cs
switch_cs:
        push    rbx
        push    rbp
        mov     rbp, rsp
        sub     rsp, 0x18

        mov     rbx, rsp
        movq    [rbx], offset .L1
        mov     [rbx+4], edi

        // Before the lcall, switch to a stack below 4GB.
        // This assumes that the data segment is below 4GB.
        mov     rsp, offset stack+0xf0
        lcall   [rbx]

        // restore rsp to the original stack
        leave
        pop     rbx
        ret

        .code32
.L1:
        call    esi
        lret


        .code64
        .globl check_mode
// returns false for 32-bit mode; true for 64-bit mode
check_mode:
        xor     eax, eax
        // In 32-bit mode, this instruction is executed as
        // inc eax; test eax, eax
        test    rax, rax
        setz    al
        ret

        .data
        .align  16
stack:  .space 0x100

这篇关于是否可以在 64 位 Linux 的同一个可执行文件中同时使用 64 位和 32 位指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆