19abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Copyright (c) 2007, Google Inc.
29abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// All rights reserved.
39abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai//
49abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Redistribution and use in source and binary forms, with or without
59abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// modification, are permitted provided that the following conditions are
69abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// met:
79abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai//
89abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai//     * Redistributions of source code must retain the above copyright
99abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// notice, this list of conditions and the following disclaimer.
109abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai//     * Redistributions in binary form must reproduce the above
119abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// copyright notice, this list of conditions and the following disclaimer
129abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// in the documentation and/or other materials provided with the
139abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// distribution.
149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai//     * Neither the name of Google Inc. nor the names of its
159abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// contributors may be used to endorse or promote products derived from
169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// this software without specific prior written permission.
179abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai//
189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
209abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
219abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
229abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
249abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
259abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
289abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
299abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
309abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Author: Alfred Peng
319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <fcntl.h>
33dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#include <sys/frame.h>
349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <sys/stat.h>
359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <sys/types.h>
369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <sys/utsname.h>
379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <sys/wait.h>
389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <unistd.h>
399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
409abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <cstdlib>
419abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include <ctime>
429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include "client/solaris/handler/minidump_generator.h"
449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include "client/minidump_file_writer-inl.h"
459abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai#include "common/solaris/file_id.h"
469abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
47dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczareknamespace {
48dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
49dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekusing namespace google_breakpad;
50dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
51dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Argument for the writer function.
52dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekstruct WriterArgument {
53dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  MinidumpFileWriter *minidump_writer;
54dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
55dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // Pid of the lwp who called WriteMinidumpToFile
56dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int requester_pid;
57dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
58dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // The stack bottom of the lwp which caused the dump.
59dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // Mainly used to find the lwp id of the crashed lwp since signal
60dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // handler may not be called in the lwp who caused it.
61dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  uintptr_t crashed_stack_bottom;
62dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
63dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // Id of the crashing lwp.
64dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int crashed_lwpid;
65dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
66dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // Signal number when crash happened. Can be 0 if this is a requested dump.
67dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int signo;
68dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
69dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // The ebp of the signal handler frame on x86.  Can be 0 if this is a
70dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // requested dump.
71dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  uintptr_t sighandler_ebp;
72dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
73dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // User context when crash happens. Can be NULL if this is a requested dump.
74dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // This is actually an out parameter, but it will be filled in at the start
75dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // of the writer LWP.
76dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  ucontext_t *sig_ctx;
77dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
78dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // Used to get information about the lwps.
79dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  SolarisLwp *lwp_lister;
80dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek};
81dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
82dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Holding context information for the callback of finding the crashing lwp.
83dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekstruct FindCrashLwpContext {
84dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  const SolarisLwp *lwp_lister;
85dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  uintptr_t crashing_stack_bottom;
86dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int crashing_lwpid;
879abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
88dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  FindCrashLwpContext() :
89dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    lwp_lister(NULL),
90dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    crashing_stack_bottom(0UL),
91dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    crashing_lwpid(-1) {
92dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  }
93dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek};
94dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
95dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Callback for list lwps.
96dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// It will compare the stack bottom of the provided lwp with the stack
97dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// bottom of the crashed lwp, it they are eqaul, this lwp is the one
98dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// who crashed.
99dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool IsLwpCrashedCallback(lwpstatus_t *lsp, void *context) {
100dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  FindCrashLwpContext *crashing_context =
101dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    static_cast<FindCrashLwpContext *>(context);
102dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  const SolarisLwp *lwp_lister = crashing_context->lwp_lister;
103dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  const prgregset_t *gregs = &(lsp->pr_reg);
104dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#if TARGET_CPU_SPARC
105dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  uintptr_t last_ebp = (*gregs)[R_FP];
106dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#elif TARGET_CPU_X86
107dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  uintptr_t last_ebp = (*gregs)[EBP];
108dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#endif
109dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  uintptr_t stack_bottom = lwp_lister->GetLwpStackBottom(last_ebp);
110dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (stack_bottom > last_ebp &&
111dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      stack_bottom == crashing_context->crashing_stack_bottom) {
112dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    // Got it. Stop iteration.
113dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    crashing_context->crashing_lwpid = lsp->pr_lwpid;
114dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return false;
115dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  }
116dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
117dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return true;
1189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
1199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
120dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Find the crashing lwpid.
121dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// This is done based on stack bottom comparing.
122dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekint FindCrashingLwp(uintptr_t crashing_stack_bottom,
123dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                    int requester_pid,
124dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                    const SolarisLwp *lwp_lister) {
125dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  FindCrashLwpContext context;
126dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context.lwp_lister = lwp_lister;
127dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context.crashing_stack_bottom = crashing_stack_bottom;
128dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  CallbackParam<LwpCallback> callback_param(IsLwpCrashedCallback,
129dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                            &context);
130dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  lwp_lister->Lwp_iter_all(lwp_lister->getpid(), &callback_param);
131dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return context.crashing_lwpid;
1329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
1339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
134dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteLwpStack(const SolarisLwp *lwp_lister,
135dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                   uintptr_t last_esp,
136dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                   UntypedMDRVA *memory,
137dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                   MDMemoryDescriptor *loc) {
138dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  uintptr_t stack_bottom = lwp_lister->GetLwpStackBottom(last_esp);
139ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (stack_bottom >= last_esp) {
1409abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    int size = stack_bottom - last_esp;
1419abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    if (size > 0) {
1429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      if (!memory->Allocate(size))
1439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai        return false;
1449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      memory->Copy(reinterpret_cast<void *>(last_esp), size);
1459abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      loc->start_of_memory_range = last_esp;
1469abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      loc->memory = memory->location();
1479abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    }
1489abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return true;
1499abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
1509abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return false;
1519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
1529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
153ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#if TARGET_CPU_SPARC
154dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteContext(MDRawContextSPARC *context, ucontext_t *sig_ctx) {
155dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  assert(sig_ctx != NULL);
156dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int* regs = sig_ctx->uc_mcontext.gregs;
157dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->context_flags = MD_CONTEXT_SPARC_FULL;
158dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
159dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->ccr = (unsigned int)(regs[0]);
160dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->pc = (unsigned int)(regs[REG_PC]);
161dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->npc = (unsigned int)(regs[REG_nPC]);
162dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->y = (unsigned int)(regs[REG_Y]);
163dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->asi = (unsigned int)(regs[19]);
164dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->fprs = (unsigned int)(regs[20]);
165dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
166dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  for ( int i = 0 ; i < 32; ++i ) {
167dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    context->g_r[i] = 0;
168dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  }
169dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
170dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  for ( int i = 1 ; i < 16; ++i ) {
171dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    context->g_r[i] = (uintptr_t)(sig_ctx->uc_mcontext.gregs[i + 3]);
172dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  }
173dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->g_r[30] = (uintptr_t)(((struct frame *)context->g_r[14])->fr_savfp);
174dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
175dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return true;
176dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek}
177dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
178dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteContext(MDRawContextSPARC *context, prgregset_t regs,
179dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                  prfpregset_t *fp_regs) {
180ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (!context || !regs)
181ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    return false;
182ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
183ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  context->context_flags = MD_CONTEXT_SPARC_FULL;
184ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
185dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->ccr = (uintptr_t)(regs[32]);
186dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->pc = (uintptr_t)(regs[R_PC]);
187dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->npc = (uintptr_t)(regs[R_nPC]);
188dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->y = (uintptr_t)(regs[R_Y]);
189dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->asi = (uintptr_t)(regs[36]);
190dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context->fprs = (uintptr_t)(regs[37]);
191ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  for ( int i = 0 ; i < 32 ; ++i ){
192dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    context->g_r[i] = (uintptr_t)(regs[i]);
193ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  }
194ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
195ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  return true;
196ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai}
197ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#elif TARGET_CPU_X86
198dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteContext(MDRawContextX86 *context, prgregset_t regs,
199dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                  prfpregset_t *fp_regs) {
2009abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!context || !regs)
2019abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
2029abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
2039abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->context_flags = MD_CONTEXT_X86_FULL;
2049abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
2059abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->cs = regs[CS];
2069abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->ds = regs[DS];
2079abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->es = regs[ES];
2089abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->fs = regs[FS];
2099abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->gs = regs[GS];
2109abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->ss = regs[SS];
2119abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->edi = regs[EDI];
2129abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->esi = regs[ESI];
2139abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->ebx = regs[EBX];
2149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->edx = regs[EDX];
2159abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->ecx = regs[ECX];
2169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->eax = regs[EAX];
2179abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->ebp = regs[EBP];
2189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->eip = regs[EIP];
2199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->esp = regs[UESP];
2209abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context->eflags = regs[EFL];
2219abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
2229abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return true;
2239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
224ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#endif /* TARGET_CPU_XXX */
2259abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
226dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Write information about a crashed Lwp.
227dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// When a lwp crash, kernel will write something on the stack for processing
228dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// signal. This makes the current stack not reliable, and our stack walker
229dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// won't figure out the whole call stack for this. So we write the stack at the
230dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// time of the crash into the minidump file, not the current stack.
231dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteCrashedLwpStream(MinidumpFileWriter *minidump_writer,
232dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                           const WriterArgument *writer_args,
233dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                           const lwpstatus_t *lsp,
234dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                           MDRawThread *lwp) {
235dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  assert(writer_args->sig_ctx != NULL);
236dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
237dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  lwp->thread_id = lsp->pr_lwpid;
238dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
239dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#if TARGET_CPU_SPARC
240dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  UntypedMDRVA memory(minidump_writer);
241dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!WriteLwpStack(writer_args->lwp_lister,
242dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     writer_args->sig_ctx->uc_mcontext.gregs[REG_O6],
243dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     &memory,
244dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     &lwp->stack))
245dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return false;
246dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
247dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawContextSPARC> context(minidump_writer);
248dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!context.Allocate())
249dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return false;
250dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  lwp->thread_context = context.location();
251dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  memset(context.get(), 0, sizeof(MDRawContextSPARC));
252dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return WriteContext(context.get(), writer_args->sig_ctx);
253dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#elif TARGET_CPU_X86
254dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  UntypedMDRVA memory(minidump_writer);
255dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!WriteLwpStack(writer_args->lwp_lister,
256dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     writer_args->sig_ctx->uc_mcontext.gregs[UESP],
257dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     &memory,
258dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     &lwp->stack))
259dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return false;
260dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
261dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawContextX86> context(minidump_writer);
262dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!context.Allocate())
263dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return false;
264dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  lwp->thread_context = context.location();
265dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  memset(context.get(), 0, sizeof(MDRawContextX86));
266dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return WriteContext(context.get(),
267dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                      (int *)&writer_args->sig_ctx->uc_mcontext.gregs,
268dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                      &writer_args->sig_ctx->uc_mcontext.fpregs);
269dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#endif
270dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek}
271dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
272dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteLwpStream(MinidumpFileWriter *minidump_writer,
273dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                    const SolarisLwp *lwp_lister,
274dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                    const lwpstatus_t *lsp, MDRawThread *lwp) {
2759abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  prfpregset_t fp_regs = lsp->pr_fpreg;
276dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  const prgregset_t *gregs = &(lsp->pr_reg);
277dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  UntypedMDRVA memory(minidump_writer);
278ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#if TARGET_CPU_SPARC
279dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!WriteLwpStack(lwp_lister,
280dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     (*gregs)[R_SP],
2819abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai                     &memory,
2829abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai                     &lwp->stack))
2839abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
2849abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
2859abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  // Write context
286dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawContextSPARC> context(minidump_writer);
287ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (!context.Allocate())
288ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    return false;
289ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  // should be the thread_id
290ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  lwp->thread_id = lsp->pr_lwpid;
291ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  lwp->thread_context = context.location();
292ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  memset(context.get(), 0, sizeof(MDRawContextSPARC));
293ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#elif TARGET_CPU_X86
294dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!WriteLwpStack(lwp_lister,
295dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     (*gregs)[UESP],
296ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                     &memory,
297ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai                     &lwp->stack))
298ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  return false;
299ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai
300ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  // Write context
301dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawContextX86> context(minidump_writer);
3029abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!context.Allocate())
3039abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
304ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  // should be the thread_id
305ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  lwp->thread_id = lsp->pr_lwpid;
3069abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  lwp->thread_context = context.location();
3079abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  memset(context.get(), 0, sizeof(MDRawContextX86));
308ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#endif /* TARGET_CPU_XXX */
3099abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return WriteContext(context.get(), (int *)gregs, &fp_regs);
3109abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
3119abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
312dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteCPUInformation(MDRawSystemInfo *sys_info) {
3139abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  struct utsname uts;
3149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  char *major, *minor, *build;
3159abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  sys_info->number_of_processors = sysconf(_SC_NPROCESSORS_CONF);
3179abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  sys_info->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN;
3189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (uname(&uts) != -1) {
3199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    // Match "i86pc" as X86 architecture.
3209abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    if (strcmp(uts.machine, "i86pc") == 0)
3219abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      sys_info->processor_architecture = MD_CPU_ARCHITECTURE_X86;
3229abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    else if (strcmp(uts.machine, "sun4u") == 0)
3239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      sys_info->processor_architecture = MD_CPU_ARCHITECTURE_SPARC;
3249abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
3259abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  major = uts.release;
3279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  minor = strchr(major, '.');
3289abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  *minor = '\0';
3299abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  ++minor;
3309abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  sys_info->major_version = atoi(major);
3319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  sys_info->minor_version = atoi(minor);
3329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  build = strchr(uts.version, '_');
3349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  ++build;
3359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  sys_info->build_number = atoi(build);
3369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return true;
3389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
3399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
340dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteOSInformation(MinidumpFileWriter *minidump_writer,
341dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                        MDRawSystemInfo *sys_info) {
3429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  sys_info->platform_id = MD_OS_SOLARIS;
3439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  struct utsname uts;
3459abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (uname(&uts) != -1) {
3469abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    char os_version[512];
3479abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    size_t space_left = sizeof(os_version);
3489abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    memset(os_version, 0, space_left);
3499abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    const char *os_info_table[] = {
3509abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      uts.sysname,
3519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      uts.release,
3529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      uts.version,
3539abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      uts.machine,
3549abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      "OpenSolaris",
3559abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      NULL
3569abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    };
3579abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    for (const char **cur_os_info = os_info_table;
3589abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai         *cur_os_info != NULL;
3599abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai         ++cur_os_info) {
3609abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      if (cur_os_info != os_info_table && space_left > 1) {
3619abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai        strcat(os_version, " ");
3629abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai        --space_left;
3639abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      }
3649abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      if (space_left > strlen(*cur_os_info)) {
3659abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai        strcat(os_version, *cur_os_info);
3669abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai        space_left -= strlen(*cur_os_info);
3679abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      } else {
3689abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai        break;
3699abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      }
3709abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    }
3719abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3729abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    MDLocationDescriptor location;
373dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    if (!minidump_writer->WriteString(os_version, 0, &location))
3749abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      return false;
3759abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    sys_info->csd_version_rva = location.rva;
3769abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
3779abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return true;
3789abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
3799abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3809abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Callback context for get writting lwp information.
3819abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaistruct LwpInfoCallbackCtx {
382dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  MinidumpFileWriter *minidump_writer;
383dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  const WriterArgument *writer_args;
3849abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  TypedMDRVA<MDRawThreadList> *list;
3859abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  int lwp_index;
3869abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai};
3879abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
3889abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaibool LwpInformationCallback(lwpstatus_t *lsp, void *context) {
3899abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  bool success = true;
390dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  LwpInfoCallbackCtx *callback_context =
391dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    static_cast<LwpInfoCallbackCtx *>(context);
392dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
393dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // The current lwp is the one to handle the crash. Ignore it.
3949abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (lsp->pr_lwpid != pthread_self()) {
3959abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    LwpInfoCallbackCtx *callback_context =
3969abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      static_cast<LwpInfoCallbackCtx *>(context);
3979abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    MDRawThread lwp;
3989abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    memset(&lwp, 0, sizeof(MDRawThread));
3999abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
400dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    if (lsp->pr_lwpid != callback_context->writer_args->crashed_lwpid ||
401dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek        callback_context->writer_args->sig_ctx == NULL) {
402dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      success = WriteLwpStream(callback_context->minidump_writer,
403dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                               callback_context->writer_args->lwp_lister,
404dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                               lsp, &lwp);
405dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    } else {
406dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      success = WriteCrashedLwpStream(callback_context->minidump_writer,
407dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                      callback_context->writer_args,
408dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                      lsp, &lwp);
409dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    }
4109abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    if (success) {
4119abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      callback_context->list->CopyIndexAfterObject(
4129abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai          callback_context->lwp_index++,
4139abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai          &lwp, sizeof(MDRawThread));
4149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    }
4159abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
4169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4179abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return success;
4189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
4199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
420dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteLwpListStream(MinidumpFileWriter *minidump_writer,
421dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                        const WriterArgument *writer_args,
422dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                        MDRawDirectory *dir) {
4239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  // Get the lwp information.
424dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  const SolarisLwp *lwp_lister = writer_args->lwp_lister;
425dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int lwp_count = lwp_lister->GetLwpCount();
4269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (lwp_count < 0)
4279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
428dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawThreadList> list(minidump_writer);
429ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (!list.AllocateObjectAndArray(lwp_count - 1, sizeof(MDRawThread)))
4309abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
4319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->stream_type = MD_THREAD_LIST_STREAM;
4329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->location = list.location();
433ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  list.get()->number_of_threads = lwp_count - 1;
4349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  LwpInfoCallbackCtx context;
436dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context.minidump_writer = minidump_writer;
437dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context.writer_args = writer_args;
4389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context.list = &list;
4399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context.lwp_index = 0;
4409abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  CallbackParam<LwpCallback> callback_param(LwpInformationCallback,
4419abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai                                            &context);
4429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  int written =
443dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    lwp_lister->Lwp_iter_all(lwp_lister->getpid(), &callback_param);
4449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return written == lwp_count;
4459abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
4469abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
447dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteCVRecord(MinidumpFileWriter *minidump_writer,
448dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                   MDRawModule *module,
449dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                   const char *module_path,
450dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                   char *realname) {
451dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDCVInfoPDB70> cv(minidump_writer);
4529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4539abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  char path[PATH_MAX];
4549abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  const char *module_name = module_path ? module_path : "<Unknown>";
4559abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  snprintf(path, sizeof(path), "/proc/self/object/%s", module_name);
4569abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
457dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  size_t module_name_length = strlen(realname);
4586162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(uint8_t)))
4599abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
460dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!cv.CopyIndexAfterObject(0, realname, module_name_length))
4619abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
4629abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4639abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  module->cv_record = cv.location();
4649abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  MDCVInfoPDB70 *cv_ptr = cv.get();
4659abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  memset(cv_ptr, 0, sizeof(MDCVInfoPDB70));
4669abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE;
4679abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  cv_ptr->age = 0;
4689abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4699abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  // Get the module identifier
4709abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  FileID file_id(path);
4719abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  unsigned char identifier[16];
4729abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4739abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (file_id.ElfFileIdentifier(identifier)) {
4749abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 |
4759abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      (uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 |
4769abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      (uint32_t)identifier[3];
4779abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data2 = (uint32_t)identifier[4] << 8 | identifier[5];
4789abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7];
4799abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[0] = identifier[8];
4809abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[1] = identifier[9];
4819abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[2] = identifier[10];
4829abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[3] = identifier[11];
4839abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[4] = identifier[12];
4849abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[5] = identifier[13];
4859abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[6] = identifier[14];
4869abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    cv_ptr->signature.data4[7] = identifier[15];
4879abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
4889abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return true;
4899abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
4909abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4919abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaistruct ModuleInfoCallbackCtx {
4929abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  MinidumpFileWriter *minidump_writer;
493dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  const WriterArgument *writer_args;
4949abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  TypedMDRVA<MDRawModuleList> *list;
4959abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  int module_index;
4969abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai};
4979abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
4989abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaibool ModuleInfoCallback(const ModuleInfo &module_info, void *context) {
4999abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  ModuleInfoCallbackCtx *callback_context =
5009abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    static_cast<ModuleInfoCallbackCtx *>(context);
5019abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  // Skip those modules without name, or those that are not modules.
5029abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (strlen(module_info.name) == 0)
5039abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return true;
5049abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5059abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  MDRawModule module;
5069abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  memset(&module, 0, sizeof(module));
5079abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  MDLocationDescriptor loc;
508dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  char path[PATH_MAX];
509dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  char buf[PATH_MAX];
510dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  char *realname;
511dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int count;
512dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
513dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  snprintf(path, sizeof (path), "/proc/self/path/%s", module_info.name);
514dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if ((count = readlink(path, buf, PATH_MAX)) < 0)
515dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return false;
516dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  buf[count] = '\0';
517dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
518dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if ((realname = strrchr(buf, '/')) == NULL)
519dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return false;
520dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  realname++;
521dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
522dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!callback_context->minidump_writer->WriteString(realname, 0, &loc))
5239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
5249abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5256162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  module.base_of_image = (uint64_t)module_info.start_addr;
5269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  module.size_of_image = module_info.size;
5279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  module.module_name_rva = loc.rva;
5289abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
529dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!WriteCVRecord(callback_context->minidump_writer, &module,
530dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                     module_info.name, realname))
5319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
5329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  callback_context->list->CopyIndexAfterObject(
5349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      callback_context->module_index++, &module, MD_MODULE_SIZE);
5359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return true;
5369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
5379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
538dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteModuleListStream(MinidumpFileWriter *minidump_writer,
539dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                           const WriterArgument *writer_args,
540dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                           MDRawDirectory *dir) {
541dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawModuleList> list(minidump_writer);
542dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  int module_count = writer_args->lwp_lister->GetModuleCount();
5439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (module_count <= 0 ||
5459abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      !list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE)) {
5469abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
5479abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
5489abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5499abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->stream_type = MD_MODULE_LIST_STREAM;
5509abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->location = list.location();
5519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  list.get()->number_of_modules = module_count;
5529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  ModuleInfoCallbackCtx context;
553dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context.minidump_writer = minidump_writer;
554dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  context.writer_args = writer_args;
5559abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context.list = &list;
5569abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  context.module_index = 0;
5579abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  CallbackParam<ModuleCallback> callback(ModuleInfoCallback, &context);
558dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return writer_args->lwp_lister->ListModules(&callback) == module_count;
5599abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
5609abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
561dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteSystemInfoStream(MinidumpFileWriter *minidump_writer,
562dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                           const WriterArgument *writer_args,
563dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                           MDRawDirectory *dir) {
564dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawSystemInfo> sys_info(minidump_writer);
5659abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5669abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!sys_info.Allocate())
5679abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
5689abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5699abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->stream_type = MD_SYSTEM_INFO_STREAM;
5709abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->location = sys_info.location();
5719abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5729abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return WriteCPUInformation(sys_info.get()) &&
573dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek         WriteOSInformation(minidump_writer, sys_info.get());
5749abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
5759abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
576dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteExceptionStream(MinidumpFileWriter *minidump_writer,
577dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                          const WriterArgument *writer_args,
578dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                          MDRawDirectory *dir) {
579dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // This happenes when this is not a crash, but a requested dump.
580dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (writer_args->sig_ctx == NULL)
5819abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
5829abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
583dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawExceptionStream> exception(minidump_writer);
5849abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!exception.Allocate())
5859abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
5869abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
5879abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->stream_type = MD_EXCEPTION_STREAM;
5889abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->location = exception.location();
589dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  exception.get()->thread_id = writer_args->crashed_lwpid;
590dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  exception.get()->exception_record.exception_code = writer_args->signo;
5919abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  exception.get()->exception_record.exception_flags = 0;
5929abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
593ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#if TARGET_CPU_SPARC
594dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (writer_args->sig_ctx != NULL) {
595dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    exception.get()->exception_record.exception_address =
596dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      writer_args->sig_ctx->uc_mcontext.gregs[REG_PC];
597dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  } else {
598dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return true;
599dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  }
600dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
601ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  // Write context of the exception.
602dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawContextSPARC> context(minidump_writer);
603ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  if (!context.Allocate())
604ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai    return false;
605ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  exception.get()->thread_context = context.location();
606ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai  memset(context.get(), 0, sizeof(MDRawContextSPARC));
607dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return WriteContext(context.get(), writer_args->sig_ctx);
608ea2bba970675e01f9964f82d3f44960c1aad05dcmmentovai#elif TARGET_CPU_X86
609dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (writer_args->sig_ctx != NULL) {
610dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    exception.get()->exception_record.exception_address =
611dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      writer_args->sig_ctx->uc_mcontext.gregs[EIP];
612dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  } else {
613dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return true;
614dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  }
615dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
6169abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  // Write context of the exception.
617dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawContextX86> context(minidump_writer);
6189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!context.Allocate())
6199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
6209abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  exception.get()->thread_context = context.location();
6219abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  memset(context.get(), 0, sizeof(MDRawContextX86));
622dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  return WriteContext(context.get(),
623dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                      (int *)&writer_args->sig_ctx->uc_mcontext.gregs,
624dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                      NULL);
625dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#endif
6269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
6279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
628dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteMiscInfoStream(MinidumpFileWriter *minidump_writer,
629dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                         const WriterArgument *writer_args,
630dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                         MDRawDirectory *dir) {
631dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawMiscInfo> info(minidump_writer);
6329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
6339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!info.Allocate())
6349abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
6359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
6369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->stream_type = MD_MISC_INFO_STREAM;
6379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->location = info.location();
6389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  info.get()->size_of_info = sizeof(MDRawMiscInfo);
6399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  info.get()->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID;
640dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  info.get()->process_id = writer_args->requester_pid;
6419abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
6429abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return true;
6439abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
6449abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
645dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool WriteBreakpadInfoStream(MinidumpFileWriter *minidump_writer,
646dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                             const WriterArgument *writer_args,
647dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                             MDRawDirectory *dir) {
648dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawBreakpadInfo> info(minidump_writer);
6499abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
6509abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!info.Allocate())
6519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
6529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
6539abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->stream_type = MD_BREAKPAD_INFO_STREAM;
6549abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  dir->location = info.location();
6559abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
6569abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  info.get()->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID |
6579abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai                         MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID;
6589abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  info.get()->dump_thread_id = getpid();
659dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  info.get()->requesting_thread_id = writer_args->requester_pid;
6609abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return true;
6619abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
6629abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
6639abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaiclass AutoLwpResumer {
6649abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai public:
6659abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  AutoLwpResumer(SolarisLwp *lwp) : lwp_(lwp) {}
6669abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  ~AutoLwpResumer() { lwp_->ControlAllLwps(false); }
6679abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai private:
6689abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  SolarisLwp *lwp_;
6699abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai};
6709abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
671dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Prototype of writer functions.
672dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarektypedef bool (*WriteStreamFN)(MinidumpFileWriter *,
673dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                              const WriterArgument *,
674dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                              MDRawDirectory *);
675dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
676dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Function table to writer a full minidump.
677dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekconst WriteStreamFN writers[] = {
678dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  WriteLwpListStream,
679dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  WriteModuleListStream,
680dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  WriteSystemInfoStream,
681dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  WriteExceptionStream,
682dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  WriteMiscInfoStream,
683dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  WriteBreakpadInfoStream,
684dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek};
685dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
6869abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Will call each writer function in the writers table.
687dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek//void* MinidumpGenerator::Write(void *argument) {
688dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekvoid* Write(void *argument) {
689dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  WriterArgument *writer_args = static_cast<WriterArgument *>(argument);
690dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
691dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (!writer_args->lwp_lister->ControlAllLwps(true))
6929abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return NULL;
6939abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
694dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  AutoLwpResumer lwpResumer(writer_args->lwp_lister);
695dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
696dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (writer_args->sighandler_ebp != 0 &&
697dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      writer_args->lwp_lister->FindSigContext(writer_args->sighandler_ebp,
698dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                              &writer_args->sig_ctx)) {
699dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    writer_args->crashed_stack_bottom =
700dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      writer_args->lwp_lister->GetLwpStackBottom(
701dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#if TARGET_CPU_SPARC
702dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek          writer_args->sig_ctx->uc_mcontext.gregs[REG_O6]
703dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#elif TARGET_CPU_X86
704dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek          writer_args->sig_ctx->uc_mcontext.gregs[UESP]
705dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#endif
706dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      );
707dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
708dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    int crashed_lwpid = FindCrashingLwp(writer_args->crashed_stack_bottom,
709dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                        writer_args->requester_pid,
710dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                        writer_args->lwp_lister);
711dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    if (crashed_lwpid > 0)
712dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek      writer_args->crashed_lwpid = crashed_lwpid;
713dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  }
7149abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
715dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  MinidumpFileWriter *minidump_writer = writer_args->minidump_writer;
716dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawHeader> header(minidump_writer);
717dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  TypedMDRVA<MDRawDirectory> dir(minidump_writer);
7189abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!header.Allocate())
7199abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return 0;
7209abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
7219abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  int writer_count = sizeof(writers) / sizeof(writers[0]);
7229abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  // Need directory space for all writers.
7239abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (!dir.AllocateArray(writer_count))
7249abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return 0;
7259abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  header.get()->signature = MD_HEADER_SIGNATURE;
7269abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  header.get()->version = MD_HEADER_VERSION;
7279abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  header.get()->time_date_stamp = time(NULL);
7289abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  header.get()->stream_count = writer_count;
7299abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  header.get()->stream_directory_rva = dir.position();
7309abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
7319abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  int dir_index = 0;
7329abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  MDRawDirectory local_dir;
7339abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  for (int i = 0; i < writer_count; ++i) {
734dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    if ((*writers[i])(minidump_writer, writer_args, &local_dir))
7359abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai      dir.CopyIndex(dir_index++, &local_dir);
7369abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
7379abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
7389abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return 0;
7399abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
7409abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
741dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek}  // namespace
742dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
743dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczareknamespace google_breakpad {
744dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
745dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekMinidumpGenerator::MinidumpGenerator() {
746dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek}
747dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
748dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekMinidumpGenerator::~MinidumpGenerator() {
749dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek}
750dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
7519abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// Write minidump into file.
7529abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai// It runs in a different thread from the crashing thread.
7539abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovaibool MinidumpGenerator::WriteMinidumpToFile(const char *file_pathname,
754dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                            int signo,
755dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                            uintptr_t sighandler_ebp,
756dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek                                            ucontext_t **sig_ctx) const {
757dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  // The exception handler thread.
758dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  pthread_t handler_thread;
759dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
7609abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  assert(file_pathname != NULL);
7619abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
7629abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  if (file_pathname == NULL)
7639abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    return false;
7649abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
765dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  MinidumpFileWriter minidump_writer;
766dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek  if (minidump_writer.Open(file_pathname)) {
767dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    WriterArgument argument;
768dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    memset(&argument, 0, sizeof(argument));
7699abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai    SolarisLwp lwp_lister(getpid());
770dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    argument.lwp_lister = &lwp_lister;
771dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    argument.minidump_writer = &minidump_writer;
772dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    argument.requester_pid = getpid();
773dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    argument.crashed_lwpid = pthread_self();
774dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    argument.signo = signo;
775dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    argument.sighandler_ebp = sighandler_ebp;
776dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    argument.sig_ctx = NULL;
777dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek
778dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    pthread_create(&handler_thread, NULL, Write, (void *)&argument);
779dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    pthread_join(handler_thread, NULL);
780dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek    return true;
7819abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  }
7829abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
7839abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai  return false;
7849abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}
7859abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai
7869abfe3d0a5bbefd85c54feda0dac2d030cbb5635mmentovai}  // namespace google_breakpad
787