我正在尝试将RR0D Rasta Ring0 Debugger从32位Linux移植到64位Linux。我已经使用vim正则表达式将32位gcc内联汇编转换为64位,如我的问题所述:How to convert Linux 32-bit gcc inline assembly to 64-bit code?
我正在使用带有-m64
标志的gcc。目标环境是Linux x86-64,自定义内核版本3.5.5。
Makefile
如下:
EXTRA_CFLAGS += -O2 -Wall -DLINUX_26 -m64
OBJ := module_nux.o breakpoint.o buffering.o command.o disasmbak.o idt.o
OBJ += keyboard.o page.o video.o utils.o import_symb.o core_rr0d.o pci.o
MODULE := rr0d.o
obj-m := $(MODULE)
rr0d-objs := $(OBJ)
default:
make -C /lib/modules/`uname -r`/build/ SUBDIRS=`pwd` modules
clean:
rm -f *.o .*.o.cmd .*.ko.cmd *.mod.c *~
rm -rf .tmp_versions
mrproper:
make clean
rm -f *.ko
make
提供了许多警告,例如warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
和warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
,但这些警告可能与该主题无关。
make
输出的最后几行可能是重要的:
/home/user/code/rr0d/0.3/core_rr0d.c: In function ‘cleanup_rr0d’:
/home/user/code/rr0d/0.3/core_rr0d.c:1938:36: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
CC [M] /home/user/code/rr0d/0.3/pci.o
LD [M] /home/user/code/rr0d/0.3/rr0d.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "RING_HOOO_SEGMENT" [/home/user/code/rr0d/0.3/rr0d.ko] undefined!
CC /home/user/code/rr0d/0.3/rr0d.mod.o
LD [M] /home/user/code/rr0d/0.3/rr0d.ko
make[1]: Leaving directory `/home/user/code/kernel/linux-3.5.5'
因此,RING_HOOO_SEGMENT
未定义。
当我尝试insmod
以insmod ./rr0d.ko
为根的模块时,我得到:
Error: could not insert module ./rr0d.ko: Unknown symbol in module
使用dmesg | tail -n 1
进行检查会得到以下输出:
[15975.412346] rr0d: Unknown symbol RING_HOOO_SEGMENT (err 0)
因此,未知符号最终为RING_HOOO_SEGMENT
。
RING_HOOO_SEGMENT
是#define
中使用vars.h
创建的常量,包含在.c
个#include "vars.h"
个文件中。
#ifdef
与vars.h
的基本#define RING_HOOO_SEGMENT
块是这一块:
#ifdef LINUX_26
#define fake_naked
#if defined(__GNUC__)
// the line below is the important one.
#define RING_HOOO_SEGMENT "$0x7b"
//#define RING_HOOO_SEGMENT "$0x60"
#elif defined(_MSC_VER)
#define RING_HOOO_SEGMENT 0x7b
#endif
#else /* LINUX_24 */
#define fake_naked _asm_("\t" \
"add $0x08, %esp\n\t" \
"popl %ebp\n" \
);
#if defined(__GNUC__)
#define RING_HOOO_SEGMENT "$0x18"
#elif defined(_MSC_VER)
#define RING_HOOO_SEGMENT 0x18
#endif
#define RING_HOOO_SEGMENT_VALUE 0x18
#endif /* LINUX_26 */
显然,如果#define RING_HOOO_SEGMENT "$0x7b"
(在#if defined(__GNUC__)
内#ifdef LINUX_26
)被注释掉,代码将无法编译,因此很明显RING_HOOO_SEGMENT
已被定义。
为RING_HOOO_SEGMENT
加注以下匹配项:
$ grep 'RING_HOOO_SEGMENT' *.c *.o *.ko
core_rr0d.c: "movq RING_HOOO_SEGMENT, %rax\n\t"\
core_rr0d.c: __asm{ movq RING_HOOO_SEGMENT, %rax}\
Binary file rr0d.ko matches
两个core_rr0d.c
行都是内联汇编。 core_rr0d.c
包含#include "vars.h"
,因此应该没问题。
二进制模块rr0d.ko
也匹配,因此它包含字符串RING_HOOO_SEGMENT
(以某种形式),即使insmod ./rr0d.ko
因Error: could not insert module ./rr0d.ko: Unknown symbol in module
而失败。
任何想法可能导致此问题的原因以及如何继续insmod
模块?
答案 0 :(得分:2)
core_rr0d.c: "movq RING_HOOO_SEGMENT, %rax\n\t"\
这里RING_HOOO_SEGMENT是一个字符串(可能是内联汇编程序块的一部分)。因此,预处理器不会替换RING_HOOO_SEGMENT
,它会按原样传递给汇编程序,而RING_HOOO_SEGMENT
的定义不可用。
幸运的是,RING_HOOO_SEGMENT
本身被定义为字符串"$0x7b"
,因此我们可以使用编译时字符串连接:
"movq " RING_HOOO_SEGMENT ", %rax\n\t"\
预处理器将RING_HOOO_SEGMENT
替换为"$0x7b"
,然后GCC会在将这些字符串传递给汇编程序之前将它们连接起来。