1
0
mirror of https://github.com/openbsd/src.git synced 2026-06-19 07:43:34 +02:00

Inline RELOC_* into boot_md.c and simplify the code based on what

we can verify at build time.  Track dt_pltgot as an Elf_Addr instead
of an Elf_Addr* to eliminat casts on both setting and using.  Set
RELATIVE_RELOC so the ld.so Makefile can verify that it has just
the relocation types we expect.

Nothing depends on archdep.h pulling in other #includes anymore, so delete
the #includes and hide the RELOC_* functions that are only used by lib/csu
behind "#ifdef RCRT0"

Tested with full build.
This commit is contained in:
guenther
2022-01-31 05:43:22 +00:00
parent a2ae35ff5f
commit fdacdf06ec
4 changed files with 89 additions and 130 deletions
+37 -52
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: boot_md.h,v 1.2 2022/01/12 21:41:06 guenther Exp $ */
/* $OpenBSD: boot_md.h,v 1.3 2022/01/31 05:43:22 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -51,23 +51,7 @@ void _dl_exit(int);
#define REDIRECT_SYSCALL(x) typeof(x) x asm("_libc_"#x) __dso_hidden
REDIRECT_SYSCALL(mprotect);
#if RELOC_TAG == DT_RELA
typedef Elf_RelA RELOC_TYPE;
#elif RELOC_TAG == DT_REL
typedef Elf_Rel RELOC_TYPE;
#else
# error "unknown RELOC_TAG"
#endif
/* The set of dynamic tags that we're interested in for bootstrapping */
struct boot_dyn {
RELOC_TYPE *dt_reloc; /* DT_RELA or DT_REL */
Elf_Addr dt_relocsz; /* DT_RELASZ or DT_RELSZ */
Elf_Addr *dt_pltgot;
Elf_Addr dt_pltrelsz;
const Elf_Sym *dt_symtab;
RELOC_TYPE *dt_jmprel;
};
static void *relro_addr;
static size_t relro_size;
@@ -85,15 +69,20 @@ void _dl_boot_bind(const long, long *, Elf_Dyn *);
void
_dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynp)
{
struct boot_dyn dynld; /* Resolver data for the loader */
AuxInfo *auxstack;
long *stack;
int n, argc;
char **argv, **envp;
long loff;
RELOC_TYPE *rp;
Elf_Phdr *phdp;
Elf_Addr i;
AuxInfo *auxstack;
long *stack;
int n, argc;
char **argv, **envp;
long loff;
Elf_Phdr *phdp;
const RELOC_TYPE *rend;
const RELOC_TYPE *dt_reloc; /* DT_RELA */
Elf_Addr dt_relocsz; /* DT_RELASZ */
Elf_Addr dt_pltgot;
Elf_Addr dt_pltrelsz;
const Elf_Sym *dt_symtab;
const RELOC_TYPE *dt_jmprel;
Elf_Addr i;
/*
* Scan argument and environment vectors. Find dynamic
@@ -126,55 +115,51 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynp)
loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */
/*
* We need to do 'selfreloc' in case the code weren't
* loaded at the address it was linked to.
*
* Scan the DYNAMIC section for the loader.
* Cache the data for easier access.
* Scan the DYNAMIC section for the items we need
*/
_dl_memset(&dynld, 0, sizeof(dynld));
dt_pltrelsz = dt_relocsz = dt_pltgot = 0;
dt_jmprel = dt_reloc = NULL;
dt_symtab = NULL;
while (dynp->d_tag != DT_NULL) {
/* first the tags that are pointers to be relocated */
if (dynp->d_tag == DT_PLTGOT)
dynld.dt_pltgot = (void *)(dynp->d_un.d_ptr + loff);
dt_pltgot = dynp->d_un.d_ptr + loff;
else if (dynp->d_tag == DT_SYMTAB)
dynld.dt_symtab = (void *)(dynp->d_un.d_ptr + loff);
dt_symtab = (void *)(dynp->d_un.d_ptr + loff);
else if (dynp->d_tag == RELOC_TAG) /* DT_{RELA,REL} */
dynld.dt_reloc = (void *)(dynp->d_un.d_ptr + loff);
dt_reloc = (void *)(dynp->d_un.d_ptr + loff);
else if (dynp->d_tag == DT_JMPREL)
dynld.dt_jmprel = (void *)(dynp->d_un.d_ptr + loff);
dt_jmprel = (void *)(dynp->d_un.d_ptr + loff);
/* Now for the tags that are just sizes or counts */
else if (dynp->d_tag == DT_PLTRELSZ)
dynld.dt_pltrelsz = dynp->d_un.d_val;
dt_pltrelsz = dynp->d_un.d_val;
else if (dynp->d_tag == RELOC_TAG+1) /* DT_{RELA,REL}SZ */
dynld.dt_relocsz = dynp->d_un.d_val;
dt_relocsz = dynp->d_un.d_val;
dynp++;
}
rp = dynld.dt_jmprel;
for (i = 0; i < dynld.dt_pltrelsz; i += sizeof *rp) {
rend = (RELOC_TYPE *)((char *)dt_jmprel + dt_pltrelsz);
for (; dt_jmprel < rend; dt_jmprel++) {
const Elf_Sym *sp;
sp = dynld.dt_symtab + ELF_R_SYM(rp->r_info);
if (!ELF_R_SYM(rp->r_info) || sp->st_value != 0) {
Elf_Addr *ra = (Elf_Addr *)(rp->r_offset + loff);
RELOC_JMPREL(rp, sp, ra, loff, dynld.dt_pltgot);
sp = dt_symtab + ELF_R_SYM(dt_jmprel->r_info);
if (!ELF_R_SYM(dt_jmprel->r_info) || sp->st_value != 0) {
Elf_Addr *ra = (Elf_Addr *)(dt_jmprel->r_offset + loff);
RELOC_JMPREL(dt_jmprel, sp, ra, loff, dt_pltgot);
}
rp++;
}
rp = dynld.dt_reloc;
for (i = 0; i < dynld.dt_relocsz; i += sizeof *rp) {
rend = (RELOC_TYPE *)((char *)dt_reloc + dt_relocsz);
for (; dt_reloc < rend; dt_reloc++) {
Elf_Addr *ra;
const Elf_Sym *sp;
sp = dynld.dt_symtab + ELF_R_SYM(rp->r_info);
if (!ELF_R_SYM(rp->r_info) || sp->st_value != 0) {
ra = (Elf_Addr *)(rp->r_offset + loff);
RELOC_DYN(rp, sp, ra, loff);
sp = dt_symtab + ELF_R_SYM(dt_reloc->r_info);
if (!ELF_R_SYM(dt_reloc->r_info) || sp->st_value != 0) {
ra = (Elf_Addr *)(dt_reloc->r_offset + loff);
RELOC_DYN(dt_reloc, sp, ra, loff);
}
rp++;
}
/* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */
+3 -1
View File
@@ -1,4 +1,4 @@
# $OpenBSD: Makefile.inc,v 1.5 2019/10/21 02:36:43 guenther Exp $
# $OpenBSD: Makefile.inc,v 1.6 2022/01/31 05:43:22 guenther Exp $
CFLAGS += -fpic
AFLAGS += -fpic
@@ -8,3 +8,5 @@ MDOBJ= _dyncall.o _remU.o _remI.o _divI.o _divU.o _div_const.o
${MDOBJ}:
ar x `$(CC) -print-libgcc-file-name` ${MDOBJ}
OBJS+=${MDOBJ}
RELATIVE_RELOC=R_PARISC_(IPLT|DIR32|PLABEL32)
+12 -12
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: archdep.h,v 1.17 2021/11/14 22:07:38 guenther Exp $ */
/* $OpenBSD: archdep.h,v 1.18 2022/01/31 05:43:22 guenther Exp $ */
/*
* Copyright (c) 2004 Michael Shalayeff
@@ -33,26 +33,28 @@
#define RELOC_TAG DT_RELA
#define MACHID EM_PARISC /* ELF e_machine ID value checked */
#include <elf.h>
#include <machine/reloc.h>
#include "syscall.h"
#include "util.h"
#include <sys/exec_elf.h>
Elf_Addr _dl_md_plabel(Elf_Addr, Elf_Addr *);
/* Only used in lib/csu/boot.h */
#ifdef RCRT0
static inline void
RELOC_JMPREL(Elf_RelA *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v,
Elf_Addr *pltgot)
RELOC_JMPREL(const Elf_RelA *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v,
Elf_Addr pltgot)
{
if (ELF_R_TYPE(r->r_info) == RELOC_IPLT) {
p[0] = v + s->st_value + r->r_addend;
p[1] = (Elf_Addr)pltgot;
p[1] = pltgot;
} else {
_dl_exit(5);
}
}
static inline void
RELOC_DYN(Elf_RelA *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v)
RELOC_DYN(const Elf_RelA *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v)
{
if (ELF_R_TYPE(r->r_info) == RELOC_DIR32) {
if (ELF_R_SYM(r->r_info) != 0)
@@ -66,7 +68,5 @@ RELOC_DYN(Elf_RelA *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v)
}
}
void _hppa_dl_dtors(void);
Elf_Addr _dl_md_plabel(Elf_Addr, Elf_Addr *);
#endif /* RCRT0 */
#endif /* _HPPA_ARCHDEP_H_ */
+37 -65
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: boot_md.c,v 1.5 2021/11/14 22:07:38 guenther Exp $ */
/* $OpenBSD: boot_md.c,v 1.6 2022/01/31 05:43:22 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -34,37 +34,14 @@
#define _DYN_LOADER
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/exec.h>
#include <sys/sysctl.h>
#include <nlist.h>
#include <link.h>
#include <dlfcn.h>
#include <sys/exec_elf.h>
#include "syscall.h"
#include "archdep.h"
#include "stdlib.h"
#include "util.h"
#include "archdep.h" /* for RELOC_TAG */
#include "../../lib/csu/os-note-elf.h"
#if RELOC_TAG == DT_RELA
typedef Elf_RelA RELOC_TYPE;
#elif RELOC_TAG == DT_REL
typedef Elf_Rel RELOC_TYPE;
#else
# error "unknown RELOC_TAG"
#endif
/* The set of dynamic tags that we're interested in for bootstrapping */
struct boot_dyn {
RELOC_TYPE *dt_reloc; /* DT_RELA or DT_REL */
Elf_Addr dt_relocsz; /* DT_RELASZ or DT_RELSZ */
Elf_Addr *dt_pltgot;
Elf_Addr dt_pltrelsz;
const Elf_Sym *dt_symtab;
RELOC_TYPE *dt_jmprel;
};
/*
* Local decls.
@@ -74,14 +51,18 @@ void _dl_boot_bind(const long, long *, Elf_Dyn *) __boot;
void
_dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynp)
{
struct boot_dyn dynld; /* Resolver data for the loader */
AuxInfo *auxstack;
long *stack;
int n, argc;
char **argv, **envp;
long loff;
Elf_Addr i;
RELOC_TYPE *rp;
AuxInfo *auxstack;
long *stack;
int n, argc;
char **argv, **envp;
long loff;
const RELOC_TYPE *rend;
const RELOC_TYPE *dt_reloc; /* DT_RELA */
Elf_Addr dt_relocsz; /* DT_RELASZ */
Elf_Addr dt_pltgot;
Elf_Addr dt_pltrelsz;
const Elf_Sym *dt_symtab;
const RELOC_TYPE *dt_jmprel;
/*
* Scan argument and environment vectors. Find dynamic
@@ -114,57 +95,48 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynp)
loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */
/*
* We need to do 'selfreloc' in case the code weren't
* loaded at the address it was linked to.
*
* Scan the DYNAMIC section for the loader.
* Cache the data for easier access.
* Scan the DYNAMIC section for the loader for the two items we need
*/
_dl_memset(&dynld, 0, sizeof(dynld));
dt_pltrelsz = dt_relocsz = dt_pltgot = 0;
dt_jmprel = dt_reloc = NULL;
dt_symtab = NULL;
while (dynp->d_tag != DT_NULL) {
/* first the tags that are pointers to be relocated */
if (dynp->d_tag == DT_PLTGOT)
dynld.dt_pltgot = (void *)(dynp->d_un.d_ptr + loff);
dt_pltgot = dynp->d_un.d_ptr + loff;
else if (dynp->d_tag == DT_SYMTAB)
dynld.dt_symtab = (void *)(dynp->d_un.d_ptr + loff);
dt_symtab = (void *)(dynp->d_un.d_ptr + loff);
else if (dynp->d_tag == RELOC_TAG) /* DT_{RELA,REL} */
dynld.dt_reloc = (void *)(dynp->d_un.d_ptr + loff);
dt_reloc = (void *)(dynp->d_un.d_ptr + loff);
else if (dynp->d_tag == DT_JMPREL)
dynld.dt_jmprel = (void *)(dynp->d_un.d_ptr + loff);
dt_jmprel = (void *)(dynp->d_un.d_ptr + loff);
/* Now for the tags that are just sizes or counts */
else if (dynp->d_tag == DT_PLTRELSZ)
dynld.dt_pltrelsz = dynp->d_un.d_val;
dt_pltrelsz = dynp->d_un.d_val;
else if (dynp->d_tag == RELOC_TAG+1) /* DT_{RELA,REL}SZ */
dynld.dt_relocsz = dynp->d_un.d_val;
dt_relocsz = dynp->d_un.d_val;
dynp++;
}
rp = dynld.dt_jmprel;
for (i = 0; i < dynld.dt_pltrelsz; i += sizeof *rp) {
rend = (RELOC_TYPE *)((char *)dt_jmprel + dt_pltrelsz);
for (; dt_jmprel < rend; dt_jmprel++) {
Elf_Addr *ra;
const Elf_Sym *sp;
sp = dynld.dt_symtab + ELF_R_SYM(rp->r_info);
if (ELF_R_SYM(rp->r_info) && sp->st_value == 0)
_dl_exit(5);
ra = (Elf_Addr *)(rp->r_offset + loff);
RELOC_JMPREL(rp, sp, ra, loff, dynld.dt_pltgot);
rp++;
sp = dt_symtab + ELF_R_SYM(dt_jmprel->r_info);
ra = (Elf_Addr *)(dt_jmprel->r_offset + loff);
ra[0] = loff + sp->st_value + dt_jmprel->r_addend;
ra[1] = dt_pltgot;
}
rp = dynld.dt_reloc;
for (i = 0; i < dynld.dt_relocsz; i += sizeof *rp) {
rend = (RELOC_TYPE *)((char *)dt_reloc + dt_relocsz);
for (; dt_reloc < rend; dt_reloc++) {
Elf_Addr *ra;
const Elf_Sym *sp;
sp = dynld.dt_symtab + ELF_R_SYM(rp->r_info);
if (ELF_R_SYM(rp->r_info) && sp->st_value == 0)
_dl_exit(6);
ra = (Elf_Addr *)(rp->r_offset + loff);
RELOC_DYN(rp, sp, ra, loff);
rp++;
sp = dt_symtab + ELF_R_SYM(dt_reloc->r_info);
ra = (Elf_Addr *)(dt_reloc->r_offset + loff);
*ra = loff + sp->st_value + dt_reloc->r_addend;
}
}