/* SPDX-License-Identifier: GPL-2.0 */ /* * This file is included twice from vdso2c.c. It generates code for 32-bit * and 64-bit vDSOs. We need both for 64-bit builds, since 32-bit vDSOs * are built for 32-bit userspace.
*/
for (i = 0; i < len; i++) { if (i % 10 == 0)
fprintf(outfile, "\n\t");
fprintf(outfile, "0x%02X, ", (int)(data)[i]);
}
}
/* * Extract a section from the input data into a standalone blob. Used to * capture kernel-only data that needs to persist indefinitely, e.g. the * exception fixup tables, but only in the kernel, i.e. the section can * be stripped from the final vDSO image.
*/ staticvoid BITSFUNC(extract)(constunsignedchar *data, size_t data_len,
FILE *outfile, ELF(Shdr) *sec, constchar *name)
{ unsignedlong offset;
size_t len;
offset = (unsignedlong)GET_LE(&sec->sh_offset);
len = (size_t)GET_LE(&sec->sh_size);
if (offset + len > data_len)
fail("section to extract overruns input data");
if (GET_LE(&hdr->e_type) != ET_DYN)
fail("input is not a shared object\n");
/* Walk the segment table. */ for (i = 0; i < GET_LE(&hdr->e_phnum); i++) { if (GET_LE(&pt[i].p_type) == PT_LOAD) { if (found_load)
fail("multiple PT_LOAD segs\n");
if (GET_LE(&pt[i].p_offset) != 0 ||
GET_LE(&pt[i].p_vaddr) != 0)
fail("PT_LOAD in wrong place\n");
if (GET_LE(&pt[i].p_memsz) != GET_LE(&pt[i].p_filesz))
fail("cannot handle memsz != filesz\n");
if (stripped_len < load_size)
fail("stripped input is too short\n");
if (!dyn)
fail("input has no PT_DYNAMIC section -- your toolchain is buggy\n");
/* Walk the dynamic table */ for (i = 0; dyn + i < dyn_end &&
GET_LE(&dyn[i].d_tag) != DT_NULL; i++) {
typeof(dyn[i].d_tag) tag = GET_LE(&dyn[i].d_tag); if (tag == DT_REL || tag == DT_RELSZ || tag == DT_RELA ||
tag == DT_RELENT || tag == DT_TEXTREL)
fail("vdso image contains dynamic relocations\n");
}
/* Walk the section table */
secstrings_hdr = raw_addr + GET_LE(&hdr->e_shoff) +
GET_LE(&hdr->e_shentsize)*GET_LE(&hdr->e_shstrndx);
secstrings = raw_addr + GET_LE(&secstrings_hdr->sh_offset); for (i = 0; i < GET_LE(&hdr->e_shnum); i++) {
ELF(Shdr) *sh = raw_addr + GET_LE(&hdr->e_shoff) +
GET_LE(&hdr->e_shentsize) * i; if (GET_LE(&sh->sh_type) == SHT_SYMTAB)
symtab_hdr = sh;
if (!strcmp(secstrings + GET_LE(&sh->sh_name), ".altinstructions"))
alt_sec = sh; if (!strcmp(secstrings + GET_LE(&sh->sh_name), "__ex_table"))
extable_sec = sh;
}
syms_nr = GET_LE(&symtab_hdr->sh_size) / GET_LE(&symtab_hdr->sh_entsize); /* Walk the symbol table */ for (i = 0; i < syms_nr; i++) { unsignedint k;
ELF(Sym) *sym = raw_addr + GET_LE(&symtab_hdr->sh_offset) +
GET_LE(&symtab_hdr->sh_entsize) * i; constchar *sym_name = raw_addr +
GET_LE(&strtab_hdr->sh_offset) +
GET_LE(&sym->st_name);
for (k = 0; k < NSYMS; k++) { if (!strcmp(sym_name, required_syms[k].name)) { if (syms[k]) {
fail("duplicate symbol %s\n",
required_syms[k].name);
}
/* * Careful: we use negative addresses, but * st_value is unsigned, so we rely * on syms[k] being a signed type of the * correct width.
*/
syms[k] = GET_LE(&sym->st_value);
}
}
}
if (!image_name) {
fwrite(stripped_addr, stripped_len, 1, outfile); return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.