Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/amd64/elf_machdep.c
Show First 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | if (dst != NULL) { | ||||
xsave_mask; | xsave_mask; | ||||
} else | } else | ||||
len += elf64_populate_note(NT_X86_XSTATE, NULL, NULL, | len += elf64_populate_note(NT_X86_XSTATE, NULL, NULL, | ||||
cpu_max_ext_state_size, NULL); | cpu_max_ext_state_size, NULL); | ||||
} | } | ||||
*off = len; | *off = len; | ||||
} | } | ||||
#define ERI_LOCAL 0x0001 | |||||
#define ERI_ONLYIFUNC 0x0002 | |||||
/* Process one elf relocation with addend. */ | /* Process one elf relocation with addend. */ | ||||
static int | static int | ||||
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, | elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, | ||||
int type, int local, elf_lookup_fn lookup) | int type, elf_lookup_fn lookup, int flags) | ||||
{ | { | ||||
Elf64_Addr *where, val; | Elf64_Addr *where, val; | ||||
Elf32_Addr *where32, val32; | Elf32_Addr *where32, val32; | ||||
Elf_Addr addr; | Elf_Addr addr; | ||||
Elf_Addr addend; | Elf_Addr addend; | ||||
Elf_Size rtype, symidx; | Elf_Size rtype, symidx; | ||||
const Elf_Rel *rel; | const Elf_Rel *rel; | ||||
const Elf_Rela *rela; | const Elf_Rela *rela; | ||||
Show All 23 Lines | case ELF_RELOC_RELA: | ||||
addend = rela->r_addend; | addend = rela->r_addend; | ||||
rtype = ELF_R_TYPE(rela->r_info); | rtype = ELF_R_TYPE(rela->r_info); | ||||
symidx = ELF_R_SYM(rela->r_info); | symidx = ELF_R_SYM(rela->r_info); | ||||
break; | break; | ||||
default: | default: | ||||
panic("unknown reloc type %d\n", type); | panic("unknown reloc type %d\n", type); | ||||
} | } | ||||
if (((flags & ERI_ONLYIFUNC) == 0) ^ (rtype != R_X86_64_IRELATIVE)) | |||||
return (0); | |||||
switch (rtype) { | switch (rtype) { | ||||
case R_X86_64_NONE: /* none */ | case R_X86_64_NONE: /* none */ | ||||
break; | break; | ||||
case R_X86_64_64: /* S + A */ | case R_X86_64_64: /* S + A */ | ||||
error = lookup(lf, symidx, 1, &addr); | error = lookup(lf, symidx, 1, &addr); | ||||
val = addr + addend; | val = addr + addend; | ||||
Show All 26 Lines | case R_X86_64_32S: /* S + A sign extend */ | ||||
break; | break; | ||||
case R_X86_64_COPY: /* none */ | case R_X86_64_COPY: /* none */ | ||||
/* | /* | ||||
* There shouldn't be copy relocations in kernel | * There shouldn't be copy relocations in kernel | ||||
* objects. | * objects. | ||||
*/ | */ | ||||
printf("kldload: unexpected R_COPY relocation\n"); | printf("kldload: unexpected R_COPY relocation\n"); | ||||
return -1; | return (-1); | ||||
break; | break; | ||||
case R_X86_64_GLOB_DAT: /* S */ | case R_X86_64_GLOB_DAT: /* S */ | ||||
case R_X86_64_JMP_SLOT: /* XXX need addend + offset */ | case R_X86_64_JMP_SLOT: /* XXX need addend + offset */ | ||||
error = lookup(lf, symidx, 1, &addr); | error = lookup(lf, symidx, 1, &addr); | ||||
if (error != 0) | if (error != 0) | ||||
return -1; | return -1; | ||||
if (*where != addr) | if (*where != addr) | ||||
*where = addr; | *where = addr; | ||||
break; | break; | ||||
case R_X86_64_RELATIVE: /* B + A */ | case R_X86_64_RELATIVE: /* B + A */ | ||||
addr = relocbase + addend; | addr = relocbase + addend; | ||||
val = addr; | val = addr; | ||||
if (*where != val) | if (*where != val) | ||||
*where = val; | *where = val; | ||||
break; | break; | ||||
case R_X86_64_IRELATIVE: | |||||
addr = relocbase + addend; | |||||
val = ((Elf64_Addr (*)(void))addr)(); | |||||
if (*where != val) | |||||
*where = val; | |||||
break; | |||||
default: | default: | ||||
printf("kldload: unexpected relocation type %ld\n", | printf("kldload: unexpected relocation type %ld\n", | ||||
rtype); | rtype); | ||||
return -1; | return (-1); | ||||
} | } | ||||
return(0); | return (0); | ||||
} | } | ||||
int | int | ||||
elf_reloc_ifunc(linker_file_t lf, Elf_Addr relocbase, const void *data, | |||||
int type, elf_lookup_fn lookup) | |||||
{ | |||||
return (elf_reloc_internal(lf, relocbase, data, type, lookup, | |||||
ERI_ONLYIFUNC)); | |||||
} | |||||
int | |||||
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, | elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, | ||||
elf_lookup_fn lookup) | elf_lookup_fn lookup) | ||||
{ | { | ||||
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); | return (elf_reloc_internal(lf, relocbase, data, type, lookup, 0)); | ||||
} | } | ||||
int | int | ||||
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, | elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, | ||||
int type, elf_lookup_fn lookup) | int type, elf_lookup_fn lookup) | ||||
{ | { | ||||
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); | return (elf_reloc_internal(lf, relocbase, data, type, lookup, | ||||
ERI_LOCAL)); | |||||
} | } | ||||
int | int | ||||
elf_cpu_load_file(linker_file_t lf __unused) | elf_cpu_load_file(linker_file_t lf __unused) | ||||
{ | { | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
elf_cpu_unload_file(linker_file_t lf __unused) | elf_cpu_unload_file(linker_file_t lf __unused) | ||||
{ | { | ||||
return (0); | return (0); | ||||
} | } |