diff options
author | peter <peter@FreeBSD.org> | 2005-06-30 07:49:22 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2005-06-30 07:49:22 +0000 |
commit | 921b3c5ee4556d6428b9c88c71d3b69e0da1345b (patch) | |
tree | dad118ce52d6d607680db2768f086c4ee826fd22 /sys/kern/imgact_elf.c | |
parent | 14ff9254d85bc5b36288a2b4ba9db5bcb52f7587 (diff) | |
download | FreeBSD-src-921b3c5ee4556d6428b9c88c71d3b69e0da1345b.zip FreeBSD-src-921b3c5ee4556d6428b9c88c71d3b69e0da1345b.tar.gz |
Jumbo-commit to enhance 32 bit application support on 64 bit kernels.
This is good enough to be able to run a RELENG_4 gdb binary against
a RELENG_4 application, along with various other tools (eg: 4.x gcore).
We use this at work.
ia32_reg.[ch]: handle the 32 bit register file format, used by ptrace,
procfs and core dumps.
procfs_*regs.c: vary the format of proc/XXX/*regs depending on the client
and target application.
procfs_map.c: Don't print a 64 bit value to 32 bit consumers, or their
sscanf fails. They expect an unsigned long.
imgact_elf.c: produce a valid 32 bit coredump for 32 bit apps.
sys_process.c: handle 32 bit consumers debugging 32 bit targets. Note
that 64 bit consumers can still debug 32 bit targets.
IA64 has got stubs for ia32_reg.c.
Known limitations: a 5.x/6.x gdb uses get/setcontext(), which isn't
implemented in the 32/64 wrapper yet. We also make a tiny patch to
gdb pacify it over conflicting formats of ld-elf.so.1.
Approved by: re
Diffstat (limited to 'sys/kern/imgact_elf.c')
-rw-r--r-- | sys/kern/imgact_elf.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 9f46c97..6a88500 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -31,6 +31,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_compat.h" + #include <sys/param.h> #include <sys/exec.h> #include <sys/fcntl.h> @@ -66,6 +68,11 @@ __FBSDID("$FreeBSD$"); #include <machine/elf.h> #include <machine/md_var.h> +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 +#include <machine/fpu.h> +#include <compat/ia32/ia32_reg.h> +#endif + #define OLD_EI_BRAND 8 static int __elfN(check_header)(const Elf_Ehdr *hdr); @@ -1118,17 +1125,31 @@ __elfN(corehdr)(td, vp, cred, numsegs, hdr, hdrsize) td)); /* XXXKSE */ } +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 +typedef struct prstatus32 elf_prstatus_t; +typedef struct prpsinfo32 elf_prpsinfo_t; +typedef struct fpreg32 elf_prfpregset_t; +typedef struct fpreg32 elf_fpregset_t; +typedef struct reg32 elf_gregset_t; +#else +typedef prstatus_t elf_prstatus_t; +typedef prpsinfo_t elf_prpsinfo_t; +typedef prfpregset_t elf_prfpregset_t; +typedef prfpregset_t elf_fpregset_t; +typedef gregset_t elf_gregset_t; +#endif + static void __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) { struct { - prstatus_t status; - prfpregset_t fpregset; - prpsinfo_t psinfo; + elf_prstatus_t status; + elf_prfpregset_t fpregset; + elf_prpsinfo_t psinfo; } *tempdata; - prstatus_t *status; - prfpregset_t *fpregset; - prpsinfo_t *psinfo; + elf_prstatus_t *status; + elf_prfpregset_t *fpregset; + elf_prpsinfo_t *psinfo; struct proc *p; struct thread *thr; size_t ehoff, noteoff, notesz, phoff; @@ -1160,7 +1181,7 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) if (dst != NULL) { psinfo->pr_version = PRPSINFO_VERSION; - psinfo->pr_psinfosz = sizeof(prpsinfo_t); + psinfo->pr_psinfosz = sizeof(elf_prpsinfo_t); strlcpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname)); /* * XXX - We don't fill in the command line arguments properly @@ -1182,14 +1203,19 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) while (thr != NULL) { if (dst != NULL) { status->pr_version = PRSTATUS_VERSION; - status->pr_statussz = sizeof(prstatus_t); - status->pr_gregsetsz = sizeof(gregset_t); - status->pr_fpregsetsz = sizeof(fpregset_t); + status->pr_statussz = sizeof(elf_prstatus_t); + status->pr_gregsetsz = sizeof(elf_gregset_t); + status->pr_fpregsetsz = sizeof(elf_fpregset_t); status->pr_osreldate = osreldate; status->pr_cursig = p->p_sig; status->pr_pid = thr->td_tid; +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 + fill_regs32(thr, &status->pr_reg); + fill_fpregs32(thr, fpregset); +#else fill_regs(thr, &status->pr_reg); fill_fpregs(thr, fpregset); +#endif } __elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status, sizeof *status); @@ -1235,7 +1261,11 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) ehdr->e_ident[EI_ABIVERSION] = 0; ehdr->e_ident[EI_PAD] = 0; ehdr->e_type = ET_CORE; +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 + ehdr->e_machine = EM_386; +#else ehdr->e_machine = ELF_ARCH; +#endif ehdr->e_version = EV_CURRENT; ehdr->e_entry = 0; ehdr->e_phoff = phoff; |