Home | History | Annotate | Download | only in minidump_writer
      1 // Copyright (c) 2010, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // This code writes out minidump files:
     31 //   http://msdn.microsoft.com/en-us/library/ms680378(VS.85,loband).aspx
     32 //
     33 // Minidumps are a Microsoft format which Breakpad uses for recording crash
     34 // dumps. This code has to run in a compromised environment (the address space
     35 // may have received SIGSEGV), thus the following rules apply:
     36 //   * You may not enter the dynamic linker. This means that we cannot call
     37 //     any symbols in a shared library (inc libc). Because of this we replace
     38 //     libc functions in linux_libc_support.h.
     39 //   * You may not call syscalls via the libc wrappers. This rule is a subset
     40 //     of the first rule but it bears repeating. We have direct wrappers
     41 //     around the system calls in linux_syscall_support.h.
     42 //   * You may not malloc. There's an alternative allocator in memory.h and
     43 //     a canonical instance in the LinuxDumper object. We use the placement
     44 //     new form to allocate objects and we don't delete them.
     45 
     46 #include "client/linux/handler/minidump_descriptor.h"
     47 #include "client/linux/minidump_writer/minidump_writer.h"
     48 #include "client/minidump_file_writer-inl.h"
     49 
     50 #include <ctype.h>
     51 #include <errno.h>
     52 #include <fcntl.h>
     53 #include <link.h>
     54 #include <stdio.h>
     55 #if defined(__ANDROID__)
     56 #include <sys/system_properties.h>
     57 #endif
     58 #include <sys/types.h>
     59 #include <sys/ucontext.h>
     60 #include <sys/user.h>
     61 #include <sys/utsname.h>
     62 #include <time.h>
     63 #include <unistd.h>
     64 
     65 #include <algorithm>
     66 
     67 #include "client/linux/dump_writer_common/seccomp_unwinder.h"
     68 #include "client/linux/dump_writer_common/thread_info.h"
     69 #include "client/linux/dump_writer_common/ucontext_reader.h"
     70 #include "client/linux/handler/exception_handler.h"
     71 #include "client/linux/minidump_writer/cpu_set.h"
     72 #include "client/linux/minidump_writer/line_reader.h"
     73 #include "client/linux/minidump_writer/linux_dumper.h"
     74 #include "client/linux/minidump_writer/linux_ptrace_dumper.h"
     75 #include "client/linux/minidump_writer/proc_cpuinfo_reader.h"
     76 #include "client/minidump_file_writer.h"
     77 #include "common/linux/linux_libc_support.h"
     78 #include "common/minidump_type_helper.h"
     79 #include "google_breakpad/common/minidump_format.h"
     80 #include "third_party/lss/linux_syscall_support.h"
     81 
     82 namespace {
     83 
     84 using google_breakpad::AppMemoryList;
     85 using google_breakpad::ExceptionHandler;
     86 using google_breakpad::CpuSet;
     87 using google_breakpad::LineReader;
     88 using google_breakpad::LinuxDumper;
     89 using google_breakpad::LinuxPtraceDumper;
     90 using google_breakpad::MDTypeHelper;
     91 using google_breakpad::MappingEntry;
     92 using google_breakpad::MappingInfo;
     93 using google_breakpad::MappingList;
     94 using google_breakpad::MinidumpFileWriter;
     95 using google_breakpad::PageAllocator;
     96 using google_breakpad::ProcCpuInfoReader;
     97 using google_breakpad::RawContextCPU;
     98 using google_breakpad::SeccompUnwinder;
     99 using google_breakpad::ThreadInfo;
    100 using google_breakpad::TypedMDRVA;
    101 using google_breakpad::UContextReader;
    102 using google_breakpad::UntypedMDRVA;
    103 using google_breakpad::wasteful_vector;
    104 
    105 typedef MDTypeHelper<sizeof(void*)>::MDRawDebug MDRawDebug;
    106 typedef MDTypeHelper<sizeof(void*)>::MDRawLinkMap MDRawLinkMap;
    107 
    108 class MinidumpWriter {
    109  public:
    110   // The following kLimit* constants are for when minidump_size_limit_ is set
    111   // and the minidump size might exceed it.
    112   //
    113   // Estimate for how big each thread's stack will be (in bytes).
    114   static const unsigned kLimitAverageThreadStackLength = 8 * 1024;
    115   // Number of threads whose stack size we don't want to limit.  These base
    116   // threads will simply be the first N threads returned by the dumper (although
    117   // the crashing thread will never be limited).  Threads beyond this count are
    118   // the extra threads.
    119   static const unsigned kLimitBaseThreadCount = 20;
    120   // Maximum stack size to dump for any extra thread (in bytes).
    121   static const unsigned kLimitMaxExtraThreadStackLen = 2 * 1024;
    122   // Make sure this number of additional bytes can fit in the minidump
    123   // (exclude the stack data).
    124   static const unsigned kLimitMinidumpFudgeFactor = 64 * 1024;
    125 
    126   MinidumpWriter(const char* minidump_path,
    127                  int minidump_fd,
    128                  const ExceptionHandler::CrashContext* context,
    129                  const MappingList& mappings,
    130                  const AppMemoryList& appmem,
    131                  LinuxDumper* dumper)
    132       : fd_(minidump_fd),
    133         path_(minidump_path),
    134         ucontext_(context ? &context->context : NULL),
    135 #if !defined(__ARM_EABI__) && !defined(__mips__)
    136         float_state_(context ? &context->float_state : NULL),
    137 #endif
    138         dumper_(dumper),
    139         minidump_size_limit_(-1),
    140         memory_blocks_(dumper_->allocator()),
    141         mapping_list_(mappings),
    142         app_memory_list_(appmem) {
    143     // Assert there should be either a valid fd or a valid path, not both.
    144     assert(fd_ != -1 || minidump_path);
    145     assert(fd_ == -1 || !minidump_path);
    146   }
    147 
    148   bool Init() {
    149     if (!dumper_->Init())
    150       return false;
    151 
    152     if (fd_ != -1)
    153       minidump_writer_.SetFile(fd_);
    154     else if (!minidump_writer_.Open(path_))
    155       return false;
    156 
    157     return dumper_->ThreadsSuspend();
    158   }
    159 
    160   ~MinidumpWriter() {
    161     // Don't close the file descriptor when it's been provided explicitly.
    162     // Callers might still need to use it.
    163     if (fd_ == -1)
    164       minidump_writer_.Close();
    165     dumper_->ThreadsResume();
    166   }
    167 
    168   bool Dump() {
    169     // A minidump file contains a number of tagged streams. This is the number
    170     // of stream which we write.
    171     unsigned kNumWriters = 13;
    172 
    173     TypedMDRVA<MDRawHeader> header(&minidump_writer_);
    174     TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
    175     if (!header.Allocate())
    176       return false;
    177     if (!dir.AllocateArray(kNumWriters))
    178       return false;
    179     my_memset(header.get(), 0, sizeof(MDRawHeader));
    180 
    181     header.get()->signature = MD_HEADER_SIGNATURE;
    182     header.get()->version = MD_HEADER_VERSION;
    183     header.get()->time_date_stamp = time(NULL);
    184     header.get()->stream_count = kNumWriters;
    185     header.get()->stream_directory_rva = dir.position();
    186 
    187     unsigned dir_index = 0;
    188     MDRawDirectory dirent;
    189 
    190     if (!WriteThreadListStream(&dirent))
    191       return false;
    192     dir.CopyIndex(dir_index++, &dirent);
    193 
    194     if (!WriteMappings(&dirent))
    195       return false;
    196     dir.CopyIndex(dir_index++, &dirent);
    197 
    198     if (!WriteAppMemory())
    199       return false;
    200 
    201     if (!WriteMemoryListStream(&dirent))
    202       return false;
    203     dir.CopyIndex(dir_index++, &dirent);
    204 
    205     if (!WriteExceptionStream(&dirent))
    206       return false;
    207     dir.CopyIndex(dir_index++, &dirent);
    208 
    209     if (!WriteSystemInfoStream(&dirent))
    210       return false;
    211     dir.CopyIndex(dir_index++, &dirent);
    212 
    213     dirent.stream_type = MD_LINUX_CPU_INFO;
    214     if (!WriteFile(&dirent.location, "/proc/cpuinfo"))
    215       NullifyDirectoryEntry(&dirent);
    216     dir.CopyIndex(dir_index++, &dirent);
    217 
    218     dirent.stream_type = MD_LINUX_PROC_STATUS;
    219     if (!WriteProcFile(&dirent.location, GetCrashThread(), "status"))
    220       NullifyDirectoryEntry(&dirent);
    221     dir.CopyIndex(dir_index++, &dirent);
    222 
    223     dirent.stream_type = MD_LINUX_LSB_RELEASE;
    224     if (!WriteFile(&dirent.location, "/etc/lsb-release"))
    225       NullifyDirectoryEntry(&dirent);
    226     dir.CopyIndex(dir_index++, &dirent);
    227 
    228     dirent.stream_type = MD_LINUX_CMD_LINE;
    229     if (!WriteProcFile(&dirent.location, GetCrashThread(), "cmdline"))
    230       NullifyDirectoryEntry(&dirent);
    231     dir.CopyIndex(dir_index++, &dirent);
    232 
    233     dirent.stream_type = MD_LINUX_ENVIRON;
    234     if (!WriteProcFile(&dirent.location, GetCrashThread(), "environ"))
    235       NullifyDirectoryEntry(&dirent);
    236     dir.CopyIndex(dir_index++, &dirent);
    237 
    238     dirent.stream_type = MD_LINUX_AUXV;
    239     if (!WriteProcFile(&dirent.location, GetCrashThread(), "auxv"))
    240       NullifyDirectoryEntry(&dirent);
    241     dir.CopyIndex(dir_index++, &dirent);
    242 
    243     dirent.stream_type = MD_LINUX_MAPS;
    244     if (!WriteProcFile(&dirent.location, GetCrashThread(), "maps"))
    245       NullifyDirectoryEntry(&dirent);
    246     dir.CopyIndex(dir_index++, &dirent);
    247 
    248     dirent.stream_type = MD_LINUX_DSO_DEBUG;
    249     if (!WriteDSODebugStream(&dirent))
    250       NullifyDirectoryEntry(&dirent);
    251     dir.CopyIndex(dir_index++, &dirent);
    252 
    253     // If you add more directory entries, don't forget to update kNumWriters,
    254     // above.
    255 
    256     dumper_->ThreadsResume();
    257     return true;
    258   }
    259 
    260   bool FillThreadStack(MDRawThread* thread, uintptr_t stack_pointer,
    261                        int max_stack_len, uint8_t** stack_copy) {
    262     *stack_copy = NULL;
    263     const void* stack;
    264     size_t stack_len;
    265     if (dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
    266       UntypedMDRVA memory(&minidump_writer_);
    267       if (max_stack_len >= 0 &&
    268           stack_len > static_cast<unsigned int>(max_stack_len)) {
    269         stack_len = max_stack_len;
    270       }
    271       if (!memory.Allocate(stack_len))
    272         return false;
    273       *stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
    274       dumper_->CopyFromProcess(*stack_copy, thread->thread_id, stack,
    275                                stack_len);
    276       memory.Copy(*stack_copy, stack_len);
    277       thread->stack.start_of_memory_range =
    278           reinterpret_cast<uintptr_t>(stack);
    279       thread->stack.memory = memory.location();
    280       memory_blocks_.push_back(thread->stack);
    281     } else {
    282       thread->stack.start_of_memory_range = stack_pointer;
    283       thread->stack.memory.data_size = 0;
    284       thread->stack.memory.rva = minidump_writer_.position();
    285     }
    286     return true;
    287   }
    288 
    289   // Write information about the threads.
    290   bool WriteThreadListStream(MDRawDirectory* dirent) {
    291     const unsigned num_threads = dumper_->threads().size();
    292 
    293     TypedMDRVA<uint32_t> list(&minidump_writer_);
    294     if (!list.AllocateObjectAndArray(num_threads, sizeof(MDRawThread)))
    295       return false;
    296 
    297     dirent->stream_type = MD_THREAD_LIST_STREAM;
    298     dirent->location = list.location();
    299 
    300     *list.get() = num_threads;
    301 
    302     // If there's a minidump size limit, check if it might be exceeded.  Since
    303     // most of the space is filled with stack data, just check against that.
    304     // If this expects to exceed the limit, set extra_thread_stack_len such
    305     // that any thread beyond the first kLimitBaseThreadCount threads will
    306     // have only kLimitMaxExtraThreadStackLen bytes dumped.
    307     int extra_thread_stack_len = -1;  // default to no maximum
    308     if (minidump_size_limit_ >= 0) {
    309       const unsigned estimated_total_stack_size = num_threads *
    310           kLimitAverageThreadStackLength;
    311       const off_t estimated_minidump_size = minidump_writer_.position() +
    312           estimated_total_stack_size + kLimitMinidumpFudgeFactor;
    313       if (estimated_minidump_size > minidump_size_limit_)
    314         extra_thread_stack_len = kLimitMaxExtraThreadStackLen;
    315     }
    316 
    317     for (unsigned i = 0; i < num_threads; ++i) {
    318       MDRawThread thread;
    319       my_memset(&thread, 0, sizeof(thread));
    320       thread.thread_id = dumper_->threads()[i];
    321 
    322       // We have a different source of information for the crashing thread. If
    323       // we used the actual state of the thread we would find it running in the
    324       // signal handler with the alternative stack, which would be deeply
    325       // unhelpful.
    326       if (static_cast<pid_t>(thread.thread_id) == GetCrashThread() &&
    327           ucontext_ &&
    328           !dumper_->IsPostMortem()) {
    329         uint8_t* stack_copy;
    330         const uintptr_t stack_ptr = UContextReader::GetStackPointer(ucontext_);
    331         if (!FillThreadStack(&thread, stack_ptr, -1, &stack_copy))
    332           return false;
    333 
    334         // Copy 256 bytes around crashing instruction pointer to minidump.
    335         const size_t kIPMemorySize = 256;
    336         uint64_t ip = UContextReader::GetInstructionPointer(ucontext_);
    337         // Bound it to the upper and lower bounds of the memory map
    338         // it's contained within. If it's not in mapped memory,
    339         // don't bother trying to write it.
    340         bool ip_is_mapped = false;
    341         MDMemoryDescriptor ip_memory_d;
    342         for (unsigned j = 0; j < dumper_->mappings().size(); ++j) {
    343           const MappingInfo& mapping = *dumper_->mappings()[j];
    344           if (ip >= mapping.start_addr &&
    345               ip < mapping.start_addr + mapping.size) {
    346             ip_is_mapped = true;
    347             // Try to get 128 bytes before and after the IP, but
    348             // settle for whatever's available.
    349             ip_memory_d.start_of_memory_range =
    350               std::max(mapping.start_addr,
    351                        uintptr_t(ip - (kIPMemorySize / 2)));
    352             uintptr_t end_of_range =
    353               std::min(uintptr_t(ip + (kIPMemorySize / 2)),
    354                        uintptr_t(mapping.start_addr + mapping.size));
    355             ip_memory_d.memory.data_size =
    356               end_of_range - ip_memory_d.start_of_memory_range;
    357             break;
    358           }
    359         }
    360 
    361         if (ip_is_mapped) {
    362           UntypedMDRVA ip_memory(&minidump_writer_);
    363           if (!ip_memory.Allocate(ip_memory_d.memory.data_size))
    364             return false;
    365           uint8_t* memory_copy =
    366               reinterpret_cast<uint8_t*>(Alloc(ip_memory_d.memory.data_size));
    367           dumper_->CopyFromProcess(
    368               memory_copy,
    369               thread.thread_id,
    370               reinterpret_cast<void*>(ip_memory_d.start_of_memory_range),
    371               ip_memory_d.memory.data_size);
    372           ip_memory.Copy(memory_copy, ip_memory_d.memory.data_size);
    373           ip_memory_d.memory = ip_memory.location();
    374           memory_blocks_.push_back(ip_memory_d);
    375         }
    376 
    377         TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
    378         if (!cpu.Allocate())
    379           return false;
    380         my_memset(cpu.get(), 0, sizeof(RawContextCPU));
    381 #if !defined(__ARM_EABI__) && !defined(__mips__)
    382         UContextReader::FillCPUContext(cpu.get(), ucontext_, float_state_);
    383 #else
    384         UContextReader::FillCPUContext(cpu.get(), ucontext_);
    385 #endif
    386         if (stack_copy)
    387           SeccompUnwinder::PopSeccompStackFrame(cpu.get(), thread, stack_copy);
    388         thread.thread_context = cpu.location();
    389         crashing_thread_context_ = cpu.location();
    390       } else {
    391         ThreadInfo info;
    392         if (!dumper_->GetThreadInfoByIndex(i, &info))
    393           return false;
    394 
    395         uint8_t* stack_copy;
    396         int max_stack_len = -1;  // default to no maximum for this thread
    397         if (minidump_size_limit_ >= 0 && i >= kLimitBaseThreadCount)
    398           max_stack_len = extra_thread_stack_len;
    399         if (!FillThreadStack(&thread, info.stack_pointer, max_stack_len,
    400             &stack_copy))
    401           return false;
    402 
    403         TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
    404         if (!cpu.Allocate())
    405           return false;
    406         my_memset(cpu.get(), 0, sizeof(RawContextCPU));
    407         info.FillCPUContext(cpu.get());
    408         if (stack_copy)
    409           SeccompUnwinder::PopSeccompStackFrame(cpu.get(), thread, stack_copy);
    410         thread.thread_context = cpu.location();
    411         if (dumper_->threads()[i] == GetCrashThread()) {
    412           crashing_thread_context_ = cpu.location();
    413           if (!dumper_->IsPostMortem()) {
    414             // This is the crashing thread of a live process, but
    415             // no context was provided, so set the crash address
    416             // while the instruction pointer is already here.
    417             dumper_->set_crash_address(info.GetInstructionPointer());
    418           }
    419         }
    420       }
    421 
    422       list.CopyIndexAfterObject(i, &thread, sizeof(thread));
    423     }
    424 
    425     return true;
    426   }
    427 
    428   // Write application-provided memory regions.
    429   bool WriteAppMemory() {
    430     for (AppMemoryList::const_iterator iter = app_memory_list_.begin();
    431          iter != app_memory_list_.end();
    432          ++iter) {
    433       uint8_t* data_copy =
    434         reinterpret_cast<uint8_t*>(dumper_->allocator()->Alloc(iter->length));
    435       dumper_->CopyFromProcess(data_copy, GetCrashThread(), iter->ptr,
    436                                iter->length);
    437 
    438       UntypedMDRVA memory(&minidump_writer_);
    439       if (!memory.Allocate(iter->length)) {
    440         return false;
    441       }
    442       memory.Copy(data_copy, iter->length);
    443       MDMemoryDescriptor desc;
    444       desc.start_of_memory_range = reinterpret_cast<uintptr_t>(iter->ptr);
    445       desc.memory = memory.location();
    446       memory_blocks_.push_back(desc);
    447     }
    448 
    449     return true;
    450   }
    451 
    452   static bool ShouldIncludeMapping(const MappingInfo& mapping) {
    453     if (mapping.name[0] == 0 ||  // only want modules with filenames.
    454         // Only want to include one mapping per shared lib.
    455         // Avoid filtering executable mappings.
    456         (mapping.offset != 0 && !mapping.exec) ||
    457         mapping.size < 4096) {  // too small to get a signature for.
    458       return false;
    459     }
    460 
    461     return true;
    462   }
    463 
    464   // If there is caller-provided information about this mapping
    465   // in the mapping_list_ list, return true. Otherwise, return false.
    466   bool HaveMappingInfo(const MappingInfo& mapping) {
    467     for (MappingList::const_iterator iter = mapping_list_.begin();
    468          iter != mapping_list_.end();
    469          ++iter) {
    470       // Ignore any mappings that are wholly contained within
    471       // mappings in the mapping_info_ list.
    472       if (mapping.start_addr >= iter->first.start_addr &&
    473           (mapping.start_addr + mapping.size) <=
    474           (iter->first.start_addr + iter->first.size)) {
    475         return true;
    476       }
    477     }
    478     return false;
    479   }
    480 
    481   // Write information about the mappings in effect. Because we are using the
    482   // minidump format, the information about the mappings is pretty limited.
    483   // Because of this, we also include the full, unparsed, /proc/$x/maps file in
    484   // another stream in the file.
    485   bool WriteMappings(MDRawDirectory* dirent) {
    486     const unsigned num_mappings = dumper_->mappings().size();
    487     unsigned num_output_mappings = mapping_list_.size();
    488 
    489     for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
    490       const MappingInfo& mapping = *dumper_->mappings()[i];
    491       if (ShouldIncludeMapping(mapping) && !HaveMappingInfo(mapping))
    492         num_output_mappings++;
    493     }
    494 
    495     TypedMDRVA<uint32_t> list(&minidump_writer_);
    496     if (num_output_mappings) {
    497       if (!list.AllocateObjectAndArray(num_output_mappings, MD_MODULE_SIZE))
    498         return false;
    499     } else {
    500       // Still create the module list stream, although it will have zero
    501       // modules.
    502       if (!list.Allocate())
    503         return false;
    504     }
    505 
    506     dirent->stream_type = MD_MODULE_LIST_STREAM;
    507     dirent->location = list.location();
    508     *list.get() = num_output_mappings;
    509 
    510     // First write all the mappings from the dumper
    511     unsigned int j = 0;
    512     for (unsigned i = 0; i < num_mappings; ++i) {
    513       const MappingInfo& mapping = *dumper_->mappings()[i];
    514       if (!ShouldIncludeMapping(mapping) || HaveMappingInfo(mapping))
    515         continue;
    516 
    517       MDRawModule mod;
    518       if (!FillRawModule(mapping, true, i, mod, NULL))
    519         return false;
    520       list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
    521     }
    522     // Next write all the mappings provided by the caller
    523     for (MappingList::const_iterator iter = mapping_list_.begin();
    524          iter != mapping_list_.end();
    525          ++iter) {
    526       MDRawModule mod;
    527       if (!FillRawModule(iter->first, false, 0, mod, iter->second))
    528         return false;
    529       list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
    530     }
    531 
    532     return true;
    533   }
    534 
    535   // Fill the MDRawModule |mod| with information about the provided
    536   // |mapping|. If |identifier| is non-NULL, use it instead of calculating
    537   // a file ID from the mapping.
    538   bool FillRawModule(const MappingInfo& mapping,
    539                      bool member,
    540                      unsigned int mapping_id,
    541                      MDRawModule& mod,
    542                      const uint8_t* identifier) {
    543     my_memset(&mod, 0, MD_MODULE_SIZE);
    544 
    545     mod.base_of_image = mapping.start_addr;
    546     mod.size_of_image = mapping.size;
    547 
    548     uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX];
    549     uint8_t* cv_ptr = cv_buf;
    550 
    551     const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE;
    552     my_memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
    553     cv_ptr += sizeof(cv_signature);
    554     uint8_t* signature = cv_ptr;
    555     cv_ptr += sizeof(MDGUID);
    556     if (identifier) {
    557       // GUID was provided by caller.
    558       my_memcpy(signature, identifier, sizeof(MDGUID));
    559     } else {
    560       // Note: ElfFileIdentifierForMapping() can manipulate the |mapping.name|.
    561       dumper_->ElfFileIdentifierForMapping(mapping, member,
    562                                            mapping_id, signature);
    563     }
    564     my_memset(cv_ptr, 0, sizeof(uint32_t));  // Set age to 0 on Linux.
    565     cv_ptr += sizeof(uint32_t);
    566 
    567     char file_name[NAME_MAX];
    568     char file_path[NAME_MAX];
    569     LinuxDumper::GetMappingEffectiveNameAndPath(
    570         mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
    571 
    572     const size_t file_name_len = my_strlen(file_name);
    573     UntypedMDRVA cv(&minidump_writer_);
    574     if (!cv.Allocate(MDCVInfoPDB70_minsize + file_name_len + 1))
    575       return false;
    576 
    577     // Write pdb_file_name
    578     my_memcpy(cv_ptr, file_name, file_name_len + 1);
    579     cv.Copy(cv_buf, MDCVInfoPDB70_minsize + file_name_len + 1);
    580 
    581     mod.cv_record = cv.location();
    582 
    583     MDLocationDescriptor ld;
    584     if (!minidump_writer_.WriteString(file_path, my_strlen(file_path), &ld))
    585       return false;
    586     mod.module_name_rva = ld.rva;
    587     return true;
    588   }
    589 
    590   bool WriteMemoryListStream(MDRawDirectory* dirent) {
    591     TypedMDRVA<uint32_t> list(&minidump_writer_);
    592     if (memory_blocks_.size()) {
    593       if (!list.AllocateObjectAndArray(memory_blocks_.size(),
    594                                        sizeof(MDMemoryDescriptor)))
    595         return false;
    596     } else {
    597       // Still create the memory list stream, although it will have zero
    598       // memory blocks.
    599       if (!list.Allocate())
    600         return false;
    601     }
    602 
    603     dirent->stream_type = MD_MEMORY_LIST_STREAM;
    604     dirent->location = list.location();
    605 
    606     *list.get() = memory_blocks_.size();
    607 
    608     for (size_t i = 0; i < memory_blocks_.size(); ++i) {
    609       list.CopyIndexAfterObject(i, &memory_blocks_[i],
    610                                 sizeof(MDMemoryDescriptor));
    611     }
    612     return true;
    613   }
    614 
    615   bool WriteExceptionStream(MDRawDirectory* dirent) {
    616     TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_);
    617     if (!exc.Allocate())
    618       return false;
    619     my_memset(exc.get(), 0, sizeof(MDRawExceptionStream));
    620 
    621     dirent->stream_type = MD_EXCEPTION_STREAM;
    622     dirent->location = exc.location();
    623 
    624     exc.get()->thread_id = GetCrashThread();
    625     exc.get()->exception_record.exception_code = dumper_->crash_signal();
    626     exc.get()->exception_record.exception_address = dumper_->crash_address();
    627     exc.get()->thread_context = crashing_thread_context_;
    628 
    629     return true;
    630   }
    631 
    632   bool WriteSystemInfoStream(MDRawDirectory* dirent) {
    633     TypedMDRVA<MDRawSystemInfo> si(&minidump_writer_);
    634     if (!si.Allocate())
    635       return false;
    636     my_memset(si.get(), 0, sizeof(MDRawSystemInfo));
    637 
    638     dirent->stream_type = MD_SYSTEM_INFO_STREAM;
    639     dirent->location = si.location();
    640 
    641     WriteCPUInformation(si.get());
    642     WriteOSInformation(si.get());
    643 
    644     return true;
    645   }
    646 
    647   bool WriteDSODebugStream(MDRawDirectory* dirent) {
    648     ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr) *>(dumper_->auxv()[AT_PHDR]);
    649     char* base;
    650     int phnum = dumper_->auxv()[AT_PHNUM];
    651     if (!phnum || !phdr)
    652       return false;
    653 
    654     // Assume the program base is at the beginning of the same page as the PHDR
    655     base = reinterpret_cast<char *>(reinterpret_cast<uintptr_t>(phdr) & ~0xfff);
    656 
    657     // Search for the program PT_DYNAMIC segment
    658     ElfW(Addr) dyn_addr = 0;
    659     for (; phnum >= 0; phnum--, phdr++) {
    660       ElfW(Phdr) ph;
    661       if (!dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph)))
    662         return false;
    663 
    664       // Adjust base address with the virtual address of the PT_LOAD segment
    665       // corresponding to offset 0
    666       if (ph.p_type == PT_LOAD && ph.p_offset == 0) {
    667         base -= ph.p_vaddr;
    668       }
    669       if (ph.p_type == PT_DYNAMIC) {
    670         dyn_addr = ph.p_vaddr;
    671       }
    672     }
    673     if (!dyn_addr)
    674       return false;
    675 
    676     ElfW(Dyn) *dynamic = reinterpret_cast<ElfW(Dyn) *>(dyn_addr + base);
    677 
    678     // The dynamic linker makes information available that helps gdb find all
    679     // DSOs loaded into the program. If this information is indeed available,
    680     // dump it to a MD_LINUX_DSO_DEBUG stream.
    681     struct r_debug* r_debug = NULL;
    682     uint32_t dynamic_length = 0;
    683 
    684     for (int i = 0; ; ++i) {
    685       ElfW(Dyn) dyn;
    686       dynamic_length += sizeof(dyn);
    687       if (!dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic + i,
    688                                     sizeof(dyn))) {
    689         return false;
    690       }
    691 
    692 #ifdef __mips__
    693       if (dyn.d_tag == DT_MIPS_RLD_MAP) {
    694         r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
    695         continue;
    696       }
    697 #else
    698       if (dyn.d_tag == DT_DEBUG) {
    699         r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
    700         continue;
    701       }
    702 #endif
    703       else if (dyn.d_tag == DT_NULL) {
    704         break;
    705       }
    706     }
    707 
    708     // The "r_map" field of that r_debug struct contains a linked list of all
    709     // loaded DSOs.
    710     // Our list of DSOs potentially is different from the ones in the crashing
    711     // process. So, we have to be careful to never dereference pointers
    712     // directly. Instead, we use CopyFromProcess() everywhere.
    713     // See <link.h> for a more detailed discussion of the how the dynamic
    714     // loader communicates with debuggers.
    715 
    716     // Count the number of loaded DSOs
    717     int dso_count = 0;
    718     struct r_debug debug_entry;
    719     if (!dumper_->CopyFromProcess(&debug_entry, GetCrashThread(), r_debug,
    720                                   sizeof(debug_entry))) {
    721       return false;
    722     }
    723     for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
    724       struct link_map map;
    725       if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)))
    726         return false;
    727 
    728       ptr = map.l_next;
    729       dso_count++;
    730     }
    731 
    732     MDRVA linkmap_rva = minidump_writer_.kInvalidMDRVA;
    733     if (dso_count > 0) {
    734       // If we have at least one DSO, create an array of MDRawLinkMap
    735       // entries in the minidump file.
    736       TypedMDRVA<MDRawLinkMap> linkmap(&minidump_writer_);
    737       if (!linkmap.AllocateArray(dso_count))
    738         return false;
    739       linkmap_rva = linkmap.location().rva;
    740       int idx = 0;
    741 
    742       // Iterate over DSOs and write their information to mini dump
    743       for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
    744         struct link_map map;
    745         if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)))
    746           return  false;
    747 
    748         ptr = map.l_next;
    749         char filename[257] = { 0 };
    750         if (map.l_name) {
    751           dumper_->CopyFromProcess(filename, GetCrashThread(), map.l_name,
    752                                    sizeof(filename) - 1);
    753         }
    754         MDLocationDescriptor location;
    755         if (!minidump_writer_.WriteString(filename, 0, &location))
    756           return false;
    757         MDRawLinkMap entry;
    758         entry.name = location.rva;
    759         entry.addr = map.l_addr;
    760         entry.ld = reinterpret_cast<uintptr_t>(map.l_ld);
    761         linkmap.CopyIndex(idx++, &entry);
    762       }
    763     }
    764 
    765     // Write MD_LINUX_DSO_DEBUG record
    766     TypedMDRVA<MDRawDebug> debug(&minidump_writer_);
    767     if (!debug.AllocateObjectAndArray(1, dynamic_length))
    768       return false;
    769     my_memset(debug.get(), 0, sizeof(MDRawDebug));
    770     dirent->stream_type = MD_LINUX_DSO_DEBUG;
    771     dirent->location = debug.location();
    772 
    773     debug.get()->version = debug_entry.r_version;
    774     debug.get()->map = linkmap_rva;
    775     debug.get()->dso_count = dso_count;
    776     debug.get()->brk = debug_entry.r_brk;
    777     debug.get()->ldbase = debug_entry.r_ldbase;
    778     debug.get()->dynamic = reinterpret_cast<uintptr_t>(dynamic);
    779 
    780     wasteful_vector<char> dso_debug_data(dumper_->allocator(), dynamic_length);
    781     // The passed-in size to the constructor (above) is only a hint.
    782     // Must call .resize() to do actual initialization of the elements.
    783     dso_debug_data.resize(dynamic_length);
    784     dumper_->CopyFromProcess(&dso_debug_data[0], GetCrashThread(), dynamic,
    785                              dynamic_length);
    786     debug.CopyIndexAfterObject(0, &dso_debug_data[0], dynamic_length);
    787 
    788     return true;
    789   }
    790 
    791   void set_minidump_size_limit(off_t limit) { minidump_size_limit_ = limit; }
    792 
    793  private:
    794   void* Alloc(unsigned bytes) {
    795     return dumper_->allocator()->Alloc(bytes);
    796   }
    797 
    798   pid_t GetCrashThread() const {
    799     return dumper_->crash_thread();
    800   }
    801 
    802   void NullifyDirectoryEntry(MDRawDirectory* dirent) {
    803     dirent->stream_type = 0;
    804     dirent->location.data_size = 0;
    805     dirent->location.rva = 0;
    806   }
    807 
    808 #if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
    809   bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
    810     char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0};
    811     static const char vendor_id_name[] = "vendor_id";
    812 
    813     struct CpuInfoEntry {
    814       const char* info_name;
    815       int value;
    816       bool found;
    817     } cpu_info_table[] = {
    818       { "processor", -1, false },
    819 #if defined(__i386__) || defined(__x86_64__)
    820       { "model", 0, false },
    821       { "stepping",  0, false },
    822       { "cpu family", 0, false },
    823 #endif
    824     };
    825 
    826     // processor_architecture should always be set, do this first
    827     sys_info->processor_architecture =
    828 #if defined(__mips__)
    829         MD_CPU_ARCHITECTURE_MIPS;
    830 #elif defined(__i386__)
    831         MD_CPU_ARCHITECTURE_X86;
    832 #else
    833         MD_CPU_ARCHITECTURE_AMD64;
    834 #endif
    835 
    836     const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
    837     if (fd < 0)
    838       return false;
    839 
    840     {
    841       PageAllocator allocator;
    842       ProcCpuInfoReader* const reader = new(allocator) ProcCpuInfoReader(fd);
    843       const char* field;
    844       while (reader->GetNextField(&field)) {
    845         for (size_t i = 0;
    846              i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]);
    847              i++) {
    848           CpuInfoEntry* entry = &cpu_info_table[i];
    849           if (i > 0 && entry->found) {
    850             // except for the 'processor' field, ignore repeated values.
    851             continue;
    852           }
    853           if (!my_strcmp(field, entry->info_name)) {
    854             size_t value_len;
    855             const char* value = reader->GetValueAndLen(&value_len);
    856             if (value_len == 0)
    857               continue;
    858 
    859             uintptr_t val;
    860             if (my_read_decimal_ptr(&val, value) == value)
    861               continue;
    862 
    863             entry->value = static_cast<int>(val);
    864             entry->found = true;
    865           }
    866         }
    867 
    868         // special case for vendor_id
    869         if (!my_strcmp(field, vendor_id_name)) {
    870           size_t value_len;
    871           const char* value = reader->GetValueAndLen(&value_len);
    872           if (value_len > 0)
    873             my_strlcpy(vendor_id, value, sizeof(vendor_id));
    874         }
    875       }
    876       sys_close(fd);
    877     }
    878 
    879     // make sure we got everything we wanted
    880     for (size_t i = 0;
    881          i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]);
    882          i++) {
    883       if (!cpu_info_table[i].found) {
    884         return false;
    885       }
    886     }
    887     // cpu_info_table[0] holds the last cpu id listed in /proc/cpuinfo,
    888     // assuming this is the highest id, change it to the number of CPUs
    889     // by adding one.
    890     cpu_info_table[0].value++;
    891 
    892     sys_info->number_of_processors = cpu_info_table[0].value;
    893 #if defined(__i386__) || defined(__x86_64__)
    894     sys_info->processor_level      = cpu_info_table[3].value;
    895     sys_info->processor_revision   = cpu_info_table[1].value << 8 |
    896                                      cpu_info_table[2].value;
    897 #endif
    898 
    899     if (vendor_id[0] != '\0') {
    900       my_memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
    901                 sizeof(sys_info->cpu.x86_cpu_info.vendor_id));
    902     }
    903     return true;
    904   }
    905 #elif defined(__arm__) || defined(__aarch64__)
    906   bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
    907     // The CPUID value is broken up in several entries in /proc/cpuinfo.
    908     // This table is used to rebuild it from the entries.
    909     const struct CpuIdEntry {
    910       const char* field;
    911       char        format;
    912       char        bit_lshift;
    913       char        bit_length;
    914     } cpu_id_entries[] = {
    915       { "CPU implementer", 'x', 24, 8 },
    916       { "CPU variant", 'x', 20, 4 },
    917       { "CPU part", 'x', 4, 12 },
    918       { "CPU revision", 'd', 0, 4 },
    919     };
    920 
    921     // The ELF hwcaps are listed in the "Features" entry as textual tags.
    922     // This table is used to rebuild them.
    923     const struct CpuFeaturesEntry {
    924       const char* tag;
    925       uint32_t hwcaps;
    926     } cpu_features_entries[] = {
    927 #if defined(__arm__)
    928       { "swp",  MD_CPU_ARM_ELF_HWCAP_SWP },
    929       { "half", MD_CPU_ARM_ELF_HWCAP_HALF },
    930       { "thumb", MD_CPU_ARM_ELF_HWCAP_THUMB },
    931       { "26bit", MD_CPU_ARM_ELF_HWCAP_26BIT },
    932       { "fastmult", MD_CPU_ARM_ELF_HWCAP_FAST_MULT },
    933       { "fpa", MD_CPU_ARM_ELF_HWCAP_FPA },
    934       { "vfp", MD_CPU_ARM_ELF_HWCAP_VFP },
    935       { "edsp", MD_CPU_ARM_ELF_HWCAP_EDSP },
    936       { "java", MD_CPU_ARM_ELF_HWCAP_JAVA },
    937       { "iwmmxt", MD_CPU_ARM_ELF_HWCAP_IWMMXT },
    938       { "crunch", MD_CPU_ARM_ELF_HWCAP_CRUNCH },
    939       { "thumbee", MD_CPU_ARM_ELF_HWCAP_THUMBEE },
    940       { "neon", MD_CPU_ARM_ELF_HWCAP_NEON },
    941       { "vfpv3", MD_CPU_ARM_ELF_HWCAP_VFPv3 },
    942       { "vfpv3d16", MD_CPU_ARM_ELF_HWCAP_VFPv3D16 },
    943       { "tls", MD_CPU_ARM_ELF_HWCAP_TLS },
    944       { "vfpv4", MD_CPU_ARM_ELF_HWCAP_VFPv4 },
    945       { "idiva", MD_CPU_ARM_ELF_HWCAP_IDIVA },
    946       { "idivt", MD_CPU_ARM_ELF_HWCAP_IDIVT },
    947       { "idiv", MD_CPU_ARM_ELF_HWCAP_IDIVA | MD_CPU_ARM_ELF_HWCAP_IDIVT },
    948 #elif defined(__aarch64__)
    949       // No hwcaps on aarch64.
    950 #endif
    951     };
    952 
    953     // processor_architecture should always be set, do this first
    954     sys_info->processor_architecture =
    955 #if defined(__aarch64__)
    956         MD_CPU_ARCHITECTURE_ARM64;
    957 #else
    958         MD_CPU_ARCHITECTURE_ARM;
    959 #endif
    960 
    961     // /proc/cpuinfo is not readable under various sandboxed environments
    962     // (e.g. Android services with the android:isolatedProcess attribute)
    963     // prepare for this by setting default values now, which will be
    964     // returned when this happens.
    965     //
    966     // Note: Bogus values are used to distinguish between failures (to
    967     //       read /sys and /proc files) and really badly configured kernels.
    968     sys_info->number_of_processors = 0;
    969     sys_info->processor_level = 1U;  // There is no ARMv1
    970     sys_info->processor_revision = 42;
    971     sys_info->cpu.arm_cpu_info.cpuid = 0;
    972     sys_info->cpu.arm_cpu_info.elf_hwcaps = 0;
    973 
    974     // Counting the number of CPUs involves parsing two sysfs files,
    975     // because the content of /proc/cpuinfo will only mirror the number
    976     // of 'online' cores, and thus will vary with time.
    977     // See http://www.kernel.org/doc/Documentation/cputopology.txt
    978     {
    979       CpuSet cpus_present;
    980       CpuSet cpus_possible;
    981 
    982       int fd = sys_open("/sys/devices/system/cpu/present", O_RDONLY, 0);
    983       if (fd >= 0) {
    984         cpus_present.ParseSysFile(fd);
    985         sys_close(fd);
    986 
    987         fd = sys_open("/sys/devices/system/cpu/possible", O_RDONLY, 0);
    988         if (fd >= 0) {
    989           cpus_possible.ParseSysFile(fd);
    990           sys_close(fd);
    991 
    992           cpus_present.IntersectWith(cpus_possible);
    993           int cpu_count = cpus_present.GetCount();
    994           if (cpu_count > 255)
    995             cpu_count = 255;
    996           sys_info->number_of_processors = static_cast<uint8_t>(cpu_count);
    997         }
    998       }
    999     }
   1000 
   1001     // Parse /proc/cpuinfo to reconstruct the CPUID value, as well
   1002     // as the ELF hwcaps field. For the latter, it would be easier to
   1003     // read /proc/self/auxv but unfortunately, this file is not always
   1004     // readable from regular Android applications on later versions
   1005     // (>= 4.1) of the Android platform.
   1006     const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
   1007     if (fd < 0) {
   1008       // Do not return false here to allow the minidump generation
   1009       // to happen properly.
   1010       return true;
   1011     }
   1012 
   1013     {
   1014       PageAllocator allocator;
   1015       ProcCpuInfoReader* const reader =
   1016           new(allocator) ProcCpuInfoReader(fd);
   1017       const char* field;
   1018       while (reader->GetNextField(&field)) {
   1019         for (size_t i = 0;
   1020              i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
   1021              ++i) {
   1022           const CpuIdEntry* entry = &cpu_id_entries[i];
   1023           if (my_strcmp(entry->field, field) != 0)
   1024             continue;
   1025           uintptr_t result = 0;
   1026           const char* value = reader->GetValue();
   1027           const char* p = value;
   1028           if (value[0] == '0' && value[1] == 'x') {
   1029             p = my_read_hex_ptr(&result, value+2);
   1030           } else if (entry->format == 'x') {
   1031             p = my_read_hex_ptr(&result, value);
   1032           } else {
   1033             p = my_read_decimal_ptr(&result, value);
   1034           }
   1035           if (p == value)
   1036             continue;
   1037 
   1038           result &= (1U << entry->bit_length)-1;
   1039           result <<= entry->bit_lshift;
   1040           sys_info->cpu.arm_cpu_info.cpuid |=
   1041               static_cast<uint32_t>(result);
   1042         }
   1043 #if defined(__arm__)
   1044         // Get the architecture version from the "Processor" field.
   1045         // Note that it is also available in the "CPU architecture" field,
   1046         // however, some existing kernels are misconfigured and will report
   1047         // invalid values here (e.g. 6, while the CPU is ARMv7-A based).
   1048         // The "Processor" field doesn't have this issue.
   1049         if (!my_strcmp(field, "Processor")) {
   1050           size_t value_len;
   1051           const char* value = reader->GetValueAndLen(&value_len);
   1052           // Expected format: <text> (v<level><endian>)
   1053           // Where <text> is some text like "ARMv7 Processor rev 2"
   1054           // and <level> is a decimal corresponding to the ARM
   1055           // architecture number. <endian> is either 'l' or 'b'
   1056           // and corresponds to the endianess, it is ignored here.
   1057           while (value_len > 0 && my_isspace(value[value_len-1]))
   1058             value_len--;
   1059 
   1060           size_t nn = value_len;
   1061           while (nn > 0 && value[nn-1] != '(')
   1062             nn--;
   1063           if (nn > 0 && value[nn] == 'v') {
   1064             uintptr_t arch_level = 5;
   1065             my_read_decimal_ptr(&arch_level, value + nn + 1);
   1066             sys_info->processor_level = static_cast<uint16_t>(arch_level);
   1067           }
   1068         }
   1069 #elif defined(__aarch64__)
   1070         // The aarch64 architecture does not provide the architecture level
   1071         // in the Processor field, so we instead check the "CPU architecture"
   1072         // field.
   1073         if (!my_strcmp(field, "CPU architecture")) {
   1074           uintptr_t arch_level = 0;
   1075           const char* value = reader->GetValue();
   1076           const char* p = value;
   1077           p = my_read_decimal_ptr(&arch_level, value);
   1078           if (p == value)
   1079             continue;
   1080           sys_info->processor_level = static_cast<uint16_t>(arch_level);
   1081         }
   1082 #endif
   1083         // Rebuild the ELF hwcaps from the 'Features' field.
   1084         if (!my_strcmp(field, "Features")) {
   1085           size_t value_len;
   1086           const char* value = reader->GetValueAndLen(&value_len);
   1087 
   1088           // Parse each space-separated tag.
   1089           while (value_len > 0) {
   1090             const char* tag = value;
   1091             size_t tag_len = value_len;
   1092             const char* p = my_strchr(tag, ' ');
   1093             if (p != NULL) {
   1094               tag_len = static_cast<size_t>(p - tag);
   1095               value += tag_len + 1;
   1096               value_len -= tag_len + 1;
   1097             } else {
   1098               tag_len = strlen(tag);
   1099               value_len = 0;
   1100             }
   1101             for (size_t i = 0;
   1102                 i < sizeof(cpu_features_entries)/
   1103                     sizeof(cpu_features_entries[0]);
   1104                 ++i) {
   1105               const CpuFeaturesEntry* entry = &cpu_features_entries[i];
   1106               if (tag_len == strlen(entry->tag) &&
   1107                   !memcmp(tag, entry->tag, tag_len)) {
   1108                 sys_info->cpu.arm_cpu_info.elf_hwcaps |= entry->hwcaps;
   1109                 break;
   1110               }
   1111             }
   1112           }
   1113         }
   1114       }
   1115       sys_close(fd);
   1116     }
   1117 
   1118     return true;
   1119   }
   1120 #else
   1121 #  error "Unsupported CPU"
   1122 #endif
   1123 
   1124   bool WriteFile(MDLocationDescriptor* result, const char* filename) {
   1125     const int fd = sys_open(filename, O_RDONLY, 0);
   1126     if (fd < 0)
   1127       return false;
   1128 
   1129     // We can't stat the files because several of the files that we want to
   1130     // read are kernel seqfiles, which always have a length of zero. So we have
   1131     // to read as much as we can into a buffer.
   1132     static const unsigned kBufSize = 1024 - 2*sizeof(void*);
   1133     struct Buffers {
   1134       Buffers* next;
   1135       size_t len;
   1136       uint8_t data[kBufSize];
   1137     } *buffers = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
   1138     buffers->next = NULL;
   1139     buffers->len = 0;
   1140 
   1141     size_t total = 0;
   1142     for (Buffers* bufptr = buffers;;) {
   1143       ssize_t r;
   1144       do {
   1145         r = sys_read(fd, &bufptr->data[bufptr->len], kBufSize - bufptr->len);
   1146       } while (r == -1 && errno == EINTR);
   1147 
   1148       if (r < 1)
   1149         break;
   1150 
   1151       total += r;
   1152       bufptr->len += r;
   1153       if (bufptr->len == kBufSize) {
   1154         bufptr->next = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
   1155         bufptr = bufptr->next;
   1156         bufptr->next = NULL;
   1157         bufptr->len = 0;
   1158       }
   1159     }
   1160     sys_close(fd);
   1161 
   1162     if (!total)
   1163       return false;
   1164 
   1165     UntypedMDRVA memory(&minidump_writer_);
   1166     if (!memory.Allocate(total))
   1167       return false;
   1168     for (MDRVA pos = memory.position(); buffers; buffers = buffers->next) {
   1169       // Check for special case of a zero-length buffer.  This should only
   1170       // occur if a file's size happens to be a multiple of the buffer's
   1171       // size, in which case the final sys_read() will have resulted in
   1172       // zero bytes being read after the final buffer was just allocated.
   1173       if (buffers->len == 0) {
   1174         // This can only occur with final buffer.
   1175         assert(buffers->next == NULL);
   1176         continue;
   1177       }
   1178       memory.Copy(pos, &buffers->data, buffers->len);
   1179       pos += buffers->len;
   1180     }
   1181     *result = memory.location();
   1182     return true;
   1183   }
   1184 
   1185   bool WriteOSInformation(MDRawSystemInfo* sys_info) {
   1186 #if defined(__ANDROID__)
   1187     sys_info->platform_id = MD_OS_ANDROID;
   1188 #else
   1189     sys_info->platform_id = MD_OS_LINUX;
   1190 #endif
   1191 
   1192     struct utsname uts;
   1193     if (uname(&uts))
   1194       return false;
   1195 
   1196     static const size_t buf_len = 512;
   1197     char buf[buf_len] = {0};
   1198     size_t space_left = buf_len - 1;
   1199     const char* info_table[] = {
   1200       uts.sysname,
   1201       uts.release,
   1202       uts.version,
   1203       uts.machine,
   1204       NULL
   1205     };
   1206     bool first_item = true;
   1207     for (const char** cur_info = info_table; *cur_info; cur_info++) {
   1208       static const char separator[] = " ";
   1209       size_t separator_len = sizeof(separator) - 1;
   1210       size_t info_len = my_strlen(*cur_info);
   1211       if (info_len == 0)
   1212         continue;
   1213 
   1214       if (space_left < info_len + (first_item ? 0 : separator_len))
   1215         break;
   1216 
   1217       if (!first_item) {
   1218         my_strlcat(buf, separator, sizeof(buf));
   1219         space_left -= separator_len;
   1220       }
   1221 
   1222       first_item = false;
   1223       my_strlcat(buf, *cur_info, sizeof(buf));
   1224       space_left -= info_len;
   1225     }
   1226 
   1227     MDLocationDescriptor location;
   1228     if (!minidump_writer_.WriteString(buf, 0, &location))
   1229       return false;
   1230     sys_info->csd_version_rva = location.rva;
   1231 
   1232     return true;
   1233   }
   1234 
   1235   bool WriteProcFile(MDLocationDescriptor* result, pid_t pid,
   1236                      const char* filename) {
   1237     char buf[NAME_MAX];
   1238     if (!dumper_->BuildProcPath(buf, pid, filename))
   1239       return false;
   1240     return WriteFile(result, buf);
   1241   }
   1242 
   1243   // Only one of the 2 member variables below should be set to a valid value.
   1244   const int fd_;  // File descriptor where the minidum should be written.
   1245   const char* path_;  // Path to the file where the minidum should be written.
   1246 
   1247   const struct ucontext* const ucontext_;  // also from the signal handler
   1248 #if !defined(__ARM_EABI__) && !defined(__mips__)
   1249   const google_breakpad::fpstate_t* const float_state_;  // ditto
   1250 #endif
   1251   LinuxDumper* dumper_;
   1252   MinidumpFileWriter minidump_writer_;
   1253   off_t minidump_size_limit_;
   1254   MDLocationDescriptor crashing_thread_context_;
   1255   // Blocks of memory written to the dump. These are all currently
   1256   // written while writing the thread list stream, but saved here
   1257   // so a memory list stream can be written afterwards.
   1258   wasteful_vector<MDMemoryDescriptor> memory_blocks_;
   1259   // Additional information about some mappings provided by the caller.
   1260   const MappingList& mapping_list_;
   1261   // Additional memory regions to be included in the dump,
   1262   // provided by the caller.
   1263   const AppMemoryList& app_memory_list_;
   1264 };
   1265 
   1266 
   1267 bool WriteMinidumpImpl(const char* minidump_path,
   1268                        int minidump_fd,
   1269                        off_t minidump_size_limit,
   1270                        pid_t crashing_process,
   1271                        const void* blob, size_t blob_size,
   1272                        const MappingList& mappings,
   1273                        const AppMemoryList& appmem) {
   1274   LinuxPtraceDumper dumper(crashing_process);
   1275   const ExceptionHandler::CrashContext* context = NULL;
   1276   if (blob) {
   1277     if (blob_size != sizeof(ExceptionHandler::CrashContext))
   1278       return false;
   1279     context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
   1280     dumper.set_crash_address(
   1281         reinterpret_cast<uintptr_t>(context->siginfo.si_addr));
   1282     dumper.set_crash_signal(context->siginfo.si_signo);
   1283     dumper.set_crash_thread(context->tid);
   1284   }
   1285   MinidumpWriter writer(minidump_path, minidump_fd, context, mappings,
   1286                         appmem, &dumper);
   1287   // Set desired limit for file size of minidump (-1 means no limit).
   1288   writer.set_minidump_size_limit(minidump_size_limit);
   1289   if (!writer.Init())
   1290     return false;
   1291   return writer.Dump();
   1292 }
   1293 
   1294 }  // namespace
   1295 
   1296 namespace google_breakpad {
   1297 
   1298 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
   1299                    const void* blob, size_t blob_size) {
   1300   return WriteMinidumpImpl(minidump_path, -1, -1,
   1301                            crashing_process, blob, blob_size,
   1302                            MappingList(), AppMemoryList());
   1303 }
   1304 
   1305 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
   1306                    const void* blob, size_t blob_size) {
   1307   return WriteMinidumpImpl(NULL, minidump_fd, -1,
   1308                            crashing_process, blob, blob_size,
   1309                            MappingList(), AppMemoryList());
   1310 }
   1311 
   1312 bool WriteMinidump(const char* minidump_path, pid_t process,
   1313                    pid_t process_blamed_thread) {
   1314   LinuxPtraceDumper dumper(process);
   1315   // MinidumpWriter will set crash address
   1316   dumper.set_crash_signal(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED);
   1317   dumper.set_crash_thread(process_blamed_thread);
   1318   MinidumpWriter writer(minidump_path, -1, NULL, MappingList(),
   1319                         AppMemoryList(), &dumper);
   1320   if (!writer.Init())
   1321     return false;
   1322   return writer.Dump();
   1323 }
   1324 
   1325 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
   1326                    const void* blob, size_t blob_size,
   1327                    const MappingList& mappings,
   1328                    const AppMemoryList& appmem) {
   1329   return WriteMinidumpImpl(minidump_path, -1, -1, crashing_process,
   1330                            blob, blob_size,
   1331                            mappings, appmem);
   1332 }
   1333 
   1334 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
   1335                    const void* blob, size_t blob_size,
   1336                    const MappingList& mappings,
   1337                    const AppMemoryList& appmem) {
   1338   return WriteMinidumpImpl(NULL, minidump_fd, -1, crashing_process,
   1339                            blob, blob_size,
   1340                            mappings, appmem);
   1341 }
   1342 
   1343 bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
   1344                    pid_t crashing_process,
   1345                    const void* blob, size_t blob_size,
   1346                    const MappingList& mappings,
   1347                    const AppMemoryList& appmem) {
   1348   return WriteMinidumpImpl(minidump_path, -1, minidump_size_limit,
   1349                            crashing_process, blob, blob_size,
   1350                            mappings, appmem);
   1351 }
   1352 
   1353 bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
   1354                    pid_t crashing_process,
   1355                    const void* blob, size_t blob_size,
   1356                    const MappingList& mappings,
   1357                    const AppMemoryList& appmem) {
   1358   return WriteMinidumpImpl(NULL, minidump_fd, minidump_size_limit,
   1359                            crashing_process, blob, blob_size,
   1360                            mappings, appmem);
   1361 }
   1362 
   1363 bool WriteMinidump(const char* filename,
   1364                    const MappingList& mappings,
   1365                    const AppMemoryList& appmem,
   1366                    LinuxDumper* dumper) {
   1367   MinidumpWriter writer(filename, -1, NULL, mappings, appmem, dumper);
   1368   if (!writer.Init())
   1369     return false;
   1370   return writer.Dump();
   1371 }
   1372 
   1373 }  // namespace google_breakpad
   1374