【发布时间】:2012-09-27 16:05:30
【问题描述】:
我正在尝试将 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 是在vars.h 中使用#define 创建的常量,它包含在带有#include "vars.h" 的多个.c 文件中。
vars.h 和#define RING_HOOO_SEGMENT 的基本#ifdef 块是这个:
#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 模块?
【问题讨论】:
标签: c gcc linux-kernel x86-64 inline-assembly