The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/core_elf32.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: core_elf32.c,v 1.14 2004/09/17 14:11:24 skrll Exp $    */
    2 
    3 /*
    4  * Copyright (c) 2001 Wasabi Systems, Inc.
    5  * All rights reserved.
    6  *
    7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed for the NetBSD Project by
   20  *      Wasabi Systems, Inc.
   21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
   22  *    or promote products derived from this software without specific prior
   23  *    written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
   29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35  * POSSIBILITY OF SUCH DAMAGE.
   36  */
   37 
   38 /*
   39  * core_elf32.c/core_elf64.c: Support for the Elf32/Elf64 core file format.
   40  */
   41 
   42 #include <sys/cdefs.h>
   43 __KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.14 2004/09/17 14:11:24 skrll Exp $");
   44 
   45 /* If not included by core_elf64.c, ELFSIZE won't be defined. */
   46 #ifndef ELFSIZE
   47 #define ELFSIZE         32
   48 #endif
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/proc.h>
   53 #include <sys/vnode.h>
   54 #include <sys/exec_elf.h>
   55 #include <sys/ptrace.h>
   56 
   57 #include <machine/reg.h>
   58 
   59 #include <uvm/uvm_extern.h>
   60 
   61 struct countsegs_state {
   62         int     npsections;
   63 };
   64 
   65 int     ELFNAMEEND(coredump_countsegs)(struct proc *, struct vnode *,
   66             struct ucred *, struct uvm_coredump_state *);
   67 
   68 struct writesegs_state {
   69         off_t   offset;
   70         off_t   secoff;
   71 };
   72 
   73 int     ELFNAMEEND(coredump_writeseghdrs)(struct proc *, struct vnode *,
   74             struct ucred *, struct uvm_coredump_state *);
   75 int     ELFNAMEEND(coredump_writesegs)(struct proc *, struct vnode *,
   76             struct ucred *, struct uvm_coredump_state *);
   77 
   78 int     ELFNAMEEND(coredump_notes)(struct proc *, struct lwp *, struct vnode *,
   79             struct ucred *, size_t *, off_t);
   80 int     ELFNAMEEND(coredump_note)(struct proc *, struct lwp *, struct vnode *,
   81             struct ucred *, size_t *, off_t);
   82 
   83 #define ELFROUNDSIZE    4       /* XXX Should it be sizeof(Elf_Word)? */
   84 #define elfround(x)     roundup((x), ELFROUNDSIZE)
   85 
   86 int
   87 ELFNAMEEND(coredump)(struct lwp *l, struct vnode *vp, struct ucred *cred)
   88 {
   89         struct proc *p;
   90         Elf_Ehdr ehdr;
   91         Elf_Phdr phdr;
   92         struct countsegs_state cs;
   93         struct writesegs_state ws;
   94         off_t notestart, secstart;
   95         size_t notesize;
   96         int error;
   97 
   98         p = l->l_proc;
   99         /*
  100          * We have to make a total of 3 passes across the map:
  101          *
  102          *      1. Count the number of map entries (the number of
  103          *         PT_LOAD sections).
  104          *
  105          *      2. Write the P-section headers.
  106          *
  107          *      3. Write the P-sections.
  108          */
  109 
  110         /* Pass 1: count the entries. */
  111         cs.npsections = 0;
  112         error = uvm_coredump_walkmap(p, vp, cred,
  113             ELFNAMEEND(coredump_countsegs), &cs);
  114         if (error)
  115                 return (error);
  116 
  117         /* Get the size of the notes. */
  118         error = ELFNAMEEND(coredump_notes)(p, l, vp, cred, &notesize, 0);
  119         if (error)
  120                 return (error);
  121 
  122         /* Count the PT_NOTE section. */
  123         cs.npsections++;
  124 
  125         memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
  126 #if ELFSIZE == 32
  127         ehdr.e_ident[EI_CLASS] = ELFCLASS32;
  128 #elif ELFSIZE == 64
  129         ehdr.e_ident[EI_CLASS] = ELFCLASS64;
  130 #endif
  131         ehdr.e_ident[EI_DATA] = ELFDEFNNAME(MACHDEP_ENDIANNESS);
  132         ehdr.e_ident[EI_VERSION] = EV_CURRENT;
  133         /* XXX Should be the OSABI/ABI version of the executable. */
  134         ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
  135         ehdr.e_ident[EI_ABIVERSION] = 0;
  136 
  137         ehdr.e_type = ET_CORE;
  138         /* XXX This should be the e_machine of the executable. */
  139         ehdr.e_machine = ELFDEFNNAME(MACHDEP_ID);
  140         ehdr.e_version = EV_CURRENT;
  141         ehdr.e_entry = 0;
  142         ehdr.e_phoff = sizeof(ehdr);
  143         ehdr.e_shoff = 0;
  144         ehdr.e_flags = 0;
  145         ehdr.e_ehsize = sizeof(ehdr);
  146         ehdr.e_phentsize = sizeof(Elf_Phdr);
  147         ehdr.e_phnum = cs.npsections;
  148         ehdr.e_shentsize = 0;
  149         ehdr.e_shnum = 0;
  150         ehdr.e_shstrndx = 0;
  151 
  152         /* Write out the ELF header. */
  153         error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&ehdr,
  154             (int)sizeof(ehdr), (off_t)0,
  155             UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, NULL);
  156 
  157         ws.offset = ehdr.e_phoff;
  158         notestart = ws.offset + (sizeof(phdr) * cs.npsections);
  159         secstart = round_page(notestart + notesize);
  160 
  161         /* Pass 2: now write the P-section headers. */
  162         ws.secoff = secstart;
  163         error = uvm_coredump_walkmap(p, vp, cred,
  164             ELFNAMEEND(coredump_writeseghdrs), &ws);
  165         if (error)
  166                 return (error);
  167 
  168         /* Write out the PT_NOTE header. */
  169         phdr.p_type = PT_NOTE;
  170         phdr.p_offset = notestart;
  171         phdr.p_vaddr = 0;
  172         phdr.p_paddr = 0;
  173         phdr.p_filesz = notesize;
  174         phdr.p_memsz = 0;
  175         phdr.p_flags = PF_R;
  176         phdr.p_align = ELFROUNDSIZE;
  177 
  178         error = vn_rdwr(UIO_WRITE, vp,
  179             (caddr_t)&phdr, sizeof(phdr),
  180             ws.offset, UIO_SYSSPACE,
  181             IO_NODELOCKED|IO_UNIT, cred, NULL, NULL);
  182         if (error)
  183                 return (error);
  184 
  185         ws.offset += sizeof(phdr);
  186 
  187 #ifdef DIAGNOSTIC
  188         if (ws.offset != notestart)
  189                 panic("coredump: offset %lld != notestart %lld",
  190                     (long long) ws.offset, (long long) notestart);
  191 #endif
  192 
  193         /* Write out the notes. */
  194         error = ELFNAMEEND(coredump_notes)(p, l, vp, cred, &notesize, ws.offset);
  195 
  196         ws.offset += notesize;
  197 
  198 #ifdef DIAGNOSTIC
  199         if (round_page(ws.offset) != secstart)
  200                 panic("coredump: offset %lld != secstart %lld",
  201                     (long long) round_page(ws.offset), (long long) secstart);
  202 #endif
  203 
  204         /* Pass 3: finally, write the sections themselves. */
  205         ws.secoff = secstart;
  206         error = uvm_coredump_walkmap(p, vp, cred,
  207             ELFNAMEEND(coredump_writesegs), &ws);
  208         if (error)
  209                 return (error);
  210 
  211         return (error);
  212 }
  213 
  214 int
  215 ELFNAMEEND(coredump_countsegs)(struct proc *p, struct vnode *vp,
  216     struct ucred *cred, struct uvm_coredump_state *us)
  217 {
  218         struct countsegs_state *cs = us->cookie;
  219 
  220         cs->npsections++;
  221         return (0);
  222 }
  223 
  224 int
  225 ELFNAMEEND(coredump_writeseghdrs)(struct proc *p, struct vnode *vp,
  226     struct ucred *cred, struct uvm_coredump_state *us)
  227 {
  228         struct writesegs_state *ws = us->cookie;
  229         Elf_Phdr phdr;
  230         vsize_t size;
  231         int error;
  232 
  233         size = us->end - us->start;
  234 
  235         phdr.p_type = PT_LOAD;
  236         phdr.p_offset = ws->secoff;
  237         phdr.p_vaddr = us->start;
  238         phdr.p_paddr = 0;
  239         phdr.p_filesz = (us->flags & UVM_COREDUMP_NODUMP) ? 0 : size;
  240         phdr.p_memsz = size;
  241         phdr.p_flags = 0;
  242         if (us->prot & VM_PROT_READ)
  243                 phdr.p_flags |= PF_R;
  244         if (us->prot & VM_PROT_WRITE)
  245                 phdr.p_flags |= PF_W;
  246         if (us->prot & VM_PROT_EXECUTE)
  247                 phdr.p_flags |= PF_X;
  248         phdr.p_align = PAGE_SIZE;
  249 
  250         error = vn_rdwr(UIO_WRITE, vp,
  251             (caddr_t)&phdr, sizeof(phdr),
  252             ws->offset, UIO_SYSSPACE,
  253             IO_NODELOCKED|IO_UNIT, cred, NULL, NULL);
  254         if (error)
  255                 return (error);
  256 
  257         ws->offset += sizeof(phdr);
  258         ws->secoff += phdr.p_filesz;
  259 
  260         return (0);
  261 }
  262 
  263 int
  264 ELFNAMEEND(coredump_writesegs)(struct proc *p, struct vnode *vp,
  265     struct ucred *cred, struct uvm_coredump_state *us)
  266 {
  267         struct writesegs_state *ws = us->cookie;
  268         vsize_t size;
  269         int error;
  270 
  271         if (us->flags & UVM_COREDUMP_NODUMP)
  272                 return (0);
  273 
  274         size = us->end - us->start;
  275 
  276         error = vn_rdwr(UIO_WRITE, vp,
  277             (caddr_t) us->start, size,
  278             ws->secoff, UIO_USERSPACE,
  279             IO_NODELOCKED|IO_UNIT, cred, NULL, p);
  280         if (error)
  281                 return (error);
  282 
  283         ws->secoff += size;
  284 
  285         return (0);
  286 }
  287 
  288 int
  289 ELFNAMEEND(coredump_notes)(struct proc *p, struct lwp *l, struct vnode *vp,
  290     struct ucred *cred, size_t *sizep, off_t offset)
  291 {
  292         struct netbsd_elfcore_procinfo cpi;
  293         Elf_Nhdr nhdr;
  294         size_t size, notesize;
  295         int error;
  296         struct lwp *l0;
  297 
  298         size = 0;
  299 
  300         /* First, write an elfcore_procinfo. */
  301         notesize = sizeof(nhdr) + elfround(sizeof(ELF_NOTE_NETBSD_CORE_NAME)) +
  302             elfround(sizeof(cpi));
  303         if (offset) {
  304                 cpi.cpi_version = NETBSD_ELFCORE_PROCINFO_VERSION;
  305                 cpi.cpi_cpisize = sizeof(cpi);
  306                 cpi.cpi_signo = p->p_sigctx.ps_signo;
  307                 cpi.cpi_sigcode = p->p_sigctx.ps_code;
  308                 cpi.cpi_siglwp = p->p_sigctx.ps_lwp;
  309 
  310                 memcpy(&cpi.cpi_sigpend, &p->p_sigctx.ps_siglist,
  311                     sizeof(cpi.cpi_sigpend));
  312                 memcpy(&cpi.cpi_sigmask, &p->p_sigctx.ps_sigmask,
  313                     sizeof(cpi.cpi_sigmask));
  314                 memcpy(&cpi.cpi_sigignore, &p->p_sigctx.ps_sigignore,
  315                     sizeof(cpi.cpi_sigignore));
  316                 memcpy(&cpi.cpi_sigcatch, &p->p_sigctx.ps_sigcatch,
  317                     sizeof(cpi.cpi_sigcatch));
  318 
  319                 cpi.cpi_pid = p->p_pid;
  320                 cpi.cpi_ppid = p->p_pptr->p_pid;
  321                 cpi.cpi_pgrp = p->p_pgid;
  322                 cpi.cpi_sid = p->p_session->s_sid;
  323 
  324                 cpi.cpi_ruid = p->p_cred->p_ruid;
  325                 cpi.cpi_euid = p->p_ucred->cr_uid;
  326                 cpi.cpi_svuid = p->p_cred->p_svuid;
  327 
  328                 cpi.cpi_rgid = p->p_cred->p_rgid;
  329                 cpi.cpi_egid = p->p_ucred->cr_gid;
  330                 cpi.cpi_svgid = p->p_cred->p_svgid;
  331 
  332                 cpi.cpi_nlwps = p->p_nlwps;
  333                 strlcpy(cpi.cpi_name, p->p_comm, sizeof(cpi.cpi_name));
  334 
  335                 nhdr.n_namesz = sizeof(ELF_NOTE_NETBSD_CORE_NAME);
  336                 nhdr.n_descsz = sizeof(cpi);
  337                 nhdr.n_type = ELF_NOTE_NETBSD_CORE_PROCINFO;
  338 
  339                 error = ELFNAMEEND(coredump_writenote)(p, vp, cred, offset,
  340                     &nhdr, ELF_NOTE_NETBSD_CORE_NAME, &cpi);
  341                 if (error)
  342                         return (error);
  343 
  344                 offset += notesize;
  345         }
  346 
  347         size += notesize;
  348 
  349         /* XXX Add hook for machdep per-proc notes. */
  350 
  351         /*
  352          * Now write the register info for the thread that caused the
  353          * coredump.
  354          */
  355         error = ELFNAMEEND(coredump_note)(p, l, vp, cred, &notesize, offset);
  356         if (error)
  357                 return (error);
  358         if (offset)
  359                 offset += notesize;
  360         size += notesize;
  361 
  362         /*
  363          * Now, for each LWP, write the register info and any other
  364          * per-LWP notes.
  365          */
  366         LIST_FOREACH(l0, &p->p_lwps, l_sibling) {
  367                 if (l0 == l)            /* we've taken care of this thread */
  368                         continue;
  369                 error = ELFNAMEEND(coredump_note)(p, l0, vp, cred,
  370                     &notesize, offset);
  371                 if (error)
  372                         return (error);
  373                 if (offset)
  374                         offset += notesize;
  375                 size += notesize;
  376         }
  377 
  378         *sizep = size;
  379         return (0);
  380 }
  381 
  382 int
  383 ELFNAMEEND(coredump_note)(struct proc *p, struct lwp *l, struct vnode *vp,
  384     struct ucred *cred, size_t *sizep, off_t offset)
  385 {
  386         Elf_Nhdr nhdr;
  387         int size, notesize, error;
  388         int namesize;
  389         char name[64];
  390         struct reg intreg;
  391 #ifdef PT_GETFPREGS
  392         struct fpreg freg;
  393 #endif
  394 
  395         size = 0;
  396 
  397         snprintf(name, sizeof(name), "%s@%d", ELF_NOTE_NETBSD_CORE_NAME,
  398             l->l_lid);
  399         namesize = strlen(name) + 1;
  400 
  401         notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg));
  402         if (offset) {
  403                 PHOLD(l);
  404                 error = process_read_regs(l, &intreg);
  405                 PRELE(l);
  406                 if (error)
  407                         return (error);
  408 
  409                 nhdr.n_namesz = namesize;
  410                 nhdr.n_descsz = sizeof(intreg);
  411                 nhdr.n_type = PT_GETREGS;
  412 
  413                 error = ELFNAMEEND(coredump_writenote)(p, vp, cred,
  414                     offset, &nhdr, name, &intreg);
  415                 if (error)
  416                         return (error);
  417 
  418                 offset += notesize;
  419         }
  420         size += notesize;
  421 
  422 #ifdef PT_GETFPREGS
  423         notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg));
  424         if (offset) {
  425                 PHOLD(l);
  426                 error = process_read_fpregs(l, &freg);
  427                 PRELE(l);
  428                 if (error)
  429                         return (error);
  430 
  431                 nhdr.n_namesz = namesize;
  432                 nhdr.n_descsz = sizeof(freg);
  433                 nhdr.n_type = PT_GETFPREGS;
  434 
  435                 error = ELFNAMEEND(coredump_writenote)(p, vp, cred,
  436                     offset, &nhdr, name, &freg);
  437                 if (error)
  438                         return (error);
  439 
  440                 offset += notesize;
  441         }
  442         size += notesize;
  443 #endif
  444         *sizep = size;
  445         /* XXX Add hook for machdep per-LWP notes. */
  446         return (0);
  447 }
  448 
  449 int
  450 ELFNAMEEND(coredump_writenote)(struct proc *p, struct vnode *vp,
  451     struct ucred *cred, off_t offset, Elf_Nhdr *nhdr, const char *name,
  452     void *data)
  453 {
  454         int error;
  455 
  456         error = vn_rdwr(UIO_WRITE, vp,
  457             (caddr_t) nhdr, sizeof(*nhdr),
  458             offset, UIO_SYSSPACE,
  459             IO_NODELOCKED|IO_UNIT, cred, NULL, NULL);
  460         if (error)
  461                 return (error);
  462 
  463         offset += sizeof(*nhdr);
  464 
  465         error = vn_rdwr(UIO_WRITE, vp,
  466             (caddr_t)name, nhdr->n_namesz,
  467             offset, UIO_SYSSPACE,
  468             IO_NODELOCKED|IO_UNIT, cred, NULL, NULL);
  469         if (error)
  470                 return (error);
  471 
  472         offset += elfround(nhdr->n_namesz);
  473 
  474         error = vn_rdwr(UIO_WRITE, vp,
  475             data, nhdr->n_descsz,
  476             offset, UIO_SYSSPACE,
  477             IO_NODELOCKED|IO_UNIT, cred, NULL, NULL);
  478 
  479         return (error);
  480 }

Cache object: 52c85f31e18a204990163fdc930a6976


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.