The write
syscall has the following functional prototype:
write syscall具有以下功能原型:
size_t write(int, const void *buf, size_t nbytes);
How do I call the write
syscall using inline assembler in GCC under MacOS X?
如何在MacOS X下使用GCC中的内联汇编程序调用写syscall ?
2 个解决方案
#1
11
A generic solution to this type of question: Write a short test program doing the write() call you are interested in, and then use gcc -S
to produce assembly or use otool
to disassemble the binary; find out how the write() call was assembled and transform that into the appropriate inline assembly.
这类问题的通用解决方案:编写一个简短的测试程序,编写您感兴趣的Write()调用,然后使用gcc -S来生成汇编或使用otool来分解二进制文件;了解write()调用是如何组装的,并将其转换为适当的内联程序集。
(edit) To see the actual syscall, follow the library call in the assembly code. In the example of write()
, following the indirections will lead you via libSystem.B.dylib
to _write
in libsystem_kernel.dylib
, which you can disassemble using otool
.
(编辑)要查看实际的syscall,请遵循程序集代码中的库调用。在write()示例中,跟随indirections将通过libSystem.B引导您。在libsystem_kernel中写入_write的dylib。dylib,可以用otool拆卸。
(edit2) Full example below, using this test program test.c
:
(edit2)完整示例,使用此测试程序测试。
#include <stdio.h>
int main(void)
{
char buf[] = "test\n";
ssize_t n;
n = write(2, buf, sizeof(buf));
return n;
}
Compile and test, using -O1 -fverbose-asm
to get concise, readable machine code:
编译和测试,使用-O1 -fverbose-asm获得简洁、可读的机器代码:
% gcc -O1 -fverbose-asm -o test test.c
% ./test
test
Use otool
to disassemble main()
in the test
binary:
在测试二进制文件中使用otool分解main():
% otool -p _main -tvV test
test:
(__TEXT,__text) section
_main:
0000000100000ef0 pushq %rbp
0000000100000ef1 movq %rsp,%rbp
0000000100000ef4 subq $0x10,%rsp
0000000100000ef8 leaq 0xfa(%rbp),%rsi
0000000100000efc movb $0x74,0xfa(%rbp)
0000000100000f00 movb $0x65,0xfb(%rbp)
0000000100000f04 movb $0x73,0xfc(%rbp)
0000000100000f08 movb $0x74,0xfd(%rbp)
0000000100000f0c movb $0x0a,0xfe(%rbp)
0000000100000f10 movb $0x00,0xff(%rbp)
0000000100000f14 movl $0x00000002,%edi
0000000100000f19 movl $0x00000006,%edx
0000000100000f1e xorb %al,%al
0000000100000f20 callq 0x100000f32 ; symbol stub for: _write
0000000100000f25 addq $0x10,%rsp
0000000100000f29 popq %rbp
0000000100000f2a ret
List the libraries test
is dynamically linked against to find _write
:
列出库测试被动态链接到查找_write:
% otool -L test
test:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
Try to locate _write
in libSystem.B.dylib
:
尝试在libSystem.B.dylib中找到_write:
% otool -p _write -tvV /usr/lib/libSystem.B.dylib
/usr/lib/libSystem.B.dylib:
(__TEXT,__text) section
Can't find -p symbol: _write
Check the dependencies of libSystem.B.dylib
:
检查libSystem.B.dylib的依赖关系:
% otool -L /usr/lib/libSystem.B.dylib
/usr/lib/libSystem.B.dylib:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/usr/lib/system/libcache.dylib (compatibility version 1.0.0, current version 47.0.0)
/usr/lib/system/libcommonCrypto.dylib (compatibility version 1.0.0, current version 55010.0.0)
/usr/lib/system/libcompiler_rt.dylib (compatibility version 1.0.0, current version 6.0.0)
/usr/lib/system/libcopyfile.dylib (compatibility version 1.0.0, current version 85.1.0)
/usr/lib/system/libdispatch.dylib (compatibility version 1.0.0, current version 187.9.0)
/usr/lib/system/libdnsinfo.dylib (compatibility version 1.0.0, current version 395.11.0)
/usr/lib/system/libdyld.dylib (compatibility version 1.0.0, current version 195.6.0)
/usr/lib/system/libkeymgr.dylib (compatibility version 1.0.0, current version 23.0.0)
/usr/lib/system/liblaunch.dylib (compatibility version 1.0.0, current version 392.38.0)
/usr/lib/system/libmacho.dylib (compatibility version 1.0.0, current version 800.0.0)
/usr/lib/system/libmathCommon.A.dylib (compatibility version 1.0.0, current version 2026.0.0)
/usr/lib/system/libquarantine.dylib (compatibility version 1.0.0, current version 36.6.0)
/usr/lib/system/libremovefile.dylib (compatibility version 1.0.0, current version 21.1.0)
/usr/lib/system/libsystem_blocks.dylib (compatibility version 1.0.0, current version 53.0.0)
/usr/lib/system/libsystem_c.dylib (compatibility version 1.0.0, current version 763.13.0)
/usr/lib/system/libsystem_dnssd.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libsystem_info.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libsystem_kernel.dylib (compatibility version 1.0.0, current version 1699.26.8)
/usr/lib/system/libsystem_network.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libsystem_notify.dylib (compatibility version 1.0.0, current version 80.1.0)
/usr/lib/system/libsystem_sandbox.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libunc.dylib (compatibility version 1.0.0, current version 24.0.0)
/usr/lib/system/libunwind.dylib (compatibility version 1.0.0, current version 30.0.0)
/usr/lib/system/libxpc.dylib (compatibility version 1.0.0, current version 77.19.0)
Guess that _write
is probably contained in libsystem_kernel.dylib
(or alternatively try all of them):
假设_write可能包含在libsystem_kernel中。dylib(或者尝试所有方法):
% otool -p _write -tvV /usr/lib/system/libsystem_kernel.dylib | head -20
(__TEXT,__text) section
_write:
0000000000017fd4 movl $0x02000004,%eax
0000000000017fd9 movq %rcx,%r10
0000000000017fdc syscall
0000000000017fde jae 0x00017fe5
0000000000017fe0 jmp cerror
0000000000017fe5 ret
0000000000017fe6 nop
0000000000017fe7 nop
[...]
Now we have all the assembly we need to construct the inline assembly version of test
:
现在我们已经有了构建内联测试程序集版本所需的所有程序集:
#include <stdio.h>
int main(void)
{
char buf[] = "test\n";
ssize_t n;
asm volatile (
"movl $0x00000002, %%edi\n" /* first argument */
"movl $0x00000006, %%edx\n" /* third argument */
"movl $0x02000004, %%eax\n" /* syscall number */
"syscall\n"
: "=A"(n) /* %rax: return value */
: "S"(buf)); /* %rsi: second argument */
return n;
}
Compile and test:
编译和测试:
% gcc -O1 -fverbose-asm -o test-asm test-asm.c
% ./test-asm
test
That seems to work. The inline assembly above is not very refined; for example, you could pass in the first and third arguments dynamically as well, instead of hardcoding them in the assembly code.
这似乎工作。上面的内联程序集不是很完善;例如,您也可以动态地传递第一个和第三个参数,而不是在汇编代码中硬编码它们。
#2
2
The Linux solution is something like this:
Linux解决方案是这样的:
.data mytext:
.ascii "Hello World\n"
.text
_mywrite:
movl $0x04, %eax # Syscall No. 4 = write
movl $0x01, %ebx # File. 1 = stdout
movl $mytext, %ecx
movl $0x0c, %edx # text length (hope I counted correctly)
int $0x80 # Interrupt 0x80 -> make syscall
Should be similar on other Unix systems like Mac, but better check the syscall number (0x04) in the documentation.
应该类似于其他Unix系统,如Mac,但是最好检查文档中的syscall编号(0x04)。
#1
11
A generic solution to this type of question: Write a short test program doing the write() call you are interested in, and then use gcc -S
to produce assembly or use otool
to disassemble the binary; find out how the write() call was assembled and transform that into the appropriate inline assembly.
这类问题的通用解决方案:编写一个简短的测试程序,编写您感兴趣的Write()调用,然后使用gcc -S来生成汇编或使用otool来分解二进制文件;了解write()调用是如何组装的,并将其转换为适当的内联程序集。
(edit) To see the actual syscall, follow the library call in the assembly code. In the example of write()
, following the indirections will lead you via libSystem.B.dylib
to _write
in libsystem_kernel.dylib
, which you can disassemble using otool
.
(编辑)要查看实际的syscall,请遵循程序集代码中的库调用。在write()示例中,跟随indirections将通过libSystem.B引导您。在libsystem_kernel中写入_write的dylib。dylib,可以用otool拆卸。
(edit2) Full example below, using this test program test.c
:
(edit2)完整示例,使用此测试程序测试。
#include <stdio.h>
int main(void)
{
char buf[] = "test\n";
ssize_t n;
n = write(2, buf, sizeof(buf));
return n;
}
Compile and test, using -O1 -fverbose-asm
to get concise, readable machine code:
编译和测试,使用-O1 -fverbose-asm获得简洁、可读的机器代码:
% gcc -O1 -fverbose-asm -o test test.c
% ./test
test
Use otool
to disassemble main()
in the test
binary:
在测试二进制文件中使用otool分解main():
% otool -p _main -tvV test
test:
(__TEXT,__text) section
_main:
0000000100000ef0 pushq %rbp
0000000100000ef1 movq %rsp,%rbp
0000000100000ef4 subq $0x10,%rsp
0000000100000ef8 leaq 0xfa(%rbp),%rsi
0000000100000efc movb $0x74,0xfa(%rbp)
0000000100000f00 movb $0x65,0xfb(%rbp)
0000000100000f04 movb $0x73,0xfc(%rbp)
0000000100000f08 movb $0x74,0xfd(%rbp)
0000000100000f0c movb $0x0a,0xfe(%rbp)
0000000100000f10 movb $0x00,0xff(%rbp)
0000000100000f14 movl $0x00000002,%edi
0000000100000f19 movl $0x00000006,%edx
0000000100000f1e xorb %al,%al
0000000100000f20 callq 0x100000f32 ; symbol stub for: _write
0000000100000f25 addq $0x10,%rsp
0000000100000f29 popq %rbp
0000000100000f2a ret
List the libraries test
is dynamically linked against to find _write
:
列出库测试被动态链接到查找_write:
% otool -L test
test:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
Try to locate _write
in libSystem.B.dylib
:
尝试在libSystem.B.dylib中找到_write:
% otool -p _write -tvV /usr/lib/libSystem.B.dylib
/usr/lib/libSystem.B.dylib:
(__TEXT,__text) section
Can't find -p symbol: _write
Check the dependencies of libSystem.B.dylib
:
检查libSystem.B.dylib的依赖关系:
% otool -L /usr/lib/libSystem.B.dylib
/usr/lib/libSystem.B.dylib:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/usr/lib/system/libcache.dylib (compatibility version 1.0.0, current version 47.0.0)
/usr/lib/system/libcommonCrypto.dylib (compatibility version 1.0.0, current version 55010.0.0)
/usr/lib/system/libcompiler_rt.dylib (compatibility version 1.0.0, current version 6.0.0)
/usr/lib/system/libcopyfile.dylib (compatibility version 1.0.0, current version 85.1.0)
/usr/lib/system/libdispatch.dylib (compatibility version 1.0.0, current version 187.9.0)
/usr/lib/system/libdnsinfo.dylib (compatibility version 1.0.0, current version 395.11.0)
/usr/lib/system/libdyld.dylib (compatibility version 1.0.0, current version 195.6.0)
/usr/lib/system/libkeymgr.dylib (compatibility version 1.0.0, current version 23.0.0)
/usr/lib/system/liblaunch.dylib (compatibility version 1.0.0, current version 392.38.0)
/usr/lib/system/libmacho.dylib (compatibility version 1.0.0, current version 800.0.0)
/usr/lib/system/libmathCommon.A.dylib (compatibility version 1.0.0, current version 2026.0.0)
/usr/lib/system/libquarantine.dylib (compatibility version 1.0.0, current version 36.6.0)
/usr/lib/system/libremovefile.dylib (compatibility version 1.0.0, current version 21.1.0)
/usr/lib/system/libsystem_blocks.dylib (compatibility version 1.0.0, current version 53.0.0)
/usr/lib/system/libsystem_c.dylib (compatibility version 1.0.0, current version 763.13.0)
/usr/lib/system/libsystem_dnssd.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libsystem_info.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libsystem_kernel.dylib (compatibility version 1.0.0, current version 1699.26.8)
/usr/lib/system/libsystem_network.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libsystem_notify.dylib (compatibility version 1.0.0, current version 80.1.0)
/usr/lib/system/libsystem_sandbox.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/system/libunc.dylib (compatibility version 1.0.0, current version 24.0.0)
/usr/lib/system/libunwind.dylib (compatibility version 1.0.0, current version 30.0.0)
/usr/lib/system/libxpc.dylib (compatibility version 1.0.0, current version 77.19.0)
Guess that _write
is probably contained in libsystem_kernel.dylib
(or alternatively try all of them):
假设_write可能包含在libsystem_kernel中。dylib(或者尝试所有方法):
% otool -p _write -tvV /usr/lib/system/libsystem_kernel.dylib | head -20
(__TEXT,__text) section
_write:
0000000000017fd4 movl $0x02000004,%eax
0000000000017fd9 movq %rcx,%r10
0000000000017fdc syscall
0000000000017fde jae 0x00017fe5
0000000000017fe0 jmp cerror
0000000000017fe5 ret
0000000000017fe6 nop
0000000000017fe7 nop
[...]
Now we have all the assembly we need to construct the inline assembly version of test
:
现在我们已经有了构建内联测试程序集版本所需的所有程序集:
#include <stdio.h>
int main(void)
{
char buf[] = "test\n";
ssize_t n;
asm volatile (
"movl $0x00000002, %%edi\n" /* first argument */
"movl $0x00000006, %%edx\n" /* third argument */
"movl $0x02000004, %%eax\n" /* syscall number */
"syscall\n"
: "=A"(n) /* %rax: return value */
: "S"(buf)); /* %rsi: second argument */
return n;
}
Compile and test:
编译和测试:
% gcc -O1 -fverbose-asm -o test-asm test-asm.c
% ./test-asm
test
That seems to work. The inline assembly above is not very refined; for example, you could pass in the first and third arguments dynamically as well, instead of hardcoding them in the assembly code.
这似乎工作。上面的内联程序集不是很完善;例如,您也可以动态地传递第一个和第三个参数,而不是在汇编代码中硬编码它们。
#2
2
The Linux solution is something like this:
Linux解决方案是这样的:
.data mytext:
.ascii "Hello World\n"
.text
_mywrite:
movl $0x04, %eax # Syscall No. 4 = write
movl $0x01, %ebx # File. 1 = stdout
movl $mytext, %ecx
movl $0x0c, %edx # text length (hope I counted correctly)
int $0x80 # Interrupt 0x80 -> make syscall
Should be similar on other Unix systems like Mac, but better check the syscall number (0x04) in the documentation.
应该类似于其他Unix系统,如Mac,但是最好检查文档中的syscall编号(0x04)。