/* Iterate over all sections in the ELF. */ #define for_each_section(var) \ for (var = elf.sh_table; var < elf.sh_table + elf16toh(elf.ehdr->e_shnum); ++var)
/* Iterate over all Elf64_Rela relocations in a given section. */ #define for_each_rela(shdr, var) \ for (var = elf_ptr(Elf64_Rela, elf64toh(shdr->sh_offset)); \
var < elf_ptr(Elf64_Rela, elf64toh(shdr->sh_offset) + elf64toh(shdr->sh_size)); var++)
/* True if a string starts with a given prefix. */ staticinlinebool starts_with(constchar *str, constchar *prefix)
{ return memcmp(str, prefix, strlen(prefix)) == 0;
}
/* Returns a string containing the name of a given section. */ staticinlineconstchar *section_name(Elf64_Shdr *shdr)
{ return elf.sh_string + elf32toh(shdr->sh_name);
}
/* Returns a pointer to the first byte of section data. */ staticinlineconstchar *section_begin(Elf64_Shdr *shdr)
{ return elf_ptr(char, elf64toh(shdr->sh_offset));
}
/* Find a section by its offset from the beginning of the file. */ staticinline Elf64_Shdr *section_by_off(Elf64_Off off)
{
assert_ne(off, 0UL, "%lu"); return elf_ptr(Elf64_Shdr, off);
}
/* Find a section by its index. */ staticinline Elf64_Shdr *section_by_idx(uint16_t idx)
{
assert_ne(idx, SHN_UNDEF, "%u"); return &elf.sh_table[idx];
}
/* *Memory-mapthegivenELFfile,performsanitychecks,and *populateglobalstate.
*/ staticvoid init_elf(constchar *path)
{ int fd, ret; struct stat stat;
/* Store path in the global struct for error printing. */
elf.path = path;
/* Open the ELF file. */
fd = open(path, O_RDONLY); if (fd < 0)
fatal_perror("Could not open ELF file");
/* Get status of ELF file to obtain its size. */
ret = fstat(fd, &stat); if (ret < 0) {
close(fd);
fatal_perror("Could not get status of ELF file");
}
/* mmap() the entire ELF file read-only at an arbitrary address. */
elf.begin = mmap(0, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (elf.begin == MAP_FAILED) {
close(fd);
fatal_perror("Could not mmap ELF file");
}
/* mmap() was successful, close the FD. */
close(fd);
/* Get pointer to the ELF header. */
assert_ge(stat.st_size, sizeof(*elf.ehdr), "%lu");
elf.ehdr = elf_ptr(Elf64_Ehdr, 0);
/* Sanity check that this is an ELF64 relocatable object for AArch64. */
assert_eq(elf.ehdr->e_ident[EI_CLASS], ELFCLASS64, "%u");
assert_eq(elf.ehdr->e_ident[EI_DATA], ELFENDIAN, "%u");
assert_eq(elf16toh(elf.ehdr->e_type), ET_REL, "%u");
assert_eq(elf16toh(elf.ehdr->e_machine), EM_AARCH64, "%u");
/* Populate fields of the global struct. */
elf.sh_table = section_by_off(elf64toh(elf.ehdr->e_shoff));
elf.sh_string = section_begin(section_by_idx(elf16toh(elf.ehdr->e_shstrndx)));
}
/* Print the prologue of the output ASM file. */ staticvoid emit_prologue(void)
{
printf(".data\n" ".pushsection " HYP_RELOC_SECTION ", \"a\"\n");
}
/* Print ASM statements needed as a prologue to a processed hyp section. */ staticvoid emit_section_prologue(constchar *sh_orig_name)
{ /* Declare the hyp section symbol. */
printf(".global %s%s\n", HYP_SECTION_SYMBOL_PREFIX, sh_orig_name);
}
/* *PrintASMstatementstocreateahyprelocationentryforagiven *R_AARCH64_ABS64relocation. * *Thelinkerofvmlinuxwillpopulatethepositiongivenby`rela`with *anabsolute64-bitkernelVA.Ifthekernelisrelocatable,itwill *alsogenerateadynamicrelocationentrysothatthekernelcanshift *theaddressatruntimeforKASLR. * *Emita32-bitoffsetfromthecurrentaddresstothepositiongiven *by`rela`.ThiswaythekernelcaniterateoverallkernelVAsused *byhypatruntimeandconvertthemtohypVAs.However,thatoffset *willnotbeknownuntillinkingof`vmlinux`,soemitaPREL32 *relocationreferencingasymbolthatthehyplinkerscriptputat *thebeginningoftherelocatedsection+theoffsetfrom`rela`.
*/ staticvoid emit_rela_abs64(Elf64_Rela *rela, constchar *sh_orig_name)
{ /* Offset of this reloc from the beginning of HYP_RELOC_SECTION. */ static size_t reloc_offset;
/* Create storage for the 32-bit offset. */
printf(".word 0\n");
/* Skip all non-hyp sections. */ if (!starts_with(sh_orig_name, HYP_SECTION_PREFIX)) return;
emit_section_prologue(sh_orig_name);
for_each_rela(sh_rela, rela) {
uint32_t type = (uint32_t)elf64toh(rela->r_info);
/* Check that rela points inside the relocated section. */
assert_lt(elf64toh(rela->r_offset), elf64toh(sh_orig->sh_size), "0x%lx");
switch (type) { /* *Datarelocationstogenerateabsoluteaddressing. *Emitahyprelocation.
*/ case R_AARCH64_ABS64:
emit_rela_abs64(rela, sh_orig_name); break; /* Allow 32-bit absolute relocation, for kCFI type hashes. */ case R_AARCH64_ABS32: break; /* Allow position-relative data relocations. */ case R_AARCH64_PREL64: case R_AARCH64_PREL32: case R_AARCH64_PREL16: case R_AARCH64_PLT32: break; /* Allow relocations to generate PC-relative addressing. */ case R_AARCH64_LD_PREL_LO19: case R_AARCH64_ADR_PREL_LO21: case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_ADR_PREL_PG_HI21_NC: case R_AARCH64_ADD_ABS_LO12_NC: case R_AARCH64_LDST8_ABS_LO12_NC: case R_AARCH64_LDST16_ABS_LO12_NC: case R_AARCH64_LDST32_ABS_LO12_NC: case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_LDST128_ABS_LO12_NC: break; /* Allow relative relocations for control-flow instructions. */ case R_AARCH64_TSTBR14: case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_CALL26: break; /* Allow group relocations to create PC-relative offset inline. */ case R_AARCH64_MOVW_PREL_G0: case R_AARCH64_MOVW_PREL_G0_NC: case R_AARCH64_MOVW_PREL_G1: case R_AARCH64_MOVW_PREL_G1_NC: case R_AARCH64_MOVW_PREL_G2: case R_AARCH64_MOVW_PREL_G2_NC: case R_AARCH64_MOVW_PREL_G3: break; default:
fatal_error("Unexpected RELA type %u", type);
}
}
}
/* Iterate over all sections and emit hyp relocation data for RELA sections. */ staticvoid emit_all_relocs(void)
{
Elf64_Shdr *shdr;
for_each_section(shdr) { switch (elf32toh(shdr->sh_type)) { case SHT_REL:
fatal_error("Unexpected SHT_REL section \"%s\"",
section_name(shdr)); case SHT_RELA:
emit_rela_section(shdr); break;
}
}
}
int main(int argc, constchar **argv)
{ if (argc != 2) {
fprintf(stderr, "Usage: %s <elf_input>\n", argv[0]); return EXIT_FAILURE;
}
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.