Skip to content

Commit

Permalink
kldxref: Reduce divergence between per-architecture files
Browse files Browse the repository at this point in the history
Note that relbase is always 0 for DSOs so its omission for __KLD_SHARED
architectures was not a bug in practice.

Whilst here, also parenthesise the dest offset for where to avoid
transiently creating an out-of-bounds pointer, which is UB (though even
on CHERI architectures, where capability bounds compression can result
in that creating invalid capabilities that will trap on dereference,
optimisation will reassociate to the correct form in practice and thus
work just fine).
  • Loading branch information
jrtc27 committed Dec 14, 2023
1 parent aaba149 commit 2a622f1
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 79 deletions.
22 changes: 13 additions & 9 deletions usr.sbin/kldxref/ef_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,25 @@ ef_aarch64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
GElf_Size rtype, symidx;
const GElf_Rela *rela;

if (reltype != ELF_T_RELA)
switch (reltype) {
case ELF_T_RELA:
rela = (const GElf_Rela *)reldata;
where = (char *)dest + (relbase + rela->r_offset - dataoff);
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
break;
default:
return (EINVAL);

rela = (const GElf_Rela *)reldata;
where = (char *)dest - dataoff + rela->r_offset;
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
}

if (where < (char *)dest || where >= (char *)dest + len)
return (0);

switch(rtype) {
switch (rtype) {
case R_AARCH64_RELATIVE:
le64enc(where, relbase + addend);
addr = relbase + addend;
le64enc(where, addr);
break;
case R_AARCH64_ABS64:
addr = EF_SYMADDR(ef, symidx) + addend;
Expand Down
28 changes: 12 additions & 16 deletions usr.sbin/kldxref/ef_amd64.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,32 +36,31 @@
#include "ef.h"

/*
* Apply relocations to the values we got from the file. `relbase' is the
* target relocation address of the section, and `dataoff' is the target
* relocation address of the data in `dest'.
* Apply relocations to the values obtained from the file. `relbase' is the
* target relocation address of the section, and `dataoff/len' is the region
* that is to be relocated, and has been copied to *dest
*/
static int
ef_amd64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
{
char *where;
GElf_Addr val;
GElf_Addr addend, addr;
GElf_Addr addr, addend;
GElf_Size rtype, symidx;
const GElf_Rel *rel;
const GElf_Rela *rela;

switch (reltype) {
case ELF_T_REL:
rel = (const GElf_Rel *)reldata;
where = (char *)dest + relbase + rel->r_offset - dataoff;
where = (char *)dest + (relbase + rel->r_offset - dataoff);
addend = 0;
rtype = GELF_R_TYPE(rel->r_info);
symidx = GELF_R_SYM(rel->r_info);
break;
case ELF_T_RELA:
rela = (const GElf_Rela *)reldata;
where = (char *)dest + relbase + rela->r_offset - dataoff;
where = (char *)dest + (relbase + rela->r_offset - dataoff);
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
Expand Down Expand Up @@ -90,23 +89,20 @@ ef_amd64_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
case R_X86_64_NONE: /* none */
break;
case R_X86_64_64: /* S + A */
addr = EF_SYMADDR(ef, symidx);
val = addr + addend;
le64enc(where, val);
addr = EF_SYMADDR(ef, symidx) + addend;
le64enc(where, addr);
break;
case R_X86_64_32S: /* S + A sign extend */
addr = EF_SYMADDR(ef, symidx);
val = (Elf32_Addr)(addr + addend);
le32enc(where, val);
addr = EF_SYMADDR(ef, symidx) + addend;
le32enc(where, addr);
break;
case R_X86_64_GLOB_DAT: /* S */
addr = EF_SYMADDR(ef, symidx);
le64enc(where, addr);
break;
case R_X86_64_RELATIVE: /* B + A */
addr = addend + relbase;
val = addr;
le64enc(where, val);
addr = relbase + addend;
le64enc(where, addr);
break;
default:
warnx("unhandled relocation type %d", (int)rtype);
Expand Down
12 changes: 6 additions & 6 deletions usr.sbin/kldxref/ef_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
#include "ef.h"

/*
* Apply relocations to the values we got from the file. `relbase' is the
* target relocation address of the section, and `dataoff' is the target
* relocation address of the data in `dest'.
* Apply relocations to the values obtained from the file. `relbase' is the
* target relocation address of the section, and `dataoff/len' is the region
* that is to be relocated, and has been copied to *dest
*/
static int
ef_arm_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
Expand All @@ -54,14 +54,14 @@ ef_arm_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
switch (reltype) {
case ELF_T_REL:
rel = (const GElf_Rel *)reldata;
where = (char *)dest + relbase + rel->r_offset - dataoff;
where = (char *)dest + (relbase + rel->r_offset - dataoff);
addend = 0;
rtype = GELF_R_TYPE(rel->r_info);
symidx = GELF_R_SYM(rel->r_info);
break;
case ELF_T_RELA:
rela = (const GElf_Rela *)reldata;
where = (char *)dest + relbase + rela->r_offset - dataoff;
where = (char *)dest + (relbase + rela->r_offset - dataoff);
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
Expand All @@ -82,7 +82,7 @@ ef_arm_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
le32enc(where, addr);
break;
case R_ARM_RELATIVE: /* B + A */
addr = addend + relbase;
addr = relbase + addend;
le32enc(where, addr);
break;
default:
Expand Down
17 changes: 8 additions & 9 deletions usr.sbin/kldxref/ef_i386.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
#include "ef.h"

/*
* Apply relocations to the values we got from the file. `relbase' is the
* target relocation address of the section, and `dataoff' is the target
* relocation address of the data in `dest'.
* Apply relocations to the values obtained from the file. `relbase' is the
* target relocation address of the section, and `dataoff/len' is the region
* that is to be relocated, and has been copied to *dest
*/
static int
ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
Expand All @@ -53,14 +53,14 @@ ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
switch (reltype) {
case ELF_T_REL:
rel = (const GElf_Rel *)reldata;
where = (char *)dest + relbase + rel->r_offset - dataoff;
where = (char *)dest + (relbase + rel->r_offset - dataoff);
addend = 0;
rtype = GELF_R_TYPE(rel->r_info);
symidx = GELF_R_SYM(rel->r_info);
break;
case ELF_T_RELA:
rela = (const GElf_Rela *)reldata;
where = (char *)dest + relbase + rela->r_offset - dataoff;
where = (char *)dest + (relbase + rela->r_offset - dataoff);
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
Expand All @@ -76,13 +76,12 @@ ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
addend = le32dec(where);

switch (rtype) {
case R_386_RELATIVE: /* A + B */
addr = addend + relbase;
case R_386_RELATIVE: /* B + A */
addr = relbase + addend;
le32enc(where, addr);
break;
case R_386_32: /* S + A - P */
addr = EF_SYMADDR(ef, symidx);
addr += addend;
addr = EF_SYMADDR(ef, symidx) + addend;
le32enc(where, addr);
break;
case R_386_GLOB_DAT: /* S */
Expand Down
29 changes: 13 additions & 16 deletions usr.sbin/kldxref/ef_mips.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,31 @@
#include "ef.h"

/*
* Apply relocations to the values we got from the file. `relbase' is the
* target relocation address of the section, and `dataoff' is the target
* relocation address of the data in `dest'.
* Apply relocations to the values obtained from the file. `relbase' is the
* target relocation address of the section, and `dataoff/len' is the region
* that is to be relocated, and has been copied to *dest
*/
static int
ef_mips_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
{
char *where;
GElf_Addr val;
GElf_Addr addr, addend;
GElf_Size rtype, symidx;
const GElf_Rel *rel;
const GElf_Rela *rela;
GElf_Addr addend, addr;
GElf_Size rtype, symidx;

switch (reltype) {
case ELF_T_REL:
rel = (const GElf_Rel *)reldata;
where = (char *)dest + relbase + rel->r_offset - dataoff;
where = (char *)dest + (relbase + rel->r_offset - dataoff);
addend = 0;
rtype = GELF_R_TYPE(rel->r_info);
symidx = GELF_R_SYM(rel->r_info);
break;
case ELF_T_RELA:
rela = (const GElf_Rela *)reldata;
where = (char *)dest + relbase + rela->r_offset - dataoff;
where = (char *)dest + (relbase + rela->r_offset - dataoff);
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
Expand Down Expand Up @@ -92,20 +91,18 @@ ef_mips_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,

switch (rtype) {
case R_MIPS_64: /* S + A */
addr = EF_SYMADDR(ef, symidx);
val = addr + addend;
addr = EF_SYMADDR(ef, symidx) + addend;
if (elf_encoding(ef) == ELFDATA2LSB)
le64enc(where, val);
le64enc(where, addr);
else
be64enc(where, val);
be64enc(where, addr);
break;
case R_MIPS_32: /* S + A */
addr = EF_SYMADDR(ef, symidx);
val = addr + addend;
addr = EF_SYMADDR(ef, symidx) + addend;
if (elf_encoding(ef) == ELFDATA2LSB)
le32enc(where, val);
le32enc(where, addr);
else
be32enc(where, val);
be32enc(where, addr);
break;
default:
warnx("unhandled relocation type %d", (int)rtype);
Expand Down
39 changes: 21 additions & 18 deletions usr.sbin/kldxref/ef_powerpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,48 +40,51 @@
* target relocation address of the section, and `dataoff/len' is the region
* that is to be relocated, and has been copied to *dest
*/
int
static int
ef_ppc_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
{
char *where;
GElf_Addr addend, val;
GElf_Addr addr, addend;
GElf_Size rtype, symidx;
const GElf_Rela *rela;

if (reltype != ELF_T_RELA)
switch (reltype) {
case ELF_T_RELA:
rela = (const GElf_Rela *)reldata;
where = (char *)dest + (relbase + rela->r_offset - dataoff);
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
break;
default:
return (EINVAL);

rela = (const GElf_Rela *)reldata;
where = (char *)dest - dataoff + rela->r_offset;
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
}

if (where < (char *)dest || where >= (char *)dest + len)
return (0);

switch (rtype) {
case R_PPC_RELATIVE: /* word32|doubleword64 B + A */
val = relbase + addend;
addr = relbase + addend;
if (elf_class(ef) == ELFCLASS64) {
if (elf_encoding(ef) == ELFDATA2LSB)
le64enc(where, val);
le64enc(where, addr);
else
be64enc(where, val);
be64enc(where, addr);
} else
be32enc(where, val);
be32enc(where, addr);
break;
case R_PPC_ADDR32: /* word32 S + A */
val = EF_SYMADDR(ef, symidx) + addend;
be32enc(where, val);
addr = EF_SYMADDR(ef, symidx) + addend;
be32enc(where, addr);
break;
case R_PPC64_ADDR64: /* doubleword64 S + A */
val = EF_SYMADDR(ef, symidx) + addend;
addr = EF_SYMADDR(ef, symidx) + addend;
if (elf_encoding(ef) == ELFDATA2LSB)
le64enc(where, val);
le64enc(where, addr);
else
be64enc(where, val);
be64enc(where, addr);
break;
default:
warnx("unhandled relocation type %d", (int)rtype);
Expand Down
15 changes: 10 additions & 5 deletions usr.sbin/kldxref/ef_riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,24 @@

#include "ef.h"

int
/*
* Apply relocations to the values obtained from the file. `relbase' is the
* target relocation address of the section, and `dataoff/len' is the region
* that is to be relocated, and has been copied to *dest
*/
static int
ef_riscv_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest)
{
char *where;
const GElf_Rela *rela;
GElf_Addr addend, addr;
GElf_Addr addr, addend;
GElf_Size rtype, symidx;
const GElf_Rela *rela;

switch (reltype) {
case ELF_T_RELA:
rela = (const GElf_Rela *)reldata;
where = (char *)dest + relbase + rela->r_offset - dataoff;
where = (char *)dest + (relbase + rela->r_offset - dataoff);
addend = rela->r_addend;
rtype = GELF_R_TYPE(rela->r_info);
symidx = GELF_R_SYM(rela->r_info);
Expand All @@ -68,7 +73,7 @@ ef_riscv_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
le64enc(where, addr);
break;
case R_RISCV_RELATIVE: /* B + A */
addr = addend + relbase;
addr = relbase + addend;
le64enc(where, addr);
break;
default:
Expand Down

0 comments on commit 2a622f1

Please sign in to comment.