staticconstchar * const sym_regex_kernel[S_NSYMTYPES] = { /* * Following symbols have been audited. There values are constant and do * not change if bzImage is loaded at a different physical address than * the address for which it has been compiled. Don't warn user about * absolute relocations present w.r.t these symbols.
*/
[S_ABS] = "^(xen_irq_disable_direct_reloc$|" "xen_save_fl_direct_reloc$|" "xen_elfnote_.+_offset$|" "VDSO|" "__kcfi_typeid_|" "__crc_)",
/* * These symbols are known to be relative, even if the linker marks them * as absolute (typically defined outside any section in the linker script.)
*/
[S_REL] = "^(__init_(begin|end)|" "__x86_cpu_dev_(start|end)|" "__alt_instructions(_end)?|" "(__iommu_table|__apicdrivers|__smp_locks)(_end)?|" "__(start|end)_pci_.*|" #if CONFIG_FW_LOADER "__(start|end)_builtin_fw|" #endif "__(start|stop)___ksymtab(_gpl)?|" "__(start|stop)___kcrctab(_gpl)?|" "__(start|stop)___param|" "__(start|stop)___modver|" "__(start|stop)___bug_table|" "__tracedata_(start|end)|" "__(start|stop)_notes|" "__end_rodata|" "__end_rodata_aligned|" "__initramfs_start|" "(jiffies|jiffies_64)|" #if ELF_BITS == 64 "__end_rodata_hpage_align|" #endif "_end)$"
};
staticconstchar * const sym_regex_realmode[S_NSYMTYPES] = { /* * These symbols are known to be relative, even if the linker marks them * as absolute (typically defined outside any section in the linker script.)
*/
[S_REL] = "^pa_",
/* * These are 16-bit segment symbols when compiling 16-bit code.
*/
[S_SEG] = "^real_mode_seg$",
/* * These are offsets belonging to segments, as opposed to linear addresses, * when compiling 16-bit code.
*/
[S_LIN] = "^pa_",
};
for (i = 0; i < shnum; i++) { struct section *sec = &secs[i];
if (sec->shdr.sh_type != SHT_STRTAB) continue;
sec->strtab = malloc(sec->shdr.sh_size); if (!sec->strtab)
die("malloc of %" FMT " bytes for strtab failed\n", sec->shdr.sh_size);
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
die("Seek to %" FMT " failed: %s\n", sec->shdr.sh_offset, strerror(errno));
if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) != sec->shdr.sh_size)
die("Cannot read symbol table: %s\n", strerror(errno));
}
}
staticvoid read_symtabs(FILE *fp)
{ int i, j;
for (i = 0; i < shnum; i++) { struct section *sec = &secs[i]; int num_syms;
switch (sec->shdr.sh_type) { case SHT_SYMTAB_SHNDX:
sec->xsymtab = malloc(sec->shdr.sh_size); if (!sec->xsymtab)
die("malloc of %" FMT " bytes for xsymtab failed\n", sec->shdr.sh_size);
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
die("Seek to %" FMT " failed: %s\n", sec->shdr.sh_offset, strerror(errno));
if (fread(sec->xsymtab, 1, sec->shdr.sh_size, fp) != sec->shdr.sh_size)
die("Cannot read extended symbol table: %s\n", strerror(errno));
shxsymtabndx = i; continue;
case SHT_SYMTAB:
num_syms = sec->shdr.sh_size / sizeof(Elf_Sym);
sec->symtab = malloc(sec->shdr.sh_size); if (!sec->symtab)
die("malloc of %" FMT " bytes for symtab failed\n", sec->shdr.sh_size);
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
die("Seek to %" FMT " failed: %s\n", sec->shdr.sh_offset, strerror(errno));
if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) != sec->shdr.sh_size)
die("Cannot read symbol table: %s\n", strerror(errno));
/* * Do not perform relocations in .notes section; any * values there are meant for pre-boot consumption (e.g. * startup_xen).
*/ if (sec_applies->shdr.sh_type == SHT_NOTE) continue;
rel = &sec->reltab[j];
sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
name = sym_name(sym_strtab, sym);
if (sym->st_shndx != SHN_ABS) continue;
/* Absolute symbols are not relocated if bzImage is * loaded at a non-compiled address. Display a warning * to user at compile time about the absolute * relocations present. * * User need to audit the code to make sure * some symbols which should have been section * relative have not become absolute because of some * linker optimization or wrong programming usage. * * Before warning check if this absolute symbol * relocation is harmless.
*/ if (is_reloc(S_ABS, name) || is_reloc(S_REL, name)) continue;
if (!printed) {
printf("WARNING: Absolute relocations present\n");
printf("Offset Info Type Sym.Value Sym.Name\n");
printed = 1;
}
/* Walk through the relocations */ for (i = 0; i < shnum; i++) { char *sym_strtab;
Elf_Sym *sh_symtab; struct section *sec_applies, *sec_symtab; int j; struct section *sec = &secs[i];
/* * Do not perform relocations in .notes sections; any * values there are meant for pre-boot consumption (e.g. * startup_xen).
*/ if (sec_applies->shdr.sh_type == SHT_NOTE) continue;
switch (r_type) { case R_X86_64_NONE: /* NONE can be ignored. */ break;
case R_X86_64_PC32: case R_X86_64_PLT32: case R_X86_64_REX_GOTPCRELX: /* * PC relative relocations don't need to be adjusted. * * NB: R_X86_64_PLT32 can be treated as R_X86_64_PC32.
*/ break;
case R_X86_64_PC64: /* * Only used by jump labels
*/ break;
case R_X86_64_32: case R_X86_64_32S: case R_X86_64_64: if (shn_abs) { /* * Whitelisted absolute symbols do not require * relocation.
*/ if (is_reloc(S_ABS, symname)) break;
if (headtext) {
die("Absolute reference to symbol '%s' not permitted in .head.text\n",
symname); break;
}
/* * Relocation offsets for 64 bit kernels are output * as 32 bits and sign extended back to 64 bits when * the relocations are processed. * Make sure that the offset will fit.
*/ if ((int32_t)offset != (int64_t)offset)
die("Relocation offset doesn't fit in 32 bits\n");
if (r_type == R_X86_64_64)
add_reloc(&relocs64, offset); else
add_reloc(&relocs32, offset); break;
switch (r_type) { case R_386_NONE: case R_386_PC32: case R_386_PC16: case R_386_PC8: case R_386_PLT32: /* * NONE can be ignored and PC relative relocations don't need * to be adjusted. Because sym must be defined, R_386_PLT32 can * be treated the same way as R_386_PC32.
*/ break;
case R_386_32: if (shn_abs) { /* * Whitelisted absolute symbols do not require * relocation.
*/ if (is_reloc(S_ABS, symname)) break;
switch (r_type) { case R_386_NONE: case R_386_PC32: case R_386_PC16: case R_386_PC8: case R_386_PLT32: /* * NONE can be ignored and PC relative relocations don't need * to be adjusted. Because sym must be defined, R_386_PLT32 can * be treated the same way as R_386_PC32.
*/ break;
case R_386_16: if (shn_abs) { /* * Whitelisted absolute symbols do not require * relocation.
*/ if (is_reloc(S_ABS, symname)) break;
staticvoid emit_relocs(int as_text, int use_real_mode)
{ int i; int (*write_reloc)(uint32_t, FILE *) = write32; int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, constchar *symname);
#if ELF_BITS == 64 if (!use_real_mode)
do_reloc = do_reloc64; else
die("--realmode not valid for a 64-bit ELF file"); #else if (!use_real_mode)
do_reloc = do_reloc32; else
do_reloc = do_reloc_real; #endif
/* Collect up the relocations */
walk_relocs(do_reloc);
if (relocs16.count && !use_real_mode)
die("Segment relocations found but --realmode not specified\n");
/* Order the relocations for more efficient processing */
sort_relocs(&relocs32); #if ELF_BITS == 64
sort_relocs(&relocs64); #else
sort_relocs(&relocs16); #endif
/* Print the relocations */ if (as_text) { /* Print the relocations in a form suitable that * gas will like.
*/
printf(".section \".data.reloc\",\"a\"\n");
printf(".balign 4\n");
write_reloc = write32_as_text;
}
if (use_real_mode) {
write_reloc(relocs16.count, stdout); for (i = 0; i < relocs16.count; i++)
write_reloc(relocs16.offset[i], stdout);
write_reloc(relocs32.count, stdout); for (i = 0; i < relocs32.count; i++)
write_reloc(relocs32.offset[i], stdout);
} else { #if ELF_BITS == 64 /* Print a stop */
write_reloc(0, stdout);
/* Now print each relocation */ for (i = 0; i < relocs64.count; i++)
write_reloc(relocs64.offset[i], stdout); #endif
/* Print a stop */
write_reloc(0, stdout);
/* Now print each relocation */ for (i = 0; i < relocs32.count; i++)
write_reloc(relocs32.offset[i], stdout);
}
}
/* * As an aid to debugging problems with different linkers * print summary information about the relocs. * Since different linkers tend to emit the sections in * different orders we use the section names in the output.
*/ staticint do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, constchar *symname)
{
printf("%s\t%s\t%s\t%s\n",
sec_name(sec->shdr.sh_info),
rel_type(ELF_R_TYPE(rel->r_info)),
symname,
sec_name(sym_index(sym)));
#if ELF_BITS == 64 # define process process_64 #else # define process process_32 #endif
void process(FILE *fp, int use_real_mode, int as_text, int show_absolute_syms, int show_absolute_relocs, int show_reloc_info)
{
regex_init(use_real_mode);
read_ehdr(fp);
read_shdrs(fp);
read_strtabs(fp);
read_symtabs(fp);
read_relocs(fp);
if (show_absolute_syms) {
print_absolute_symbols(); return;
}
if (show_absolute_relocs) {
print_absolute_relocs(); return;
}
if (show_reloc_info) {
print_reloc_info(); 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.