Android 10 insmodソース分析
34517 ワード
Android 10 insmodソース分析 insmod関数 sys_finit_module マクロ定義等価 概要_NR_init_moduleとsys_init_module
本明細書のコードはrk 3399-android 10に由来する.
insmod関数
ここでのinsmod関数は、ドライバロードwifi_です.load_driverの後に呼び出される関数:wifiについてload_driverのソースコード分析前のブログ:android移植wifi駆動プロセスporting
ファイルの場所:
ここで、彼が呼び出した関数は次のとおりです.
syscallについて:
このセクションでは、長い間多くの資料を調べてきましたが、macroマクロ定義と呼び出された関数との具体的なつながりは理解できません.ちゃんと指導して欲しい...
についてNR_finit_module:
現在、insmodは上述の定義によって、このコード
sys_finit_moduleの定義:
注意:asmlinkageは、レジスタではなくスタックからの関数読み出しのパラメータを表します.
sys_finit_module
まず,上記から総合すると,この関数定義式は:
次に上のsys_を見てみましょうfinit_moduleが呼び出す次のレベルの関数.ファイルの場所:
マクロ定義の等価
マクロ定義の最終等価についてはsyscalls.hファイル.
上から分かるようにSYSCALL_DEFINE3 ==》 SYSCALL_DEFINEx(3,_finit_module,VA_ARGS)のうち_VA_ARGS__対応はSYSCALL_DEFINE 3の後のすべてのパラメータセット、すなわち
以上より、SYSCALL_を知るDEFINEx ==》 __SYSCALL_DEFINEx(3, _finit_module, VA_ARGS)
分析を続けたのか
以上より、
上記各種類のマクロ変換:
実際には
についてNR_init_moduleとsys_init_module
この部分のコードを学ぶ時、ネット上のいくつかのブログを参考にして、しかしどうしてみんなが書いたinsmod呼び出しの関数がすべて__ですかを知りませんNR_init_module、つまりsys_init_module、バージョンの違いでしょう.
比較のために、そのコードも貼り付けます.
場所の定義:
ファイルの場所:
比較すると、両者の違いはinit_moduleは従来のcopy_を通じてfrom_userはkoコードをコピーし、finit_moduleは、ファイル記述子fdによってvfsの下位層の読み出し関数を呼び出してkoコードをカーネルに読み出す.
まとめ:学習の過程で、
modprobeとinsmodの違い: modprobeはload module時の依存関係 を解決できる. modprobeデフォルトでは/lib/moduules/現在のkernel/下にmoduleが検索されますが、insmodはそのパラメータの中でmodule のみが検索されます.
本明細書のコードはrk 3399-android 10に由来する.
insmod関数
ここでのinsmod関数は、ドライバロードwifi_です.load_driverの後に呼び出される関数:wifiについてload_driverのソースコード分析前のブログ:android移植wifi駆動プロセスporting
ファイルの場所:
rk3399-android-10/frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp
static int insmod(const char *filename, const char *args) {
int ret;
int fd;
fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
printf("insmod filename = %s
",filename);
if (fd < 0) {
PLOG(ERROR) << "Failed to open " << filename;
return -1;
}
ret = syscall(__NR_finit_module, fd, args, 0);
close(fd);
if (ret < 0) {
PLOG(ERROR) << "finit_module return: " << ret;
}
return ret;
}
ここで、彼が呼び出した関数は次のとおりです.
syscallについて:
rk3399-android-10/kernel/arch/arm/kernel/entry-common.S
.macro syscall, nr, func
.ifgt __sys_nr -
r
.error "Duplicated/unorded system call entry"
.endif
.rept
r - __sys_nr
.long sys_ni_syscall
.endr
.long \func
.equ __sys_nr,
r + 1
このセクションでは、長い間多くの資料を調べてきましたが、macroマクロ定義と呼び出された関数との具体的なつながりは理解できません.ちゃんと指導して欲しい...
についてNR_finit_module:
rk3399-android-10/kernel/include/uapi/asm-generic/unistd.h
#define __NR_finit_module 273//
__SYSCALL(__NR_finit_module, sys_finit_module)
現在、insmodは上述の定義によって、このコード
syscall(__NR_finit_module, fd, args, 0);
を通じて、システム呼び出し番号(割り込み番号)を利用してsys_を呼び出すことができることしか知られていない.finit_module,finit_moduleのシステム呼び出し番号は__です.NR_finit_module. sys_finit_moduleの定義:
rk3399-android-10/kernel/include/linux/syscalls.h
asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
注意:asmlinkageは、レジスタではなくスタックからの関数読み出しのパラメータを表します.
sys_finit_module
rk3399-android-10/kernel/kernel/module.c
には、次の定義があります.SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
{
struct load_info info = {
};
loff_t size;
void *hdr;
int err;
err = may_init_module();
if (err)
return err;
pr_debug("finit_module: fd=%d, uargs=%p, flags=%i
", fd, uargs, flags);
if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS
|MODULE_INIT_IGNORE_VERMAGIC))
return -EINVAL;
err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX, READING_MODULE);
// rk3399-android-10/kernel/fs/exec.c , , fd
if (err)
return err;
info.hdr = hdr;
info.len = size;
return load_module(&info, uargs, flags);
}
まず,上記から総合すると,この関数定義式は:
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
であることが分かる.この行の意味はasmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
の行の定義とほぼ同じです.詳細な中間のマクロ定義の変換過程に興味のある可視文章の「マクロ定義の等価」章.次に上のsys_を見てみましょうfinit_moduleが呼び出す次のレベルの関数.ファイルの場所:
rk3399-android-10/kernel/kernel/module.c
static int may_init_module(void)
{
if (!capable(CAP_SYS_MODULE) || modules_disabled)//capable , 0
//CAP_SYS_MODULE , rk3399-android-10/kernel/include/uapi/linux/capability.h
return -EPERM;
return 0;
}
//load_module ,
static int load_module(struct load_info *info, const char __user *uargs,
int flags)
{
struct module *mod;
long err = 0;
char *after_dashes
err = elf_header_check(info);
.....
return do_init_module(mod);
...
}
マクロ定義の等価
マクロ定義の最終等価についてはsyscalls.hファイル.
rk3399-android-10/kernel/include/linux/syscalls.h
#ifndef SYSCALL_DEFINE0
#define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0); \
asmlinkage long sys_##sname(void); \
ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \
asmlinkage long sys_##sname(void)
#endif /* SYSCALL_DEFINE0 */
#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
上から分かるようにSYSCALL_DEFINE3 ==》 SYSCALL_DEFINEx(3,_finit_module,VA_ARGS)のうち_VA_ARGS__対応はSYSCALL_DEFINE 3の後のすべてのパラメータセット、すなわち
int, fd, const char __user *, uargs, int, flags
またはrk3399-android-10/kernel/include/linux/syscalls.h
で、以下の定義があります.#define SYSCALL_DEFINEx(x, sname, ...) \
SYSCALL_METADATA(sname, x, __VA_ARGS__) \
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
以上より、SYSCALL_を知るDEFINEx ==》 __SYSCALL_DEFINEx(3, _finit_module, VA_ARGS)
分析を続けたのか
rk3399-android-10/kernel/include/linux/syscalls.h
で#ifndef __SYSCALL_DEFINEx
#define __SYSCALL_DEFINEx(x, name, ...) \
__diag_push(); \
__diag_ignore(GCC, 8, "-Wattribute-alias", \
"Type aliasing is used to sanitize syscall arguments");\
asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
__attribute__((alias(__stringify(__se_sys##name)))); \
c \
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
{ \
long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
__MAP(x,__SC_TEST,__VA_ARGS__); \
__PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
return ret; \
} \
__diag_pop(); \
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#endif /* __SYSCALL_DEFINEx */
以上より、
__SYSCALL_DEFINEx(3, _finit_module, __VA_ARGS__)
は、asmlinkage long sys_finit_module(__MAP(3,__SC_DECL, __VA_ARGS__)) \
__attribute__((alias(__stringify(__se_sys_finit_module)))); \
ALLOW_ERROR_INJECTION(sys_finit_module, ERRNO); \
static inline long __do_sys_finit_module(__MAP(3,__SC_DECL,__VA_ARGS__));\
asmlinkage long __se_sys_finit_module(__MAP(3,__SC_LONG,__VA_ARGS__));\
asmlinkage long __se_sys_finit_module(__MAP(3,__SC_LONG,__VA_ARGS__)) \
{
\
long ret = __do_sys_finit_module(__MAP(3,__SC_CAST,__VA_ARGS__));\
__MAP(3,__SC_TEST,__VA_ARGS__); \
__PROTECT(3, ret,__MAP(3,__SC_ARGS,__VA_ARGS__)); \
return ret; \
}\
static inline long __do_sys_finit_module(__MAP(3,__SC_DECL, __VA_ARGS__))
上記各種類のマクロ変換:
asmlinkage long sys_finit_module(int fd, const char __user * uargs, int flags) \
__attribute__((alias(__stringify(__se_sys_finit_module)))); \
ALLOW_ERROR_INJECTION(sys_finit_module, ERRNO); \
static inline long __do_sys_finit_module(int fd, const char __user * uargs, int flags);\
asmlinkage long __se_sys_finit_module(long fd, long uargs, long flags);\
asmlinkage long __se_sys_finit_module(long fd, long uargs, long flags) \
{
\
long ret = __do_sys_finit_module( (int) fd, (const char __user *) uargs, (int) flags);\
BUILD_BUG_ON_ZERO(sizeof(int) > sizeof(long)); \
BUILD_BUG_ON_ZERO(sizeof(char*) > sizeof(long)); \
__PROTECT(2, ret, fd, uargs , flags); \
return ret; \
}\
static inline long __do_sys_finit_module(int fd, const char __user * uargs, int flags)
実際には
SYSCALL_DEFINE3(finit_module,int, fd, 。。。)
であり、最終的にはasmlinkage long sys_finit_module(int fd, 。。。)
に等価である.についてNR_init_moduleとsys_init_module
この部分のコードを学ぶ時、ネット上のいくつかのブログを参考にして、しかしどうしてみんなが書いたinsmod呼び出しの関数がすべて__ですかを知りませんNR_init_module、つまりsys_init_module、バージョンの違いでしょう.
比較のために、そのコードも貼り付けます.
場所の定義:
rk3399-android-10/kernel/include/linux/syscalls.h
asmlinkage long sys_init_module(void __user *umod, unsigned long len,
const char __user *uargs);
ファイルの場所:
rk3399-android-10/kernel/kernel/module.c
SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs)
{
int err;
struct load_info info = {
};
err = may_init_module();
if (err)
return err;
printk("init_module: umod=%p, len=%lu, uargs=%p
",umod,len,uargs);
pr_debug("init_module: umod=%p, len=%lu, uargs=%p
",
umod, len, uargs);
err = copy_module_from_user(umod, len, &info);
if (err)
return err;
return load_module(&info, uargs, 0);
}
比較すると、両者の違いはinit_moduleは従来のcopy_を通じてfrom_userはkoコードをコピーし、finit_moduleは、ファイル記述子fdによってvfsの下位層の読み出し関数を呼び出してkoコードをカーネルに読み出す.
まとめ:学習の過程で、
external/kmod/tools/modprobe.c
に位置するinsmod関数があり、ツールmodprobeで使用されるinsmod関数と推定されることが分かった.ここにコードを貼らない.modprobeとinsmodの違い: