Index: sys/amd64/linux/linux_sysvec.c =================================================================== --- sys/amd64/linux/linux_sysvec.c +++ sys/amd64/linux/linux_sysvec.c @@ -739,7 +739,7 @@ .sv_sigcode = &_binary_linux_locore_o_start, .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux ELF64", - .sv_coredump = elf64_coredump, + .sv_coredump = linux64_coredump, .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, Index: sys/amd64/linux32/linux32_sysvec.c =================================================================== --- sys/amd64/linux32/linux32_sysvec.c +++ sys/amd64/linux32/linux32_sysvec.c @@ -906,7 +906,7 @@ .sv_sigcode = &_binary_linux32_locore_o_start, .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux ELF32", - .sv_coredump = elf32_coredump, + .sv_coredump = linux32_coredump, .sv_imgact_try = linux_exec_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_minuser = VM_MIN_ADDRESS, Index: sys/compat/linux/linux_elf.h =================================================================== --- /dev/null +++ sys/compat/linux/linux_elf.h @@ -0,0 +1,56 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2018 Chuck Tuffli + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _COMPAT_LINUX_ELF_H_ +#define _COMPAT_LINUX_ELF_H_ + +struct l_elf_siginfo { + l_int si_signo; + l_int si_code; + l_int si_errno; +}; + +typedef struct linux_pt_regset l_elf_gregset_t; + +struct linux_elf_prstatus { + struct l_elf_siginfo pr_info; + l_short pr_cursig; + l_ulong pr_sigpend; + l_ulong pr_sighold; + l_pid_t pr_pid; + l_pid_t pr_ppid; + l_pid_t pr_pgrp; + l_pid_t pr_sid; + l_timeval pr_utime; + l_timeval pr_stime; + l_timeval pr_cutime; + l_timeval pr_cstime; + l_elf_gregset_t pr_reg; + l_int pr_fpvalid; +}; + +#endif Index: sys/compat/linux/linux_elf.c =================================================================== --- /dev/null +++ sys/compat/linux/linux_elf.c @@ -0,0 +1,526 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2021 Edward Tomasz Napierala + * Copyright (c) 2018 Chuck Tuffli + * Copyright (c) 2017 Dell EMC + * Copyright (c) 2000 David O'Brien + * Copyright (c) 1995-1996 Søren Schmidt + * Copyright (c) 1996 Peter Wemm + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory as part of the CHERI for Hypervisors and Operating Systems + * (CHaOS) project, funded by EPSRC grant EP/V000292/1. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if defined(COMPAT_LINUX32) && __ELF_WORD_SIZE == 32 +#define linux_pt_regset linux_pt_regset32 +#define bsd_to_linux_regset bsd_to_linux_regset32 +#include +#else +#include +#endif +#include +#include +#include + +#define __linuxN(x) __CONCAT(__CONCAT(__CONCAT(linux,__ELF_WORD_SIZE),_),x) + +#define ELF_NOTE_ROUNDSIZE 4 +#define CORE_BUF_SIZE (16 * 1024) + +#define LINUX_NT_AUXV 6 + +/* Linux core notes are labeled "CORE" */ +static const char LINUX_ABI_VENDOR[] = "CORE"; + +/* + * Code for generating ELF core dumps. + */ + +typedef void (*outfunc_t)(void *, struct sbuf *, size_t *); + +struct note_info { + int type; /* Note type. */ + outfunc_t outfunc; /* Output function. */ + void *outarg; /* Argument for the output function. */ + size_t outsize; /* Output size. */ + TAILQ_ENTRY(note_info) link; /* Link to the next note info. */ +}; + +TAILQ_HEAD(note_info_list, note_info); + +static int corehdr(struct coredump_params *, int, void *, size_t, + struct note_info_list *, size_t, int); +static void prepare_notes(struct thread *, struct note_info_list *, + size_t *); +static void putnote(struct note_info *, struct sbuf *); +static size_t register_note(struct note_info_list *, int, outfunc_t, void *); + +static void note_fpregset(void *, struct sbuf *, size_t *); +static void note_prpsinfo(void *, struct sbuf *, size_t *); +static void note_prstatus(void *, struct sbuf *, size_t *); +static void note_threadmd(void *, struct sbuf *, size_t *); +static void note_linux_nt_auxv(void *, struct sbuf *, size_t *); + +int +__linuxN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) +{ + struct ucred *cred = td->td_ucred; + int error; + struct sseg_closure seginfo; + struct note_info_list notelst; + struct coredump_params params; + struct note_info *ninfo; + void *hdr; + size_t hdrsize, notesz, coresize; + + hdr = NULL; + TAILQ_INIT(¬elst); + + /* Size the program segments. */ + __elfN(size_segments)(td, &seginfo, flags); + + /* + * Collect info about the core file header area. + */ + hdrsize = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * (1 + seginfo.count); + if (seginfo.count + 1 >= PN_XNUM) + hdrsize += sizeof(Elf_Shdr); + prepare_notes(td, ¬elst, ¬esz); + coresize = round_page(hdrsize + notesz) + seginfo.size; + + /* Set up core dump parameters. */ + params.offset = 0; + params.active_cred = cred; + params.file_cred = NOCRED; + params.td = td; + params.vp = vp; + params.comp = NULL; + +#ifdef RACCT + if (racct_enable) { + PROC_LOCK(td->td_proc); + error = racct_add(td->td_proc, RACCT_CORE, coresize); + PROC_UNLOCK(td->td_proc); + if (error != 0) { + error = EFAULT; + goto done; + } + } +#endif + if (coresize >= limit) { + error = EFAULT; + goto done; + } + + /* + * Allocate memory for building the header, fill it up, + * and write it out following the notes. + */ + hdr = malloc(hdrsize, M_TEMP, M_WAITOK); + error = corehdr(¶ms, seginfo.count, hdr, hdrsize, ¬elst, + notesz, flags); + + /* Write the contents of all of the writable segments. */ + if (error == 0) { + Elf_Phdr *php; + off_t offset; + int i; + + php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; + offset = round_page(hdrsize + notesz); + for (i = 0; i < seginfo.count; i++) { + error = core_output((caddr_t)(uintptr_t)php->p_vaddr, + php->p_filesz, offset, ¶ms, NULL); + if (error != 0) + break; + offset += php->p_filesz; + php++; + } + } + if (error) { + log(LOG_WARNING, + "Failed to write core file for process %s (error %d)\n", + curproc->p_comm, error); + } + +done: + while ((ninfo = TAILQ_FIRST(¬elst)) != NULL) { + TAILQ_REMOVE(¬elst, ninfo, link); + free(ninfo, M_TEMP); + } + if (hdr != NULL) + free(hdr, M_TEMP); + + return (error); +} + +/* + * Write the core file header to the file, including padding up to + * the page boundary. + */ +static int +corehdr(struct coredump_params *p, int numsegs, void *hdr, + size_t hdrsize, struct note_info_list *notelst, size_t notesz, int flags) +{ + struct note_info *ninfo; + struct sbuf *sb; + int error; + + /* Fill in the header. */ + bzero(hdr, hdrsize); + __elfN(puthdr)(p->td, hdr, hdrsize, numsegs, notesz, flags | SVC_LINUX); + + sb = sbuf_new(NULL, NULL, CORE_BUF_SIZE, SBUF_FIXEDLEN); + sbuf_set_drain(sb, sbuf_drain_core_output, p); + sbuf_start_section(sb, NULL); + sbuf_bcat(sb, hdr, hdrsize); + TAILQ_FOREACH(ninfo, notelst, link) + putnote(ninfo, sb); + /* Align up to a page boundary for the program segments. */ + sbuf_end_section(sb, -1, PAGE_SIZE, 0); + error = sbuf_finish(sb); + sbuf_delete(sb); + + return (error); +} + +static void +prepare_notes(struct thread *td, struct note_info_list *list, + size_t *sizep) +{ + struct proc *p; + struct thread *thr; + size_t size; + + p = td->td_proc; + size = 0; + + /* + * To have the debugger select the right thread (LWP) as the initial + * thread, we dump the state of the thread passed to us in td first. + * This is the thread that causes the core dump and thus likely to + * be the right thread one wants to have selected in the debugger. + */ + thr = td; + while (thr != NULL) { + size += register_note(list, NT_PRSTATUS, note_prstatus, thr); + size += register_note(list, NT_PRPSINFO, note_prpsinfo, p); + size += register_note(list, LINUX_NT_AUXV, note_linux_nt_auxv, p); + size += register_note(list, NT_FPREGSET, note_fpregset, thr); + size += register_note(list, -1, + note_threadmd, thr); + + thr = (thr == td) ? TAILQ_FIRST(&p->p_threads) : + TAILQ_NEXT(thr, td_plist); + if (thr == td) + thr = TAILQ_NEXT(thr, td_plist); + } + + *sizep = size; +} + +static size_t +register_note(struct note_info_list *list, int type, outfunc_t out, void *arg) +{ + struct note_info *ninfo; + size_t size, notesize; + + size = 0; + out(arg, NULL, &size); + ninfo = malloc(sizeof(*ninfo), M_TEMP, M_ZERO | M_WAITOK); + ninfo->type = type; + ninfo->outfunc = out; + ninfo->outarg = arg; + ninfo->outsize = size; + TAILQ_INSERT_TAIL(list, ninfo, link); + + if (type == -1) + return (size); + + notesize = sizeof(Elf_Note) + /* note header */ + roundup2(sizeof(LINUX_ABI_VENDOR), ELF_NOTE_ROUNDSIZE) + + /* note name */ + roundup2(size, ELF_NOTE_ROUNDSIZE); /* note description */ + + return (notesize); +} + +static void +putnote(struct note_info *ninfo, struct sbuf *sb) +{ + Elf_Note note; + ssize_t old_len, sect_len; + size_t new_len, descsz, i; + + if (ninfo->type == -1) { + ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); + return; + } + + note.n_namesz = sizeof(LINUX_ABI_VENDOR); + note.n_descsz = ninfo->outsize; + note.n_type = ninfo->type; + + sbuf_bcat(sb, ¬e, sizeof(note)); + sbuf_start_section(sb, &old_len); + sbuf_bcat(sb, LINUX_ABI_VENDOR, sizeof(LINUX_ABI_VENDOR)); + sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); + if (note.n_descsz == 0) + return; + sbuf_start_section(sb, &old_len); + ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize); + sect_len = sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0); + if (sect_len < 0) + return; + + new_len = (size_t)sect_len; + descsz = roundup(note.n_descsz, ELF_NOTE_ROUNDSIZE); + if (new_len < descsz) { + /* + * It is expected that individual note emitters will correctly + * predict their expected output size and fill up to that size + * themselves, padding in a format-specific way if needed. + * However, in case they don't, just do it here with zeros. + */ + for (i = 0; i < descsz - new_len; i++) + sbuf_putc(sb, 0); + } else if (new_len > descsz) { + /* + * We can't always truncate sb -- we may have drained some + * of it already. + */ + KASSERT(new_len == descsz, ("%s: Note type %u changed as we " + "read it (%zu > %zu). Since it is longer than " + "expected, this coredump's notes are corrupt. THIS " + "IS A BUG in the note_procstat routine for type %u.\n", + __func__, (unsigned)note.n_type, new_len, descsz, + (unsigned)note.n_type)); + } +} + +/* + * Miscellaneous note out functions. + */ + +#if defined(COMPAT_LINUX32) && __ELF_WORD_SIZE == 32 +typedef struct linux_elf_prstatus elf_prstatus_t; +typedef struct prpsinfo32 elf_prpsinfo_t; +typedef struct fpreg32 elf_prfpregset_t; +#else +typedef struct linux_elf_prstatus elf_prstatus_t; +typedef prpsinfo_t elf_prpsinfo_t; +typedef prfpregset_t elf_prfpregset_t; +#endif + +static void +note_prpsinfo(void *arg, struct sbuf *sb, size_t *sizep) +{ + struct sbuf sbarg; + size_t len; + char *cp, *end; + struct proc *p; + elf_prpsinfo_t *psinfo; + int error; + + p = (struct proc *)arg; + if (sb != NULL) { + KASSERT(*sizep == sizeof(*psinfo), ("invalid size")); + psinfo = malloc(sizeof(*psinfo), M_TEMP, M_ZERO | M_WAITOK); + psinfo->pr_version = PRPSINFO_VERSION; + psinfo->pr_psinfosz = sizeof(elf_prpsinfo_t); + strlcpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname)); + PROC_LOCK(p); + if (p->p_args != NULL) { + len = sizeof(psinfo->pr_psargs) - 1; + if (len > p->p_args->ar_length) + len = p->p_args->ar_length; + memcpy(psinfo->pr_psargs, p->p_args->ar_args, len); + PROC_UNLOCK(p); + error = 0; + } else { + _PHOLD(p); + PROC_UNLOCK(p); + sbuf_new(&sbarg, psinfo->pr_psargs, + sizeof(psinfo->pr_psargs), SBUF_FIXEDLEN); + error = proc_getargv(curthread, p, &sbarg); + PRELE(p); + if (sbuf_finish(&sbarg) == 0) + len = sbuf_len(&sbarg) - 1; + else + len = sizeof(psinfo->pr_psargs) - 1; + sbuf_delete(&sbarg); + } + if (error || len == 0) + strlcpy(psinfo->pr_psargs, p->p_comm, + sizeof(psinfo->pr_psargs)); + else { + KASSERT(len < sizeof(psinfo->pr_psargs), + ("len is too long: %zu vs %zu", len, + sizeof(psinfo->pr_psargs))); + cp = psinfo->pr_psargs; + end = cp + len - 1; + for (;;) { + cp = memchr(cp, '\0', end - cp); + if (cp == NULL) + break; + *cp = ' '; + } + } + psinfo->pr_pid = p->p_pid; + sbuf_bcat(sb, psinfo, sizeof(*psinfo)); + free(psinfo, M_TEMP); + } + *sizep = sizeof(*psinfo); +} + +static void +note_prstatus(void *arg, struct sbuf *sb, size_t *sizep) +{ + struct thread *td; + elf_prstatus_t *status; +#if defined(COMPAT_LINUX32) && __ELF_WORD_SIZE == 32 + struct reg32 pr_reg; +#else + struct reg pr_reg; +#endif + + td = (struct thread *)arg; + if (sb != NULL) { + KASSERT(*sizep == sizeof(*status), ("invalid size")); + status = malloc(sizeof(*status), M_TEMP, M_ZERO | M_WAITOK); + + /* + * XXX: Some fields missing. + */ + status->pr_cursig = td->td_proc->p_sig; + status->pr_pid = td->td_tid; + +#if defined(COMPAT_LINUX32) && __ELF_WORD_SIZE == 32 + fill_regs32(td, &pr_reg); +#else + fill_regs(td, &pr_reg); +#endif + bsd_to_linux_regset(&pr_reg, &status->pr_reg); + sbuf_bcat(sb, status, sizeof(*status)); + free(status, M_TEMP); + } + *sizep = sizeof(*status); +} + +static void +note_fpregset(void *arg, struct sbuf *sb, size_t *sizep) +{ + struct thread *td; + elf_prfpregset_t *fpregset; + + td = (struct thread *)arg; + if (sb != NULL) { + KASSERT(*sizep == sizeof(*fpregset), ("invalid size")); + fpregset = malloc(sizeof(*fpregset), M_TEMP, M_ZERO | M_WAITOK); +#if defined(COMPAT_LINUX32) && __ELF_WORD_SIZE == 32 + fill_fpregs32(td, fpregset); +#else + fill_fpregs(td, fpregset); +#endif + sbuf_bcat(sb, fpregset, sizeof(*fpregset)); + free(fpregset, M_TEMP); + } + *sizep = sizeof(*fpregset); +} + +/* + * Allow for MD specific notes, as well as any MD + * specific preparations for writing MI notes. + */ +static void +note_threadmd(void *arg, struct sbuf *sb, size_t *sizep) +{ + struct thread *td; + void *buf; + size_t size; + + td = (struct thread *)arg; + size = *sizep; + if (size != 0 && sb != NULL) + buf = malloc(size, M_TEMP, M_ZERO | M_WAITOK); + else + buf = NULL; + size = 0; + __elfN(dump_thread)(td, buf, &size); + KASSERT(sb == NULL || *sizep == size, ("invalid size")); + if (size != 0 && sb != NULL) + sbuf_bcat(sb, buf, size); + free(buf, M_TEMP); + *sizep = size; +} + +static void +note_linux_nt_auxv(void *arg, struct sbuf *sb, size_t *sizep) +{ + struct proc *p; + size_t size; + + p = (struct proc *)arg; + if (sb == NULL) { + size = 0; + sb = sbuf_new(NULL, NULL, 320, SBUF_FIXEDLEN); + sbuf_set_drain(sb, sbuf_count_drain, &size); + PHOLD(p); + proc_getauxv(curthread, p, sb); + PRELE(p); + sbuf_finish(sb); + sbuf_delete(sb); + *sizep = size; + } else { + PHOLD(p); + proc_getauxv(curthread, p, sb); + PRELE(p); + } +} Index: sys/compat/linux/linux_elf32.c =================================================================== --- /dev/null +++ sys/compat/linux/linux_elf32.c @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Edward Tomasz Napierala + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory as part of the CHERI for Hypervisors and Operating Systems + * (CHaOS) project, funded by EPSRC grant EP/V000292/1. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#define __ELF_WORD_SIZE 32 +#include Index: sys/compat/linux/linux_elf64.c =================================================================== --- /dev/null +++ sys/compat/linux/linux_elf64.c @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Edward Tomasz Napierala + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory as part of the CHERI for Hypervisors and Operating Systems + * (CHaOS) project, funded by EPSRC grant EP/V000292/1. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#define __ELF_WORD_SIZE 64 +#include Index: sys/compat/linux/linux_emul.h =================================================================== --- sys/compat/linux/linux_emul.h +++ sys/compat/linux/linux_emul.h @@ -58,6 +58,8 @@ void linux_thread_dtor(struct thread *); void linux_thread_detach(struct thread *); int linux_common_execve(struct thread *, struct image_args *); +int linux32_coredump(struct thread *, struct vnode *, off_t, int); +int linux64_coredump(struct thread *, struct vnode *, off_t, int); /* process emuldata flags */ #define LINUX_XDEPR_REQUEUEOP 0x00000001 /* uses deprecated Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -1822,7 +1822,14 @@ ehdr->e_ident[EI_CLASS] = ELF_CLASS; ehdr->e_ident[EI_DATA] = ELF_DATA; ehdr->e_ident[EI_VERSION] = EV_CURRENT; - ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; + if (flags & SVC_LINUX) { + /* + * That's correct, Linux doesn't use ELFOSABI_LINUX. + */ + ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE; + } else { + ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; + } ehdr->e_ident[EI_ABIVERSION] = 0; ehdr->e_ident[EI_PAD] = 0; ehdr->e_type = ET_CORE; Index: sys/modules/linux/Makefile =================================================================== --- sys/modules/linux/Makefile +++ sys/modules/linux/Makefile @@ -26,6 +26,7 @@ .endif .if ${MACHINE_CPUARCH} == "amd64" SRCS+= linux${SFX}_support.s +SRCS+= linux_elf32.c .else SRCS+= linux_copyout.c .endif Index: sys/modules/linux64/Makefile =================================================================== --- sys/modules/linux64/Makefile +++ sys/modules/linux64/Makefile @@ -18,6 +18,7 @@ linux_support.s .if ${MACHINE_CPUARCH} == "amd64" SRCS+= linux_dummy_x86.c +SRCS+= linux_elf64.c .endif DPSRCS= assym.inc linux_genassym.c Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -175,6 +175,7 @@ #define SVC_PT_COREDUMP 0x00000001 /* dump requested by ptrace(2) */ #define SVC_NOCOMPRESS 0x00000002 /* disable compression. */ #define SVC_ALL 0x00000004 /* dump everything */ +#define SVC_LINUX 0x00000008 /* Linux corefile format */ #ifdef _KERNEL extern struct sysentvec aout_sysvec;