Debian Mips 系统调用 unistd.h 丢失?
Debian Mips System Calls unistd.h Missing?
我正在 运行使用 qemu 构建 Debian Squeeze mips 架构,只是想弄清楚我可以放入 $v0 中执行的系统调用是什么。我找到了这个 webpage。虽然此页面确实告诉我写命令使用 4。我执行以下操作:
我正在使用 this image 安装 Debian Squeeze。
是的,它使用mips作为系统架构:
uname -a
Linux debian 2.6.32-5-4kc-malta #1 Sat Feb 16 12:43:42 UTC 2013 mips GNU/Linux
--test.asm--
.global __start
.text
__start:
li $v0, 4
li $a0, 1
la $a1, out_string
li $a2, 12
syscall
.data
out_string: .asciiz "Hello World\n"
现在我 assemble 使用 'as' 并且 link 使用 'ld'
as -march=mips32 -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
不幸的是,这导致了错误:Illegal Instruction
。
我已经编译了以下 c 程序以确定写入函数使用的偏移量及其要仔细检查的参数。
--write.c--
#include <stdio.h>
int main(int argc, char *argv[]){
printf("Hello World\n");
return 0;
}
运行宁 strace -i ./write.out
给出:
[2abbcbe0] write(1, "Hello World\n", 12Hello World)
write 的手册页说明如下:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
我尝试使用 write 命令来输出 "Hello World",它自己确实工作得很好。
这里描述了 write 函数的作用以及我是如何达到我的编码方式的 test.asm:
fd 或 $a0 - 从打开调用中获得的文件描述符。它是一个整数值。还可以分别为标准输入、标准输出和标准错误给出值 0、1、2
buff or $a1 - 指向一个字符数组,可以用来存放从fd指向的文件中获取的内容。
nbytes 或 $a2 - 指定要从字符数组写入 fd 指向的文件的字节数。
这样我们就得到了顺序:
#0x4 being what unistd.h for mips tells us the system call code is 4
$v0, 4
#Set first argument to the std output 1 for the file descriptor
$a0, 1
#Set the address for the string or buff
$a1, out_string
#Set nbytes or total bytes of the string
$a2, 12
此示例在 Mars 和 Spim 中运行良好,但使用一个参数而不是 3 个参数:
--example.asm--
.data
out_string: .asciiz "\nHello, World!\n"
.text
main:
li $v0, 4
la $a0, out_string
syscall
li $v0, 10
syscall
因为我得到 Illegal Instruction
和 test.asm 这意味着我必须指向一个无效的指令。虽然系统调用代码如前所述here。不正确,即使它是 mips 架构的 unistd.h 文件,我们确认查看写入的手册页及其参数。所以现在我尝试了 strace,认为 $v0 早先指向了错误的指令,并使用 0x2abbcbe0
找到了指令指针。也许这会奏效?让我们试试。
在 strace 中,-i 选项在系统调用时打印指令指针。
所以我编辑asm文件
--test.asm--
.global __start
.text
__start:
li $v0, 0x2abbcbe0
li $a0, 1
la $a1, out_string
li $a2, 12
syscall
.data
out_string: .asciiz "Hello World\n"
运行 assemble 和 link 再次处理:
as -march=mips32 -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
不幸的是,这导致了错误:再次 Illegal Instruction
。
我还颠倒了 $a 寄存器,以为我是向后做的,我 运行 多次跟踪并确认指令指针中的值没有改变,这表明实际上禁用了 aslr .我在 /usr/include/ 中查找了 unistd.h 文件,它看起来与开头显示的网站中的文件完全不同。有趣的是,这种结构在 spim 和 Mars 中都能完美运行,它们都使用 li $v0, 4 模拟它们的打印/写入系统调用。我知道 Mars 和 Spim 使用它们自己的模拟系统调用。以为 strace 会帮我找到它们,但这似乎行不通。
在哪里可以找到 $v0 的正确值?我觉得我已经把 Google 刮到了现在毫无意义的地方。
也许我弄乱了 asm 文件及其语法?
让我们尝试更简单的方法 运行ning exit:
.global __start
.text
__start:
li $v0, 1
li $a0, 0
syscall
Assemble link 和 运行
as -march=mips32 -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
Illegal Instruction
没有-march=mips32
也试过了
as -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
Illegal Instruction
这应该是最容易执行的事情了。
我在这里不知所措,请大家帮忙。
如果您愿意使用 Linux 系统调用,那么在 MIPS 平台(马耳他)上您可以找到系统调用列表 here。在此体系结构上,Linux 将其系统调用从 4000 开始映射。所使用的 ABI 是 MIPS o32。该文件的片段如下。请注意,您可以在系统中的 /usr/include/asm/unistd.h
:
中找到该文件的副本
#define __NR_Linux 4000
#define __NR_exit (__NR_Linux + 1)
#define __NR_write (__NR_Linux + 4)
#define __NR_exit_group (__NR_Linux + 246)
下面的代码应该打印 Hello World
然后退出:
.text
.globl __start
__start:
li $v0, 4004
li $a0, 1
la $a1, out_string
li $a2, 12
syscall
li $v0, 4001
la $a0, 1
syscall
.data
out_string: .asciiz "Hello World\n"
__NR_exit_group
(4246) 在 Linux man pages 中定义并且在一个主要方面不同于正常的 exit
(4001):
This system call is equivalent to exit(2) except that it terminates not only the calling thread, but all threads in the calling process's thread group.
我正在 运行使用 qemu 构建 Debian Squeeze mips 架构,只是想弄清楚我可以放入 $v0 中执行的系统调用是什么。我找到了这个 webpage。虽然此页面确实告诉我写命令使用 4。我执行以下操作:
我正在使用 this image 安装 Debian Squeeze。
是的,它使用mips作为系统架构:
uname -a
Linux debian 2.6.32-5-4kc-malta #1 Sat Feb 16 12:43:42 UTC 2013 mips GNU/Linux
--test.asm--
.global __start
.text
__start:
li $v0, 4
li $a0, 1
la $a1, out_string
li $a2, 12
syscall
.data
out_string: .asciiz "Hello World\n"
现在我 assemble 使用 'as' 并且 link 使用 'ld'
as -march=mips32 -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
不幸的是,这导致了错误:Illegal Instruction
。
我已经编译了以下 c 程序以确定写入函数使用的偏移量及其要仔细检查的参数。
--write.c--
#include <stdio.h>
int main(int argc, char *argv[]){
printf("Hello World\n");
return 0;
}
运行宁 strace -i ./write.out
给出:
[2abbcbe0] write(1, "Hello World\n", 12Hello World)
write 的手册页说明如下:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
我尝试使用 write 命令来输出 "Hello World",它自己确实工作得很好。
这里描述了 write 函数的作用以及我是如何达到我的编码方式的 test.asm:
fd 或 $a0 - 从打开调用中获得的文件描述符。它是一个整数值。还可以分别为标准输入、标准输出和标准错误给出值 0、1、2
buff or $a1 - 指向一个字符数组,可以用来存放从fd指向的文件中获取的内容。
nbytes 或 $a2 - 指定要从字符数组写入 fd 指向的文件的字节数。
这样我们就得到了顺序:
#0x4 being what unistd.h for mips tells us the system call code is 4
$v0, 4
#Set first argument to the std output 1 for the file descriptor
$a0, 1
#Set the address for the string or buff
$a1, out_string
#Set nbytes or total bytes of the string
$a2, 12
此示例在 Mars 和 Spim 中运行良好,但使用一个参数而不是 3 个参数:
--example.asm--
.data
out_string: .asciiz "\nHello, World!\n"
.text
main:
li $v0, 4
la $a0, out_string
syscall
li $v0, 10
syscall
因为我得到 Illegal Instruction
和 test.asm 这意味着我必须指向一个无效的指令。虽然系统调用代码如前所述here。不正确,即使它是 mips 架构的 unistd.h 文件,我们确认查看写入的手册页及其参数。所以现在我尝试了 strace,认为 $v0 早先指向了错误的指令,并使用 0x2abbcbe0
找到了指令指针。也许这会奏效?让我们试试。
在 strace 中,-i 选项在系统调用时打印指令指针。
所以我编辑asm文件
--test.asm--
.global __start
.text
__start:
li $v0, 0x2abbcbe0
li $a0, 1
la $a1, out_string
li $a2, 12
syscall
.data
out_string: .asciiz "Hello World\n"
运行 assemble 和 link 再次处理:
as -march=mips32 -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
不幸的是,这导致了错误:再次 Illegal Instruction
。
我还颠倒了 $a 寄存器,以为我是向后做的,我 运行 多次跟踪并确认指令指针中的值没有改变,这表明实际上禁用了 aslr .我在 /usr/include/ 中查找了 unistd.h 文件,它看起来与开头显示的网站中的文件完全不同。有趣的是,这种结构在 spim 和 Mars 中都能完美运行,它们都使用 li $v0, 4 模拟它们的打印/写入系统调用。我知道 Mars 和 Spim 使用它们自己的模拟系统调用。以为 strace 会帮我找到它们,但这似乎行不通。
在哪里可以找到 $v0 的正确值?我觉得我已经把 Google 刮到了现在毫无意义的地方。
也许我弄乱了 asm 文件及其语法?
让我们尝试更简单的方法 运行ning exit:
.global __start
.text
__start:
li $v0, 1
li $a0, 0
syscall
Assemble link 和 运行
as -march=mips32 -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
Illegal Instruction
没有-march=mips32
as -o test.o test.asm
ld -o test.out test.o
chmod +x test.out
./test.out
Illegal Instruction
这应该是最容易执行的事情了。
我在这里不知所措,请大家帮忙。
如果您愿意使用 Linux 系统调用,那么在 MIPS 平台(马耳他)上您可以找到系统调用列表 here。在此体系结构上,Linux 将其系统调用从 4000 开始映射。所使用的 ABI 是 MIPS o32。该文件的片段如下。请注意,您可以在系统中的 /usr/include/asm/unistd.h
:
#define __NR_Linux 4000
#define __NR_exit (__NR_Linux + 1)
#define __NR_write (__NR_Linux + 4)
#define __NR_exit_group (__NR_Linux + 246)
下面的代码应该打印 Hello World
然后退出:
.text
.globl __start
__start:
li $v0, 4004
li $a0, 1
la $a1, out_string
li $a2, 12
syscall
li $v0, 4001
la $a0, 1
syscall
.data
out_string: .asciiz "Hello World\n"
__NR_exit_group
(4246) 在 Linux man pages 中定义并且在一个主要方面不同于正常的 exit
(4001):
This system call is equivalent to exit(2) except that it terminates not only the calling thread, but all threads in the calling process's thread group.