---- 整理自 王利涛老师 课程
实验环境:宅学部落 www.zhaixue.cc
main.c – add() – add.c add.h add.o ⇒ ar ⇒ libmath.so / libmath.a
main.c – sub() – sub.c sub.h sub.o ⇒ ar ⇒ libmath.so / libmath.a
swi / svc
man 2 syscall
.text
.global _start
_start:
mov r0, #1 /* stdout*/
add r1, pc, #16 /* address of the string*/
mov r2, #12 /* string length*/
mov r7, #4 /*syscall for 'write'*/
swi #0 /* software interrupt*/
_exit:
mov r7, #1 /* syscall for 'exit'*/
swi #0 /* software interrupt*/
_string:
.asciz "Hello world\n" @ our string, NULL terminated
.text
_start:
mov $4, %eax /* syscall write */
mov $1, %ebx /* fd */
mov $str, %ecx
mov $13, %edx
int $0x80
mov $1, %eax
mov $0, %ebx
int $0x80
.data
str:
.string "Hello world!\n"
.text
_start:
mov $1, %rax /* syscall write */
mov $1, %rdi /* fd */
mov $str, %rsi
mov $13, %rdx
syscall
mov $60, %rax
mov $0, %rdi
syscall
.data
str:
.string "Hello world!\n"
#include
#include
int main(void)
{
printf("Hello world!\n");
write(1, "Hello world!\n", 13);
// 系统调用号1 标准输出 字符串内容 字符串长度
syscall(1, 1, "Hello syscall!\n", 15);
return 0;
}
#include
#include
int main(void)
{
printf("Hello world!\n");
write(1, "Hello world!\n", 13);
// 系统调用号4 标准输出 字符串内容 字符串长度
syscall(4, 1, "Hello syscall!\n", 15);
return 0;
}
// kernel\linux-5.10.4\arch\arm\include\generated\uapi\asm\unistd-common.h
...
#define __NR_kill (__NR_SYSCALL_BASE + 37) // 系统调用号
...
// kernel\linux-5.10.4\include\linux\syscalls.h
...
asmlinkage long sys_kill(pid_t pid, int sig); // 系统调用函数声明
asmlinkage long sys_tkill(pid_t pid, int sig);
asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig);
...
// kernel\linux-5.10.4\kernel\signal.c
...
/**
* sys_kill - send a signal to a process
* @pid: the PID of the process
* @sig: signal to be sent
*/
SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) // 系统调用函数实现
{
struct kernel_siginfo info;
prepare_kill_siginfo(sig, &info);
return kill_something_info(sig, &info, pid);
}
...
// kernel\linux-5.10.4\arch\arm\include\generated\calls-eabi.S
...
NATIVE(37, sys_kill) // 中断向量表
...
// kernel\linux-5.10.4\arch\arm\kernel\entry-common.S
// 中断处理程序
proc/<PID>/maps
# 查看进程的虚拟地址空间是如何使用的。
#include
#include
typedef time_t (*time_fp)(time_t *);
int main(void)
{
time_t t1, t2;
t1 = time(NULL);
time_fp fp = (time_fp)0xffffffffff600400; // 可以下载 glibc-2.22 之前的版本,
// 搜索:grep -nr VSYSCALL_ADDR_vtime 查看这里的地址。
t2 = fp(NULL);
printf("t1 = %ld\n", t1);
printf("t2 = %ld\n", t2);
return 0;
}
# cat /proc/self/maps
(6.2.2 中演示)arch/arm/kernel/vdso.c
struct vdso_data
可以关闭随机地址功能:echo 0 > /proc/sys/kernel/randomize_va_space
可以通过:cat /proc/self/smaps
查看 vdso 大小。(输出内容较多,截取 vdso 大小的部分如下)
起始地址:0x7ffff7fcd000
偏移:0x9e0
#include
#include
typedef time_t (*time_fp)(time_t *);
int main(void)
{
time_t t1, t2;
t1 = time(NULL);
time_fp fp = (time_fp)(0x7ffff7fcd000 + 0x9e0); // 见上述2,起始地址 + 偏移
t2 = fp(NULL);
printf("t1 = %ld\n", t1);
printf("t2 = %ld\n", t2);
return 0;
}