Print this page
13925 core files should include DWARF (fix mismerge)
13925 core files should include DWARF
Reviewed by: Rich Lowe <richlowe@richlowe.net>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Adam Leventhal <adam.leventhal@gmail.com>
Approved by: Dan McDonald <danmcd@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/exec/elf/elf.c
          +++ new/usr/src/uts/common/exec/elf/elf.c
↓ open down ↓ 61 lines elided ↑ open up ↑
  62   62  #include <sys/machelf.h>
  63   63  #include <sys/shm_impl.h>
  64   64  #include <sys/archsystm.h>
  65   65  #include <sys/fasttrap.h>
  66   66  #include <sys/brand.h>
  67   67  #include "elf_impl.h"
  68   68  #include <sys/sdt.h>
  69   69  #include <sys/siginfo.h>
  70   70  #include <sys/random.h>
  71   71  
       72 +#include <core_shstrtab.h>
       73 +
  72   74  #if defined(__x86)
  73   75  #include <sys/comm_page_util.h>
  74   76  #include <sys/fp.h>
  75   77  #endif /* defined(__x86) */
  76   78  
  77   79  
  78   80  extern int at_flags;
  79   81  extern volatile size_t aslr_max_brk_skew;
  80   82  
  81   83  #define ORIGIN_STR      "ORIGIN"
↓ open down ↓ 19 lines elided ↑ open up ↑
 101  103  extern uint_t elf_nshdr_max;
 102  104  extern size_t elf_shstrtab_max;
 103  105  #else
 104  106  size_t elf_datasz_max = 1 * 1024 * 1024;
 105  107  size_t elf_zeropg_sz = 4 * 1024;
 106  108  uint_t elf_nphdr_max = 1000;
 107  109  uint_t elf_nshdr_max = 10000;
 108  110  size_t elf_shstrtab_max = 100 * 1024;
 109  111  #endif
 110  112  
 111      -
 112      -
 113      -typedef enum {
 114      -        STR_CTF,
 115      -        STR_SYMTAB,
 116      -        STR_DYNSYM,
 117      -        STR_STRTAB,
 118      -        STR_DYNSTR,
 119      -        STR_SHSTRTAB,
 120      -        STR_NUM
 121      -} shstrtype_t;
 122      -
 123      -static const char *shstrtab_data[] = {
 124      -        ".SUNW_ctf",
 125      -        ".symtab",
 126      -        ".dynsym",
 127      -        ".strtab",
 128      -        ".dynstr",
 129      -        ".shstrtab"
 130      -};
 131      -
 132      -typedef struct shstrtab {
 133      -        uint_t  sst_ndx[STR_NUM];
 134      -        uint_t  sst_cur;
 135      -} shstrtab_t;
 136      -
 137      -static void
 138      -shstrtab_init(shstrtab_t *s)
 139      -{
 140      -        bzero(&s->sst_ndx, sizeof (s->sst_ndx));
 141      -        s->sst_cur = 1;
 142      -}
 143      -
 144      -static uint_t
 145      -shstrtab_ndx(shstrtab_t *s, shstrtype_t type)
 146      -{
 147      -        uint_t ret;
 148      -
 149      -        if ((ret = s->sst_ndx[type]) != 0)
 150      -                return (ret);
 151      -
 152      -        ret = s->sst_ndx[type] = s->sst_cur;
 153      -        s->sst_cur += strlen(shstrtab_data[type]) + 1;
 154      -
 155      -        return (ret);
 156      -}
 157      -
 158      -static size_t
 159      -shstrtab_size(const shstrtab_t *s)
 160      -{
 161      -        return (s->sst_cur);
 162      -}
 163      -
 164      -static void
 165      -shstrtab_dump(const shstrtab_t *s, char *buf)
 166      -{
 167      -        uint_t i, ndx;
 168      -
 169      -        *buf = '\0';
 170      -        for (i = 0; i < STR_NUM; i++) {
 171      -                if ((ndx = s->sst_ndx[i]) != 0)
 172      -                        (void) strcpy(buf + ndx, shstrtab_data[i]);
 173      -        }
 174      -}
 175      -
 176  113  static int
 177  114  dtrace_safe_phdr(Phdr *phdrp, struct uarg *args, uintptr_t base)
 178  115  {
 179  116          ASSERT(phdrp->p_type == PT_SUNWDTRACE);
 180  117  
 181  118          /*
 182  119           * See the comment in fasttrap.h for information on how to safely
 183  120           * update this program header.
 184  121           */
 185  122          if (phdrp->p_memsz < PT_SUNWDTRACE_SIZE ||
↓ open down ↓ 1781 lines elided ↑ open up ↑
1967 1904  
1968 1905                  n -= len - resid;
1969 1906                  off += len - resid;
1970 1907          }
1971 1908  
1972 1909          ctx->ecc_doffset += src->sh_size;
1973 1910  }
1974 1911  
1975 1912  /*
1976 1913   * Walk sections for a given ELF object, counting (or copying) those of
1977      - * interest (CTF, symtab, strtab).
     1914 + * interest (CTF, symtab, strtab, DWARF debug).
     1915 + *
     1916 + * Returns UINT_MAX upon low-memory.
1978 1917   */
1979 1918  static uint_t
1980 1919  elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr,
1981 1920      Shdr *v, uint_t idx, uint_t remain, shstrtab_t *shstrtab)
1982 1921  {
1983 1922          Ehdr ehdr;
1984 1923          const core_content_t content = ctx->ecc_content;
1985 1924          cred_t *credp = ctx->ecc_credp;
1986 1925          Shdr *ctf = NULL, *symtab = NULL, *strtab = NULL;
1987 1926          uintptr_t off = 0;
1988 1927          uint_t nshdrs, shstrndx, nphdrs, count = 0;
1989 1928          u_offset_t *doffp = &ctx->ecc_doffset;
1990 1929          boolean_t ctf_link = B_FALSE;
1991 1930          caddr_t shbase;
1992 1931          size_t shsize, shstrsize;
1993 1932          char *shstrbase;
1994 1933  
1995      -        if ((content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)) == 0) {
     1934 +        if ((content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | CC_CONTENT_DEBUG))
     1935 +            == 0) {
1996 1936                  return (0);
1997 1937          }
1998 1938  
1999 1939          if (getelfhead(mvp, credp, &ehdr, &nshdrs, &shstrndx, &nphdrs) != 0 ||
2000 1940              getelfshdr(mvp, credp, &ehdr, nshdrs, shstrndx, &shbase, &shsize,
2001 1941              &shstrbase, &shstrsize) != 0) {
2002 1942                  return (0);
2003 1943          }
2004 1944  
2005 1945          /* Starting at index 1 skips SHT_NULL which is expected at index 0 */
↓ open down ↓ 17 lines elided ↑ open up ↑
2023 1963                                  symchk = (Shdr *)(shbase +
2024 1964                                      shdr->sh_link * ehdr.e_shentsize);
2025 1965                                  ctf_link = B_TRUE;
2026 1966                          } else {
2027 1967                                  continue;
2028 1968                          }
2029 1969                  } else if (symtab == NULL &&
2030 1970                      (content & CC_CONTENT_SYMTAB) != 0 &&
2031 1971                      strcmp(name, shstrtab_data[STR_SYMTAB]) == 0) {
2032 1972                          symchk = shdr;
     1973 +                } else if ((content & CC_CONTENT_DEBUG) != 0 &&
     1974 +                    strncmp(name, ".debug_", strlen(".debug_")) == 0) {
     1975 +                        /*
     1976 +                         * The design of the above check is intentional.  In
     1977 +                         * particular, we want to capture any sections that
     1978 +                         * begin with '.debug_' for a few reasons:
     1979 +                         *
     1980 +                         * 1) Various revisions to the DWARF spec end up
     1981 +                         * changing the set of section headers that
     1982 +                         * exist. This ensures that we don't need to change
     1983 +                         * the kernel to get a new version.
     1984 +                         *
     1985 +                         * 2) Other software uses .debug_ sections for things
     1986 +                         * which aren't DWARF. This allows them to be captured
     1987 +                         * as well.
     1988 +                         *
     1989 +                         * Because of this, we emit straight here, unlike the
     1990 +                         * other two sections where we wait until we're done
     1991 +                         * scanning.
     1992 +                         */
     1993 +
     1994 +                        /* We're only counting, don't emit! */
     1995 +                        if (v == NULL) {
     1996 +                                count++;
     1997 +                                continue;
     1998 +                        }
     1999 +
     2000 +                        elf_ctx_resize_scratch(ctx, shdr->sh_size);
     2001 +                        if (!shstrtab_ndx(shstrtab, name, &v[idx].sh_name)) {
     2002 +                                count = UINT_MAX;
     2003 +                                goto done;
     2004 +                        }
     2005 +                        v[idx].sh_addr = (Addr)(uintptr_t)saddr;
     2006 +                        v[idx].sh_type = shdr->sh_type;
     2007 +                        v[idx].sh_addralign = shdr->sh_addralign;
     2008 +                        *doffp = roundup(*doffp, v[idx].sh_addralign);
     2009 +                        v[idx].sh_offset = *doffp;
     2010 +                        v[idx].sh_size = shdr->sh_size;
     2011 +                        v[idx].sh_link = 0;
     2012 +                        v[idx].sh_entsize = shdr->sh_entsize;
     2013 +                        v[idx].sh_info = shdr->sh_info;
     2014 +
     2015 +                        elf_copy_scn(ctx, shdr, mvp, &v[idx]);
     2016 +                        count++;
     2017 +                        idx++;
     2018 +                        continue;
2033 2019                  } else {
2034 2020                          continue;
2035 2021                  }
2036 2022  
2037 2023                  ASSERT(symchk != NULL);
2038 2024                  if ((symchk->sh_type != SHT_DYNSYM &&
2039 2025                      symchk->sh_type != SHT_SYMTAB) ||
2040 2026                      symchk->sh_link == 0 || symchk->sh_link >= nshdrs) {
2041 2027                          ctf_link = B_FALSE;
2042 2028                          continue;
2043 2029                  }
2044 2030                  strchk = (Shdr *)(shbase + symchk->sh_link * ehdr.e_shentsize);
2045 2031                  if (strchk->sh_type != SHT_STRTAB) {
2046 2032                          ctf_link = B_FALSE;
2047 2033                          continue;
2048 2034                  }
2049 2035                  symtab = symchk;
2050 2036                  strtab = strchk;
2051 2037  
2052      -                if (symtab != NULL && ctf != NULL) {
     2038 +                if (symtab != NULL && ctf != NULL &&
     2039 +                    (content & CC_CONTENT_DEBUG) == 0) {
2053 2040                          /* No other shdrs are of interest at this point */
2054 2041                          break;
2055 2042                  }
2056 2043          }
2057 2044  
2058 2045          if (ctf != NULL)
2059 2046                  count += 1;
2060 2047          if (symtab != NULL)
2061 2048                  count += 2;
     2049 +
2062 2050          if (v == NULL || count == 0 || count > remain) {
2063 2051                  count = MIN(count, remain);
2064 2052                  goto done;
2065 2053          }
2066 2054  
2067 2055          /* output CTF section */
2068 2056          if (ctf != NULL) {
2069 2057                  elf_ctx_resize_scratch(ctx, ctf->sh_size);
2070 2058  
2071      -                v[idx].sh_name = shstrtab_ndx(shstrtab, STR_CTF);
     2059 +                if (!shstrtab_ndx(shstrtab, shstrtab_data[STR_CTF],
     2060 +                    &v[idx].sh_name)) {
     2061 +                        count = UINT_MAX;
     2062 +                        goto done;
     2063 +                }
     2064 +
2072 2065                  v[idx].sh_addr = (Addr)(uintptr_t)saddr;
2073 2066                  v[idx].sh_type = SHT_PROGBITS;
2074 2067                  v[idx].sh_addralign = 4;
2075 2068                  *doffp = roundup(*doffp, v[idx].sh_addralign);
2076 2069                  v[idx].sh_offset = *doffp;
2077 2070                  v[idx].sh_size = ctf->sh_size;
2078 2071  
2079 2072                  if (ctf_link) {
2080 2073                          /*
2081 2074                           * The linked symtab (and strtab) will be output
↓ open down ↓ 10 lines elided ↑ open up ↑
2092 2085          }
2093 2086  
2094 2087          /* output SYMTAB/STRTAB sections */
2095 2088          if (symtab != NULL) {
2096 2089                  uint_t symtab_name, strtab_name;
2097 2090  
2098 2091                  elf_ctx_resize_scratch(ctx,
2099 2092                      MAX(symtab->sh_size, strtab->sh_size));
2100 2093  
2101 2094                  if (symtab->sh_type == SHT_DYNSYM) {
2102      -                        symtab_name = shstrtab_ndx(shstrtab, STR_DYNSYM);
2103      -                        strtab_name = shstrtab_ndx(shstrtab, STR_DYNSTR);
     2095 +                        if (!shstrtab_ndx(shstrtab, shstrtab_data[STR_DYNSYM],
     2096 +                            &symtab_name) ||
     2097 +                            !shstrtab_ndx(shstrtab, shstrtab_data[STR_DYNSTR],
     2098 +                            &strtab_name)) {
     2099 +                                count = UINT_MAX;
     2100 +                                goto done;
     2101 +                        }
2104 2102                  } else {
2105      -                        symtab_name = shstrtab_ndx(shstrtab, STR_SYMTAB);
2106      -                        strtab_name = shstrtab_ndx(shstrtab, STR_STRTAB);
     2103 +                        if (!shstrtab_ndx(shstrtab, shstrtab_data[STR_SYMTAB],
     2104 +                            &symtab_name) ||
     2105 +                            !shstrtab_ndx(shstrtab, shstrtab_data[STR_STRTAB],
     2106 +                            &strtab_name)) {
     2107 +                                count = UINT_MAX;
     2108 +                                goto done;
     2109 +                        }
2107 2110                  }
2108 2111  
2109 2112                  v[idx].sh_name = symtab_name;
2110 2113                  v[idx].sh_type = symtab->sh_type;
2111 2114                  v[idx].sh_addr = symtab->sh_addr;
2112 2115                  if (ehdr.e_type == ET_DYN || v[idx].sh_addr == 0)
2113 2116                          v[idx].sh_addr += (Addr)(uintptr_t)saddr;
2114 2117                  v[idx].sh_addralign = symtab->sh_addralign;
2115 2118                  *doffp = roundup(*doffp, v[idx].sh_addralign);
2116 2119                  v[idx].sh_offset = *doffp;
↓ open down ↓ 40 lines elided ↑ open up ↑
2157 2160          uint_t idx = 0, remain;
2158 2161          shstrtab_t shstrtab;
2159 2162          struct as *as = ctx->ecc_p->p_as;
2160 2163          int error = 0;
2161 2164  
2162 2165          ASSERT(AS_WRITE_HELD(as));
2163 2166  
2164 2167          if (v != NULL) {
2165 2168                  ASSERT(nv != 0);
2166 2169  
2167      -                shstrtab_init(&shstrtab);
     2170 +                if (!shstrtab_init(&shstrtab))
     2171 +                        return (ENOMEM);
2168 2172                  remain = nv;
2169 2173          } else {
2170 2174                  ASSERT(nv == 0);
2171 2175  
2172 2176                  /*
2173 2177                   * The shdrs are being counted, rather than outputting them
2174 2178                   * into a buffer.  Leave room for two entries: the SHT_NULL at
2175 2179                   * index 0 and the shstrtab at the end.
2176 2180                   */
2177 2181                  remain = UINT_MAX - 2;
↓ open down ↓ 27 lines elided ↑ open up ↑
2205 2209  
2206 2210                  /*
2207 2211                   * Skip this segment unless the protection bits look like
2208 2212                   * what we'd expect for a text segment.
2209 2213                   */
2210 2214                  if ((prot & (PROT_WRITE | PROT_EXEC)) != PROT_EXEC)
2211 2215                          continue;
2212 2216  
2213 2217                  count = elf_process_obj_scns(ctx, mvp, saddr, v, idx, remain,
2214 2218                      &shstrtab);
     2219 +                if (count == UINT_MAX) {
     2220 +                        error = ENOMEM;
     2221 +                        goto done;
     2222 +                }
2215 2223  
2216 2224                  ASSERT(count <= remain);
2217 2225                  ASSERT(v == NULL || (idx + count) < nv);
2218 2226  
2219 2227                  remain -= count;
2220 2228                  idx += count;
2221 2229                  lastvp = mvp;
2222 2230          }
2223 2231  
2224 2232          if (v == NULL) {
2225 2233                  if (idx == 1) {
2226 2234                          *nshdrsp = 0;
2227 2235                  } else {
2228 2236                          /* Include room for the shrstrtab at the end */
2229 2237                          *nshdrsp = idx + 1;
2230 2238                  }
     2239 +                /* No need to free up shstrtab so we can just return. */
2231 2240                  return (0);
2232 2241          }
2233 2242  
2234 2243          if (idx != nv - 1) {
2235 2244                  cmn_err(CE_WARN, "elfcore: core dump failed for "
2236 2245                      "process %d; address space is changing",
2237 2246                      ctx->ecc_p->p_pid);
2238      -                return (EIO);
     2247 +                error = EIO;
     2248 +                goto done;
2239 2249          }
2240 2250  
2241      -        v[idx].sh_name = shstrtab_ndx(&shstrtab, STR_SHSTRTAB);
     2251 +        if (!shstrtab_ndx(&shstrtab, shstrtab_data[STR_SHSTRTAB],
     2252 +            &v[idx].sh_name)) {
     2253 +                error = ENOMEM;
     2254 +                goto done;
     2255 +        }
2242 2256          v[idx].sh_size = shstrtab_size(&shstrtab);
2243 2257          v[idx].sh_addralign = 1;
2244 2258          v[idx].sh_offset = ctx->ecc_doffset;
2245 2259          v[idx].sh_flags = SHF_STRINGS;
2246 2260          v[idx].sh_type = SHT_STRTAB;
2247 2261  
2248 2262          elf_ctx_resize_scratch(ctx, v[idx].sh_size);
2249 2263          VERIFY3U(ctx->ecc_bufsz, >=, v[idx].sh_size);
2250 2264          shstrtab_dump(&shstrtab, ctx->ecc_buf);
2251 2265  
2252 2266          error = core_write(ctx->ecc_vp, UIO_SYSSPACE, ctx->ecc_doffset,
2253 2267              ctx->ecc_buf, v[idx].sh_size, ctx->ecc_rlimit, ctx->ecc_credp);
2254 2268          if (error == 0) {
2255 2269                  ctx->ecc_doffset += v[idx].sh_size;
2256 2270          }
2257 2271  
     2272 +done:
     2273 +        if (v != NULL)
     2274 +                shstrtab_fini(&shstrtab);
2258 2275          return (error);
2259 2276  }
2260 2277  
2261 2278  int
2262 2279  elfcore(vnode_t *vp, proc_t *p, cred_t *credp, rlim64_t rlimit, int sig,
2263 2280      core_content_t content)
2264 2281  {
2265 2282          u_offset_t poffset, soffset, doffset;
2266 2283          int error;
2267 2284          uint_t i, nphdrs, nshdrs;
↓ open down ↓ 27 lines elided ↑ open up ↑
2295 2312          ASSERT(p == ttoproc(curthread));
2296 2313          prstop(0, 0);
2297 2314  
2298 2315          AS_LOCK_ENTER(as, RW_WRITER);
2299 2316          nphdrs = prnsegs(as, 0) + 2;            /* two CORE note sections */
2300 2317  
2301 2318          /*
2302 2319           * Count the number of section headers we're going to need.
2303 2320           */
2304 2321          nshdrs = 0;
2305      -        if (content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)) {
     2322 +        if (content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | CC_CONTENT_DEBUG))
2306 2323                  VERIFY0(elf_process_scns(&ctx, NULL, 0, &nshdrs));
2307      -        }
2308 2324          AS_LOCK_EXIT(as);
2309 2325  
2310 2326          /*
2311 2327           * The core file contents may require zero section headers, but if
2312 2328           * we overflow the 16 bits allotted to the program header count in
2313 2329           * the ELF header, we'll need that program header at index zero.
2314 2330           */
2315 2331          if (nshdrs == 0 && nphdrs >= PN_XNUM) {
2316 2332                  nshdrs = 1;
2317 2333          }
2318 2334  
2319 2335          /*
2320      -         * Allocate a buffer which is sized adequately to hold the ehdr, phdrs
2321      -         * or shdrs needed to produce the core file.  It is used for the three
2322      -         * tasks sequentially, not simultaneously, so it does not need space
2323      -         * for all three data at once, only the largest one.
     2336 +         * Allocate a buffer which is sized adequately to hold the ehdr,
     2337 +         * phdrs, DWARF debug, or shdrs needed to produce the core file.  It
     2338 +         * is used for the four tasks sequentially, not simultaneously, so it
     2339 +         * does not need space for all four data at once, only the largest
     2340 +         * one.
2324 2341           */
2325 2342          VERIFY(nphdrs >= 2);
2326 2343          phdrsz = nphdrs * sizeof (Phdr);
2327 2344          shdrsz = nshdrs * sizeof (Shdr);
2328 2345          bigsize = MAX(sizeof (Ehdr), MAX(phdrsz, shdrsz));
2329 2346          bigwad = kmem_alloc(bigsize, KM_SLEEP);
2330 2347  
2331 2348          ehdr = (Ehdr *)bigwad;
2332 2349          bzero(ehdr, sizeof (*ehdr));
2333 2350  
↓ open down ↓ 478 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX