- 论坛徽章:
- 0
|
本帖最后由 71v5 于 2014-06-26 15:20 编辑
[__ElfN(Brandinfo)类型的数据对象]:
__ElfN(Brandinfo)数据对象使得freebsd可以不加修改的执行在其它os上编译好的elf可执行文件
(比如linux,前提是底层硬件平台要一致),如果想要在freebsd上执行一个在其他操作系统上已经编
译好的elf可执行文件,那么freebsd内核中都要为相应的操作系统定义其对应的Elf32_Brandinfo数据对象,
并且在内核初始化阶段将其添加到elf_brand_list数组中,在解析elf可执行文件的过程中,函数
__elfN(get_brandinfo)会根据elf文件中包含的信息在数组elf_brand_list中选择一个最合适的
Elf32_Brandinfo对象。- /*********************************************************************************************
- * 成员描述:
- brand:
- Operating system / ABI identification,在不同的操作系统上编译一个c文件后,elf可执行
- 文件头部都有相应的标识符来标识该c文件具体是在哪种操作系统上编译的,elf可执行文件头
- 部的这个标识符就和brand成员想对应,常见取值如下:
- #define ELFOSABI_LINUX 3 GNU/Linux
- #define ELFOSABI_FREEBSD 9 FreeBSD。
- machine:
- 标识了底层的硬件cpu平台,在elf可执行文件头部也有其对应的成员,常见值如下:
- #define EM_386 3 Intel i386.
- #define EM_ARM 40 ARM.
-
- compat_3_brand:
- 一个字符串,__elfN(get_brandinfo)函数在选择适用该elf可执行文件的__ElfN(Brandinfo)
- 对象时使用。
- emul_path,interp_path,interp_newpath:
- 指向三个解释器的路径名字符串,这里的解释器不是类似shell,python等这样的解释器,
- 这里的解释器负责对elf可执行文件中未解决的符号引用进行解析,即用实际有意义的值替换
- 这些符号,典型就是c程序使用了函数库中的相关函数。
- 在elf可执行文件中,类型为PT_INTERP的程序段中也包含一个解释器的路径名字符串,这个
- 解释器一般情况下和interp_path成员指向的解释器相同。
- emul_path:如果该成员非空,那么emul_path指向的字符串作为解释器路径名的一部分。
- interp_path:指向一个有意义的解释器字符串。
- interp_newpath:如果该成员非空,首先使用该解释器。
-
- flags:一些标志。
- brand_note:只有elf可执行文件包含类型为PT_NOTE的程序段时,该成员的值才有意义,
- 这里忽略。
- sysvec:最最重要的成员,指向的数据对象类型为struct sysentvec,该数据对象包含了
- 内核实现系统调用的方法表,以及从系统调用获取参数的方法,在系统调用返回
- 时进行相应处理的方法。假如在linux系统上编译了一个c代码,改代码执行了
- 一个read系统调用,在linux系统上编译后得到的elf可执行文件依然可以在freebsd
- 上不加修改的执行,只要正确设置了struct proc对象的sysvec成员(该成员正是
- 这里的sysvec成员),再加上上面描述的解释器的帮助,那么就可以正确的运行。
- 这里说的比较抽象,后续在分享系统调用陷入机制的过程中会以一个实例来说明,
- 这样就一目了然了。
- *********************************************/
- 67 typedef struct {
- 68 int brand;
- 69 int machine;
- 70 const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */
- 71 const char *emul_path;
- 72 const char *interp_path;
- 73 struct sysentvec *sysvec;
- 74 const char *interp_newpath;
- 75 int flags;
- 76 Elf_Brandnote *brand_note;
- 77 #define BI_CAN_EXEC_DYN 0x0001
- 78 #define BI_BRAND_NOTE 0x0002 /* May have note.ABI-tag section. */
- 79 #define BI_BRAND_NOTE_MANDATORY 0x0004 /* Must have note.ABI-tag section. */
- 80 } __ElfN(Brandinfo);
复制代码 下面列出内核中定义的几个比较典型的Elf32_Brandinfo数据对象:
[支持在freebsd上编译好的elf可执行文件]:- 87 static Elf32_Brandinfo freebsd_brand_info = {
- 88 .brand = ELFOSABI_FREEBSD,
- 89 .machine = EM_386,
- 90 .compat_3_brand = "FreeBSD",
- 91 .emul_path = NULL,
- 92 .interp_path = "/libexec/ld-elf.so.1",
- 93 .sysvec = &elf32_freebsd_sysvec,
- 94 .interp_newpath = NULL,
- 95 .brand_note = &elf32_freebsd_brandnote,
- 96 .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
- 97 };
复制代码 [用来支持在linux上编译好的elf可执行文件]:- 1083 static Elf32_Brandinfo linux_glibc2brand = {
- 1084 .brand = ELFOSABI_LINUX,
- 1085 .machine = EM_386,
- 1086 .compat_3_brand = "Linux",
- 1087 .emul_path = "/compat/linux",
- 1088 .interp_path = "/lib/ld-linux.so.2",
- 1089 .sysvec = &elf_linux_sysvec,
- 1090 .interp_newpath = NULL,
- 1091 .brand_note = &linux_brandnote,
- 1092 .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
- 1093 };
复制代码 Elf32_Brandinfo类型的数据对象最后都通过函数elf32_insert_brand_entry添加到elf_brand_list数组中:- /***************************************************************************
- * #define OLD_EI_BRAND 8
- static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
-
- __elfN(insert_brand_entry)函数作用一目了然,再次假设数组elf_brand_list
- 初始化后取值如下:
- elf_brand_list[0] = &freebsd_brand_info;
- elf_brand_list[1] = &linux_glibc2brand;
- **********************************/
- 206 int
- 207 __elfN(insert_brand_entry)(Elf_Brandinfo *entry)
- 208 {
- 209 int i;
- 210
- 211 for (i = 0; i < MAX_BRANDS; i++) {
- 212 if (elf_brand_list[i] == NULL) {
- 213 elf_brand_list[i] = entry;
- 214 break;
- 215 }
- 216 }
- 217 if (i == MAX_BRANDS) {
- 218 printf("WARNING: %s: could not insert brandinfo entry: %p\n",
- 219 __func__, entry);
- 220 return (-1);
- 221 }
- 222 return (0);
- 223 }
复制代码 |
|