^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * This file is included twice from vdso2c.c. It generates code for 32-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * and 64-bit vDSOs. We need both for 64-bit builds, since 32-bit vDSOs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * are built for 32-bit userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) void *stripped_addr, size_t stripped_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) FILE *outfile, const char *image_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) int found_load = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) unsigned long load_size = -1; /* Work around bogus warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) unsigned long mapping_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned long i, syms_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *alt_sec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ELF(Dyn) *dyn = 0, *dyn_end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) const char *secstrings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) INT_BITS syms[NSYMS] = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_LE(&hdr->e_phoff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (GET_LE(&hdr->e_type) != ET_DYN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) fail("input is not a shared object\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Walk the segment table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) for (i = 0; i < GET_LE(&hdr->e_phnum); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (GET_LE(&pt[i].p_type) == PT_LOAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (found_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) fail("multiple PT_LOAD segs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (GET_LE(&pt[i].p_offset) != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) GET_LE(&pt[i].p_vaddr) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) fail("PT_LOAD in wrong place\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (GET_LE(&pt[i].p_memsz) != GET_LE(&pt[i].p_filesz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) fail("cannot handle memsz != filesz\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) load_size = GET_LE(&pt[i].p_memsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) found_load = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) } else if (GET_LE(&pt[i].p_type) == PT_DYNAMIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) dyn = raw_addr + GET_LE(&pt[i].p_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) dyn_end = raw_addr + GET_LE(&pt[i].p_offset) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) GET_LE(&pt[i].p_memsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (!found_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) fail("no PT_LOAD seg\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (stripped_len < load_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) fail("stripped input is too short\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (!dyn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) fail("input has no PT_DYNAMIC section -- your toolchain is buggy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Walk the dynamic table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) for (i = 0; dyn + i < dyn_end &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) GET_LE(&dyn[i].d_tag) != DT_NULL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) typeof(dyn[i].d_tag) tag = GET_LE(&dyn[i].d_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (tag == DT_REL || tag == DT_RELSZ || tag == DT_RELA ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) tag == DT_RELENT || tag == DT_TEXTREL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) fail("vdso image contains dynamic relocations\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Walk the section table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) secstrings_hdr = raw_addr + GET_LE(&hdr->e_shoff) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) GET_LE(&hdr->e_shentsize)*GET_LE(&hdr->e_shstrndx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) secstrings = raw_addr + GET_LE(&secstrings_hdr->sh_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) for (i = 0; i < GET_LE(&hdr->e_shnum); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ELF(Shdr) *sh = raw_addr + GET_LE(&hdr->e_shoff) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) GET_LE(&hdr->e_shentsize) * i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (GET_LE(&sh->sh_type) == SHT_SYMTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) symtab_hdr = sh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (!strcmp(secstrings + GET_LE(&sh->sh_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ".altinstructions"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) alt_sec = sh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!symtab_hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) fail("no symbol table\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) strtab_hdr = raw_addr + GET_LE(&hdr->e_shoff) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) GET_LE(&hdr->e_shentsize) * GET_LE(&symtab_hdr->sh_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) syms_nr = GET_LE(&symtab_hdr->sh_size) / GET_LE(&symtab_hdr->sh_entsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Walk the symbol table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) for (i = 0; i < syms_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ELF(Sym) *sym = raw_addr + GET_LE(&symtab_hdr->sh_offset) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) GET_LE(&symtab_hdr->sh_entsize) * i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) const char *sym_name = raw_addr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) GET_LE(&strtab_hdr->sh_offset) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) GET_LE(&sym->st_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) for (k = 0; k < NSYMS; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!strcmp(sym_name, required_syms[k].name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (syms[k]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) fail("duplicate symbol %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) required_syms[k].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Careful: we use negative addresses, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * st_value is unsigned, so we rely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * on syms[k] being a signed type of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * correct width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) syms[k] = GET_LE(&sym->st_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Validate mapping addresses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) INT_BITS symval = syms[special_pages[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (!symval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) continue; /* The mapping isn't used; ignore it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (symval % 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) fail("%s must be a multiple of 4096\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) required_syms[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (symval + 4096 < syms[sym_vvar_start])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) fail("%s underruns vvar_start\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) required_syms[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (symval + 4096 > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) fail("%s is on the wrong side of the vdso text\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) required_syms[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (syms[sym_vvar_start] % 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) fail("vvar_begin must be a multiple of 4096\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!image_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) fwrite(stripped_addr, stripped_len, 1, outfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) mapping_size = (stripped_len + 4095) / 4096 * 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) fprintf(outfile, "/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) fprintf(outfile, "#include <linux/linkage.h>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) fprintf(outfile, "#include <asm/page_types.h>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) fprintf(outfile, "#include <asm/vdso.h>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) fprintf(outfile, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) fprintf(outfile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "static unsigned char raw_data[%lu] __ro_after_init __aligned(PAGE_SIZE) = {",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) mapping_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) for (i = 0; i < stripped_len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (i % 10 == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) fprintf(outfile, "\n\t");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) fprintf(outfile, "0x%02X, ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) (int)((unsigned char *)stripped_addr)[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) fprintf(outfile, "\n};\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) fprintf(outfile, "const struct vdso_image %s = {\n", image_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) fprintf(outfile, "\t.data = raw_data,\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) fprintf(outfile, "\t.size = %lu,\n", mapping_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (alt_sec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) fprintf(outfile, "\t.alt = %lu,\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) (unsigned long)GET_LE(&alt_sec->sh_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) fprintf(outfile, "\t.alt_len = %lu,\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) (unsigned long)GET_LE(&alt_sec->sh_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) for (i = 0; i < NSYMS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (required_syms[i].export && syms[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) required_syms[i].name, (int64_t)syms[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) fprintf(outfile, "};\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }