diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c --- a/stand/common/load_elf.c +++ b/stand/common/load_elf.c @@ -545,6 +545,7 @@ Elf_Dyn *dp; Elf_Addr adp; Elf_Addr ctors; + Elf_Addr uuid; int ndp; int symstrindex; int symtabindex; @@ -731,16 +732,27 @@ shdr[ehdr->e_shstrndx].sh_offset, chunk); if (shstr) { for (i = 0; i < ehdr->e_shnum; i++) { - if (strcmp(shstr + shdr[i].sh_name, - ".ctors") != 0) - continue; - ctors = shdr[i].sh_addr; - file_addmetadata(fp, MODINFOMD_CTORS_ADDR, - sizeof(ctors), &ctors); - size = shdr[i].sh_size; - file_addmetadata(fp, MODINFOMD_CTORS_SIZE, - sizeof(size), &size); - break; + if (strcmp(shstr + shdr[i].sh_name, ".ctors") == + 0) { + ctors = shdr[i].sh_addr; + file_addmetadata(fp, + MODINFOMD_CTORS_ADDR, sizeof(ctors), + &ctors); + size = shdr[i].sh_size; + file_addmetadata(fp, + MODINFOMD_CTORS_SIZE, sizeof(size), + &size); + } else if (strcmp(shstr + shdr[i].sh_name, + ".note.gnu.build-id") == 0) { + uuid = shdr[i].sh_addr; + file_addmetadata(fp, + MODINFOMD_UUID_ADDR, sizeof(uuid), + &uuid); + size = shdr[i].sh_size; + file_addmetadata(fp, + MODINFOMD_UUID_SIZE, sizeof(size), + &size); + } } free(shstr); } diff --git a/stand/common/load_elf_obj.c b/stand/common/load_elf_obj.c --- a/stand/common/load_elf_obj.c +++ b/stand/common/load_elf_obj.c @@ -263,6 +263,7 @@ #endif case SHT_INIT_ARRAY: case SHT_FINI_ARRAY: + case SHT_NOTE: if ((shdr[i].sh_flags & SHF_ALLOC) == 0) break; lastaddr = roundup(lastaddr, shdr[i].sh_addralign); diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -79,6 +79,8 @@ const int kld_off_filename = offsetof(struct linker_file, filename); const int kld_off_pathname = offsetof(struct linker_file, pathname); const int kld_off_next = offsetof(struct linker_file, link.tqe_next); +const int kld_off_uuid_addr = offsetof(struct linker_file, uuid_addr); +const int kld_off_uuid_size = offsetof(struct linker_file, uuid_size); /* * static char *linker_search_path(const char *name, struct mod_depend @@ -669,6 +671,8 @@ lf->ndeps = 0; lf->deps = NULL; lf->loadcnt = ++loadcnt; + lf->uuid_addr = NULL; + lf->uuid_size = 0; #ifdef __arm__ lf->exidx_addr = 0; lf->exidx_size = 0; diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -448,8 +448,8 @@ link_elf_init(void* arg) { Elf_Dyn *dp; - Elf_Addr *ctors_addrp; - Elf_Size *ctors_sizep; + Elf_Addr *ctors_addrp, *uuid_addrp; + Elf_Size *ctors_sizep, *uuid_sizep; caddr_t modptr, baseptr, sizeptr; elf_file_t ef; const char *modname; @@ -510,6 +510,15 @@ *ctors_addrp; linker_kernel_file->ctors_size = *ctors_sizep; } + uuid_addrp = (Elf_Addr *)preload_search_info(modptr, + MODINFO_METADATA | MODINFOMD_UUID_ADDR); + uuid_sizep = (Elf_Size *)preload_search_info(modptr, + MODINFO_METADATA | MODINFOMD_UUID_SIZE); + if (uuid_addrp != NULL && uuid_sizep != NULL) { + linker_kernel_file->uuid_addr = ef->address + + *uuid_addrp; + linker_kernel_file->uuid_size = *uuid_sizep; + } } (void)link_elf_preload_parse_symbols(ef); @@ -880,8 +889,8 @@ link_elf_link_preload(linker_class_t cls, const char *filename, linker_file_t *result) { - Elf_Addr *ctors_addrp; - Elf_Size *ctors_sizep; + Elf_Addr *ctors_addrp, *uuid_addrp; + Elf_Size *ctors_sizep, *uuid_sizep; caddr_t modptr, baseptr, sizeptr, dynptr; char *type; elf_file_t ef; @@ -931,6 +940,15 @@ lf->ctors_size = *ctors_sizep; } + uuid_addrp = (Elf_Addr *)preload_search_info(modptr, + MODINFO_METADATA | MODINFOMD_UUID_ADDR); + uuid_sizep = (Elf_Size *)preload_search_info(modptr, + MODINFO_METADATA | MODINFOMD_UUID_SIZE); + if (uuid_addrp != NULL && uuid_sizep != NULL) { + lf->uuid_addr = ef->address + *uuid_addrp; + lf->uuid_size = *uuid_sizep; + } + #ifdef __arm__ link_elf_locate_exidx_preload(lf, modptr); #endif @@ -1296,6 +1314,12 @@ /* Record relocated address and size of .ctors. */ lf->ctors_addr = mapbase + shdr[i].sh_addr - base_vaddr; lf->ctors_size = shdr[i].sh_size; + } else if (shdr[i].sh_type == SHT_NOTE && + strcmp(shstrs + shdr[i].sh_name, ".note.gnu.build-id") == + 0) { + /* Record relocated address and size of uuid */ + lf->uuid_addr = mapbase + shdr[i].sh_addr - base_vaddr; + lf->uuid_size = shdr[i].sh_size; } } if (symtabindex < 0 || symstrindex < 0) diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -603,6 +603,13 @@ ef->relatab[ra].sec = shdr[i].sh_info; ra++; break; + case SHT_NOTE: + if (strcmp(ef->shstrtab + shdr[i].sh_name, + ".note.gnu.build-id")) + break; + lf->uuid_addr = (caddr_t)shdr[i].sh_addr; + lf->uuid_size = shdr[i].sh_size; + break; } } if (pb != ef->nprogtab) { @@ -1206,6 +1213,23 @@ } ra++; break; + case SHT_NOTE: + if (strcmp(ef->shstrtab + shdr[i].sh_name, + ".note.gnu.build-id")) + break; + lf->uuid_addr = malloc(shdr[i].sh_size, M_LINKER, + M_WAITOK); + lf->uuid_size = shdr[i].sh_size; + error = vn_rdwr(UIO_READ, nd->ni_vp, lf->uuid_addr, + shdr[i].sh_size, shdr[i].sh_offset, UIO_SYSSPACE, + IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); + if (error) + goto out; + if (resid != 0) { + error = EINVAL; + goto out; + } + break; } } if (pb != ef->nprogtab) { diff --git a/sys/kern/subr_module.c b/sys/kern/subr_module.c --- a/sys/kern/subr_module.c +++ b/sys/kern/subr_module.c @@ -378,6 +378,12 @@ case MODINFOMD_CTORS_SIZE: sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE"); break; + case MODINFOMD_UUID_ADDR: + sbuf_cat(sbp, "MODINFOMD_UUID_ADDR"); + break; + case MODINFOMD_UUID_SIZE: + sbuf_cat(sbp, "MODINFOMD_UUID_SIZE"); + break; case MODINFOMD_FW_HANDLE: sbuf_cat(sbp, "MODINFOMD_FW_HANDLE"); break; @@ -449,6 +455,7 @@ break; case MODINFO_SIZE: case MODINFO_METADATA | MODINFOMD_CTORS_SIZE: + case MODINFO_METADATA | MODINFOMD_UUID_SIZE: sbuf_printf(sbp, "%lu", *(u_long *)bptr); break; case MODINFO_ADDR: @@ -458,6 +465,7 @@ case MODINFO_METADATA | MODINFOMD_KERNEND: case MODINFO_METADATA | MODINFOMD_ENVP: case MODINFO_METADATA | MODINFOMD_CTORS_ADDR: + case MODINFO_METADATA | MODINFOMD_UUID_ADDR: #ifdef MODINFOMD_SMAP case MODINFO_METADATA | MODINFOMD_SMAP: #endif diff --git a/sys/sys/linker.h b/sys/sys/linker.h --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -82,6 +82,8 @@ size_t size; /* size of file */ caddr_t ctors_addr; /* address of .ctors/.init_array */ size_t ctors_size; /* size of .ctors/.init_array */ + caddr_t uuid_addr; + size_t uuid_size; enum { LF_NONE = 0, LF_CTORS, @@ -242,6 +244,8 @@ #define MODINFOMD_FW_HANDLE 0x000c /* Firmware dependent handle */ #define MODINFOMD_KEYBUF 0x000d /* Crypto key intake buffer */ #define MODINFOMD_FONT 0x000e /* Console font */ +#define MODINFOMD_UUID_ADDR 0x000f /* address of uuid */ +#define MODINFOMD_UUID_SIZE 0x0010 /* size of uuid */ #define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ #define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */