rel->r_offset = elf_addr_to_cpu(rel->r_offset); /* Set offset into kernel image */
rel->r_offset -= base; #if (ELF_BITS == 32)
rel->r_info = elf_xword_to_cpu(rel->r_info); #else /* Convert MIPS64 RELA format - only the symbol * index needs converting to native endianness
*/
rel->r_info = rel->r_info;
ELF_R_SYM(rel->r_info) = elf32_to_cpu(ELF_R_SYM(rel->r_info)); #endif #if (SHT_REL_TYPE == SHT_RELA)
rel->r_addend = elf_xword_to_cpu(rel->r_addend); #endif
}
}
}
staticvoid remove_relocs(FILE *fp)
{ int i;
Elf_Shdr shdr;
for (i = 0; i < ehdr.e_shnum; i++) { struct section *sec = &secs[i];
if (sec->shdr.sh_type != SHT_REL_TYPE) continue;
if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0)
die("Seek to %d failed: %s\n",
sec->shdr_offset, strerror(errno));
if (fread(&shdr, sizeof(shdr), 1, fp) != 1)
die("Cannot read ELF section headers %d/%d: %s\n",
i, ehdr.e_shnum, strerror(errno));
/* Set relocation section size to 0, effectively removing it. * This is necessary due to lack of support for relocations * in objcopy when creating 32bit elf from 64bit elf.
*/
shdr.sh_size = 0;
if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0)
die("Seek to %d failed: %s\n",
sec->shdr_offset, strerror(errno));
if (fwrite(&shdr, sizeof(shdr), 1, fp) != 1)
die("Cannot write ELF section headers %d/%d: %s\n",
i, ehdr.e_shnum, strerror(errno));
}
}
staticvoid add_reloc(struct relocs *r, uint32_t offset, unsigned type)
{ /* Relocation representation in binary table: * |76543210|76543210|76543210|76543210| * | Type | offset from _text >> 2 |
*/
offset >>= 2; if (offset > 0x00FFFFFF)
die("Kernel image exceeds maximum size for relocation!\n");
/* Walk through the relocations */ for (i = 0; i < ehdr.e_shnum; i++) { char *sym_strtab;
Elf_Sym *sh_symtab; struct section *sec_applies, *sec_symtab; int j; struct section *sec = &secs[i];
if ((bind == STB_WEAK) && (sym->st_value == 0)) { /* Don't relocate weak symbols without a target */ return 0;
}
if (regex_skip_reloc(symname)) return 0;
switch (r_type) { case R_MIPS_NONE: case R_MIPS_REL32: case R_MIPS_PC16: case R_MIPS_PC21_S2: case R_MIPS_PC26_S2: /* * NONE can be ignored and PC relative relocations don't * need to be adjusted.
*/ case R_MIPS_HIGHEST: case R_MIPS_HIGHER: /* We support relocating within the same 4Gb segment only, * thus leaving the top 32bits unchanged
*/ case R_MIPS_LO16: /* We support relocating by 64k jumps only * thus leaving the bottom 16bits unchanged
*/ break;
case R_MIPS_64: case R_MIPS_32: case R_MIPS_26: case R_MIPS_HI16:
add_reloc(&relocs, rel->r_offset, r_type); break;
staticint write_reloc_as_text(uint32_t v, FILE *f)
{ int res;
res = fprintf(f, "\t.long 0x%08"PRIx32"\n", v); if (res < 0) return res; else returnsizeof(uint32_t);
}
staticvoid emit_relocs(int as_text, int as_bin, FILE *outf)
{ int i; int (*write_reloc)(uint32_t, FILE *) = write_reloc_as_bin; int size = 0; int size_reserved; struct section *sec_reloc;
sec_reloc = sec_lookup(".data.reloc"); if (!sec_reloc)
die("Could not find relocation section\n");
size_reserved = sec_reloc->shdr.sh_size;
/* Collect up the relocations */
walk_relocs(do_reloc);
/* 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"); /* Output text to stdout */
write_reloc = write_reloc_as_text;
outf = stdout;
} elseif (as_bin) { /* Output raw binary to stdout */
outf = stdout;
} else { /* Seek to offset of the relocation section. * Each relocation is then written into the * vmlinux kernel image.
*/ if (fseek(outf, sec_reloc->shdr.sh_offset, SEEK_SET) < 0) {
die("Seek to %d failed: %s\n",
sec_reloc->shdr.sh_offset, strerror(errno));
}
}
for (i = 0; i < relocs.count; i++)
size += write_reloc(relocs.offset[i], outf);
/* Print a stop, but only if we've actually written some relocs */ if (size)
size += write_reloc(0, outf);
if (size > size_reserved) /* Die, but suggest a value for CONFIG_RELOCATION_TABLE_SIZE * which will fix this problem and allow a bit of headroom * if more kernel features are enabled
*/
die("Relocations overflow available space!\n" \ "Please adjust CONFIG_RELOCATION_TABLE_SIZE " \ "to at least 0x%08x\n", (size + 0x1000) & ~0xFFF);
}
/* * 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("%16s 0x%08x %16s %40s %16s\n",
sec_name(sec->shdr.sh_info),
(unsignedint)rel->r_offset,
rel_type(ELF_R_TYPE(rel->r_info)),
symname,
sec_name(sym->st_shndx)); return 0;
}
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.